fix(runtime-core): avoid script setup bindings overwriting reserved ctx properties (#4570)

This commit is contained in:
ygj6 2021-09-16 23:16:07 +08:00 committed by GitHub
parent a31303f835
commit 14fcced281
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 14 deletions

View File

@ -482,6 +482,54 @@ describe('api: createApp', () => {
expect(serializeInner(root)).toBe('hello') expect(serializeInner(root)).toBe('hello')
}) })
test('return property "_" should not overwrite "ctx._", __isScriptSetup: false', () => {
const Comp = defineComponent({
setup() {
return {
_: ref(0) // return property "_" should not overwrite "ctx._"
}
},
render() {
return h('input', {
ref: 'input'
})
}
})
const root1 = nodeOps.createElement('div')
createApp(Comp).mount(root1)
expect(
`setup() return property "_" should not start with "$" or "_" which are reserved prefixes for Vue internals.`
).toHaveBeenWarned()
})
test('return property "_" should not overwrite "ctx._", __isScriptSetup: true', () => {
const Comp = defineComponent({
setup() {
return {
_: ref(0), // return property "_" should not overwrite "ctx._"
__isScriptSetup: true // mock __isScriptSetup = true
}
},
render() {
return h('input', {
ref: 'input'
})
}
})
const root1 = nodeOps.createElement('div')
const app = createApp(Comp).mount(root1)
// trigger
app.$refs.input
expect(
`TypeError: Cannot read property '__isScriptSetup' of undefined`
).not.toHaveBeenWarned()
})
// config.compilerOptions is tested in packages/vue since it is only // config.compilerOptions is tested in packages/vue since it is only
// supported in the full build. // supported in the full build.
}) })

View File

@ -538,20 +538,22 @@ export function exposeSetupStateOnRenderContext(
) { ) {
const { ctx, setupState } = instance const { ctx, setupState } = instance
Object.keys(toRaw(setupState)).forEach(key => { Object.keys(toRaw(setupState)).forEach(key => {
if (!setupState.__isScriptSetup && (key[0] === '$' || key[0] === '_')) { if (!setupState.__isScriptSetup) {
warn( if (key[0] === '$' || key[0] === '_') {
`setup() return property ${JSON.stringify( warn(
key `setup() return property ${JSON.stringify(
)} should not start with "$" or "_" ` + key
`which are reserved prefixes for Vue internals.` )} should not start with "$" or "_" ` +
) `which are reserved prefixes for Vue internals.`
return )
return
}
Object.defineProperty(ctx, key, {
enumerable: true,
configurable: true,
get: () => setupState[key],
set: NOOP
})
} }
Object.defineProperty(ctx, key, {
enumerable: true,
configurable: true,
get: () => setupState[key],
set: NOOP
})
}) })
} }