Skip to content

Commit 44ea824

Browse files
authored
Merge pull request #8028 from QwikDev/v2-fix-unblocking-chores
fix: scheduling previously blocked chore
2 parents 0f76bec + b6eebcd commit 44ea824

File tree

7 files changed

+279
-28
lines changed

7 files changed

+279
-28
lines changed

.changeset/yummy-grapes-make.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: scheduling previously blocked chore

packages/qwik/src/core/client/chore-array.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ export class ChoreArray extends Array<Chore> {
3636
}
3737

3838
delete(value: Chore) {
39-
// const idx = this.sortedFindIndex(this, value);
40-
// if (idx >= 0) {
41-
// this.splice(idx, 1);
42-
// }
43-
// return idx;
4439
const idx = this.indexOf(value);
4540
if (idx >= 0) {
4641
this.splice(idx, 1);

packages/qwik/src/core/client/vnode.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,23 +1668,18 @@ export const vnode_getProps = (vnode: ElementVNode | VirtualVNode): unknown[] =>
16681668
};
16691669

16701670
export const vnode_isDescendantOf = (vnode: VNode, ancestor: VNode): boolean => {
1671-
let parent: VNode | null = vnode_getParentOrProjectionParent(vnode);
1671+
let parent: VNode | null = vnode_getProjectionParentOrParent(vnode);
16721672
while (parent) {
16731673
if (parent === ancestor) {
16741674
return true;
16751675
}
1676-
parent = vnode_getParentOrProjectionParent(parent);
1676+
parent = vnode_getProjectionParentOrParent(parent);
16771677
}
16781678
return false;
16791679
};
16801680

1681-
export const vnode_getParentOrProjectionParent = (vnode: VNode): VNode | null => {
1682-
const parentProjection: VNode | null = vnode.slotParent;
1683-
if (parentProjection) {
1684-
// This is a projection, so we need to check the parent of the projection
1685-
return parentProjection;
1686-
}
1687-
return vnode.parent;
1681+
export const vnode_getProjectionParentOrParent = (vnode: VNode): VNode | null => {
1682+
return vnode.slotParent || vnode.parent;
16881683
};
16891684

16901685
export const vnode_getNode = (vnode: VNode | null): Element | Text | null => {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
vnode_getParentOrProjectionParent,
2+
vnode_getProjectionParentOrParent,
33
vnode_isDescendantOf,
44
vnode_isVNode,
55
} from '../client/vnode';
@@ -138,7 +138,7 @@ function findAncestorBlockingChore(chore: Chore, type: ChoreSetType): Chore | nu
138138
const isNormalQueue = type === ChoreSetType.CHORES;
139139
// Walk up the ancestor tree and check the map
140140
let current: VNode | null = host;
141-
current = vnode_getParentOrProjectionParent(current);
141+
current = vnode_getProjectionParentOrParent(current);
142142
while (current) {
143143
const blockingChores = isNormalQueue ? current.chores : current.blockedChores;
144144
if (blockingChores) {
@@ -148,7 +148,7 @@ function findAncestorBlockingChore(chore: Chore, type: ChoreSetType): Chore | nu
148148
}
149149
}
150150
}
151-
current = vnode_getParentOrProjectionParent(current);
151+
current = vnode_getProjectionParentOrParent(current);
152152
}
153153
return null;
154154
}

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -969,13 +969,30 @@ describe('addBlockedChore', () => {
969969
const blockedChore1 = createMockChore(ChoreType.VISIBLE, { el: 'host1' });
970970
const blockedChore2 = createMockChore(ChoreType.TASK, { el: 'host2' });
971971
const blockingChore = createMockChore(ChoreType.NODE_DIFF, { el: 'host3' });
972-
blockingChore.$blockedChores$ = [blockedChore1];
972+
blockingChore.$blockedChores$ = new ChoreArray();
973+
blockingChore.$blockedChores$.add(blockedChore1);
973974
const blockedChores = new Set<Chore>([blockedChore1]);
974975

975976
addBlockedChore(blockedChore2, blockingChore, blockedChores);
976977

977-
expect(blockingChore.$blockedChores$).toEqual([blockedChore1, blockedChore2]);
978+
expect(blockingChore.$blockedChores$).toEqual([blockedChore2, blockedChore1]);
978979
expect(blockedChores.has(blockedChore1)).toBe(true);
979980
expect(blockedChores.has(blockedChore2)).toBe(true);
980981
});
982+
983+
it('should not add duplicate blocked chores', () => {
984+
const blockedChore = createMockChore(ChoreType.VISIBLE, { el: 'host1' });
985+
const blockingChore = createMockChore(ChoreType.NODE_DIFF, { el: 'host2' });
986+
const blockedChores = new Set<Chore>();
987+
988+
// Add the same blocked chore twice
989+
addBlockedChore(blockedChore, blockingChore, blockedChores);
990+
addBlockedChore(blockedChore, blockingChore, blockedChores);
991+
992+
// Should only contain the chore once
993+
expect(blockingChore.$blockedChores$).toEqual([blockedChore]);
994+
expect(blockingChore.$blockedChores$?.length).toBe(1);
995+
expect(blockedChores.has(blockedChore)).toBe(true);
996+
expect(blockedChores.size).toBe(1);
997+
});
981998
});

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export interface Chore<T extends ChoreType = ChoreType> {
154154
$target$: ChoreTarget | null;
155155
$payload$: unknown;
156156
$state$: ChoreState;
157-
$blockedChores$: Chore[] | null;
157+
$blockedChores$: ChoreArray | null;
158158
$startTime$: number | undefined;
159159
$endTime$: number | undefined;
160160

@@ -361,10 +361,7 @@ This is often caused by modifying a signal in an already rendered component duri
361361
return chore;
362362
}
363363
if (!isRunningChore(chore)) {
364-
const idx = choreQueue.add(chore);
365-
if (idx < 0 && vnode_isVNode(chore.$host$)) {
366-
(chore.$host$.chores ||= new ChoreArray()).add(chore);
367-
}
364+
addChore(chore, choreQueue);
368365
}
369366
DEBUG && debugTrace('schedule', chore, choreQueue, blockedChores);
370367

