Skip to content

Commit

Permalink
polish: warn when an existing property starting with $ is not pro… (v…
Browse files Browse the repository at this point in the history
  • Loading branch information
posva authored and yyx990803 committed Oct 24, 2018
1 parent 496635e commit 952ae33
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/core/instance/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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
}
Expand All @@ -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]
}
Expand Down
44 changes: 44 additions & 0 deletions test/unit/features/instance/render-proxy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
})
}

0 comments on commit 952ae33

Please sign in to comment.