Skip to content

Commit efdb879

Browse files
committed
feat: schedule computed and serialized signals qrls only
1 parent 289a8b4 commit efdb879

File tree

2 files changed

+62
-78
lines changed

2 files changed

+62
-78
lines changed

packages/qwik/src/core/shared/shared-serialization.ts

Lines changed: 56 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ const inflate = (
224224
}
225225
break;
226226
case TypeIds.QRL:
227+
case TypeIds.PreloadQRL:
227228
inflateQRL(container, target);
228229
break;
229230
case TypeIds.Task:
@@ -462,6 +463,7 @@ const allocate = (container: DeserializeContainer, typeId: number, value: unknow
462463
case TypeIds.Object:
463464
return {};
464465
case TypeIds.QRL:
466+
case TypeIds.PreloadQRL:
465467
const qrl =
466468
typeof value === 'number'
467469
? // root reference
@@ -859,30 +861,15 @@ const discoverValuesForVNodeData = (vnodeData: VNodeData, callback: (value: unkn
859861

860862
class PromiseResult {
861863
constructor(
862-
public $resolved$: boolean,
863-
public $value$: unknown
864-
) {}
865-
}
866-
867-
class ResourceResult extends PromiseResult {
868-
constructor(
864+
public $type$: number,
869865
public $resolved$: boolean,
870866
public $value$: unknown,
871-
public $effects$: Map<string | symbol, Set<EffectSubscription>> | null
872-
) {
873-
super($resolved$, $value$);
874-
}
875-
}
876-
877-
class SerializerResult extends PromiseResult {
878-
constructor(
879-
public $resolved$: boolean,
880-
public $value$: unknown,
881-
public $effects$: null | Set<EffectSubscription>,
882-
public $qrl$: QRLInternal | null
883-
) {
884-
super($resolved$, $value$);
885-
}
867+
public $effects$:
868+
| Map<string | symbol, Set<EffectSubscription>>
869+
| Set<EffectSubscription>
870+
| null = null,
871+
public $qrl$: QRLInternal | null = null
872+
) {}
886873
}
887874
/**
888875
* Format:
@@ -900,7 +887,9 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
900887
const forwardRefs: number[] = [];
901888
let forwardRefsId = 0;
902889
const promises: Set<Promise<unknown>> = new Set();
890+
const preloadQrls = new Set<QRLInternal>();
903891
let parent: unknown = null;
892+
const isRootObject = () => depth === 0;
904893

905894
const outputArray = (value: unknown[], writeFn: (value: unknown, idx: number) => void) => {
906895
$writer$.write('[');
@@ -941,6 +930,23 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
941930
}
942931
};
943932

933+
const addPreloadQrl = (qrl: QRLInternal) => {
934+
preloadQrls.add(qrl);
935+
serializationContext.$addRoot$(qrl, null);
936+
};
937+
938+
const outputRootRef = (value: unknown, elseCallback: () => void) => {
939+
const seen = $wasSeen$(value);
940+
const rootRefPath = $pathMap$.get(value);
941+
if (isRootObject() && seen && seen.$parent$ !== null && rootRefPath) {
942+
output(TypeIds.RootRef, rootRefPath);
943+
} else if (depth > 0 && seen && seen.$rootIndex$ !== -1) {
944+
output(TypeIds.RootRef, seen.$rootIndex$);
945+
} else {
946+
elseCallback();
947+
}
948+
};
949+
944950
const writeValue = (value: unknown) => {
945951
if (fastSkipSerialize(value as object)) {
946952
output(TypeIds.Constant, Constants.Undefined);
@@ -954,29 +960,16 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
954960
} else if (value === Fragment) {
955961
output(TypeIds.Constant, Constants.Fragment);
956962
} else if (isQrl(value)) {
957-
// TODO: this is the same logic as for strings
958-
const seen = $wasSeen$(value);
959-
const rootRefPath = $pathMap$.get(value);
960-
const isRootObject = depth === 0;
961-
if (
962-
isRootObject &&
963-
seen &&
964-
seen.$parent$ !== null &&
965-
rootRefPath
966-
// && rootRefPathIsShorterThanObject
967-
) {
968-
output(TypeIds.RootRef, rootRefPath);
969-
} else if (depth > 0 && seen && seen.$rootIndex$ !== -1) {
970-
output(TypeIds.RootRef, seen.$rootIndex$);
971-
} else {
963+
outputRootRef(value, () => {
972964
const qrl = qrlToString(serializationContext, value);
973-
if (!isRootObject) {
974-
const id = serializationContext.$addRoot$(qrl);
975-
output(TypeIds.QRL, id);
965+
const type = preloadQrls.has(value) ? TypeIds.PreloadQRL : TypeIds.QRL;
966+
if (isRootObject()) {
967+
output(type, qrl);
976968
} else {
977-
output(TypeIds.QRL, qrl);
969+
const id = serializationContext.$addRoot$(qrl);
970+
output(type, id);
978971
}
979-
}
972+
});
980973
} else if (isQwikComponent(value)) {
981974
const [qrl]: [QRLInternal] = (value as any)[SERIALIZABLE_STATE];
982975
serializationContext.$renderSymbols$.add(qrl.$symbol$);
@@ -1022,27 +1015,9 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
10221015
if (value.length === 0) {
10231016
output(TypeIds.Constant, Constants.EmptyString);
10241017
} else {
1025-
// const rootRefPathIsShorterThanObject =
1026-
// typeof rootRefPath === 'string'
1027-
// ? // check if calculated root ref path is shorter than the object
1028-
// rootRefPath.length <= value.length
1029-
// : true;
1030-
const seen = $wasSeen$(value);
1031-
const rootRefPath = $pathMap$.get(value);
1032-
const isRootObject = depth === 0;
1033-
if (
1034-
isRootObject &&
1035-
seen &&
1036-
seen.$parent$ !== null &&
1037-
rootRefPath
1038-
// && rootRefPathIsShorterThanObject
1039-
) {
1040-
output(TypeIds.RootRef, rootRefPath);
1041-
} else if (depth > 0 && seen && seen.$rootIndex$ !== -1) {
1042-
output(TypeIds.RootRef, seen.$rootIndex$);
1043-
} else {
1018+
outputRootRef(value, () => {
10441019
output(TypeIds.String, value);
1045-
}
1020+
});
10461021
}
10471022
} else if (typeof value === 'undefined') {
10481023
output(TypeIds.Constant, Constants.Undefined);
@@ -1099,7 +1074,12 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
10991074
serializationContext.$resources$.add(value);
11001075
// TODO the effects include the resource return which has duplicate data
11011076
const forwardRefId = $resolvePromise$(value.value, $addRoot$, (resolved, resolvedValue) => {
1102-
return new ResourceResult(resolved, resolvedValue, getStoreHandler(value)!.$effects$);
1077+
return new PromiseResult(
1078+
TypeIds.Resource,
1079+
resolved,
1080+
resolvedValue,
1081+
getStoreHandler(value)!.$effects$
1082+
);
11031083
});
11041084
output(TypeIds.ForwardRef, forwardRefId);
11051085
} else {
@@ -1128,7 +1108,7 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
11281108
const result = value[SerializerSymbol](value);
11291109
if (isPromise(result)) {
11301110
const forwardRef = $resolvePromise$(result, $addRoot$, (resolved, resolvedValue) => {
1131-
return new SerializerResult(resolved, resolvedValue, null, null);
1111+
return new PromiseResult(TypeIds.SerializerSignal, resolved, resolvedValue, null, null);
11321112
});
11331113
output(TypeIds.ForwardRef, forwardRef);
11341114
} else {
@@ -1157,11 +1137,13 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
11571137
output(TypeIds.RefVNode, value.$ssrNode$.id);
11581138
} else if (value instanceof SignalImpl) {
11591139
if (value instanceof SerializerSignalImpl) {
1140+
addPreloadQrl(value.$computeQrl$);
11601141
const forwardRefId = $resolvePromise$(
11611142
$getCustomSerializerPromise$(value, value.$untrackedValue$),
11621143
$addRoot$,
11631144
(resolved, resolvedValue) => {
1164-
return new SerializerResult(
1145+
return new PromiseResult(
1146+
TypeIds.SerializerSignal,
11651147
resolved,
11661148
resolvedValue,
11671149
value.$effects$,
@@ -1191,7 +1173,7 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
11911173
...(value.$effects$ || []),
11921174
]);
11931175
} else if (value instanceof ComputedSignalImpl) {
1194-
serializationContext.$addRoot$(value.$computeQrl$, null);
1176+
addPreloadQrl(value.$computeQrl$);
11951177
const out: [QRLInternal, Set<EffectSubscription> | null, unknown?] = [
11961178
value.$computeQrl$,
11971179
// TODO check if we can use domVRef for effects
@@ -1281,13 +1263,13 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
12811263
output(TypeIds.Task, out);
12821264
} else if (isPromise(value)) {
12831265
const forwardRefId = $resolvePromise$(value, $addRoot$, (resolved, resolvedValue) => {
1284-
return new PromiseResult(resolved, resolvedValue);
1266+
return new PromiseResult(TypeIds.Promise, resolved, resolvedValue);
12851267
});
12861268
output(TypeIds.ForwardRef, forwardRefId);
12871269
} else if (value instanceof PromiseResult) {
1288-
if (value instanceof ResourceResult) {
1270+
if (value.$type$ === TypeIds.Resource) {
12891271
output(TypeIds.Resource, [value.$resolved$, value.$value$, value.$effects$]);
1290-
} else if (value instanceof SerializerResult) {
1272+
} else if (value.$type$ === TypeIds.SerializerSignal) {
12911273
if (value.$qrl$) {
12921274
output(TypeIds.SerializerSignal, [value.$qrl$, value.$effects$, value.$value$]);
12931275
} else if (value.$resolved$) {
@@ -1634,8 +1616,8 @@ export function preprocessState(data: unknown[], container: DeserializeContainer
16341616
return type === TypeIds.ForwardRefs;
16351617
};
16361618

1637-
const isQrlType = (type: TypeIds) => {
1638-
return type === TypeIds.QRL;
1619+
const isPreloadQrlType = (type: TypeIds) => {
1620+
return type === TypeIds.PreloadQRL;
16391621
};
16401622

16411623
const processRootRef = (index: number) => {
@@ -1676,7 +1658,7 @@ export function preprocessState(data: unknown[], container: DeserializeContainer
16761658
processRootRef(i);
16771659
} else if (isForwardRefsMap(data[i] as TypeIds)) {
16781660
container.$forwardRefs$ = data[i + 1] as number[];
1679-
} else if (isQrlType(data[i] as TypeIds)) {
1661+
} else if (isPreloadQrlType(data[i] as TypeIds)) {
16801662
container.$initialQRLsIndexes$ ||= [];
16811663
container.$initialQRLsIndexes$.push(i / 2);
16821664
}
@@ -1841,6 +1823,7 @@ export const enum TypeIds {
18411823
Map,
18421824
Uint8Array,
18431825
QRL,
1826+
PreloadQRL,
18441827
Task,
18451828
Resource,
18461829
Component,
@@ -1877,6 +1860,7 @@ export const _typeIdNames = [
18771860
'Map',
18781861
'Uint8Array',
18791862
'QRL',
1863+
'PreloadQRL',
18801864
'Task',
18811865
'Resource',
18821866
'Component',

packages/qwik/src/core/shared/shared-serialization.unit.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,8 @@ describe('shared-serialization', () => {
468468
Constant null
469469
Number 2
470470
]
471-
2 QRL "mock-chunk#dirty[4]"
472-
3 QRL "mock-chunk#clean[4]"
471+
2 PreloadQRL "mock-chunk#dirty[4]"
472+
3 PreloadQRL "mock-chunk#clean[4]"
473473
4 Signal [
474474
Number 1
475475
]
@@ -496,14 +496,14 @@ describe('shared-serialization', () => {
496496
expect(dumpState(objs)).toMatchInlineSnapshot(`
497497
"
498498
0 ForwardRef 0
499-
1 SerializerSignal [
500-
QRL 2
499+
1 PreloadQRL "mock-chunk#custom_createSerializer_qrl"
500+
2 SerializerSignal [
501+
RootRef 1
501502
Constant null
502503
Number 4
503504
]
504-
2 String "mock-chunk#custom_createSerializer_qrl"
505505
3 ForwardRefs [
506-
1
506+
2
507507
]
508508
(72 chars)"
509509
`);

0 commit comments

Comments
 (0)