Skip to content

Commit 44768e7

Browse files
committed
feat: new find blocking chore implementation
1 parent 832d66e commit 44768e7

File tree

3 files changed

+55
-23
lines changed

3 files changed

+55
-23
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { VNodeFlags } from './types';
2+
import { Chore } from '../shared/scheduler';
23
import { mapApp_findIndx, mapArray_get } from './util-mapArray';
34
import {
45
vnode_ensureElementInflated,
@@ -11,6 +12,8 @@ import {
1112
export abstract class VNode {
1213
props: (string | null | boolean)[] | null = null;
1314
slotParent: VNode | null = null;
15+
chores: Set<Chore> | null = null;
16+
blockedChores: Set<Chore> | null = null;
1417

1518
getSlotParent(): VNode | null {
1619
return this.slotParent;

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

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1-
import { vnode_isDescendantOf, vnode_isVNode } from '../client/vnode';
1+
import {
2+
vnode_getParentOrProjectionParent,
3+
vnode_isDescendantOf,
4+
vnode_isVNode,
5+
} from '../client/vnode';
26
import { Task, TaskFlags } from '../use/use-task';
37
import type { QRLInternal } from './qrl/qrl-class';
48
import type { Chore } from './scheduler';
59
import type { Container, HostElement } from './types';
610
import { ChoreType } from './util-chore-type';
711
import { ELEMENT_SEQ } from './utils/markers';
812
import { isNumber } from './utils/types';
9-
import type { ClientContainer } from '../client/types';
13+
import type { VNode } from '../client/vnode-impl';
1014

1115
type BlockingRule = {
1216
blockedType: ChoreType;
1317
blockingType: ChoreType;
1418
match: (blocked: Chore, blocking: Chore, container: Container) => boolean;
1519
};
1620

21+
const enum ChoreSetType {
22+
CHORES,
23+
BLOCKED_CHORES,
24+
}
25+
1726
/**
1827
* Rules for determining if a chore is blocked by another chore. Some chores can block other chores.
1928
* They cannot run until the blocking chore has completed.
@@ -120,19 +129,25 @@ function isSameQrl(a: QRLInternal<unknown>, b: QRLInternal<unknown>): boolean {
120129
return a.$symbol$ === b.$symbol$;
121130
}
122131

123-
function findBlockingChoreInQueue(
124-
chore: Chore,
125-
choreQueue: Chore[],
126-
container: Container
127-
): Chore | null {
128-
for (const candidate of choreQueue) {
129-
// everything after VISIBLE is not blocking. Visible task, task and resource should not block anything in this rule.
130-
if (candidate.$type$ >= ChoreType.VISIBLE || candidate.$type$ === ChoreType.TASK) {
131-
continue;
132-
}
133-
if (isDescendant(chore, candidate)) {
134-
return candidate;
132+
function findAncestorBlockingChore(chore: Chore, type: ChoreSetType): Chore | null {
133+
const host = chore.$host$;
134+
if (!vnode_isVNode(host)) {
135+
return null;
136+
}
137+
const isNormalQueue = type === ChoreSetType.CHORES;
138+
// Walk up the ancestor tree and check the map
139+
let current: VNode | null = host;
140+
current = vnode_getParentOrProjectionParent(current);
141+
while (current) {
142+
const blockingChores = isNormalQueue ? current.chores : current.blockedChores;
143+
if (blockingChores) {
144+
for (const blockingChore of blockingChores) {
145+
if (blockingChore.$type$ < ChoreType.VISIBLE && blockingChore.$type$ !== ChoreType.TASK) {
146+
return blockingChore;
147+
}
148+
}
135149
}
150+
current = vnode_getParentOrProjectionParent(current);
136151
}
137152
return null;
138153
}
@@ -144,18 +159,17 @@ export function findBlockingChore(
144159
runningChores: Set<Chore>,
145160
container: Container
146161
): Chore | null {
147-
const blockingChoreInChoreQueue = findBlockingChoreInQueue(chore, choreQueue, container);
162+
const blockingChoreInChoreQueue = findAncestorBlockingChore(chore, ChoreSetType.CHORES);
148163
if (blockingChoreInChoreQueue) {
149164
return blockingChoreInChoreQueue;
150165
}
151-
// const blockingChoreInBlockedChores = findBlockingChoreInQueue(
152-
// chore,
153-
// Array.from(blockedChores),
154-
// container
155-
// );
156-
// if (blockingChoreInBlockedChores) {
157-
// return blockingChoreInBlockedChores;
158-
// }
166+
const blockingChoreInBlockedChores = findAncestorBlockingChore(
167+
chore,
168+
ChoreSetType.BLOCKED_CHORES
169+
);
170+
if (blockingChoreInBlockedChores) {
171+
return blockingChoreInBlockedChores;
172+
}
159173

160174
for (const rule of BLOCKING_RULES) {
161175
if (chore.$type$ !== rule.blockedType) {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ This is often caused by modifying a signal in an already rendered component duri
460460
addBlockedChore(blockedChore, blockingChore, blockedChores);
461461
} else {
462462
blockedChores.delete(blockedChore);
463+
if (vnode_isVNode(blockedChore.$host$)) {
464+
blockedChore.$host$.blockedChores?.delete(blockedChore);
465+
}
463466
sortedInsert(choreQueue, blockedChore, (container as DomContainer).rootVNode || null);
464467
blockedChoresScheduled = true;
465468
}
@@ -488,6 +491,9 @@ This is often caused by modifying a signal in an already rendered component duri
488491
) {
489492
// skip deleted chore
490493
DEBUG && debugTrace('skip chore', chore, choreQueue, blockedChores);
494+
if (vnode_isVNode(chore.$host$)) {
495+
chore.$host$.chores?.delete(chore);
496+
}
491497
continue;
492498
}
493499

@@ -564,6 +570,9 @@ This is often caused by modifying a signal in an already rendered component duri
564570
chore.$state$ = ChoreState.DONE;
565571
chore.$returnValue$ = value;
566572
chore.$resolve$?.(value);
573+
if (vnode_isVNode(chore.$host$)) {
574+
chore.$host$.chores?.delete(chore);
575+
}
567576
DEBUG && debugTrace('execute.DONE', chore, choreQueue, blockedChores);
568577
}
569578

@@ -865,6 +874,9 @@ This is often caused by modifying a signal in an already rendered component duri
865874
if (idx < 0) {
866875
/// 2. Insert the chore into the queue.
867876
sortedArray.splice(~idx, 0, value);
877+
if (vnode_isVNode(value.$host$)) {
878+
(value.$host$.chores || (value.$host$.chores = new Set())).add(value);
879+
}
868880
return value;
869881
}
870882

@@ -904,6 +916,9 @@ export function addBlockedChore(
904916
blockingChore.$blockedChores$ ||= [];
905917
blockingChore.$blockedChores$.push(blockedChore);
906918
blockedChores.add(blockedChore);
919+
if (vnode_isVNode(blockedChore.$host$)) {
920+
(blockedChore.$host$.blockedChores ||= new Set()).add(blockedChore);
921+
}
907922
}
908923

909924
function choreTypeToName(type: ChoreType): string {

0 commit comments

Comments
 (0)