Skip to content

Commit ac95674

Browse files
committed
feat(cursors): compute chore impl
1 parent 1bd1df9 commit ac95674

File tree

5 files changed

+34
-17
lines changed

5 files changed

+34
-17
lines changed

packages/qwik/src/core/internal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export type { VirtualVNode as _VirtualVNode } from './shared/vnode/virtual-vnode
3333
export { _hasStoreEffects, isStore as _isStore } from './reactive-primitives/impl/store';
3434
export { _wrapProp, _wrapSignal } from './reactive-primitives/internal-api';
3535
export { SubscriptionData as _SubscriptionData } from './reactive-primitives/subscription-data';
36-
export { _EFFECT_BACK_REF } from './reactive-primitives/types';
36+
export { _EFFECT_BACK_REF } from './reactive-primitives/backref';
3737
export {
3838
isStringifiable as _isStringifiable,
3939
type Stringifiable as _Stringifiable,

packages/qwik/src/core/reactive-primitives/impl/wrapped-signal-impl.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { vnode_setProp } from '../../client/vnode';
22
import { assertFalse } from '../../shared/error/assert';
33
import { QError, qError } from '../../shared/error/error';
44
import type { Container, HostElement } from '../../shared/types';
5-
import { HOST_EFFECTS } from '../../shared/utils/markers';
5+
import { HOST_SIGNAL } from '../../shared/utils/markers';
66
import { ChoreBits } from '../../shared/vnode/enums/chore-bits.enum';
77
import { trackSignal } from '../../use/use-core';
88
import { getValueProp } from '../internal-api';
@@ -46,7 +46,7 @@ export class WrappedSignalImpl<T> extends SignalImpl<T> implements BackRef {
4646
this.$computeIfNeeded$();
4747
} catch (_) {
4848
if (this.$container$ && this.$hostElement$) {
49-
vnode_setProp(this.$hostElement$, HOST_EFFECTS, this.$effects$);
49+
vnode_setProp(this.$hostElement$, HOST_SIGNAL, this);
5050
markVNodeDirty(this.$container$, this.$hostElement$, ChoreBits.COMPUTE);
5151
}
5252
}
@@ -64,7 +64,7 @@ export class WrappedSignalImpl<T> extends SignalImpl<T> implements BackRef {
6464
force() {
6565
this.$flags$ |= SignalFlags.RUN_EFFECTS;
6666
if (this.$container$ && this.$hostElement$) {
67-
vnode_setProp(this.$hostElement$, HOST_EFFECTS, this.$effects$);
67+
vnode_setProp(this.$hostElement$, HOST_SIGNAL, this);
6868
markVNodeDirty(this.$container$, this.$hostElement$, ChoreBits.COMPUTE);
6969
}
7070
}

packages/qwik/src/core/shared/cursor/chore-execution.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,27 @@ import {
1616
QScopedStyle,
1717
NODE_PROPS_DATA_KEY,
1818
NODE_DIFF_DATA_KEY,
19+
HOST_SIGNAL,
1920
} from '../utils/markers';
2021
import { addComponentStylePrefix } from '../utils/scoped-styles';
21-
import { isPromise, retryOnPromise, safeCall } from '../utils/promises';
22+
import { isPromise, maybeThen, retryOnPromise, safeCall } from '../utils/promises';
2223
import type { ValueOrPromise } from '../utils/types';
2324
import type { Container, HostElement } from '../types';
2425
import type { VNode } from '../vnode/vnode';
2526
import { VNodeFlags, type ClientContainer } from '../../client/types';
2627
import type { Cursor } from './cursor';
2728
import type { NodeProp } from '../../reactive-primitives/subscription-data';
28-
import { isSignal } from '../../reactive-primitives/utils';
29+
import { isSignal, scheduleEffects } from '../../reactive-primitives/utils';
2930
import type { Signal } from '../../reactive-primitives/signal.public';
3031
import { serializeAttribute } from '../utils/styles';
3132
import type { ISsrNode, SSRContainer } from '../../ssr/ssr-types';
3233
import type { ElementVNode } from '../vnode/element-vnode';
3334
import { VNodeOperationType } from '../vnode/enums/vnode-operation-type.enum';
3435
import type { JSXOutput } from '../jsx/types/jsx-node';
3536
import { getAfterFlushTasks, setAfterFlushTasks, setExtraPromises } from './cursor-props';
37+
import { invoke, newInvokeContext } from '../../use/use-core';
38+
import type { WrappedSignalImpl } from '../../reactive-primitives/impl/wrapped-signal-impl';
39+
import { SignalFlags } from '../../reactive-primitives/types';
3640

3741
/**
3842
* Executes tasks for a vNode if the TASKS dirty bit is set. Tasks are stored in the ELEMENT_SEQ
@@ -337,11 +341,24 @@ export function executeCleanup(vNode: VNode, container: Container): void {
337341
*/
338342
export function executeCompute(vNode: VNode, container: Container): ValueOrPromise<void> {
339343
vNode.dirty &= ~ChoreBits.COMPUTE;
340-
341-
// Compute chores are typically handled by the reactive system.
342-
// This is a placeholder for explicit compute chores if needed.
343-
344-
// TODO remove or use
345-
346-
return;
344+
const target = container.getHostProp<WrappedSignalImpl<unknown> | null>(vNode, HOST_SIGNAL);
345+
if (!target) {
346+
return;
347+
}
348+
const effects = target.$effects$;
349+
350+
const ctx = newInvokeContext();
351+
ctx.$container$ = container;
352+
// needed for computed signals and throwing QRLs
353+
return maybeThen(
354+
retryOnPromise(() =>
355+
invoke.call(target, ctx, (target as WrappedSignalImpl<unknown>).$computeIfNeeded$)
356+
),
357+
() => {
358+
if ((target as WrappedSignalImpl<unknown>).$flags$ & SignalFlags.RUN_EFFECTS) {
359+
(target as WrappedSignalImpl<unknown>).$flags$ &= ~SignalFlags.RUN_EFFECTS;
360+
return scheduleEffects(container, target, effects);
361+
}
362+
}
363+
);
347364
}

packages/qwik/src/core/shared/cursor/cursor-props.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function mergeCursors(container: Container, newCursor: VNode, oldCursor: VNode):
103103
resolveCursor(container);
104104
// merge after flush tasks
105105
const oldAfterFlushTasks = getAfterFlushTasks(oldCursor);
106-
if (oldAfterFlushTasks) {
106+
if (oldAfterFlushTasks && oldAfterFlushTasks.length > 0) {
107107
const newAfterFlushTasks = getAfterFlushTasks(newCursor);
108108
if (newAfterFlushTasks) {
109109
newAfterFlushTasks.push(...oldAfterFlushTasks);
@@ -113,7 +113,7 @@ function mergeCursors(container: Container, newCursor: VNode, oldCursor: VNode):
113113
}
114114
// merge extra promises
115115
const oldExtraPromises = getExtraPromises(oldCursor);
116-
if (oldExtraPromises) {
116+
if (oldExtraPromises && oldExtraPromises.length > 0) {
117117
const newExtraPromises = getExtraPromises(newCursor);
118118
if (newExtraPromises) {
119119
newExtraPromises.push(...oldExtraPromises);
@@ -123,7 +123,7 @@ function mergeCursors(container: Container, newCursor: VNode, oldCursor: VNode):
123123
}
124124
// merge journal
125125
const oldJournal = getCursorJournal(oldCursor);
126-
if (oldJournal) {
126+
if (oldJournal && oldJournal.length > 0) {
127127
const newJournal = getCursorJournal(newCursor);
128128
if (newJournal) {
129129
newJournal.push(...oldJournal);

packages/qwik/src/core/shared/utils/markers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export const ELEMENT_BACKPATCH_DATA = 'qwik/backpatch';
8484
/** Key used to store pending node prop updates in vNode props. */
8585
export const NODE_PROPS_DATA_KEY = 'q:nodeProps';
8686
export const NODE_DIFF_DATA_KEY = 'q:nodeDiff';
87-
export const HOST_EFFECTS = 'q:effects';
87+
export const HOST_SIGNAL = 'q:signal';
8888
export const Q_PREFIX = 'q:';
8989

9090
/** Non serializable markers - always begins with `:` character */

0 commit comments

Comments
 (0)