Skip to content
Draft
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
2 changes: 1 addition & 1 deletion packages/docs/src/routes/api/qwik/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@
}
],
"kind": "Function",
"content": "Create an inlined QRL. This is mostly useful on the server side for serialization.\n\n\n```typescript\ninlinedQrl: <T>(symbol: T | null, symbolName: string, lexicalScopeCapture?: any[]) => QRL<T>\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nsymbol\n\n\n</td><td>\n\nT \\| null\n\n\n</td><td>\n\nThe object/function to register, or `null` to retrieve a previously registered one by hash\n\n\n</td></tr>\n<tr><td>\n\nsymbolName\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\nThe name of the symbol.\n\n\n</td></tr>\n<tr><td>\n\nlexicalScopeCapture\n\n\n</td><td>\n\nany\\[\\]\n\n\n</td><td>\n\n_(Optional)_ A set of lexically scoped variables to capture.\n\n\n</td></tr>\n</tbody></table>\n\n**Returns:**\n\n[QRL](#qrl)<!-- -->&lt;T&gt;",
"content": "Create an inlined QRL. This is mostly useful on the server side for serialization.\n\n\n```typescript\ninlinedQrl: <T>(symbol: T | null, symbolName: string, lexicalScopeCapture?: any[] | null) => QRL<T>\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nsymbol\n\n\n</td><td>\n\nT \\| null\n\n\n</td><td>\n\nThe object/function to register, or `null` to retrieve a previously registered one by hash\n\n\n</td></tr>\n<tr><td>\n\nsymbolName\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\nThe name of the symbol.\n\n\n</td></tr>\n<tr><td>\n\nlexicalScopeCapture\n\n\n</td><td>\n\nany\\[\\] \\| null\n\n\n</td><td>\n\n_(Optional)_ A set of lexically scoped variables to capture.\n\n\n</td></tr>\n</tbody></table>\n\n**Returns:**\n\n[QRL](#qrl)<!-- -->&lt;T&gt;",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/qrl/qrl.ts",
"mdFile": "core.inlinedqrl.md"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/docs/src/routes/api/qwik/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1713,7 +1713,7 @@ Create an inlined QRL. This is mostly useful on the server side for serializatio
inlinedQrl: <T>(
symbol: T | null,
symbolName: string,
lexicalScopeCapture?: any[],
lexicalScopeCapture?: any[] | null,
) => QRL<T>;
```

Expand Down Expand Up @@ -1762,7 +1762,7 @@ lexicalScopeCapture

</td><td>

any[]
any[] \| null

</td><td>

Expand Down
1 change: 1 addition & 0 deletions packages/qwik/src/core/client/dom-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
this.element = element;
this.$buildBase$ = element.getAttribute(QBaseAttr)!;
this.$instanceHash$ = element.getAttribute(QInstanceAttr)!;
console.log('======= \n\ncontainer instance hash', this.$instanceHash$);

Check failure on line 139 in packages/qwik/src/core/client/dom-container.ts

View workflow job for this annotation

GitHub Actions / Lint Package

Unexpected console statement. Only these console methods are allowed: warn, error
this.qManifestHash = element.getAttribute(QManifestHashAttr)!;
this.rootVNode = vnode_newUnMaterializedElement(this.element);
this.$rawStateData$ = [];
Expand Down
8 changes: 4 additions & 4 deletions packages/qwik/src/core/qwik.core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -394,13 +394,13 @@ export const _IMMUTABLE: unique symbol;
export const implicit$FirstArg: <FIRST, REST extends any[], RET>(fn: (qrl: QRL<FIRST>, ...rest: REST) => RET) => ((qrl: FIRST, ...rest: REST) => RET);

// @public
export const inlinedQrl: <T>(symbol: T | null, symbolName: string, lexicalScopeCapture?: any[]) => QRL<T>;
export const inlinedQrl: <T>(symbol: T | null, symbolName: string, lexicalScopeCapture?: any[] | null) => QRL<T>;

// Warning: (ae-forgotten-export) The symbol "QRLDev" needs to be exported by the entry point index.d.ts
// Warning: (ae-internal-missing-underscore) The name "inlinedQrlDEV" should be prefixed with an underscore because the declaration is marked as @internal
//
// @internal (undocumented)
export const inlinedQrlDEV: <T = any>(symbol: T, symbolName: string, opts: QRLDev, lexicalScopeCapture?: any[]) => QRL<T>;
export const inlinedQrlDEV: <T = any>(symbol: T, symbolName: string, opts: QRLDev, lexicalScopeCapture?: any[] | null) => QRL<T>;

export { isBrowser }

Expand Down Expand Up @@ -570,10 +570,10 @@ export type NativeUIEvent = UIEvent;
export type NativeWheelEvent = WheelEvent;

// @internal (undocumented)
export const _noopQrl: <T>(symbolName: string, lexicalScopeCapture?: any[]) => QRL<T>;
export const _noopQrl: <T>(symbolName: string, lexicalScopeCapture?: any[] | null) => QRL<T>;

// @internal (undocumented)
export const _noopQrlDEV: <T>(symbolName: string, opts: QRLDev, lexicalScopeCapture?: any[]) => QRL<T>;
export const _noopQrlDEV: <T>(symbolName: string, opts: QRLDev, lexicalScopeCapture?: any[] | null) => QRL<T>;

// @public
export type NoSerialize<T> = (T & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
} else {
assertTrue(
!ctx.$container$ || ctx.$container$ === target.$container$,
'Do not use signals across containers'
`Do not use signals across containers ${!!ctx.$container$?.addBackpatchEntry} ${!!target.$container$?.addBackpatchEntry}, ${ctx.$container$ === target.$container$}`

Check failure on line 136 in packages/qwik/src/core/reactive-primitives/impl/signal-impl.ts

View workflow job for this annotation

GitHub Actions / Build Qwik

Property 'addBackpatchEntry' does not exist on type 'Container'.

Check failure on line 136 in packages/qwik/src/core/reactive-primitives/impl/signal-impl.ts

View workflow job for this annotation

GitHub Actions / Build Qwik

Property 'addBackpatchEntry' does not exist on type 'Container'.
);
}
const effectSubscriber = ctx.$effectSubscriber$;
Expand Down
4 changes: 2 additions & 2 deletions packages/qwik/src/core/shared/jsx/jsx-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ const handleBindProp = (props: Props, prop: string) => {
if (value) {
if (prop === BIND_CHECKED) {
props.checked = value;
props['on:input'] = createQRL(null, '_chk', _chk, null, null, [value]);
props['on:input'] = createQRL(null, '_chk', _chk, null, [value]);
} else {
props.value = value;
props['on:input'] = createQRL(null, '_val', _val, null, null, [value]);
props['on:input'] = createQRL(null, '_val', _val, null, [value]);
}
return true;
}
Expand Down
5 changes: 1 addition & 4 deletions packages/qwik/src/core/shared/qrl/qrl-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export type QRLInternalMethods<TYPE> = {
readonly $symbol$: string;
readonly $hash$: string;

$capture$: string[] | null;
$captureRef$: unknown[] | null;
dev: QRLDev | null;

Expand Down Expand Up @@ -65,7 +64,6 @@ export const createQRL = <TYPE>(
symbol: string,
symbolRef: null | ValueOrPromise<TYPE>,
symbolFn: null | (() => Promise<Record<string, TYPE>>),
capture: null | Readonly<number[]>,
captureRef: Readonly<unknown[]> | null
): QRLInternal<TYPE> => {
if (qDev && qSerialize) {
Expand Down Expand Up @@ -128,7 +126,7 @@ export const createQRL = <TYPE>(

// Wrap functions to provide their lexical scope
const wrapFn = (fn: TYPE): TYPE => {
if (typeof fn !== 'function' || (!capture?.length && !captureRef?.length)) {
if (typeof fn !== 'function' || !captureRef?.length) {
return fn;
}
return function (this: unknown, ...args: QrlArgs<TYPE>) {
Expand Down Expand Up @@ -236,7 +234,6 @@ export const createQRL = <TYPE>(
$hash$: hash,
getFn: bindFnToContext,

$capture$: capture,
$captureRef$: captureRef,
dev: null,
resolved: undefined,
Expand Down
6 changes: 3 additions & 3 deletions packages/qwik/src/core/shared/qrl/qrl.public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export const $ = <T>(expression: T): QRL<T> => {
);
}

return createQRL<T>(null, 's' + runtimeSymbolId++, expression, null, null, null);
return createQRL<T>(null, 's' + runtimeSymbolId++, expression, null, null);
};
/** @private Use To avoid optimizer replacement */
export const dollar = $;
Expand Down Expand Up @@ -293,7 +293,7 @@ export const sync$ = <T extends Function>(fn: T): SyncQRL<T> => {
fn = new Function('return ' + fn.toString())() as any;
}

return createQRL<T>('', SYNC_QRL, fn, null, null, null) as any;
return createQRL<T>('', SYNC_QRL, fn, null, null) as any;
};

/**
Expand All @@ -314,5 +314,5 @@ export const _qrlSync = function <TYPE extends Function>(
serializedFn = fn.toString();
}
(fn as any).serialized = serializedFn;
return createQRL<TYPE>('', SYNC_QRL, fn, null, null, null) as any;
return createQRL<TYPE>('', SYNC_QRL, fn, null, null) as any;
};
16 changes: 8 additions & 8 deletions packages/qwik/src/core/shared/qrl/qrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const qrl = <T = any>(
}

// Unwrap subscribers
return createQRL<T>(chunk, symbol, null, symbolFn, null, lexicalScopeCapture);
return createQRL<T>(chunk, symbol, null, symbolFn, lexicalScopeCapture);
};

/**
Expand All @@ -90,25 +90,25 @@ export const qrl = <T = any>(
export const inlinedQrl = <T>(
symbol: T | null,
symbolName: string,
lexicalScopeCapture: any[] = EMPTY_ARRAY
lexicalScopeCapture: any[] | null = null
): QRL<T> => {
// Unwrap subscribers
return createQRL<T>(null, symbolName, symbol, null, null, lexicalScopeCapture);
return createQRL<T>(null, symbolName, symbol, null, lexicalScopeCapture);
};

/** @internal */
export const _noopQrl = <T>(
symbolName: string,
lexicalScopeCapture: any[] = EMPTY_ARRAY
lexicalScopeCapture: any[] | null = null
): QRL<T> => {
return createQRL<T>(null, symbolName, null, null, null, lexicalScopeCapture);
return createQRL<T>(null, symbolName, null, null, lexicalScopeCapture);
};

/** @internal */
export const _noopQrlDEV = <T>(
symbolName: string,
opts: QRLDev,
lexicalScopeCapture: any[] = EMPTY_ARRAY
lexicalScopeCapture: any[] | null = null
): QRL<T> => {
const newQrl = _noopQrl(symbolName, lexicalScopeCapture) as QRLInternal<T>;
newQrl.dev = opts;
Expand All @@ -120,7 +120,7 @@ export const qrlDEV = <T = any>(
chunkOrFn: string | (() => Promise<any>),
symbol: string,
opts: QRLDev,
lexicalScopeCapture: any[] = EMPTY_ARRAY
lexicalScopeCapture?: any[]
): QRL<T> => {
const newQrl = qrl(chunkOrFn, symbol, lexicalScopeCapture, 1) as QRLInternal<T>;
newQrl.dev = opts;
Expand All @@ -132,7 +132,7 @@ export const inlinedQrlDEV = <T = any>(
symbol: T,
symbolName: string,
opts: QRLDev,
lexicalScopeCapture: any[] = EMPTY_ARRAY
lexicalScopeCapture: any[] | null = null
): QRL<T> => {
const qrl = inlinedQrl(symbol, symbolName, lexicalScopeCapture) as QRLInternal<T>;
qrl.dev = opts;
Expand Down
49 changes: 13 additions & 36 deletions packages/qwik/src/core/shared/qrl/qrl.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,25 @@ describe('serialization', () => {
matchProps(parseQRL('./chunk#s1'), {
$chunk$: './chunk',
$symbol$: 's1',
$capture$: null,
});
matchProps(parseQRL('./chunk#s1[1 2]'), {
$chunk$: './chunk',
$symbol$: 's1',
$capture$: [1, 2],
});
matchProps(parseQRL('./chunk#s1[1 2]'), {
$chunk$: './chunk',
$symbol$: 's1',
$capture$: [1, 2],
});
matchProps(parseQRL('./chunk#s1[1 2]'), {
$chunk$: './chunk',
$symbol$: 's1',
$capture$: [1, 2],
});
matchProps(parseQRL('./chunk[1 2]'), {
$chunk$: './chunk',
$capture$: [1, 2],
});
matchProps(parseQRL('./path#symbol[2]'), {
$chunk$: './path',
$symbol$: 'symbol',
$capture$: [2],
});
matchProps(
parseQRL(
Expand All @@ -94,7 +88,6 @@ describe('serialization', () => {
{
$chunk$: '/src/path%2d/foo_symbol.js?_qrl_parent=/home/user/project/src/path/foo.js',
$symbol$: 'symbol',
$capture$: [2],
}
);
});
Expand All @@ -109,36 +102,22 @@ describe('serialization', () => {
new WeakMap<any, any>()
);
assert.equal(
qrlToString(serializationContext, createQRL('./chunk', '', null, null, null, null)),
qrlToString(serializationContext, createQRL('./chunk', '', null, null, null)),
'chunk#'
);
assert.equal(
qrlToString(serializationContext, createQRL('./c', 's1', null, null, null, null)),
qrlToString(serializationContext, createQRL('./c', 's1', null, null, null)),
'c#s1'
);
assert.equal(qrlToString(serializationContext, createQRL('./c', 's1', null, null, [])), 'c#s1');
assert.equal(
qrlToString(serializationContext, createQRL('./c', 's1', null, null, [], null)),
'c#s1'
);
assert.equal(
qrlToString(
serializationContext,
createQRL(
'./c',
's1',
null,
null,
// should be ignored
[1, '2'] as any,
[{}, {}]
)
),
qrlToString(serializationContext, createQRL('./c', 's1', null, null, [{}, {}])),
'c#s1[0 1]'
);
assert.equal(
qrlToString(
serializationContext,
createQRL('src/routes/[...index]/a+b/c?foo', 's1', null, null, null, [{}, {}])
createQRL('src/routes/[...index]/a+b/c?foo', 's1', null, null, [{}, {}])
),
'src/routes/[...index]/a+b/c?foo#s1[2 3]'
);
Expand Down Expand Up @@ -176,19 +155,19 @@ describe('serialization', () => {

describe('createQRL', () => {
test('should create QRL', () => {
const q = createQRL('chunk', 'symbol', 'resolved', null, null, null);
const q = createQRL('chunk', 'symbol', 'resolved', null, null);
matchProps(q, {
$chunk$: 'chunk',
$symbol$: 'symbol',
resolved: 'resolved',
});
});
test('should have .resolved: given scalar', async () => {
const q = createQRL('chunk', 'symbol', 'resolved', null, null, null);
const q = createQRL('chunk', 'symbol', 'resolved', null, null);
assert.equal(q.resolved, 'resolved');
});
test('should have .resolved: given promise for scalar', async () => {
const q = createQRL('chunk', 'symbol', Promise.resolve('resolved'), null, null, null);
const q = createQRL('chunk', 'symbol', Promise.resolve('resolved'), null, null);
assert.equal(q.resolved, undefined);
assert.equal(await q.resolve(), 'resolved');
assert.equal(q.resolved, 'resolved');
Expand All @@ -199,7 +178,6 @@ describe('createQRL', () => {
'symbol',
null,
() => Promise.resolve({ symbol: 'resolved' }),
null,
null
);
assert.equal(q.resolved, undefined);
Expand All @@ -209,31 +187,31 @@ describe('createQRL', () => {

const fn = () => 'hi';
test('should have .resolved: given function without captures', async () => {
const q = createQRL('chunk', 'symbol', fn, null, null, null);
const q = createQRL('chunk', 'symbol', fn, null, null);
assert.equal(q.resolved, fn);
});
test('should have .resolved: given promise for function without captures', async () => {
const q = createQRL('chunk', 'symbol', Promise.resolve(fn), null, null, null);
const q = createQRL('chunk', 'symbol', Promise.resolve(fn), null, null);
assert.equal(q.resolved, undefined);
assert.equal(await q.resolve(), fn);
assert.equal(q.resolved, fn);
});
test('should have .resolved: promise for function without captures', async () => {
const q = createQRL('chunk', 'symbol', null, () => Promise.resolve({ symbol: fn }), null, null);
const q = createQRL('chunk', 'symbol', null, () => Promise.resolve({ symbol: fn }), null);
assert.equal(q.resolved, undefined);
assert.equal(await q.resolve(), fn);
assert.equal(q.resolved, fn);
});

const capFn = () => useLexicalScope();
test('should have .resolved: given function with captures', async () => {
const q = createQRL('chunk', 'symbol', capFn, null, null, ['hi']);
const q = createQRL('chunk', 'symbol', capFn, null, ['hi']);
assert.isDefined(q.resolved);
assert.notEqual(q.resolved, capFn);
assert.deepEqual(q.resolved!(), ['hi']);
});
test('should have .resolved: given promise for function with captures', async () => {
const q = createQRL('chunk', 'symbol', Promise.resolve(capFn), null, null, ['hi']);
const q = createQRL('chunk', 'symbol', Promise.resolve(capFn), null, ['hi']);
assert.equal(q.resolved, undefined);
assert.deepEqual(await q(), ['hi']);
assert.notEqual(q.resolved, capFn);
Expand All @@ -245,7 +223,6 @@ describe('createQRL', () => {
'symbol',
null,
() => Promise.resolve({ symbol: capFn }),
null,
['hi']
);
assert.equal(q.resolved, undefined);
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/shared/scheduler-rules.unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function createMockTask(
}

function createMockQRL(symbol: string): QRL {
return createQRL(null, symbol, null, null, null, null) as QRL;
return createQRL(null, symbol, null, null, null) as QRL;
}

describe('findBlockingChore', () => {
Expand Down
21 changes: 16 additions & 5 deletions packages/qwik/src/core/shared/serdes/allocate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,22 @@ export const allocate = (container: DeserializeContainer, typeId: number, value:
case TypeIds.QRL:
case TypeIds.PreloadQRL: {
if (typeof value === 'string') {
const data = value.split(' ').map(Number);
const chunk = container.$getObjectById$(data[0]) as string;
const symbol = container.$getObjectById$(data[1]) as string;
const captureIds = data.length > 2 ? data.slice(2) : null;
return createQRLWithBackChannel(chunk, symbol, captureIds);
const firstSpace = value.indexOf(' ');
const chunkIdx = Number(value.slice(0, firstSpace));
const secondSpace = value.indexOf(' ', firstSpace + 1);
const symbolIdx = Number(
secondSpace === -1
? value.slice(firstSpace + 1)
: value.slice(firstSpace + 1, secondSpace)
);
const chunk = container.$getObjectById$(chunkIdx) as string;
const symbol = container.$getObjectById$(symbolIdx) as string;
const qrl = createQRLWithBackChannel(chunk, symbol);
if (secondSpace !== -1) {
// temporarily store the captured references for inflate
qrl.$captureRef$ = value.slice(secondSpace + 1) as unknown as unknown[];
}
return qrl;
} else {
return createQRLWithBackChannel('', String(value));
}
Expand Down
Loading
Loading