Browse Source

polish: warn when an existing property starting with $ is not pro… (#8214)

dev
Eduardo San Martin Morote 6 years ago
committed by Evan You
parent
commit
952ae33290
  1. 19
      src/core/instance/proxy.js
  2. 44
      test/unit/features/instance/render-proxy.spec.js

19
src/core/instance/proxy.js

@ -24,6 +24,16 @@ if (process.env.NODE_ENV !== 'production') {
)
}
const warnReservedPrefix = (target, key) => {
warn(
`Property "${key}" must be accessed with "$data.${key}" because ` +
'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
'prevent conflicts with Vue internals' +
'See: https://vuejs.org/v2/api/#data',
target
)
}
const hasProxy =
typeof Proxy !== 'undefined' && isNative(Proxy)
@ -45,9 +55,11 @@ if (process.env.NODE_ENV !== 'production') {
const hasHandler = {
has (target, key) {
const has = key in target
const isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_')
const isAllowed = allowedGlobals(key) ||
(typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data))
if (!has && !isAllowed) {
warnNonPresent(target, key)
if (key in target.$data) warnReservedPrefix(target, key)
else warnNonPresent(target, key)
}
return has || !isAllowed
}
@ -56,7 +68,8 @@ if (process.env.NODE_ENV !== 'production') {
const getHandler = {
get (target, key) {
if (typeof key === 'string' && !(key in target)) {
warnNonPresent(target, key)
if (key in target.$data) warnReservedPrefix(target, key)
else warnNonPresent(target, key)
}
return target[key]
}

44
test/unit/features/instance/render-proxy.spec.js

@ -45,5 +45,49 @@ if (typeof Proxy !== 'undefined') {
expect(vm.$el.textContent).toBe('foo')
})
it('should warn properties starting with $ when found', () => {
new Vue({
data: { $a: 'foo' },
template: `<div>{{ $a }}</div>`
}).$mount()
expect(`Property "$a" must be accessed with "$data.$a"`).toHaveBeenWarned()
})
it('should warn properties starting with _ when found', () => {
new Vue({
data: { _foo: 'foo' },
template: `<div>{{ _foo }}</div>`
}).$mount()
expect(`Property "_foo" must be accessed with "$data._foo"`).toHaveBeenWarned()
})
it('should warn properties starting with $ when not found', () => {
new Vue({
template: `<div>{{ $a }}</div>`
}).$mount()
expect(`Property or method "$a" is not defined`).toHaveBeenWarned()
expect(`Property "$a" must be accessed with "$data.$a"`).not.toHaveBeenWarned()
})
it('should warn properties starting with $ when not found (with stripped)', () => {
const render = function (h) {
return h('p', this.$a)
}
render._withStripped = true
new Vue({
data: { $a: 'foo' },
render
}).$mount()
expect(`Property "$a" must be accessed with "$data.$a"`).toHaveBeenWarned()
})
it('should not warn properties starting with $ when using $data to access', () => {
new Vue({
data: { $a: 'foo' },
template: `<div>{{ $data.$a }}</div>`
}).$mount()
expect(`Property or method "$a" is not defined`).not.toHaveBeenWarned()
})
})
}

Loading…
Cancel
Save