refactor: properly cleanup invalidated jobs

This commit is contained in:
Evan You
2018-11-08 20:08:28 -05:00
parent d39eb6cdbc
commit a95532495a
5 changed files with 130 additions and 79 deletions

View File

@@ -1,8 +1,11 @@
// TODO infinite updates detection
import { Op, setCurrentOps } from './patchNodeOps'
interface Job extends Function {
ops: Op[]
post: Function | null
post: Function[]
cleanup: Function | null
expiration: number
}
@@ -12,6 +15,8 @@ const enum Priorities {
type ErrorHandler = (err: Error) => any
let currentJob: Job | null = null
let start: number = 0
const getNow = () => window.performance.now()
const frameBudget = __JSDOM__ ? Infinity : 1000 / 60
@@ -85,10 +90,10 @@ export function handleSchedulerError(handler: ErrorHandler) {
let hasPendingFlush = false
export function queueJob(rawJob: Function, postJob?: Function | null) {
export function queueJob(rawJob: Function) {
const job = rawJob as Job
job.post = postJob || null
job.ops = job.ops || []
job.post = job.post || []
// 1. let's see if this invalidates any work that
// has already been done.
const commitIndex = commitQueue.indexOf(job)
@@ -118,6 +123,24 @@ export function queueJob(rawJob: Function, postJob?: Function | null) {
}
}
export function queuePostCommitCb(fn: Function) {
if (currentJob) {
currentJob.post.push(fn)
} else {
postCommitQueue.push(fn)
}
}
export function flushPostCommitCbs() {
// post commit hooks (updated, mounted)
// this queue is flushed in reverse becuase these hooks should be invoked
// child first
let job
while ((job = postCommitQueue.pop())) {
job()
}
}
function flush(): void {
let job
while (true) {
@@ -139,14 +162,12 @@ function flush(): void {
// all done, time to commit!
while ((job = commitQueue.shift())) {
commitJob(job)
if (job.post && postCommitQueue.indexOf(job.post) < 0) {
postCommitQueue.push(job.post)
if (job.post) {
postCommitQueue.push(...job.post)
job.post.length = 0
}
}
// post commit hooks (updated, mounted)
while ((job = postCommitQueue.shift())) {
job()
}
flushPostCommitCbs()
// some post commit hook triggered more updates...
if (patchQueue.length > 0) {
if (!__COMPAT__ && getNow() - start > frameBudget) {
@@ -174,7 +195,9 @@ function patchJob(job: Job) {
// job with existing ops means it's already been patched in a low priority queue
if (job.ops.length === 0) {
setCurrentOps(job.ops)
job()
currentJob = job
job.cleanup = job()
currentJob = null
setCurrentOps(null)
commitQueue.push(job)
}
@@ -190,4 +213,9 @@ function commitJob({ ops }: Job) {
function invalidateJob(job: Job) {
job.ops.length = 0
job.post.length = 0
if (job.cleanup) {
job.cleanup()
job.cleanup = null
}
}