fix(runtime-core/scheduler): allow component render functions to trigger itself
fix #1801
This commit is contained in:
@@ -8,12 +8,18 @@ export interface SchedulerJob {
|
||||
*/
|
||||
id?: number
|
||||
/**
|
||||
* Indicates this is a watch() callback and is allowed to trigger itself.
|
||||
* A watch callback doesn't track its dependencies so if it triggers itself
|
||||
* again, it's likely intentional and it is the user's responsibility to
|
||||
* perform recursive state mutation that eventually stabilizes.
|
||||
* Indicates whether the job is allowed to recursively trigger itself.
|
||||
* By default, a job cannot trigger itself because some built-in method calls,
|
||||
* e.g. Array.prototype.push actually performs reads as well (#1740) which
|
||||
* can lead to confusing infinite loops.
|
||||
* The allowed cases are component render functions and watch callbacks.
|
||||
* Render functions may update child component props, which in turn trigger
|
||||
* flush: "pre" watch callbacks that mutates state that the parent relies on
|
||||
* (#1801). Watch callbacks doesn't track its dependencies so if it triggers
|
||||
* itself again, it's likely intentional and it is the user's responsibility
|
||||
* to perform recursive state mutation that eventually stabilizes (#1727).
|
||||
*/
|
||||
cb?: boolean
|
||||
allowRecurse?: boolean
|
||||
}
|
||||
|
||||
let isFlushing = false
|
||||
@@ -54,7 +60,7 @@ export function queueJob(job: SchedulerJob) {
|
||||
(!queue.length ||
|
||||
!queue.includes(
|
||||
job,
|
||||
isFlushing && job.cb ? flushIndex + 1 : flushIndex
|
||||
isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex
|
||||
)) &&
|
||||
job !== currentPreFlushParentJob
|
||||
) {
|
||||
@@ -86,7 +92,10 @@ function queueCb(
|
||||
if (!isArray(cb)) {
|
||||
if (
|
||||
!activeQueue ||
|
||||
!activeQueue.includes(cb, (cb as SchedulerJob).cb ? index + 1 : index)
|
||||
!activeQueue.includes(
|
||||
cb,
|
||||
(cb as SchedulerJob).allowRecurse ? index + 1 : index
|
||||
)
|
||||
) {
|
||||
pendingQueue.push(cb)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user