Skip to content

Commit cfae18e

Browse files
committed
feat: use custom serialization
1 parent 1071854 commit cfae18e

File tree

13 files changed

+106
-87
lines changed

13 files changed

+106
-87
lines changed

packages/qwik-router/src/middleware/request-handler/request-event.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import type { ValueOrPromise } from '@qwik.dev/core';
22
import type { QwikManifest, ResolvedManifest } from '@qwik.dev/core/optimizer';
33
import { QDATA_KEY } from '../../runtime/src/constants';
4-
import type {
5-
ActionInternal,
6-
FailReturn,
7-
JSONValue,
8-
LoadedRoute,
9-
LoaderInternal,
4+
import {
5+
LoadedRouteProp,
6+
type ActionInternal,
7+
type FailReturn,
8+
type JSONValue,
9+
type LoadedRoute,
10+
type LoaderInternal,
1011
} from '../../runtime/src/types';
1112
import { isPromise } from '../../runtime/src/utils';
1213
import { createCacheControl } from './cache-control';
@@ -149,7 +150,7 @@ export function createRequestEvent(
149150
env,
150151
method: request.method,
151152
signal: request.signal,
152-
params: loadedRoute?.[1] ?? {},
153+
params: loadedRoute?.[LoadedRouteProp.Params] ?? {},
153154
pathname: url.pathname,
154155
platform,
155156
query: url.searchParams,

packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { QRL } from '@qwik.dev/core';
1+
import { type QRL } from '@qwik.dev/core';
2+
import { SerializerSymbol, _UNINITIALIZED } from '@qwik.dev/core/internal';
23
import type { Render, RenderToStringResult } from '@qwik.dev/core/server';
34
import { QACTION_KEY, QFN_KEY, QLOADER_KEY } from '../../runtime/src/constants';
45
import {
@@ -29,7 +30,6 @@ import {
2930
import { getQwikRouterServerData } from './response-page';
3031
import type { QwikSerializer, RequestEvent, RequestEventBase, RequestHandler } from './types';
3132
import { IsQData, QDATA_JSON } from './user-response';
32-
import { _UNINITIALIZED } from '@qwik.dev/core/internal';
3333

3434
export const resolveRequestHandlers = (
3535
serverPlugins: RouteModule[] | undefined,
@@ -583,6 +583,9 @@ export async function renderQData(requestEv: RequestEvent) {
583583
const loaders: Record<string, unknown> = {};
584584
for (const loaderId in allLoaders) {
585585
const loader = allLoaders[loaderId];
586+
if (typeof loader === 'object' && loader !== null && SerializerSymbol in loader) {
587+
delete (loader as any)[SerializerSymbol];
588+
}
586589
if (loader !== _UNINITIALIZED) {
587590
loaders[loaderId] = loader;
588591
}

packages/qwik-router/src/middleware/request-handler/response-page.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { SerializerSymbol } from '@qwik.dev/core';
2+
import { _UNINITIALIZED } from '@qwik.dev/core/internal';
13
import type { QwikRouterEnvData } from '../../runtime/src/types';
24
import {
35
getRequestLoaders,
@@ -8,6 +10,7 @@ import {
810
RequestRouteName,
911
} from './request-event';
1012
import type { RequestEvent } from './types';
13+
import { Q_ROUTE } from '../../runtime/src/constants';
1114

1215
export function getQwikRouterServerData(requestEv: RequestEvent) {
1316
const { url, params, request, status, locale } = requestEv;
@@ -30,13 +33,28 @@ export function getQwikRouterServerData(requestEv: RequestEvent) {
3033
reconstructedUrl.protocol = protocol;
3134
}
3235

36+
const loaders = getRequestLoaders(requestEv);
37+
38+
// shallow serialize loaders data
39+
(loaders as any)[SerializerSymbol] = (loaders: Record<string, unknown>) => {
40+
const result: Record<string, unknown> = {};
41+
for (const key in loaders) {
42+
const loader = loaders[key];
43+
if (typeof loader === 'object' && loader !== null) {
44+
(loader as any)[SerializerSymbol] = () => _UNINITIALIZED;
45+
}
46+
result[key] = _UNINITIALIZED;
47+
}
48+
return result;
49+
};
50+
3351
return {
3452
url: reconstructedUrl.href,
3553
requestHeaders,
3654
locale: locale(),
3755
nonce,
3856
containerAttributes: {
39-
'q:route': routeName,
57+
[Q_ROUTE]: routeName,
4058
},
4159
qwikrouter: {
4260
routeName,
@@ -45,7 +63,7 @@ export function getQwikRouterServerData(requestEv: RequestEvent) {
4563
loadedRoute: getRequestRoute(requestEv),
4664
response: {
4765
status: status(),
48-
loaders: getRequestLoaders(requestEv),
66+
loaders,
4967
action,
5068
formData,
5169
},

packages/qwik-router/src/runtime/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ export const QLOADER_KEY = 'qloader';
1313
export const QFN_KEY = 'qfunc';
1414

1515
export const QDATA_KEY = 'qdata';
16+
17+
export const Q_ROUTE = 'q:route';

packages/qwik-router/src/runtime/src/qwik-router-component.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@ import {
2020
_getContextElement,
2121
_getQContainerElement,
2222
_waitUntilRendered,
23-
_weakSerialize,
2423
type _ElementVNode,
2524
} from '@qwik.dev/core/internal';
2625
import { clientNavigate } from './client-navigate';
27-
import { CLIENT_DATA_CACHE } from './constants';
26+
import { CLIENT_DATA_CACHE, Q_ROUTE } from './constants';
2827
import {
2928
ContentContext,
3029
ContentInternalContext,
@@ -146,7 +145,7 @@ export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
146145
{ deep: false }
147146
);
148147
const navResolver: { r?: () => void } = {};
149-
const loaderState = useStore(_weakSerialize(env.response.loaders), { deep: false });
148+
const loaderState = useStore(env.response.loaders, { deep: false });
150149
const routeInternal = useSignal<RouteStateInternal>({
151150
type: 'initial',
152151
dest: url,
@@ -641,7 +640,7 @@ export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
641640
clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
642641
_waitUntilRendered(elm as Element).then(() => {
643642
const container = _getQContainerElement(elm as _ElementVNode)!;
644-
container.setAttribute('q:route', routeName);
643+
container.setAttribute(Q_ROUTE, routeName);
645644
const scrollState = currentScrollState(scroller);
646645
saveScrollHistory(scrollState);
647646
win._qRouterScrollEnabled = true;

packages/qwik-router/src/runtime/src/server-functions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import {
77
type ValueOrPromise,
88
untrack,
99
isBrowser,
10+
isDev,
11+
isServer,
1012
} from '@qwik.dev/core';
1113
import {
1214
_deserialize,
1315
_getContextElement,
1416
_getContextEvent,
1517
_serialize,
1618
_wrapStore,
19+
_useInvokeContext,
1720
_UNINITIALIZED,
1821
} from '@qwik.dev/core/internal';
1922

@@ -54,9 +57,6 @@ import type {
5457
} from './types';
5558
import { useAction, useLocation, useQwikRouterEnv } from './use-functions';
5659

57-
import { isDev, isServer } from '@qwik.dev/core';
58-
import { _useInvokeContext } from '@qwik.dev/core/internal';
59-
6060
import type { FormSubmitCompletedDetail } from './form-component';
6161
import { deepFreeze } from './utils';
6262
import { loadClientData } from './use-endpoint';

packages/qwik-router/src/runtime/src/utils.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,16 @@ export const getClientDataPath = (
3636
loaderIds?: string[];
3737
}
3838
) => {
39-
const search = new URLSearchParams(pageSearch);
39+
let search = pageSearch ?? '';
4040
if (options?.actionId) {
41-
search.set(QACTION_KEY, options.actionId);
42-
} else if (options?.loaderIds) {
43-
for (const id of options.loaderIds) {
44-
search.append(QLOADER_KEY, id);
41+
search += (search ? '&' : '?') + QACTION_KEY + '=' + encodeURIComponent(options.actionId);
42+
}
43+
if (options?.loaderIds) {
44+
for (const loaderId of options.loaderIds) {
45+
search += (search ? '&' : '?') + QLOADER_KEY + '=' + encodeURIComponent(loaderId);
4546
}
4647
}
47-
const searchString = search.toString();
48-
return (
49-
pathname +
50-
(pathname.endsWith('/') ? '' : '/') +
51-
'q-data.json' +
52-
(searchString.length ? '?' + searchString : '')
53-
);
48+
return pathname + (pathname.endsWith('/') ? '' : '/') + 'q-data.json' + search;
5449
};
5550

5651
export const getClientNavPath = (props: Record<string, any>, baseUrl: { url: URL }) => {

packages/qwik/src/core/core.api.md

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,9 @@ export { DomContainer as _DomContainer }
246246
// @internal (undocumented)
247247
export const _EFFECT_BACK_REF: unique symbol;
248248

249-
// Warning: (ae-forgotten-export) The symbol "VNodeFlags" needs to be exported by the entry point index.d.ts
250-
//
251249
// @internal (undocumented)
252250
export type _ElementVNode = [
253-
VNodeFlags.Element,
251+
_VNodeFlags.Element,
254252
////////////// 0 - Flags
255253
_VNode | null,
256254
/////////////// 1 - Parent
@@ -1579,7 +1577,7 @@ export type TaskFn = (ctx: TaskCtx) => ValueOrPromise<void | (() => void)>;
15791577

15801578
// @internal (undocumented)
15811579
export type _TextVNode = [
1582-
VNodeFlags.Text | VNodeFlags.Inflated,
1580+
_VNodeFlags.Text | _VNodeFlags.Inflated,
15831581
// 0 - Flags
15841582
_VNode | null,
15851583
///////////////// 1 - Parent
@@ -1751,7 +1749,7 @@ export const version: string;
17511749

17521750
// @internal (undocumented)
17531751
export type _VirtualVNode = [
1754-
VNodeFlags.Virtual,
1752+
_VNodeFlags.Virtual,
17551753
///////////// 0 - Flags
17561754
_VNode | null,
17571755
/////////////// 1 - Parent
@@ -1773,6 +1771,40 @@ export type VisibleTaskStrategy = 'intersection-observer' | 'document-ready' | '
17731771
// @internal (undocumented)
17741772
export type _VNode = _ElementVNode | _TextVNode | _VirtualVNode;
17751773

1774+
// @internal
1775+
export const enum _VNodeFlags {
1776+
// (undocumented)
1777+
Deleted = 32,
1778+
// (undocumented)
1779+
Element = 1,
1780+
// (undocumented)
1781+
ELEMENT_OR_TEXT_MASK = 5,
1782+
// (undocumented)
1783+
ELEMENT_OR_VIRTUAL_MASK = 3,
1784+
// (undocumented)
1785+
Inflated = 8,
1786+
// (undocumented)
1787+
INFLATED_TYPE_MASK = 15,
1788+
// (undocumented)
1789+
NAMESPACE_MASK = 192,
1790+
// (undocumented)
1791+
NEGATED_NAMESPACE_MASK = -193,
1792+
// (undocumented)
1793+
NS_html = 0,
1794+
// (undocumented)
1795+
NS_math = 128,
1796+
// (undocumented)
1797+
NS_svg = 64,
1798+
// (undocumented)
1799+
Resolved = 16,
1800+
// (undocumented)
1801+
Text = 4,// http://www.w3.org/1999/xhtml
1802+
// (undocumented)
1803+
TYPE_MASK = 7,// http://www.w3.org/2000/svg
1804+
// (undocumented)
1805+
Virtual = 2
1806+
}
1807+
17761808
// @internal (undocumented)
17771809
export const _waitUntilRendered: (elm: Element) => Promise<void>;
17781810

@@ -1784,9 +1816,6 @@ export function _walkJSX(ssr: SSRContainer, value: JSXOutput, options: {
17841816
parentComponentFrame: ISsrComponentFrame | null;
17851817
}): Promise<void>;
17861818

1787-
// @internal (undocumented)
1788-
export const _weakSerialize: <T extends object>(input: T) => Partial<T>;
1789-
17901819
// @public
17911820
export function withLocale<T>(locale: string, fn: () => T): T;
17921821

packages/qwik/src/core/internal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export { _wrapSignal, _wrapProp, _wrapStore } from './reactive-primitives/intern
77
export { _restProps } from './shared/utils/prop';
88
export { _IMMUTABLE, _UNINITIALIZED } from './shared/utils/constants';
99
export { _CONST_PROPS, _VAR_PROPS } from './shared/utils/constants';
10-
export { _weakSerialize } from './shared/utils/serialize-utils';
1110
export { verifySerializable as _verifySerializable } from './shared/utils/serialize-utils';
1211
export {
1312
_getContextElement,
@@ -21,6 +20,7 @@ export { _fnSignal } from './shared/qrl/inlined-fn';
2120
export type {
2221
ContainerElement as _ContainerElement,
2322
VNode as _VNode,
23+
VNodeFlags as _VNodeFlags,
2424
VirtualVNode as _VirtualVNode,
2525
TextVNode as _TextVNode,
2626
QDocument as _QDocument,

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

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { isElement, isNode } from './utils/element';
4040
import { EMPTY_ARRAY, EMPTY_OBJ } from './utils/flyweight';
4141
import { ELEMENT_ID } from './utils/markers';
4242
import { isPromise } from './utils/promises';
43-
import { SerializerSymbol, fastSkipSerialize, fastWeakSerialize } from './utils/serialize-utils';
43+
import { SerializerSymbol, fastSkipSerialize } from './utils/serialize-utils';
4444
import {
4545
_EFFECT_BACK_REF,
4646
EffectSubscriptionProp,
@@ -393,16 +393,6 @@ const inflate = (
393393
effectData.data.$isConst$ = (data as any[])[1];
394394
break;
395395
}
396-
case TypeIds.WeakObject: {
397-
const objectKeys = data as string[];
398-
target = Object.fromEntries(
399-
objectKeys.map((v) =>
400-
// initialize values with null
401-
[v, _UNINITIALIZED]
402-
)
403-
);
404-
break;
405-
}
406396
default:
407397
throw qError(QError.serializeErrorNotImplemented, [typeId]);
408398
}
@@ -472,7 +462,6 @@ const allocate = (container: DeserializeContainer, typeId: number, value: unknow
472462
case TypeIds.Array:
473463
return wrapDeserializerProxy(container as any, value as any[]);
474464
case TypeIds.Object:
475-
case TypeIds.WeakObject:
476465
return {};
477466
case TypeIds.QRL:
478467
case TypeIds.PreloadQRL:
@@ -1131,8 +1120,6 @@ async function serialize(serializationContext: SerializationContext): Promise<vo
11311120
} else if (isObjectLiteral(value)) {
11321121
if (Array.isArray(value)) {
11331122
output(TypeIds.Array, value);
1134-
} else if (fastWeakSerialize(value)) {
1135-
output(TypeIds.WeakObject, Object.keys(value));
11361123
} else {
11371124
const out: any[] = [];
11381125
for (const key in value) {
@@ -1861,7 +1848,6 @@ export const enum TypeIds {
18611848
JSXNode,
18621849
PropsProxy,
18631850
SubscriptionData,
1864-
WeakObject,
18651851
}
18661852
export const _typeIdNames = [
18671853
'RootRef',
@@ -1899,7 +1885,6 @@ export const _typeIdNames = [
18991885
'JSXNode',
19001886
'PropsProxy',
19011887
'SubscriptionData',
1902-
'WeakObject',
19031888
];
19041889

19051890
export const enum Constants {

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { $, _weakSerialize, componentQrl, noSerialize } from '@qwik.dev/core';
1+
import { $, componentQrl, noSerialize } from '@qwik.dev/core';
22
import { describe, expect, it, vi } from 'vitest';
33
import { _fnSignal, _wrapProp } from '../internal';
44
import { type SignalImpl } from '../reactive-primitives/impl/signal-impl';
@@ -65,15 +65,16 @@ describe('shared-serialization', () => {
6565
6 Constant EMPTY_OBJ
6666
7 Constant NEEDS_COMPUTATION
6767
8 Constant STORE_ALL_PROPS
68-
9 Constant Slot
69-
10 Constant Fragment
70-
11 Constant NaN
71-
12 Constant Infinity
72-
13 Constant -Infinity
73-
14 Constant MAX_SAFE_INTEGER
74-
15 Constant MAX_SAFE_INTEGER-1
75-
16 Constant MIN_SAFE_INTEGER
76-
(76 chars)"
68+
9 Constant _UNINITIALIZED
69+
10 Constant Slot
70+
11 Constant Fragment
71+
12 Constant NaN
72+
13 Constant Infinity
73+
14 Constant -Infinity
74+
15 Constant MAX_SAFE_INTEGER
75+
16 Constant MAX_SAFE_INTEGER-1
76+
17 Constant MIN_SAFE_INTEGER
77+
(81 chars)"
7778
`);
7879
});
7980
it(title(TypeIds.Number), async () => {
@@ -550,7 +551,7 @@ describe('shared-serialization', () => {
550551
expect(await dump(new SubscriptionData({ $isConst$: true, $scopedStyleIdPrefix$: null })))
551552
.toMatchInlineSnapshot(`
552553
"
553-
0 EffectData [
554+
0 SubscriptionData [
554555
Constant null
555556
Constant true
556557
]

0 commit comments

Comments
 (0)