Skip to content

Commit

Permalink
fix(runtime-core): should not cache property access during data() inv…
Browse files Browse the repository at this point in the history
…ocation (#3299)

fix #3297
  • Loading branch information
HcySunYang authored Mar 25, 2021
1 parent 4bf7ba1 commit 6e88156
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 5 deletions.
21 changes: 21 additions & 0 deletions packages/runtime-core/__tests__/rendererComponent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(`<h1>1</h1>`)
})
})
})
8 changes: 5 additions & 3 deletions packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ function createDuplicateChecker() {

type DataFn = (vm: ComponentPublicInstance) => any

export let isInBeforeCreate = false
export let shouldCacheAccess = true

export function applyOptions(
instance: ComponentInternalInstance,
Expand Down Expand Up @@ -518,15 +518,15 @@ export function applyOptions(

// applyOptions is called non-as-mixin once per instance
if (!asMixin) {
isInBeforeCreate = true
shouldCacheAccess = false
callSyncHook(
'beforeCreate',
LifecycleHooks.BEFORE_CREATE,
options,
instance,
globalMixins
)
isInBeforeCreate = false
shouldCacheAccess = true
// global mixins are applied first
applyMixins(
instance,
Expand Down Expand Up @@ -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 ` +
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-core/src/componentPublicInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
OptionTypesType,
OptionTypesKeys,
resolveMergedOptions,
isInBeforeCreate
shouldCacheAccess
} from './componentOptions'
import { EmitsOptions, EmitFn } from './componentEmits'
import { Slots } from './componentSlots'
Expand Down Expand Up @@ -305,7 +305,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
} 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
}
}
Expand Down

0 comments on commit 6e88156

Please sign in to comment.