Skip to content
Closed
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 packages/qwik/src/core/client/chore-array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export class ChoreArray extends Array<Chore> {
if (existing.$payload$ !== value.$payload$) {
existing.$payload$ = value.$payload$;
}
if (value.$type$ === ChoreType.COMPONENT && value.$extra$) {
if (!existing.$extra$) {
existing.$extra$ = value.$extra$;
}
}
return idx;
}

Expand Down
18 changes: 13 additions & 5 deletions packages/qwik/src/core/client/vnode-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import { serializeAttribute } from '../shared/utils/styles';
import { isArray, type ValueOrPromise } from '../shared/utils/types';
import { trackSignalAndAssignHost } from '../use/use-core';
import { TaskFlags, cleanupTask, isTask } from '../use/use-task';
import type { DomContainer } from './dom-container';
import { VNodeFlags, type ClientAttrs, type ClientContainer } from './types';
import { mapApp_findIndx, mapArray_set } from './util-mapArray';
import {
Expand Down Expand Up @@ -82,14 +81,16 @@ import {
import type { ElementVNode, TextVNode, VNode, VirtualVNode } from './vnode-impl';
import { getAttributeNamespace, getNewElementNamespaceData } from './vnode-namespace';

export type VNodeJournalRef = { $journal$: VNodeJournal; $refCount$: number };

export const vnode_diff = (
container: ClientContainer,
jsxNode: JSXChildren,
vStartNode: VNode,
scopedStyleIdPrefix: string | null
scopedStyleIdPrefix: string | null,
journalRef: VNodeJournalRef = { $journal$: [], $refCount$: 1 }
) => {
let journal = (container as DomContainer).$journal$;

let journal = journalRef.$journal$;
/**
* Stack is used to keep track of the state of the traversal.
*
Expand Down Expand Up @@ -231,6 +232,7 @@ export const vnode_diff = (
}
} else if (jsxValue === (SkipRender as JSXChildren)) {
// do nothing, we are skipping this node
// Note, this probably breaks async stuff
journal = [];
} else {
expectText('');
Expand Down Expand Up @@ -559,6 +561,11 @@ export const vnode_diff = (
diff(jsxNode, vHostNode);
}
}
journalRef.$refCount$--;
if (journalRef.$refCount$ === 0) {
// all done with the journal, pass it to the container
container.$journal$.push(...journalRef.$journal$);
}
}

function expectNoChildren() {
Expand Down Expand Up @@ -1268,7 +1275,8 @@ export const vnode_diff = (
* deleted.
*/
(host as VirtualVNode).flags &= ~VNodeFlags.Deleted;
container.$scheduler$(ChoreType.COMPONENT, host, componentQRL, vNodeProps);
journalRef.$refCount$++;
container.$scheduler$(ChoreType.COMPONENT, host, componentQRL, vNodeProps, journalRef);
}
}
descendContentToProject(jsxNode.children, host);
Expand Down
31 changes: 19 additions & 12 deletions packages/qwik/src/core/shared/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,17 @@
* declaration order within component.
*/

import { ChoreArray, choreComparator } from '../client/chore-array';
import { type DomContainer } from '../client/dom-container';
import { VNodeFlags, type ClientContainer } from '../client/types';
import { VNodeJournalOpCode, vnode_isVNode } from '../client/vnode';
import { vnode_diff } from '../client/vnode-diff';
import { vnode_diff, type VNodeJournalRef } from '../client/vnode-diff';
import type { ElementVNode, VirtualVNode } from '../client/vnode-impl';
import { AsyncComputedSignalImpl } from '../reactive-primitives/impl/async-computed-signal-impl';
import { ComputedSignalImpl } from '../reactive-primitives/impl/computed-signal-impl';
import { WrappedSignalImpl } from '../reactive-primitives/impl/wrapped-signal-impl';
import { isSignal, type Signal } from '../reactive-primitives/signal.public';
import { isSsrNode } from '../reactive-primitives/subscriber';
import type { NodePropPayload } from '../reactive-primitives/subscription-data';
import {
SignalFlags,
Expand All @@ -97,6 +101,7 @@ import {
} from '../reactive-primitives/types';
import { scheduleEffects } from '../reactive-primitives/utils';
import { type ISsrNode, type SSRContainer } from '../ssr/ssr-types';
import { invoke, newInvokeContext } from '../use/use-core';
import { runResource, type ResourceDescriptor } from '../use/use-resource';
import {
Task,
Expand All @@ -110,23 +115,18 @@ import { executeComponent } from './component-execution';
import type { OnRenderFn } from './component.public';
import type { Props } from './jsx/jsx-runtime';
import type { JSXOutput } from './jsx/types/jsx-node';
import { createNextTick } from './platform/next-tick';
import { isServerPlatform } from './platform/platform';
import { type QRLInternal } from './qrl/qrl-class';
import { findBlockingChore, findBlockingChoreForVisible } from './scheduler-rules';
import { SsrNodeFlags, type Container, type HostElement } from './types';
import { ChoreType } from './util-chore-type';
import { logWarn } from './utils/log';
import { QScopedStyle } from './utils/markers';
import { isPromise, maybeThen, retryOnPromise, safeCall } from './utils/promises';
import { addComponentStylePrefix } from './utils/scoped-styles';
import { serializeAttribute } from './utils/styles';
import { type ValueOrPromise } from './utils/types';
import { invoke, newInvokeContext } from '../use/use-core';
import { findBlockingChore, findBlockingChoreForVisible } from './scheduler-rules';
import { createNextTick } from './platform/next-tick';
import { AsyncComputedSignalImpl } from '../reactive-primitives/impl/async-computed-signal-impl';
import { isSsrNode } from '../reactive-primitives/subscriber';
import { logWarn } from './utils/log';
import type { ElementVNode, VirtualVNode } from '../client/vnode-impl';
import { ChoreArray, choreComparator } from '../client/chore-array';

// Turn this on to get debug output of what the scheduler is doing.
const DEBUG: boolean = false;
Expand Down Expand Up @@ -161,6 +161,7 @@ export interface Chore<T extends ChoreType = ChoreType> {
$resolve$: ((value: any) => void) | undefined;
$reject$: ((reason?: any) => void) | undefined;
$returnValue$: ValueOrPromise<ChoreReturnValue<T>>;
$extra$?: unknown;
}

export type Scheduler = ReturnType<typeof createScheduler>;
Expand Down Expand Up @@ -243,7 +244,8 @@ export const createScheduler = (
type: ChoreType.COMPONENT,
host: HostElement,
qrl: QRLInternal<OnRenderFn<unknown>>,
props: Props | null
props: Props | null,
journalRef?: VNodeJournalRef
): Chore<ChoreType.COMPONENT>;
function schedule(
type: ChoreType.NODE_DIFF,
Expand All @@ -263,7 +265,8 @@ export const createScheduler = (
type: T,
hostOrTask: HostElement | Task | null = null,
targetOrQrl: ChoreTarget | string | null = null,
payload: any = null
payload: unknown = null,
extra?: unknown
): Chore<T> | null {
if (type === ChoreType.WAIT_FOR_QUEUE && drainChore) {
return drainChore as Chore<T>;
Expand Down Expand Up @@ -293,6 +296,9 @@ export const createScheduler = (
$reject$: undefined,
$returnValue$: null!,
};
if (extra !== undefined) {
(chore as any).$extra$ = extra;
}

if (type === ChoreType.WAIT_FOR_QUEUE) {
getChorePromise(chore);
Expand Down Expand Up @@ -659,7 +665,8 @@ This is often caused by modifying a signal in an already rendered component duri
container as ClientContainer,
jsx,
host as VirtualVNode,
addComponentStylePrefix(styleScopedId)
addComponentStylePrefix(styleScopedId),
(chore as any).$extra$
)
);
}
Expand Down
Loading