fix(runtime-core): disallow recurse in vnode/directive beforeUpdate hooks
This commit is contained in:
parent
4b0ca8709a
commit
a1167c57e5
@ -7,7 +7,8 @@ import {
|
|||||||
EffectScope,
|
EffectScope,
|
||||||
markRaw,
|
markRaw,
|
||||||
track,
|
track,
|
||||||
TrackOpTypes
|
TrackOpTypes,
|
||||||
|
ReactiveEffect
|
||||||
} from '@vue/reactivity'
|
} from '@vue/reactivity'
|
||||||
import {
|
import {
|
||||||
ComponentPublicInstance,
|
ComponentPublicInstance,
|
||||||
@ -224,6 +225,10 @@ export interface ComponentInternalInstance {
|
|||||||
* Root vnode of this component's own vdom tree
|
* Root vnode of this component's own vdom tree
|
||||||
*/
|
*/
|
||||||
subTree: VNode
|
subTree: VNode
|
||||||
|
/**
|
||||||
|
* Render effect instance
|
||||||
|
*/
|
||||||
|
effect: ReactiveEffect
|
||||||
/**
|
/**
|
||||||
* Bound effect runner to be passed to schedulers
|
* Bound effect runner to be passed to schedulers
|
||||||
*/
|
*/
|
||||||
@ -460,6 +465,7 @@ export function createComponentInstance(
|
|||||||
root: null!, // to be immediately set
|
root: null!, // to be immediately set
|
||||||
next: null,
|
next: null,
|
||||||
subTree: null!, // will be set synchronously right after creation
|
subTree: null!, // will be set synchronously right after creation
|
||||||
|
effect: null!,
|
||||||
update: null!, // will be set synchronously right after creation
|
update: null!, // will be set synchronously right after creation
|
||||||
scope: new EffectScope(true /* detached */),
|
scope: new EffectScope(true /* detached */),
|
||||||
render: null,
|
render: null,
|
||||||
|
@ -826,12 +826,15 @@ function baseCreateRenderer(
|
|||||||
const newProps = n2.props || EMPTY_OBJ
|
const newProps = n2.props || EMPTY_OBJ
|
||||||
let vnodeHook: VNodeHook | undefined | null
|
let vnodeHook: VNodeHook | undefined | null
|
||||||
|
|
||||||
|
// disable recurse in beforeUpdate hooks
|
||||||
|
parentComponent && toggleRecurse(parentComponent, false)
|
||||||
if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {
|
if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {
|
||||||
invokeVNodeHook(vnodeHook, parentComponent, n2, n1)
|
invokeVNodeHook(vnodeHook, parentComponent, n2, n1)
|
||||||
}
|
}
|
||||||
if (dirs) {
|
if (dirs) {
|
||||||
invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate')
|
invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate')
|
||||||
}
|
}
|
||||||
|
parentComponent && toggleRecurse(parentComponent, true)
|
||||||
|
|
||||||
if (__DEV__ && isHmrUpdating) {
|
if (__DEV__ && isHmrUpdating) {
|
||||||
// HMR updated, force full diff
|
// HMR updated, force full diff
|
||||||
@ -1318,7 +1321,7 @@ function baseCreateRenderer(
|
|||||||
const { bm, m, parent } = instance
|
const { bm, m, parent } = instance
|
||||||
const isAsyncWrapperVNode = isAsyncWrapper(initialVNode)
|
const isAsyncWrapperVNode = isAsyncWrapper(initialVNode)
|
||||||
|
|
||||||
effect.allowRecurse = false
|
toggleRecurse(instance, false)
|
||||||
// beforeMount hook
|
// beforeMount hook
|
||||||
if (bm) {
|
if (bm) {
|
||||||
invokeArrayFns(bm)
|
invokeArrayFns(bm)
|
||||||
@ -1336,7 +1339,7 @@ function baseCreateRenderer(
|
|||||||
) {
|
) {
|
||||||
instance.emit('hook:beforeMount')
|
instance.emit('hook:beforeMount')
|
||||||
}
|
}
|
||||||
effect.allowRecurse = true
|
toggleRecurse(instance, true)
|
||||||
|
|
||||||
if (el && hydrateNode) {
|
if (el && hydrateNode) {
|
||||||
// vnode has adopted host node - perform hydration instead of mount.
|
// vnode has adopted host node - perform hydration instead of mount.
|
||||||
@ -1459,8 +1462,7 @@ function baseCreateRenderer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disallow component effect recursion during pre-lifecycle hooks.
|
// Disallow component effect recursion during pre-lifecycle hooks.
|
||||||
effect.allowRecurse = false
|
toggleRecurse(instance, false)
|
||||||
|
|
||||||
if (next) {
|
if (next) {
|
||||||
next.el = vnode.el
|
next.el = vnode.el
|
||||||
updateComponentPreRender(instance, next, optimized)
|
updateComponentPreRender(instance, next, optimized)
|
||||||
@ -1482,8 +1484,7 @@ function baseCreateRenderer(
|
|||||||
) {
|
) {
|
||||||
instance.emit('hook:beforeUpdate')
|
instance.emit('hook:beforeUpdate')
|
||||||
}
|
}
|
||||||
|
toggleRecurse(instance, true)
|
||||||
effect.allowRecurse = true
|
|
||||||
|
|
||||||
// render
|
// render
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
@ -1552,17 +1553,17 @@ function baseCreateRenderer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create reactive effect for rendering
|
// create reactive effect for rendering
|
||||||
const effect = new ReactiveEffect(
|
const effect = (instance.effect = new ReactiveEffect(
|
||||||
componentUpdateFn,
|
componentUpdateFn,
|
||||||
() => queueJob(instance.update),
|
() => queueJob(instance.update),
|
||||||
instance.scope // track it in component's effect scope
|
instance.scope // track it in component's effect scope
|
||||||
)
|
))
|
||||||
|
|
||||||
const update = (instance.update = effect.run.bind(effect) as SchedulerJob)
|
const update = (instance.update = effect.run.bind(effect) as SchedulerJob)
|
||||||
update.id = instance.uid
|
update.id = instance.uid
|
||||||
// allowRecurse
|
// allowRecurse
|
||||||
// #1801, #2043 component render effects should allow recursive updates
|
// #1801, #2043 component render effects should allow recursive updates
|
||||||
effect.allowRecurse = update.allowRecurse = true
|
toggleRecurse(instance, true)
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
effect.onTrack = instance.rtc
|
effect.onTrack = instance.rtc
|
||||||
@ -2455,6 +2456,13 @@ export function invokeVNodeHook(
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleRecurse(
|
||||||
|
{ effect, update }: ComponentInternalInstance,
|
||||||
|
allowed: boolean
|
||||||
|
) {
|
||||||
|
effect.allowRecurse = update.allowRecurse = allowed
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #1156
|
* #1156
|
||||||
* When a component is HMR-enabled, we need to make sure that all static nodes
|
* When a component is HMR-enabled, we need to make sure that all static nodes
|
||||||
|
Loading…
Reference in New Issue
Block a user