From 6e88156934a88c891fa1014c46c04a3fa1a5eaeb Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 26 Mar 2021 03:48:12 +0800 Subject: [PATCH] fix(runtime-core): should not cache property access during data() invocation (#3299) fix #3297 --- .../__tests__/rendererComponent.spec.ts | 21 +++++++++++++++++++ packages/runtime-core/src/componentOptions.ts | 8 ++++--- .../src/componentPublicInstance.ts | 4 ++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/runtime-core/__tests__/rendererComponent.spec.ts b/packages/runtime-core/__tests__/rendererComponent.spec.ts index 4c45b90a6bd..02070d384e9 100644 --- a/packages/runtime-core/__tests__/rendererComponent.spec.ts +++ b/packages/runtime-core/__tests__/rendererComponent.spec.ts @@ -275,4 +275,25 @@ describe('renderer: component', () => { await nextTick() expect(App.updated).toHaveBeenCalledTimes(0) }) + + describe('render with access caches', () => { + // #3297 + test('should not set the access cache in the data() function (production mode)', () => { + const Comp = { + data() { + ;(this as any).foo + return { foo: 1 } + }, + render() { + return h('h1', (this as any).foo) + } + } + const root = nodeOps.createElement('div') + + __DEV__ = false + render(h(Comp), root) + __DEV__ = true + expect(serializeInner(root)).toBe(`

1

`) + }) + }) }) diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 70948d41cf9..354c9425c4a 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -465,7 +465,7 @@ function createDuplicateChecker() { type DataFn = (vm: ComponentPublicInstance) => any -export let isInBeforeCreate = false +export let shouldCacheAccess = true export function applyOptions( instance: ComponentInternalInstance, @@ -518,7 +518,7 @@ export function applyOptions( // applyOptions is called non-as-mixin once per instance if (!asMixin) { - isInBeforeCreate = true + shouldCacheAccess = false callSyncHook( 'beforeCreate', LifecycleHooks.BEFORE_CREATE, @@ -526,7 +526,7 @@ export function applyOptions( instance, globalMixins ) - isInBeforeCreate = false + shouldCacheAccess = true // global mixins are applied first applyMixins( instance, @@ -893,7 +893,9 @@ function resolveData( `Plain object usage is no longer supported.` ) } + shouldCacheAccess = false const data = dataFn.call(publicThis, publicThis) + shouldCacheAccess = true if (__DEV__ && isPromise(data)) { warn( `data() returned a Promise - note data() cannot be async; If you ` + diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index bbdb0336092..78f75d8e757 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -31,7 +31,7 @@ import { OptionTypesType, OptionTypesKeys, resolveMergedOptions, - isInBeforeCreate + shouldCacheAccess } from './componentOptions' import { EmitsOptions, EmitFn } from './componentEmits' import { Slots } from './componentSlots' @@ -305,7 +305,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler = { } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { accessCache![key] = AccessTypes.CONTEXT return ctx[key] - } else if (!__FEATURE_OPTIONS_API__ || !isInBeforeCreate) { + } else if (!__FEATURE_OPTIONS_API__ || shouldCacheAccess) { accessCache![key] = AccessTypes.OTHER } }