Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/yummy-grapes-make.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@qwik.dev/core': patch
---

fix: scheduling previously blocked chore
5 changes: 0 additions & 5 deletions packages/qwik/src/core/client/chore-array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ export class ChoreArray extends Array<Chore> {
}

delete(value: Chore) {
// const idx = this.sortedFindIndex(this, value);
// if (idx >= 0) {
// this.splice(idx, 1);
// }
// return idx;
const idx = this.indexOf(value);
if (idx >= 0) {
this.splice(idx, 1);
Expand Down
13 changes: 4 additions & 9 deletions packages/qwik/src/core/client/vnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1668,23 +1668,18 @@ export const vnode_getProps = (vnode: ElementVNode | VirtualVNode): unknown[] =>
};

export const vnode_isDescendantOf = (vnode: VNode, ancestor: VNode): boolean => {
let parent: VNode | null = vnode_getParentOrProjectionParent(vnode);
let parent: VNode | null = vnode_getProjectionParentOrParent(vnode);
while (parent) {
if (parent === ancestor) {
return true;
}
parent = vnode_getParentOrProjectionParent(parent);
parent = vnode_getProjectionParentOrParent(parent);
}
return false;
};

export const vnode_getParentOrProjectionParent = (vnode: VNode): VNode | null => {
const parentProjection: VNode | null = vnode.slotParent;
if (parentProjection) {
// This is a projection, so we need to check the parent of the projection
return parentProjection;
}
return vnode.parent;
export const vnode_getProjectionParentOrParent = (vnode: VNode): VNode | null => {
return vnode.slotParent || vnode.parent;
};

export const vnode_getNode = (vnode: VNode | null): Element | Text | null => {
Expand Down
6 changes: 3 additions & 3 deletions packages/qwik/src/core/shared/scheduler-rules.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
vnode_getParentOrProjectionParent,
vnode_getProjectionParentOrParent,
vnode_isDescendantOf,
vnode_isVNode,
} from '../client/vnode';
Expand Down Expand Up @@ -138,7 +138,7 @@ function findAncestorBlockingChore(chore: Chore, type: ChoreSetType): Chore | nu
const isNormalQueue = type === ChoreSetType.CHORES;
// Walk up the ancestor tree and check the map
let current: VNode | null = host;
current = vnode_getParentOrProjectionParent(current);
current = vnode_getProjectionParentOrParent(current);
while (current) {
const blockingChores = isNormalQueue ? current.chores : current.blockedChores;
if (blockingChores) {
Expand All @@ -148,7 +148,7 @@ function findAncestorBlockingChore(chore: Chore, type: ChoreSetType): Chore | nu
}
}
}
current = vnode_getParentOrProjectionParent(current);
current = vnode_getProjectionParentOrParent(current);
}
return null;
}
Expand Down
21 changes: 19 additions & 2 deletions packages/qwik/src/core/shared/scheduler-rules.unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -969,13 +969,30 @@ describe('addBlockedChore', () => {
const blockedChore1 = createMockChore(ChoreType.VISIBLE, { el: 'host1' });
const blockedChore2 = createMockChore(ChoreType.TASK, { el: 'host2' });
const blockingChore = createMockChore(ChoreType.NODE_DIFF, { el: 'host3' });
blockingChore.$blockedChores$ = [blockedChore1];
blockingChore.$blockedChores$ = new ChoreArray();
blockingChore.$blockedChores$.add(blockedChore1);
const blockedChores = new Set<Chore>([blockedChore1]);

addBlockedChore(blockedChore2, blockingChore, blockedChores);

expect(blockingChore.$blockedChores$).toEqual([blockedChore1, blockedChore2]);
expect(blockingChore.$blockedChores$).toEqual([blockedChore2, blockedChore1]);
expect(blockedChores.has(blockedChore1)).toBe(true);
expect(blockedChores.has(blockedChore2)).toBe(true);
});

it('should not add duplicate blocked chores', () => {
const blockedChore = createMockChore(ChoreType.VISIBLE, { el: 'host1' });
const blockingChore = createMockChore(ChoreType.NODE_DIFF, { el: 'host2' });
const blockedChores = new Set<Chore>();

// Add the same blocked chore twice
addBlockedChore(blockedChore, blockingChore, blockedChores);
addBlockedChore(blockedChore, blockingChore, blockedChores);

// Should only contain the chore once
expect(blockingChore.$blockedChores$).toEqual([blockedChore]);
expect(blockingChore.$blockedChores$?.length).toBe(1);
expect(blockedChores.has(blockedChore)).toBe(true);
expect(blockedChores.size).toBe(1);
});
});
21 changes: 13 additions & 8 deletions packages/qwik/src/core/shared/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export interface Chore<T extends ChoreType = ChoreType> {
$target$: ChoreTarget | null;
$payload$: unknown;
$state$: ChoreState;
$blockedChores$: Chore[] | null;
$blockedChores$: ChoreArray | null;
$startTime$: number | undefined;
$endTime$: number | undefined;

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

Expand Down Expand Up @@ -460,7 +457,8 @@ This is often caused by modifying a signal in an already rendered component duri
if (vnode_isVNode(blockedChore.$host$)) {
blockedChore.$host$.blockedChores?.delete(blockedChore);
}
choreQueue.add(blockedChore);
addChore(blockedChore, choreQueue);
DEBUG && debugTrace('schedule.UNBLOCKED', blockedChore, choreQueue, blockedChores);
blockedChoresScheduled = true;
}
}
Expand Down Expand Up @@ -784,14 +782,21 @@ export function addBlockedChore(
undefined,
blockedChores
);
blockingChore.$blockedChores$ ||= [];
blockingChore.$blockedChores$.push(blockedChore);
blockingChore.$blockedChores$ ||= new ChoreArray();
blockingChore.$blockedChores$.add(blockedChore);
blockedChores.add(blockedChore);
if (vnode_isVNode(blockedChore.$host$)) {
(blockedChore.$host$.blockedChores ||= new ChoreArray()).add(blockedChore);
}
}

export function addChore(chore: Chore, choreArray: ChoreArray) {
const idx = choreArray.add(chore);
if (idx < 0 && vnode_isVNode(chore.$host$)) {
(chore.$host$.chores ||= new ChoreArray()).add(chore);
}
}

function choreTypeToName(type: ChoreType): string {
return (
(
Expand Down
Loading