vue: method named _update breaks component creation
Version
2.4.2
Reproduction link
[Method] https://jsfiddle.net/50wL7mdz/52180/ and [Computed] https://jsfiddle.net/7d2aytsL/
Steps to reproduce
- Add an
_updatemethod or computed property on a custom component - Add that component to the App
- Note Vue throws
TypeError
What is expected?
An method called _update is a perfectly reasonable name for a method and/or computed property, and should not be throwing simply based on it’s naming.
What is actually happening?
I have yet to dig in further but for some reason the vnode object loses it’s reference when having this method or computed name.
Uncaught TypeError: Cannot read property 'componentInstance' of null
at isPatchable (vue@2.4.2:5217)
at initComponent (vue@2.4.2:5160)
at createComponent (vue@2.4.2:5145)
at createElm (vue@2.4.2:5081)
at createChildren (vue@2.4.2:5209)
at createElm (vue@2.4.2:5114)
at Vue$3.patch [as __patch__] (vue@2.4.2:5597)
at Vue$3.Vue._update (vue@2.4.2:2418)
at Vue$3.updateComponent (vue@2.4.2:2542)
at Watcher.get (vue@2.4.2:2883)
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 24 (19 by maintainers)
Commits related to this issue
- chore: warn methods that conflict with internals close #6312 — committed to FranklinTesla/vue by yyx990803 7 years ago
- chore: warn methods that conflict with internals close #6312 — committed to ztlevi/vue by yyx990803 7 years ago
- chore: warn methods that conflict with internals close #6312 — committed to f2009/vue by yyx990803 7 years ago
Ah, I see. Since the check only happens on initialization and we’re already iterating over each property for other checks, the impact should be minimal.
@chrisvfritz The problem is some library will use prefixed method names to hide implementation. If we warn based on prefix, library users will have undesired warning.
@posva What impact on the development experience are you trying to avoid? If it’s behind a config flag, wouldn’t it only affect the experience for those who care about future compatibility? And always only in a positive way? I think hiding this important warning behind a compatibility flag is more likely to make people angry than offering them a chance to take a few minutes to prevent their apps from breaking in the future. 😄
I see this as similar to many security issues. We use SSL, even though a user’s credentials probably won’t be stolen. We’re eliminating an especially ugly scenario, despite a relatively low likelihood of occurrence. And in both cases, it’s an easy fix that you only have to make once.
If an entire Vue app could break at any time, in a way that would be difficult to diagnose or possibly even detect, do you not feel that’s worth a couple minutes to fix, even if it probably won’t happen?
@posva I agree that right now, the problem is relatively small - at least as far as we can measure, since overriding private properties can produce difficult-to-diagnose errors, or worse, subtle bugs that don’t even produce an error. Since it’s difficult to track down and report, it might remain a largely invisible problem.
And the longer we wait on something like this, the more plugins will exist and the more conflicts will arise, both with Vue and between plugins/mixins. I feel like we can wait until it’s a bigger problem, but it’s guaranteed to keep growing with Vue’s popularity and it’ll just be even more work at that point.
@JustinBeaudry Yes, we’ll have to warn about all top-level properties: data, props, computed properties, and methods.
@HerringtonDarkholme I agree with @JustinBeaudry in this case. It sounds like we all suggest not to use any underscore-prefixed datum/prop/computed/method names, because we can’t guarantee that Vue won’t conflict with them in the future. That means these plugins could already break at any moment, including in a patch release.
I think it’d be better to have a one-time “soft break” with a warning that suggests an alternate strategy. Maybe the
$_prefix could be officially reserved for private plugin properties, with a suggested namespace like$_pluginName_methodNameto avoid conflicts with other plugins. I use a similar strategy for even application-specific plugins/mixins.Then for any property registration, we could just display a warning if
/^(\$[^_]|_)/.test(key).@chrisvfritz I was trying something like that locally this morning to see if that would work and it seems to. Instead of trying to warn against collisions against specific names, just warning about method names with
_or$seems to be the best bet for now. A warning almost doesn’t seem harsh enough though IMO.@posva @HerringtonDarkholme @JustinBeaudry I might be misunderstanding, but would it not be possible to provide a warning here, if
key[0] === '_'and perhaps also ifkey[0] === '$'?Damn, I didn’t think it will be hard 🙁 In that case, it’s worth pointing it out in the docs In future versions we can use
Symbolsto prevent this, right?Vue itself uses underscore prefixes for internal methods. It’s not advised you do so.