@@ -460,7 +457,8 @@ This is often caused by modifying a signal in an already rendered component duri
460457
if (vnode_isVNode(blockedChore.$host$)) {
461458
blockedChore.$host$.blockedChores?.delete(blockedChore);
462459
}
463-
choreQueue.add(blockedChore);
460+
addChore(blockedChore, choreQueue);
461+
DEBUG && debugTrace('schedule.UNBLOCKED', blockedChore, choreQueue, blockedChores);
464462
blockedChoresScheduled = true;
465463
}
466464
}
@@ -784,14 +782,21 @@ export function addBlockedChore(
784782
undefined,
785783
blockedChores
786784
);
787-
blockingChore.$blockedChores$ ||= [];
788-
blockingChore.$blockedChores$.push(blockedChore);
785+
blockingChore.$blockedChores$ ||= new ChoreArray();
786+
blockingChore.$blockedChores$.add(blockedChore);
789787
blockedChores.add(blockedChore);
790788
if (vnode_isVNode(blockedChore.$host$)) {
791789
(blockedChore.$host$.blockedChores ||= new ChoreArray()).add(blockedChore);
792790
}
793791
}
794792

793+
export function addChore(chore: Chore, choreArray: ChoreArray) {
794+
const idx = choreArray.add(chore);
795+
if (idx < 0 && vnode_isVNode(chore.$host$)) {
796+
(chore.$host$.chores ||= new ChoreArray()).add(chore);
797+
}
798+
}
799+
795800
function choreTypeToName(type: ChoreType): string {
796801
return (
797802
(

0 commit comments

Comments
 (0)