Skip to content

Commit f026a32

Browse files
committed
fix: early return if chore is already running
1 parent c008001 commit f026a32

File tree

5 files changed

+44
-17
lines changed

5 files changed

+44
-17
lines changed

.changeset/poor-peaches-roll.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: correct running chores handling edge case

packages/qwik/src/core/shared/scheduler-journal-block.unit.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ describe('should block journal flush during node-diff and component runs', () =>
3030
let vA: ElementVNode = null!;
3131
let vAHost: VirtualVNode = null!;
3232
let choreQueue: ChoreArray;
33-
let blockedChores: Set<Chore>;
33+
let blockedChores: ChoreArray;
3434
let runningChores: Set<Chore>;
3535

3636
async function waitForDrain() {
@@ -44,7 +44,7 @@ describe('should block journal flush during node-diff and component runs', () =>
4444
const container = getDomContainer(document.body);
4545
container.handleError = vi.fn();
4646
choreQueue = new ChoreArray();
47-
blockedChores = new Set();
47+
blockedChores = new ChoreArray();
4848
runningChores = new Set();
4949
scheduler = createScheduler(
5050
container,

packages/qwik/src/core/shared/scheduler.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,13 @@ This is often caused by modifying a signal in an already rendered component duri
355355
chore.$type$ !== ChoreType.QRL_RESOLVE && chore.$type$ !== ChoreType.RUN_QRL;
356356

357357
if (shouldBlock) {
358+
const runningChore = getRunningChore(chore);
359+
if (runningChore) {
360+
if (isResourceChore(runningChore)) {
361+
addBlockedChore(chore, runningChore, blockedChores);
362+
}
363+
return chore;
364+
}
358365
const blockingChore = findBlockingChore(
359366
chore,
360367
choreQueue,
@@ -366,12 +373,6 @@ This is often caused by modifying a signal in an already rendered component duri
366373
addBlockedChore(chore, blockingChore, blockedChores);
367374
return chore;
368375
}
369-
370-
const runningChore = getRunningChore(chore);
371-
if (runningChore) {
372-
addBlockedChore(chore, runningChore, blockedChores);
373-
return chore;
374-
}
375376
}
376377

377378
addChoreAndIncrementBlockingCounter(chore, choreQueue);
@@ -890,19 +891,20 @@ function vNodeAlreadyDeleted(chore: Chore): boolean {
890891
return !!(chore.$host$ && vnode_isVNode(chore.$host$) && chore.$host$.flags & VNodeFlags.Deleted);
891892
}
892893

894+
function isResourceChore(chore: Chore): boolean {
895+
return (
896+
chore.$type$ === ChoreType.TASK &&
897+
!!chore.$payload$ &&
898+
!!((chore.$payload$ as Task).$flags$ & TaskFlags.RESOURCE)
899+
);
900+
}
901+
893902
export function addBlockedChore(
894903
blockedChore: Chore,
895904
blockingChore: Chore,
896905
blockedChores: ChoreArray
897906
): void {
898-
if (
899-
!(
900-
blockedChore.$type$ === ChoreType.TASK &&
901-
blockedChore.$payload$ &&
902-
(blockedChore.$payload$ as Task).$flags$ & TaskFlags.RESOURCE
903-
) &&
904-
choreComparator(blockedChore, blockingChore) === 0
905-
) {
907+
if (!isResourceChore(blockedChore) && choreComparator(blockedChore, blockingChore) === 0) {
906908
return;
907909
}
908910
DEBUG &&

packages/qwik/src/core/shared/scheduler.unit.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,26 @@ describe('scheduler', () => {
11591159
nextTickSpy.mockRestore();
11601160
});
11611161
});
1162+
1163+
it('should early return if chore is already running', async () => {
1164+
const mockHost = vnode_newVirtual();
1165+
mockHost.setProp('q:id', 'test-host');
1166+
const mockQrl = { $hash$: 'test-qrl-hash' } as any;
1167+
1168+
// Create and start a chore
1169+
const chore1 = scheduler(ChoreType.COMPONENT, mockHost as any, mockQrl, null);
1170+
runningChores.add(chore1!);
1171+
choreQueue.length = 0;
1172+
expect(choreQueue.length).toBe(0);
1173+
1174+
// Schedule the same chore again
1175+
scheduler(ChoreType.COMPONENT, mockHost as any, mockQrl, null);
1176+
1177+
// still 0
1178+
expect(choreQueue.length).toBe(0);
1179+
expect(blockedChores.length).toBe(0);
1180+
expect(runningChores.size).toBe(1);
1181+
});
11621182
});
11631183

11641184
function mockTask(host: VNode, opts: { index?: number; qrl?: QRL; visible?: boolean }): Task {

packages/qwik/src/core/shared/shared-container.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export abstract class _SharedContainer implements Container {
3737
};
3838

3939
const choreQueue = new ChoreArray();
40-
const blockedChores = new Set<Chore>();
40+
const blockedChores = new ChoreArray();
4141
const runningChores = new Set<Chore>();
4242
this.$scheduler$ = createScheduler(
4343
this,

0 commit comments

Comments
 (0)