Skip to content
Merged
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 .changeset/crazy-cities-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@qwik.dev/core': patch
---

fix: serialize correctly null or undefined value for signals
4 changes: 2 additions & 2 deletions packages/qwik/src/core/reactive-primitives/cleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { _PROPS_HANDLER } from '../shared/utils/constants';

/** Class for back reference to the EffectSubscription */
export abstract class BackRef {
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | null = null;
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | undefined = undefined;
}

export function clearAllEffects(container: Container, consumer: Consumer): void {
Expand Down Expand Up @@ -62,7 +62,7 @@ function clearSignal(container: Container, producer: SignalImpl, effect: EffectS
}

if (producer instanceof WrappedSignalImpl) {
producer.$hostElement$ = null;
producer.$hostElement$ = undefined;
clearAllEffects(container, producer);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ export class AsyncComputedSignalImpl<T>
implements BackRef
{
$untrackedLoading$: boolean = false;
$untrackedError$: Error | null = null;
$untrackedError$: Error | undefined = undefined;

$loadingEffects$: null | Set<EffectSubscription> = null;
$errorEffects$: null | Set<EffectSubscription> = null;
$loadingEffects$: undefined | Set<EffectSubscription> = undefined;
$errorEffects$: undefined | Set<EffectSubscription> = undefined;
$destroy$: NoSerialize<() => void> | null;
$promiseValue$: T | typeof NEEDS_COMPUTATION = NEEDS_COMPUTATION;
private $promise$: Promise<T> | null = null;

[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | null = null;
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | undefined = undefined;

constructor(
container: Container | null,
Expand All @@ -71,7 +71,7 @@ export class AsyncComputedSignalImpl<T>
this.$untrackedLoading$ = value;
this.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
this,
this.$loadingEffects$
);
Expand All @@ -83,20 +83,20 @@ export class AsyncComputedSignalImpl<T>
}

/** The error that occurred when the signal was resolved. */
get error(): Error | null {
get error(): Error | undefined {
return setupSignalValueAccess(
this,
() => (this.$errorEffects$ ||= new Set()),
() => this.untrackedError
);
}

set untrackedError(value: Error | null) {
set untrackedError(value: Error | undefined) {
if (value !== this.$untrackedError$) {
this.$untrackedError$ = value;
this.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
this,
this.$errorEffects$
);
Expand Down Expand Up @@ -136,7 +136,7 @@ export class AsyncComputedSignalImpl<T>
if (isPromise(untrackedValue)) {
const isFirstComputation = this.$promiseValue$ === NEEDS_COMPUTATION;
this.untrackedLoading = true;
this.untrackedError = null;
this.untrackedError = undefined;

if (this.$promiseValue$ !== NEEDS_COMPUTATION) {
// skip cleanup after resuming
Expand All @@ -148,7 +148,7 @@ export class AsyncComputedSignalImpl<T>
DEBUG && log('Promise resolved', promiseValue);
this.$promiseValue$ = promiseValue;
this.untrackedLoading = false;
this.untrackedError = null;
this.untrackedError = undefined;
if (this.setValue(promiseValue)) {
DEBUG && log('Scheduling effects for subscribers', this.$effects$?.size);
scheduleEffects(this.$container$, this, this.$effects$);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class ComputedSignalImpl<T, S extends QRLInternal = ComputeQRL<T>>
*/
$computeQrl$: S;
$flags$: SignalFlags | SerializationSignalFlags;
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | null = null;
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | undefined = undefined;

constructor(
container: Container | null,
Expand All @@ -55,7 +55,7 @@ export class ComputedSignalImpl<T, S extends QRLInternal = ComputeQRL<T>>
this.$flags$ |= SignalFlags.INVALID;
this.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
this,
this.$effects$
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class SignalImpl<T = any> implements Signal<T> {
$untrackedValue$: T;

/** Store a list of effects which are dependent on this signal. */
$effects$: null | Set<EffectSubscription> = null;
$effects$: undefined | Set<EffectSubscription> = undefined;
$container$: Container | null = null;
$wrappedSignal$: WrappedSignalImpl<T> | null = null;

Expand All @@ -40,7 +40,7 @@ export class SignalImpl<T = any> implements Signal<T> {
force() {
this.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
this,
this.$effects$
);
Expand Down Expand Up @@ -70,7 +70,7 @@ export class SignalImpl<T = any> implements Signal<T> {
this.$untrackedValue$ = value;
this.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
this,
this.$effects$
);
Expand Down
12 changes: 6 additions & 6 deletions packages/qwik/src/core/reactive-primitives/impl/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const getOrCreateStore = <T extends object>(
};

export class StoreHandler implements ProxyHandler<StoreTarget> {
$effects$: null | Map<string | symbol, Set<EffectSubscription>> = null;
$effects$: undefined | Map<string | symbol, Set<EffectSubscription>> = undefined;

constructor(
public $flags$: StoreFlags,
Expand All @@ -111,7 +111,7 @@ export class StoreHandler implements ProxyHandler<StoreTarget> {
const target = getStoreTarget(this)!;
this.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
this,
getEffects(target, prop, this.$effects$)
);
Expand Down Expand Up @@ -201,7 +201,7 @@ export class StoreHandler implements ProxyHandler<StoreTarget> {
// Changing the length property will trigger effects.
this.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
this,
getEffects(target, prop, this.$effects$)
);
Expand Down Expand Up @@ -294,7 +294,7 @@ function setNewValueAndTriggerEffects<T extends Record<string | symbol, any>>(
if (effects) {
currentStore.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
currentStore,
effects
);
Expand All @@ -304,7 +304,7 @@ function setNewValueAndTriggerEffects<T extends Record<string | symbol, any>>(
function getEffects<T extends Record<string | symbol, any>>(
target: T,
prop: string | symbol,
storeEffects: Map<string | symbol, Set<EffectSubscription>> | null
storeEffects: Map<string | symbol, Set<EffectSubscription>> | undefined
) {
let effectsToTrigger: Set<EffectSubscription> | undefined;

Expand All @@ -328,5 +328,5 @@ function getEffects<T extends Record<string | symbol, any>>(
effectsToTrigger!.add(effect);
}
}
return effectsToTrigger || null;
return effectsToTrigger;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export class WrappedSignalImpl<T> extends SignalImpl<T> implements BackRef {
$funcStr$: string | null;

$flags$: AllSignalFlags;
$hostElement$: HostElement | null = null;
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | null = null;
$hostElement$: HostElement | undefined = undefined;
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | undefined = undefined;

constructor(
container: Container | null,
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/reactive-primitives/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const addQrlToSerializationCtx = (
export const scheduleEffects = (
container: Container | null,
signal: SignalImpl | StoreTarget,
effects: Set<EffectSubscription> | null
effects: Set<EffectSubscription> | undefined
) => {
const isBrowser = !isServerPlatform();
if (effects) {
Expand Down
8 changes: 4 additions & 4 deletions packages/qwik/src/core/shared/jsx/props-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function createPropsProxy(owner: JSXNodeImpl): Props {
return new Proxy<any>({}, new PropsProxyHandler(owner));
}
export class PropsProxyHandler implements ProxyHandler<any> {
$effects$: null | Map<string | symbol, Set<EffectSubscription>> = null;
$effects$: undefined | Map<string | symbol, Set<EffectSubscription>> = undefined;
$container$: Container | null = null;

constructor(public owner: JSXNodeImpl) {}
Expand Down Expand Up @@ -176,19 +176,19 @@ export const triggerPropsProxyEffect = (propsProxy: PropsProxyHandler, prop: str
if (effects) {
propsProxy.$container$?.$scheduler$(
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
null,
undefined,
propsProxy,
effects
);
}
};

function getEffects(
effects: Map<string | symbol, Set<EffectSubscription>> | null,
effects: Map<string | symbol, Set<EffectSubscription>> | undefined,
prop: string | symbol
) {
// TODO: Handle STORE_ALL_PROPS
return effects?.get(prop) || null;
return effects?.get(prop);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/qwik/src/core/shared/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ export const createScheduler = (
*/
function schedule(
type: ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
host: HostElement | null,
host: HostElement | undefined,
target: Signal<unknown> | StoreTarget,
effects: Set<EffectSubscription> | null
effects: Set<EffectSubscription> | undefined
): Chore<ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS>;
function schedule(
type: ChoreType.TASK | ChoreType.VISIBLE,
Expand Down
20 changes: 11 additions & 9 deletions packages/qwik/src/core/shared/serdes/inflate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const inflate = (
task.$flags$ = v[1];
task.$index$ = v[2];
task.$el$ = v[3] as HostElement;
task[_EFFECT_BACK_REF] = v[4] as Map<EffectProperty | string, EffectSubscription> | null;
task[_EFFECT_BACK_REF] = v[4] as Map<EffectProperty | string, EffectSubscription> | undefined;
task.$state$ = v[5];
break;
case TypeIds.Resource:
Expand Down Expand Up @@ -139,7 +139,7 @@ export const inflate = (
const d = data as [
number,
unknown[],
Map<EffectProperty | string, EffectSubscription> | null,
Map<EffectProperty | string, EffectSubscription> | undefined,
AllSignalFlags,
HostElement,
...EffectSubscription[],
Expand All @@ -160,9 +160,9 @@ export const inflate = (
const asyncComputed = target as AsyncComputedSignalImpl<unknown>;
const d = data as [
AsyncComputeQRL<unknown>,
Array<EffectSubscription> | null,
Array<EffectSubscription> | null,
Array<EffectSubscription> | null,
Array<EffectSubscription> | undefined,
Array<EffectSubscription> | undefined,
Array<EffectSubscription> | undefined,
boolean,
Error,
unknown?,
Expand All @@ -172,7 +172,7 @@ export const inflate = (
asyncComputed.$loadingEffects$ = new Set(d[2]);
asyncComputed.$errorEffects$ = new Set(d[3]);
asyncComputed.$untrackedLoading$ = d[4];
asyncComputed.$untrackedError$ = d[5] || null;
asyncComputed.$untrackedError$ = d[5];
const hasValue = d.length > 6;
if (hasValue) {
asyncComputed.$untrackedValue$ = d[6];
Expand All @@ -185,9 +185,11 @@ export const inflate = (
case TypeIds.SerializerSignal:
case TypeIds.ComputedSignal: {
const computed = target as ComputedSignalImpl<unknown>;
const d = data as [QRLInternal<() => {}>, EffectSubscription[] | null, unknown?];
const d = data as [QRLInternal<() => {}>, EffectSubscription[] | undefined, unknown?];
computed.$computeQrl$ = d[0];
computed.$effects$ = new Set(d[1]);
if (d[1]) {
computed.$effects$ = new Set(d[1]);
}
const hasValue = d.length > 2;
if (hasValue) {
computed.$untrackedValue$ = d[2];
Expand Down Expand Up @@ -277,7 +279,7 @@ export const inflate = (
JSXNodeImpl | typeof _UNINITIALIZED,
Props,
Props | null,
Map<string | symbol, Set<EffectSubscription>> | null,
Map<string | symbol, Set<EffectSubscription>> | undefined,
];
let owner = d[0];
if (owner === _UNINITIALIZED) {
Expand Down
Loading