]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): pre jobs without an id should run first (#7746)
authorskirtle <65301168+skirtles-code@users.noreply.github.com>
Mon, 19 Aug 2024 02:13:50 +0000 (03:13 +0100)
committerGitHub <noreply@github.com>
Mon, 19 Aug 2024 02:13:50 +0000 (10:13 +0800)
packages/runtime-core/__tests__/scheduler.spec.ts
packages/runtime-core/src/scheduler.ts

index 079ced4bd1ad47762959bfe94d565bfe912773c6..8d74330da44897735928c587195fabae9cb03133 100644 (file)
@@ -239,6 +239,37 @@ describe('scheduler', () => {
       expect(calls).toEqual(['cb1', 'cb2', 'job1'])
     })
 
+    it('should insert pre jobs without ids first during flushing', async () => {
+      const calls: string[] = []
+      const job1: SchedulerJob = () => {
+        calls.push('job1')
+        queueJob(job3)
+        queueJob(job4)
+      }
+      // job1 has no id
+      job1.flags! |= SchedulerJobFlags.PRE
+      const job2: SchedulerJob = () => {
+        calls.push('job2')
+      }
+      job2.id = 1
+      job2.flags! |= SchedulerJobFlags.PRE
+      const job3: SchedulerJob = () => {
+        calls.push('job3')
+      }
+      // job3 has no id
+      job3.flags! |= SchedulerJobFlags.PRE
+      const job4: SchedulerJob = () => {
+        calls.push('job4')
+      }
+      // job4 has no id
+      job4.flags! |= SchedulerJobFlags.PRE
+
+      queueJob(job1)
+      queueJob(job2)
+      await nextTick()
+      expect(calls).toEqual(['job1', 'job3', 'job4', 'job2'])
+    })
+
     // #3806
     it('queue preFlushCb inside postFlushCb', async () => {
       const spy = vi.fn()
@@ -448,12 +479,20 @@ describe('scheduler', () => {
     job2.id = 2
     const job3 = () => calls.push('job3')
     job3.id = 1
+    const job4: SchedulerJob = () => calls.push('job4')
+    job4.id = 2
+    job4.flags! |= SchedulerJobFlags.PRE
+    const job5: SchedulerJob = () => calls.push('job5')
+    // job5 has no id
+    job5.flags! |= SchedulerJobFlags.PRE
 
     queueJob(job1)
     queueJob(job2)
     queueJob(job3)
+    queueJob(job4)
+    queueJob(job5)
     await nextTick()
-    expect(calls).toEqual(['job3', 'job2', 'job1'])
+    expect(calls).toEqual(['job5', 'job3', 'job4', 'job2', 'job1'])
   })
 
   test('sort SchedulerCbs based on id', async () => {
index 354ebb3a4e852bef0c2ba73b47407367a3c2c02c..bcad996299627064f107e61301bc44642e3d6ea2 100644 (file)
@@ -92,16 +92,16 @@ function findInsertionIndex(id: number) {
 
 export function queueJob(job: SchedulerJob): void {
   if (!(job.flags! & SchedulerJobFlags.QUEUED)) {
-    if (job.id == null) {
-      queue.push(job)
-    } else if (
+    const jobId = getId(job)
+    const lastJob = queue[queue.length - 1]
+    if (
+      !lastJob ||
       // fast path when the job id is larger than the tail
-      !(job.flags! & SchedulerJobFlags.PRE) &&
-      job.id >= ((queue[queue.length - 1] && queue[queue.length - 1].id) || 0)
+      (!(job.flags! & SchedulerJobFlags.PRE) && jobId >= getId(lastJob))
     ) {
       queue.push(job)
     } else {
-      queue.splice(findInsertionIndex(job.id), 0, job)
+      queue.splice(findInsertionIndex(jobId), 0, job)
     }
 
     if (!(job.flags! & SchedulerJobFlags.ALLOW_RECURSE)) {
@@ -206,7 +206,7 @@ export function flushPostFlushCbs(seen?: CountMap): void {
 }
 
 const getId = (job: SchedulerJob): number =>
-  job.id == null ? Infinity : job.id
+  job.id == null ? (job.flags! & SchedulerJobFlags.PRE ? -1 : Infinity) : job.id
 
 const comparator = (a: SchedulerJob, b: SchedulerJob): number => {
   const diff = getId(a) - getId(b)