Skip to content

Commit 728d5b7

Browse files
committed
fix(scheduler): scheduling wait for all on server
1 parent 7474c71 commit 728d5b7

File tree

6 files changed

+66
-57
lines changed

6 files changed

+66
-57
lines changed

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

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
* declaration order within component.
8181
*/
8282

83-
import { isDomContainer, type DomContainer } from '../client/dom-container';
83+
import { type DomContainer } from '../client/dom-container';
8484
import {
8585
ElementVNodeProps,
8686
VNodeFlags,
@@ -102,6 +102,7 @@ import type { OnRenderFn } from './component.public';
102102
import { assertEqual } from './error/assert';
103103
import type { Props } from './jsx/jsx-runtime';
104104
import type { JSXOutput } from './jsx/types/jsx-node';
105+
import { isServerPlatform } from './platform/platform';
105106
import { emitEvent, type QRLInternal } from './qrl/qrl-class';
106107
import { ssrNodeDocumentPosition, vnode_documentPosition } from './scheduler-document-position';
107108
import type { Container, HostElement } from './types';
@@ -178,7 +179,7 @@ export const createScheduler = (
178179
const choreQueue: Chore[] = [];
179180

180181
let currentChore: Chore | null = null;
181-
let journalFlushScheduled: boolean = false;
182+
let drainScheduled: boolean = false;
182183

183184
return schedule;
184185

@@ -242,7 +243,7 @@ export const createScheduler = (
242243
targetOrQrl: ChoreTarget | string | null = null,
243244
payload: any = null
244245
): ValueOrPromise<any> {
245-
const isServer = !isDomContainer(container);
246+
const isServer = isServerPlatform();
246247
const isComponentSsr = isServer && type === ChoreType.COMPONENT;
247248

248249
const runLater: boolean =
@@ -254,7 +255,6 @@ export const createScheduler = (
254255
type === ChoreType.CLEANUP_VISIBLE;
255256
const isClientOnly =
256257
type === ChoreType.JOURNAL_FLUSH ||
257-
type === ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS ||
258258
type === ChoreType.NODE_DIFF ||
259259
type === ChoreType.NODE_PROP;
260260

@@ -281,9 +281,9 @@ export const createScheduler = (
281281
if (!isServer || !isClientOnly) {
282282
chore = sortedInsert(choreQueue, chore, (container as DomContainer).rootVNode || null);
283283
}
284-
if (!journalFlushScheduled && runLater) {
284+
if (!drainScheduled && runLater) {
285285
// If we are not currently draining, we need to schedule a drain.
286-
journalFlushScheduled = true;
286+
drainScheduled = true;
287287
schedule(ChoreType.JOURNAL_FLUSH);
288288
scheduleDrain();
289289
}
@@ -336,37 +336,48 @@ export const createScheduler = (
336336
currentChore = chore;
337337
let returnValue: ValueOrPromise<unknown> | unknown = null;
338338
switch (chore.$type$) {
339+
case ChoreType.WAIT_FOR_ALL:
340+
{
341+
if (isServer) {
342+
drainScheduled = false;
343+
}
344+
}
345+
break;
339346
case ChoreType.JOURNAL_FLUSH:
340-
returnValue = journalFlush();
341-
journalFlushScheduled = false;
347+
{
348+
returnValue = journalFlush();
349+
drainScheduled = false;
350+
}
342351
break;
343352
case ChoreType.COMPONENT:
344-
returnValue = safeCall(
345-
() =>
346-
executeComponent(
347-
container,
348-
host,
349-
host,
350-
chore.$target$ as QRLInternal<OnRenderFn<unknown>>,
351-
chore.$payload$ as Props | null
352-
),
353-
(jsx) => {
354-
if (isServer) {
355-
return jsx;
356-
} else {
357-
const styleScopedId = container.getHostProp<string>(host, QScopedStyle);
358-
return retryOnPromise(() =>
359-
vnode_diff(
360-
container as ClientContainer,
361-
jsx,
362-
host as VirtualVNode,
363-
addComponentStylePrefix(styleScopedId)
364-
)
365-
);
366-
}
367-
},
368-
(err: any) => container.handleError(err, host)
369-
);
353+
{
354+
returnValue = safeCall(
355+
() =>
356+
executeComponent(
357+
container,
358+
host,
359+
host,
360+
chore.$target$ as QRLInternal<OnRenderFn<unknown>>,
361+
chore.$payload$ as Props | null
362+
),
363+
(jsx) => {
364+
if (isServer) {
365+
return jsx;
366+
} else {
367+
const styleScopedId = container.getHostProp<string>(host, QScopedStyle);
368+
return retryOnPromise(() =>
369+
vnode_diff(
370+
container as ClientContainer,
371+
jsx,
372+
host as VirtualVNode,
373+
addComponentStylePrefix(styleScopedId)
374+
)
375+
);
376+
}
377+
},
378+
(err: any) => container.handleError(err, host)
379+
);
380+
}
370381
break;
371382
case ChoreType.RESOURCE:
372383
{

packages/qwik/src/core/signal/signal.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import type { Props } from '../shared/jsx/jsx-runtime';
3232
import type { OnRenderFn } from '../shared/component.public';
3333
import { NEEDS_COMPUTATION } from './flags';
3434
import { QError, qError } from '../shared/error/error';
35+
import { isServerPlatform } from '../shared/platform/platform';
3536

3637
const DEBUG = false;
3738

@@ -318,6 +319,7 @@ export const triggerEffects = (
318319
signal: Signal | TargetType,
319320
effects: EffectSubscriptions[] | null
320321
) => {
322+
const isBrowser = !isServerPlatform();
321323
if (effects) {
322324
const scheduleEffect = (effectSubscriptions: EffectSubscriptions) => {
323325
const effect = effectSubscriptions[EffectSubscriptionsProp.EFFECT];
@@ -351,20 +353,22 @@ export const triggerEffects = (
351353
assertDefined(qrl, 'Component must have QRL');
352354
const props = container.getHostProp<Props>(host, ELEMENT_PROPS);
353355
container.$scheduler$(ChoreType.COMPONENT, host, qrl, props);
354-
} else if (property === EffectProperty.VNODE) {
355-
const host: HostElement = effect as any;
356-
const target = host;
357-
container.$scheduler$(ChoreType.NODE_DIFF, host, target, signal as Signal);
358-
} else {
359-
const host: HostElement = effect as any;
360-
const effectData = effectSubscriptions[EffectSubscriptionsProp.FIRST_BACK_REF_OR_DATA];
361-
if (effectData instanceof EffectPropData) {
362-
const data = effectData.data;
363-
const payload: NodePropPayload = {
364-
...data,
365-
$value$: signal as Signal,
366-
};
367-
container.$scheduler$(ChoreType.NODE_PROP, host, property, payload);
356+
} else if (isBrowser) {
357+
if (property === EffectProperty.VNODE) {
358+
const host: HostElement = effect as any;
359+
const target = host;
360+
container.$scheduler$(ChoreType.NODE_DIFF, host, target, signal as Signal);
361+
} else {
362+
const host: HostElement = effect as any;
363+
const effectData = effectSubscriptions[EffectSubscriptionsProp.FIRST_BACK_REF_OR_DATA];
364+
if (effectData instanceof EffectPropData) {
365+
const data = effectData.data;
366+
const payload: NodePropPayload = {
367+
...data,
368+
$value$: signal as Signal,
369+
};
370+
container.$scheduler$(ChoreType.NODE_PROP, host, property, payload);
371+
}
368372
}
369373
}
370374
};

packages/qwik/src/core/ssr/ssr-render-jsx.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import { qInspector } from '../shared/utils/qdev';
3636
import { serializeAttribute } from '../shared/utils/styles';
3737
import { getFileLocationFromJsx } from '../shared/utils/jsx-filename';
3838
import { queueQRL } from '../client/queue-qrl';
39-
import { ChoreType } from '../shared/scheduler';
4039

4140
class ParentComponentData {
4241
constructor(
@@ -79,10 +78,6 @@ export async function _walkJSX(
7978
styleScoped: options.currentStyleScoped,
8079
parentComponentFrame: options.parentComponentFrame,
8180
});
82-
if (ssr.$hasChores$) {
83-
ssr.$hasChores$ = false;
84-
await ssr.$scheduler$(ChoreType.WAIT_FOR_ALL);
85-
}
8681
}
8782
};
8883
await drain();

packages/qwik/src/core/ssr/ssr-types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ export interface ISsrComponentFrame {
5555
export type SymbolToChunkResolver = (symbol: string) => string;
5656

5757
export interface SSRContainer extends Container {
58-
$hasChores$: boolean;
5958
readonly tag: string;
6059
readonly writer: StreamWriter;
6160
readonly prefetchResources: PrefetchResource[];

packages/qwik/src/server/qwik-copy.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,4 @@ export { VNodeDataSeparator } from '../core/shared/vnode-data-types';
5858
export { escapeHTML } from '../core/shared/utils/character-escaping';
5959
export { getValidManifest } from '../optimizer/src/manifest';
6060
export { QError, qError } from '../core/shared/error/error';
61+
export { ChoreType } from '../core/shared/scheduler';

packages/qwik/src/server/ssr-container.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import {
5050
QSubscribers,
5151
QError,
5252
qError,
53+
ChoreType,
5354
} from './qwik-copy';
5455
import {
5556
type ContextId,
@@ -218,11 +219,9 @@ class SSRContainer extends _SharedContainer implements ISSRContainer {
218219
public $instanceHash$ = hash();
219220
// Temporary flag to find missing roots after the state was serialized
220221
private $noMoreRoots$ = false;
221-
/** True if there are scheduled tasks that need to be run */
222-
public $hasChores$ = false;
223222
constructor(opts: Required<SSRRenderOptions>) {
224223
super(
225-
() => (this.$hasChores$ = true),
224+
() => this.$scheduler$(ChoreType.WAIT_FOR_ALL),
226225
() => null,
227226
opts.renderOptions.serverData ?? EMPTY_OBJ,
228227
opts.locale

0 commit comments

Comments
 (0)