1
- import { vnode_isDescendantOf , vnode_isVNode } from '../client/vnode' ;
1
+ import {
2
+ vnode_getParentOrProjectionParent ,
3
+ vnode_isDescendantOf ,
4
+ vnode_isVNode ,
5
+ } from '../client/vnode' ;
2
6
import { Task , TaskFlags } from '../use/use-task' ;
3
7
import type { QRLInternal } from './qrl/qrl-class' ;
4
8
import type { Chore } from './scheduler' ;
5
9
import type { Container , HostElement } from './types' ;
6
10
import { ChoreType } from './util-chore-type' ;
7
11
import { ELEMENT_SEQ } from './utils/markers' ;
8
12
import { isNumber } from './utils/types' ;
9
- import type { ClientContainer } from '../client/types ' ;
13
+ import type { VNode } from '../client/vnode-impl ' ;
10
14
11
15
type BlockingRule = {
12
16
blockedType : ChoreType ;
13
17
blockingType : ChoreType ;
14
18
match : ( blocked : Chore , blocking : Chore , container : Container ) => boolean ;
15
19
} ;
16
20
21
+ const enum ChoreSetType {
22
+ CHORES ,
23
+ BLOCKED_CHORES ,
24
+ }
25
+
17
26
/**
18
27
* Rules for determining if a chore is blocked by another chore. Some chores can block other chores.
19
28
* They cannot run until the blocking chore has completed.
@@ -120,19 +129,25 @@ function isSameQrl(a: QRLInternal<unknown>, b: QRLInternal<unknown>): boolean {
120
129
return a . $symbol$ === b . $symbol$ ;
121
130
}
122
131
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
+ }
135
149
}
150
+ current = vnode_getParentOrProjectionParent ( current ) ;
136
151
}
137
152
return null ;
138
153
}
@@ -144,18 +159,17 @@ export function findBlockingChore(
144
159
runningChores : Set < Chore > ,
145
160
container : Container
146
161
) : Chore | null {
147
- const blockingChoreInChoreQueue = findBlockingChoreInQueue ( chore , choreQueue , container ) ;
162
+ const blockingChoreInChoreQueue = findAncestorBlockingChore ( chore , ChoreSetType . CHORES ) ;
148
163
if ( blockingChoreInChoreQueue ) {
149
164
return blockingChoreInChoreQueue ;
150
165
}
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
+ }
159
173
160
174
for ( const rule of BLOCKING_RULES ) {
161
175
if ( chore . $type$ !== rule . blockedType ) {
0 commit comments