@qwik.dev/core 2.0.0-alpha.5 → 2.0.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bindings/qwik.darwin-arm64.node +0 -0
- package/bindings/qwik.darwin-x64.node +0 -0
- package/bindings/qwik.linux-x64-gnu.node +0 -0
- package/bindings/qwik.win32-x64-msvc.node +0 -0
- package/bindings/qwik_wasm_bg.wasm +0 -0
- package/dist/build/package.json +1 -1
- package/dist/cli.cjs +65 -63
- package/dist/core-internal.d.ts +78 -77
- package/dist/core.cjs +1770 -1517
- package/dist/core.cjs.map +1 -1
- package/dist/core.min.mjs +1 -1
- package/dist/core.mjs +1768 -1517
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.cjs +985 -848
- package/dist/core.prod.mjs +1210 -1032
- package/dist/insights/index.qwik.cjs +3658 -160
- package/dist/insights/index.qwik.mjs +3658 -160
- package/dist/loader/index.cjs +2 -2
- package/dist/loader/index.mjs +2 -2
- package/dist/loader/package.json +1 -1
- package/dist/optimizer.cjs +230 -5691
- package/dist/optimizer.mjs +192 -5992
- package/dist/prefetch/package.json +1 -1
- package/dist/qwikloader.debug.js +12 -15
- package/dist/qwikloader.js +2 -2
- package/dist/server.cjs +754 -7067
- package/dist/server.mjs +771 -7062
- package/dist/starters/adapters/fastify/src/plugins/fastify-qwik.ts +2 -0
- package/dist/starters/features/cypress/package.json +1 -1
- package/dist/starters/features/drizzle/drizzle/schema.ts +6 -18
- package/dist/starters/features/drizzle/drizzle.config.ts +5 -4
- package/dist/starters/features/drizzle/package.json +14 -11
- package/dist/starters/features/pandacss/package.json +1 -1
- package/dist/starters/features/partytown/package.json +1 -1
- package/dist/starters/features/postcss/package.json +1 -1
- package/dist/starters/features/prisma/package.json +1 -1
- package/dist/starters/features/react/package.json +1 -1
- package/dist/starters/features/storybook/package.json +1 -1
- package/dist/starters/features/styled-vanilla-extract/package.json +2 -1
- package/dist/starters/features/tailwind/package.json +15 -9
- package/dist/starters/features/tailwind/src/global.css +1 -7
- package/dist/starters/features/turso/package.json +1 -1
- package/dist/starters/features/turso/src/utils/turso.ts +1 -1
- package/dist/starters/features/vitest/package.json +1 -1
- package/dist/testing/index.cjs +1445 -1252
- package/dist/testing/index.mjs +1455 -1256
- package/dist/testing/package.json +1 -1
- package/handlers.mjs +9 -0
- package/package.json +7 -5
- package/public.d.ts +2 -0
- package/dist/starters/features/tailwind/.vscode/settings.json +0 -3
- package/dist/starters/features/tailwind/postcss.config.cjs +0 -6
- package/dist/starters/features/tailwind/tailwind.config.js +0 -8
package/dist/core.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* @qwik.dev/core 2.0.0-alpha.
|
|
3
|
+
* @qwik.dev/core 2.0.0-alpha.7-dev+a26598a
|
|
4
4
|
* Copyright QwikDev. All Rights Reserved.
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://github.com/QwikDev/qwik/blob/main/LICENSE
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { isDev, isServer } from '@qwik.dev/core/build';
|
|
9
9
|
export { isBrowser, isDev, isServer } from '@qwik.dev/core/build';
|
|
10
10
|
|
|
11
11
|
// same as isDev but separate so we can test
|
|
@@ -118,8 +118,8 @@ const codeToText = (code, ...parts) => {
|
|
|
118
118
|
// Keep one error, one line to make it easier to search for the error message.
|
|
119
119
|
const MAP = [
|
|
120
120
|
'Error while serializing class or style attributes', // 0
|
|
121
|
-
'', // 1
|
|
122
|
-
'', // 2
|
|
121
|
+
'Scheduler not found', // 1
|
|
122
|
+
'track() received object, without prop to track', // 2
|
|
123
123
|
'Only primitive and object literals can be serialized. {{0}}', // 3
|
|
124
124
|
'', // 4 unused
|
|
125
125
|
'You can render over a existing q:container. Skipping render().', // 5
|
|
@@ -162,13 +162,11 @@ const codeToText = (code, ...parts) => {
|
|
|
162
162
|
"Element must have 'q:container' attribute.", // 42
|
|
163
163
|
'Unknown vnode type {{0}}.', // 43
|
|
164
164
|
'Materialize error: missing element: {{0}} {{1}} {{2}}', // 44
|
|
165
|
-
'
|
|
166
|
-
'
|
|
167
|
-
'
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
'SsrError: Promises not expected here.', // 50
|
|
171
|
-
'Attribute value is unsafe for SSR', // 51
|
|
165
|
+
'Cannot coerce a Signal, use `.value` instead', // 45
|
|
166
|
+
'useComputedSignal$ QRL {{0}} {{1}} returned a Promise', // 46
|
|
167
|
+
'ComputedSignal is read-only', // 47
|
|
168
|
+
'WrappedSignal is read-only', // 48
|
|
169
|
+
'Attribute value is unsafe for SSR', // 49
|
|
172
170
|
];
|
|
173
171
|
let text = MAP[code] ?? '';
|
|
174
172
|
if (parts.length) {
|
|
@@ -190,8 +188,8 @@ const codeToText = (code, ...parts) => {
|
|
|
190
188
|
var QError;
|
|
191
189
|
(function (QError) {
|
|
192
190
|
QError[QError["stringifyClassOrStyle"] = 0] = "stringifyClassOrStyle";
|
|
193
|
-
QError[QError["
|
|
194
|
-
QError[QError["
|
|
191
|
+
QError[QError["schedulerNotFound"] = 1] = "schedulerNotFound";
|
|
192
|
+
QError[QError["trackObjectWithoutProp"] = 2] = "trackObjectWithoutProp";
|
|
195
193
|
QError[QError["verifySerializable"] = 3] = "verifySerializable";
|
|
196
194
|
QError[QError["UNUSED_4"] = 4] = "UNUSED_4";
|
|
197
195
|
QError[QError["cannotRenderOverExistingContainer"] = 5] = "cannotRenderOverExistingContainer";
|
|
@@ -234,19 +232,153 @@ var QError;
|
|
|
234
232
|
QError[QError["elementWithoutContainer"] = 42] = "elementWithoutContainer";
|
|
235
233
|
QError[QError["invalidVNodeType"] = 43] = "invalidVNodeType";
|
|
236
234
|
QError[QError["materializeVNodeDataError"] = 44] = "materializeVNodeDataError";
|
|
237
|
-
QError[QError["
|
|
238
|
-
QError[QError["
|
|
239
|
-
QError[QError["
|
|
240
|
-
QError[QError["
|
|
241
|
-
QError[QError["
|
|
242
|
-
QError[QError["promisesNotExpected"] = 50] = "promisesNotExpected";
|
|
243
|
-
QError[QError["unsafeAttr"] = 51] = "unsafeAttr";
|
|
235
|
+
QError[QError["cannotCoerceSignal"] = 45] = "cannotCoerceSignal";
|
|
236
|
+
QError[QError["computedNotSync"] = 46] = "computedNotSync";
|
|
237
|
+
QError[QError["computedReadOnly"] = 47] = "computedReadOnly";
|
|
238
|
+
QError[QError["wrappedReadOnly"] = 48] = "wrappedReadOnly";
|
|
239
|
+
QError[QError["unsafeAttr"] = 49] = "unsafeAttr";
|
|
244
240
|
})(QError || (QError = {}));
|
|
245
241
|
const qError = (code, errorMessageArgs = []) => {
|
|
246
242
|
const text = codeToText(code, ...errorMessageArgs);
|
|
247
243
|
return logErrorAndStop(text, ...errorMessageArgs);
|
|
248
244
|
};
|
|
249
245
|
|
|
246
|
+
/** QRL related utilities that you can import without importing all of Qwik. */
|
|
247
|
+
const SYNC_QRL = '<sync>';
|
|
248
|
+
/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
|
|
249
|
+
const isSyncQrl = (value) => {
|
|
250
|
+
return isQrl$1(value) && value.$symbol$ == SYNC_QRL;
|
|
251
|
+
};
|
|
252
|
+
const isQrl$1 = (value) => {
|
|
253
|
+
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
254
|
+
};
|
|
255
|
+
function assertQrl(qrl) {
|
|
256
|
+
if (isDev) {
|
|
257
|
+
if (!isQrl$1(qrl)) {
|
|
258
|
+
throw new Error('Not a QRL');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const getSymbolHash = (symbolName) => {
|
|
263
|
+
const index = symbolName.lastIndexOf('_');
|
|
264
|
+
if (index > -1) {
|
|
265
|
+
return symbolName.slice(index + 1);
|
|
266
|
+
}
|
|
267
|
+
return symbolName;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* A friendly name tag for a VirtualVNode.
|
|
272
|
+
*
|
|
273
|
+
* Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
|
|
274
|
+
*
|
|
275
|
+
* The name is only added in development mode and is not included in production builds.
|
|
276
|
+
*/
|
|
277
|
+
const DEBUG_TYPE = 'q:type';
|
|
278
|
+
var VirtualType;
|
|
279
|
+
(function (VirtualType) {
|
|
280
|
+
VirtualType["Virtual"] = "V";
|
|
281
|
+
VirtualType["Fragment"] = "F";
|
|
282
|
+
VirtualType["WrappedSignal"] = "S";
|
|
283
|
+
VirtualType["Awaited"] = "A";
|
|
284
|
+
VirtualType["Component"] = "C";
|
|
285
|
+
VirtualType["InlineComponent"] = "I";
|
|
286
|
+
VirtualType["Projection"] = "P";
|
|
287
|
+
})(VirtualType || (VirtualType = {}));
|
|
288
|
+
const START = '\x1b[34m';
|
|
289
|
+
const END = '\x1b[0m';
|
|
290
|
+
const VirtualTypeName = {
|
|
291
|
+
[VirtualType.Virtual]: /* ********* */ START + 'Virtual' + END, //
|
|
292
|
+
[VirtualType.Fragment]: /* ******** */ START + 'Fragment' + END, //
|
|
293
|
+
[VirtualType.WrappedSignal]: /* *** */ START + 'Signal' + END, //
|
|
294
|
+
[VirtualType.Awaited]: /* ********* */ START + 'Awaited' + END, //
|
|
295
|
+
[VirtualType.Component]: /* ******* */ START + 'Component' + END, //
|
|
296
|
+
[VirtualType.InlineComponent]: /* * */ START + 'InlineComponent' + END, //
|
|
297
|
+
[VirtualType.Projection]: /* ****** */ START + 'Projection' + END, //
|
|
298
|
+
};
|
|
299
|
+
var QContainerValue;
|
|
300
|
+
(function (QContainerValue) {
|
|
301
|
+
QContainerValue["PAUSED"] = "paused";
|
|
302
|
+
QContainerValue["RESUMED"] = "resumed";
|
|
303
|
+
// these values below are used in the qwik loader as a plain text for the q:container selector
|
|
304
|
+
// standard dangerouslySetInnerHTML
|
|
305
|
+
QContainerValue["HTML"] = "html";
|
|
306
|
+
// textarea
|
|
307
|
+
QContainerValue["TEXT"] = "text";
|
|
308
|
+
})(QContainerValue || (QContainerValue = {}));
|
|
309
|
+
|
|
310
|
+
/** State factory of the component. */
|
|
311
|
+
const OnRenderProp = 'q:renderFn';
|
|
312
|
+
/** Component style content prefix */
|
|
313
|
+
const ComponentStylesPrefixContent = '⚡️';
|
|
314
|
+
/** `<some-element q:slot="...">` */
|
|
315
|
+
const QSlot = 'q:slot';
|
|
316
|
+
const QSlotParent = ':';
|
|
317
|
+
const QSlotRef = 'q:sref';
|
|
318
|
+
const QSlotS = 'q:s';
|
|
319
|
+
const QStyle = 'q:style';
|
|
320
|
+
const QStyleSelector = 'style[q\\:style]';
|
|
321
|
+
const QStyleSSelector = 'style[q\\:sstyle]';
|
|
322
|
+
const QStylesAllSelector = QStyleSelector + ',' + QStyleSSelector;
|
|
323
|
+
const QScopedStyle = 'q:sstyle';
|
|
324
|
+
const QCtxAttr = 'q:ctx';
|
|
325
|
+
const QBackRefs = 'q:brefs';
|
|
326
|
+
const QFuncsPrefix = 'qFuncs_';
|
|
327
|
+
const getQFuncs = (document, hash) => {
|
|
328
|
+
return document[QFuncsPrefix + hash] || [];
|
|
329
|
+
};
|
|
330
|
+
const QBaseAttr = 'q:base';
|
|
331
|
+
const QLocaleAttr = 'q:locale';
|
|
332
|
+
const QManifestHashAttr = 'q:manifest-hash';
|
|
333
|
+
const QInstanceAttr = 'q:instance';
|
|
334
|
+
const QContainerIsland = 'q:container-island';
|
|
335
|
+
const QContainerIslandEnd = '/' + QContainerIsland;
|
|
336
|
+
const QIgnore = 'q:ignore';
|
|
337
|
+
const QIgnoreEnd = '/' + QIgnore;
|
|
338
|
+
const QContainerAttr = 'q:container';
|
|
339
|
+
const QContainerAttrEnd = '/' + QContainerAttr;
|
|
340
|
+
const QTemplate = 'q:template';
|
|
341
|
+
// the same selector should be inside the qwik loader
|
|
342
|
+
// and the same selector should be inside the qwik router spa-shim and spa-init
|
|
343
|
+
const QContainerSelector = '[q\\:container]:not([q\\:container=' +
|
|
344
|
+
QContainerValue.HTML +
|
|
345
|
+
']):not([q\\:container=' +
|
|
346
|
+
QContainerValue.TEXT +
|
|
347
|
+
'])';
|
|
348
|
+
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
|
349
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
350
|
+
const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
|
|
351
|
+
const ResourceEvent = 'qResource';
|
|
352
|
+
const RenderEvent = 'qRender';
|
|
353
|
+
const TaskEvent = 'qTask';
|
|
354
|
+
const QDefaultSlot = '';
|
|
355
|
+
/**
|
|
356
|
+
* Attribute to mark that this VNode has a pointer to itself from the `qwik/json` state.
|
|
357
|
+
*
|
|
358
|
+
* As the VNode get materialized the vnode now becomes eligible for mutation. Once the vnode mutates
|
|
359
|
+
* the `VNode` references from the `qwik/json` may become invalid. For this reason, these references
|
|
360
|
+
* need to be eagerly resolved. `VNODE_REF` stores a pointer to "this" vnode. This allows the system
|
|
361
|
+
* to eagerly resolve these pointes as the vnodes are materialized.
|
|
362
|
+
*/
|
|
363
|
+
const ELEMENT_ID = 'q:id';
|
|
364
|
+
const ELEMENT_KEY = 'q:key';
|
|
365
|
+
const ELEMENT_PROPS = 'q:props';
|
|
366
|
+
const ELEMENT_SEQ = 'q:seq';
|
|
367
|
+
const ELEMENT_SEQ_IDX = 'q:seqIdx';
|
|
368
|
+
const Q_PREFIX = 'q:';
|
|
369
|
+
/** Non serializable markers - always begins with `:` character */
|
|
370
|
+
const NON_SERIALIZABLE_MARKER_PREFIX = ':';
|
|
371
|
+
const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
|
|
372
|
+
const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
|
|
373
|
+
const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
|
|
374
|
+
// comment nodes
|
|
375
|
+
const FLUSH_COMMENT = 'qkssr-f';
|
|
376
|
+
const STREAM_BLOCK_START_COMMENT = 'qkssr-pu';
|
|
377
|
+
const STREAM_BLOCK_END_COMMENT = 'qkssr-po';
|
|
378
|
+
const Q_PROPS_SEPARATOR = ':';
|
|
379
|
+
const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
|
|
380
|
+
const qwikInspectorAttr = 'data-qwik-inspector';
|
|
381
|
+
|
|
250
382
|
// keep this import from core/build so the cjs build works
|
|
251
383
|
const createPlatform = () => {
|
|
252
384
|
return {
|
|
@@ -307,7 +439,7 @@ const createPlatform = () => {
|
|
|
307
439
|
*/
|
|
308
440
|
const toUrl = (doc, containerEl, url) => {
|
|
309
441
|
const baseURI = doc.baseURI;
|
|
310
|
-
const base = new URL(containerEl.getAttribute(
|
|
442
|
+
const base = new URL(containerEl.getAttribute(QBaseAttr) ?? baseURI, baseURI);
|
|
311
443
|
return new URL(url, base);
|
|
312
444
|
};
|
|
313
445
|
let _platform = /*#__PURE__ */ createPlatform();
|
|
@@ -386,11 +518,6 @@ const maybeThen = (valueOrPromise, thenFn) => {
|
|
|
386
518
|
? valueOrPromise.then(thenFn, shouldNotError)
|
|
387
519
|
: thenFn(valueOrPromise);
|
|
388
520
|
};
|
|
389
|
-
const maybeThenPassError = (valueOrPromise, thenFn) => {
|
|
390
|
-
return isPromise(valueOrPromise)
|
|
391
|
-
? valueOrPromise.then(thenFn)
|
|
392
|
-
: thenFn(valueOrPromise);
|
|
393
|
-
};
|
|
394
521
|
const shouldNotError = (reason) => {
|
|
395
522
|
throwErrorAndStop(reason);
|
|
396
523
|
};
|
|
@@ -399,15 +526,24 @@ const delay = (timeout) => {
|
|
|
399
526
|
setTimeout(resolve, timeout);
|
|
400
527
|
});
|
|
401
528
|
};
|
|
529
|
+
// Retries a function that throws a promise.
|
|
402
530
|
function retryOnPromise(fn, retryCount = 0) {
|
|
403
|
-
|
|
404
|
-
return fn();
|
|
405
|
-
}
|
|
406
|
-
catch (e) {
|
|
531
|
+
const retryOrThrow = (e) => {
|
|
407
532
|
if (isPromise(e) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
408
533
|
return e.then(retryOnPromise.bind(null, fn, retryCount++));
|
|
409
534
|
}
|
|
410
535
|
throw e;
|
|
536
|
+
};
|
|
537
|
+
try {
|
|
538
|
+
const result = fn();
|
|
539
|
+
if (isPromise(result)) {
|
|
540
|
+
// not awaited promise is not caught by try/catch block
|
|
541
|
+
return result.catch((e) => retryOrThrow(e));
|
|
542
|
+
}
|
|
543
|
+
return result;
|
|
544
|
+
}
|
|
545
|
+
catch (e) {
|
|
546
|
+
return retryOrThrow(e);
|
|
411
547
|
}
|
|
412
548
|
}
|
|
413
549
|
|
|
@@ -450,118 +586,6 @@ var VNodeDataFlag;
|
|
|
450
586
|
VNodeDataFlag[VNodeDataFlag["SERIALIZE"] = 16] = "SERIALIZE";
|
|
451
587
|
})(VNodeDataFlag || (VNodeDataFlag = {}));
|
|
452
588
|
|
|
453
|
-
/**
|
|
454
|
-
* A friendly name tag for a VirtualVNode.
|
|
455
|
-
*
|
|
456
|
-
* Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
|
|
457
|
-
*
|
|
458
|
-
* The name is only added in development mode and is not included in production builds.
|
|
459
|
-
*/
|
|
460
|
-
const DEBUG_TYPE = 'q:type';
|
|
461
|
-
var VirtualType;
|
|
462
|
-
(function (VirtualType) {
|
|
463
|
-
VirtualType["Virtual"] = "V";
|
|
464
|
-
VirtualType["Fragment"] = "F";
|
|
465
|
-
VirtualType["WrappedSignal"] = "S";
|
|
466
|
-
VirtualType["Awaited"] = "A";
|
|
467
|
-
VirtualType["Component"] = "C";
|
|
468
|
-
VirtualType["InlineComponent"] = "I";
|
|
469
|
-
VirtualType["Projection"] = "P";
|
|
470
|
-
})(VirtualType || (VirtualType = {}));
|
|
471
|
-
const START = '\x1b[34m';
|
|
472
|
-
const END = '\x1b[0m';
|
|
473
|
-
const VirtualTypeName = {
|
|
474
|
-
[VirtualType.Virtual]: /* ********* */ START + 'Virtual' + END, //
|
|
475
|
-
[VirtualType.Fragment]: /* ******** */ START + 'Fragment' + END, //
|
|
476
|
-
[VirtualType.WrappedSignal]: /* *** */ START + 'Signal' + END, //
|
|
477
|
-
[VirtualType.Awaited]: /* ********* */ START + 'Awaited' + END, //
|
|
478
|
-
[VirtualType.Component]: /* ******* */ START + 'Component' + END, //
|
|
479
|
-
[VirtualType.InlineComponent]: /* * */ START + 'InlineComponent' + END, //
|
|
480
|
-
[VirtualType.Projection]: /* ****** */ START + 'Projection' + END, //
|
|
481
|
-
};
|
|
482
|
-
var QContainerValue;
|
|
483
|
-
(function (QContainerValue) {
|
|
484
|
-
QContainerValue["PAUSED"] = "paused";
|
|
485
|
-
QContainerValue["RESUMED"] = "resumed";
|
|
486
|
-
// these values below are used in the qwik loader as a plain text for the q:container selector
|
|
487
|
-
// standard dangerouslySetInnerHTML
|
|
488
|
-
QContainerValue["HTML"] = "html";
|
|
489
|
-
// textarea
|
|
490
|
-
QContainerValue["TEXT"] = "text";
|
|
491
|
-
})(QContainerValue || (QContainerValue = {}));
|
|
492
|
-
|
|
493
|
-
/** State factory of the component. */
|
|
494
|
-
const OnRenderProp = 'q:renderFn';
|
|
495
|
-
/** Component style content prefix */
|
|
496
|
-
const ComponentStylesPrefixContent = '⭐️';
|
|
497
|
-
/** `<some-element q:slot="...">` */
|
|
498
|
-
const QSlot = 'q:slot';
|
|
499
|
-
const QSlotParent = ':';
|
|
500
|
-
const QSlotRef = 'q:sref';
|
|
501
|
-
const QSlotS = 'q:s';
|
|
502
|
-
const QStyle = 'q:style';
|
|
503
|
-
const QStyleSelector = 'style[q\\:style]';
|
|
504
|
-
const QStyleSSelector = 'style[q\\:sstyle]';
|
|
505
|
-
const QStylesAllSelector = QStyleSelector + ',' + QStyleSSelector;
|
|
506
|
-
const QScopedStyle = 'q:sstyle';
|
|
507
|
-
const QCtxAttr = 'q:ctx';
|
|
508
|
-
const QSubscribers = 'q:subs';
|
|
509
|
-
const QFuncsPrefix = 'qFuncs_';
|
|
510
|
-
const getQFuncs = (document, hash) => {
|
|
511
|
-
return document[QFuncsPrefix + hash] || [];
|
|
512
|
-
};
|
|
513
|
-
const QBaseAttr = 'q:base';
|
|
514
|
-
const QLocaleAttr = 'q:locale';
|
|
515
|
-
const QManifestHashAttr = 'q:manifest-hash';
|
|
516
|
-
const QInstanceAttr = 'q:instance';
|
|
517
|
-
const QContainerIsland = 'q:container-island';
|
|
518
|
-
const QContainerIslandEnd = '/' + QContainerIsland;
|
|
519
|
-
const QIgnore = 'q:ignore';
|
|
520
|
-
const QIgnoreEnd = '/' + QIgnore;
|
|
521
|
-
const QContainerAttr = 'q:container';
|
|
522
|
-
const QContainerAttrEnd = '/' + QContainerAttr;
|
|
523
|
-
const QTemplate = 'q:template';
|
|
524
|
-
// the same selector should be inside the qwik loader
|
|
525
|
-
// and the same selector should be inside the qwik router spa-shim and spa-init
|
|
526
|
-
const QContainerSelector = '[q\\:container]:not([q\\:container=' +
|
|
527
|
-
QContainerValue.HTML +
|
|
528
|
-
']):not([q\\:container=' +
|
|
529
|
-
QContainerValue.TEXT +
|
|
530
|
-
'])';
|
|
531
|
-
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
|
532
|
-
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
533
|
-
const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
|
|
534
|
-
const ResourceEvent = 'qResource';
|
|
535
|
-
const RenderEvent = 'qRender';
|
|
536
|
-
const TaskEvent = 'qTask';
|
|
537
|
-
const QDefaultSlot = '';
|
|
538
|
-
/**
|
|
539
|
-
* Attribute to mark that this VNode has a pointer to itself from the `qwik/json` state.
|
|
540
|
-
*
|
|
541
|
-
* As the VNode get materialized the vnode now becomes eligible for mutation. Once the vnode mutates
|
|
542
|
-
* the `VNode` references from the `qwik/json` may become invalid. For this reason, these references
|
|
543
|
-
* need to be eagerly resolved. `VNODE_REF` stores a pointer to "this" vnode. This allows the system
|
|
544
|
-
* to eagerly resolve these pointes as the vnodes are materialized.
|
|
545
|
-
*/
|
|
546
|
-
const ELEMENT_ID = 'q:id';
|
|
547
|
-
const ELEMENT_KEY = 'q:key';
|
|
548
|
-
const ELEMENT_PROPS = 'q:props';
|
|
549
|
-
const ELEMENT_SEQ = 'q:seq';
|
|
550
|
-
const ELEMENT_SEQ_IDX = 'q:seqIdx';
|
|
551
|
-
const Q_PREFIX = 'q:';
|
|
552
|
-
/** Non serializable markers - always begins with `:` character */
|
|
553
|
-
const NON_SERIALIZABLE_MARKER_PREFIX = ':';
|
|
554
|
-
const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
|
|
555
|
-
const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
|
|
556
|
-
const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
|
|
557
|
-
// comment nodes
|
|
558
|
-
const FLUSH_COMMENT = 'qkssr-f';
|
|
559
|
-
const STREAM_BLOCK_START_COMMENT = 'qkssr-pu';
|
|
560
|
-
const STREAM_BLOCK_END_COMMENT = 'qkssr-po';
|
|
561
|
-
const Q_PROPS_SEPARATOR = ':';
|
|
562
|
-
const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
|
|
563
|
-
const qwikInspectorAttr = 'data-qwik-inspector';
|
|
564
|
-
|
|
565
589
|
let _locale = undefined;
|
|
566
590
|
/**
|
|
567
591
|
* Retrieve the current locale.
|
|
@@ -611,7 +635,7 @@ function setLocale(locale) {
|
|
|
611
635
|
_locale = locale;
|
|
612
636
|
}
|
|
613
637
|
|
|
614
|
-
const isQrl
|
|
638
|
+
const isQrl = (value) => {
|
|
615
639
|
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
616
640
|
};
|
|
617
641
|
|
|
@@ -683,21 +707,21 @@ const qrl = (chunkOrFn, symbol, lexicalScopeCapture = EMPTY_ARRAY, stackOffset =
|
|
|
683
707
|
// Emit event
|
|
684
708
|
announcedQRL.add(symbol);
|
|
685
709
|
emitEvent('qprefetch', {
|
|
686
|
-
symbols: [
|
|
710
|
+
symbols: [symbol],
|
|
687
711
|
bundles: chunk && [chunk],
|
|
688
712
|
});
|
|
689
713
|
}
|
|
690
714
|
// Unwrap subscribers
|
|
691
|
-
return createQRL(chunk, symbol, null, symbolFn, null, lexicalScopeCapture
|
|
715
|
+
return createQRL(chunk, symbol, null, symbolFn, null, lexicalScopeCapture);
|
|
692
716
|
};
|
|
693
717
|
/** @internal */
|
|
694
718
|
const inlinedQrl = (symbol, symbolName, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
695
719
|
// Unwrap subscribers
|
|
696
|
-
return createQRL(null, symbolName, symbol, null, null, lexicalScopeCapture
|
|
720
|
+
return createQRL(null, symbolName, symbol, null, null, lexicalScopeCapture);
|
|
697
721
|
};
|
|
698
722
|
/** @internal */
|
|
699
723
|
const _noopQrl = (symbolName, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
700
|
-
return createQRL(null, symbolName, null, null, null, lexicalScopeCapture
|
|
724
|
+
return createQRL(null, symbolName, null, null, null, lexicalScopeCapture);
|
|
701
725
|
};
|
|
702
726
|
/** @internal */
|
|
703
727
|
const _noopQrlDEV = (symbolName, opts, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
@@ -726,6 +750,80 @@ const _regSymbol = (symbol, hash) => {
|
|
|
726
750
|
return symbol;
|
|
727
751
|
};
|
|
728
752
|
|
|
753
|
+
var ChoreType;
|
|
754
|
+
(function (ChoreType) {
|
|
755
|
+
/// MASKS defining three levels of sorting
|
|
756
|
+
ChoreType[ChoreType["MACRO"] = 240] = "MACRO";
|
|
757
|
+
/* order of elements (not encoded here) */
|
|
758
|
+
ChoreType[ChoreType["MICRO"] = 15] = "MICRO";
|
|
759
|
+
/** Ensure that the QRL promise is resolved before processing next chores in the queue */
|
|
760
|
+
ChoreType[ChoreType["QRL_RESOLVE"] = 1] = "QRL_RESOLVE";
|
|
761
|
+
ChoreType[ChoreType["RUN_QRL"] = 2] = "RUN_QRL";
|
|
762
|
+
ChoreType[ChoreType["TASK"] = 3] = "TASK";
|
|
763
|
+
ChoreType[ChoreType["NODE_DIFF"] = 4] = "NODE_DIFF";
|
|
764
|
+
ChoreType[ChoreType["NODE_PROP"] = 5] = "NODE_PROP";
|
|
765
|
+
ChoreType[ChoreType["COMPONENT"] = 6] = "COMPONENT";
|
|
766
|
+
ChoreType[ChoreType["RECOMPUTE_AND_SCHEDULE_EFFECTS"] = 7] = "RECOMPUTE_AND_SCHEDULE_EFFECTS";
|
|
767
|
+
// Next macro level
|
|
768
|
+
ChoreType[ChoreType["JOURNAL_FLUSH"] = 16] = "JOURNAL_FLUSH";
|
|
769
|
+
// Next macro level
|
|
770
|
+
ChoreType[ChoreType["VISIBLE"] = 32] = "VISIBLE";
|
|
771
|
+
// Next macro level
|
|
772
|
+
ChoreType[ChoreType["CLEANUP_VISIBLE"] = 48] = "CLEANUP_VISIBLE";
|
|
773
|
+
// Next macro level
|
|
774
|
+
ChoreType[ChoreType["WAIT_FOR_ALL"] = 255] = "WAIT_FOR_ALL";
|
|
775
|
+
})(ChoreType || (ChoreType = {}));
|
|
776
|
+
|
|
777
|
+
// <docs markdown="../readme.md#useLexicalScope">
|
|
778
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
779
|
+
// (edit ../readme.md#useLexicalScope instead and run `pnpm docs.sync`)
|
|
780
|
+
/**
|
|
781
|
+
* Used by the Qwik Optimizer to restore the lexically scoped variables.
|
|
782
|
+
*
|
|
783
|
+
* This method should not be present in the application source code.
|
|
784
|
+
*
|
|
785
|
+
* NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
|
|
786
|
+
* (before any `await` statements.)
|
|
787
|
+
*
|
|
788
|
+
* @internal
|
|
789
|
+
*/
|
|
790
|
+
// </docs>
|
|
791
|
+
const useLexicalScope = () => {
|
|
792
|
+
const context = getInvokeContext();
|
|
793
|
+
let qrl = context.$qrl$;
|
|
794
|
+
if (!qrl) {
|
|
795
|
+
const el = context.$element$;
|
|
796
|
+
assertDefined(el, 'invoke: element must be defined inside useLexicalScope()', context);
|
|
797
|
+
const containerElement = _getQContainerElement(el);
|
|
798
|
+
assertDefined(containerElement, `invoke: cant find parent q:container of`, el);
|
|
799
|
+
const container = getDomContainer(containerElement);
|
|
800
|
+
qrl = container.parseQRL(decodeURIComponent(String(context.$url$)));
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
assertQrl(qrl);
|
|
804
|
+
assertDefined(qrl.$captureRef$, 'invoke: qrl $captureRef$ must be defined inside useLexicalScope()', qrl);
|
|
805
|
+
}
|
|
806
|
+
return qrl.$captureRef$;
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* This is called by qwik-loader to schedule a QRL. It has to be synchronous.
|
|
811
|
+
*
|
|
812
|
+
* @internal
|
|
813
|
+
*/
|
|
814
|
+
const queueQRL = (...args) => {
|
|
815
|
+
// This will already check container
|
|
816
|
+
const [runQrl] = useLexicalScope();
|
|
817
|
+
const context = getInvokeContext();
|
|
818
|
+
const hostElement = context.$hostElement$;
|
|
819
|
+
const container = getDomContainer(hostElement);
|
|
820
|
+
const scheduler = container.$scheduler$;
|
|
821
|
+
if (!scheduler) {
|
|
822
|
+
throw qError(QError.schedulerNotFound);
|
|
823
|
+
}
|
|
824
|
+
return scheduler(ChoreType.RUN_QRL, hostElement, runQrl, args);
|
|
825
|
+
};
|
|
826
|
+
|
|
729
827
|
/**
|
|
730
828
|
* Allows to project the children of the current component. <Slot/> can only be used within the
|
|
731
829
|
* context of a component defined with `component$`.
|
|
@@ -850,6 +948,47 @@ function isPreventDefault(key) {
|
|
|
850
948
|
return key.startsWith('preventdefault:');
|
|
851
949
|
}
|
|
852
950
|
|
|
951
|
+
function getFileLocationFromJsx(jsxDev) {
|
|
952
|
+
if (!jsxDev) {
|
|
953
|
+
return null;
|
|
954
|
+
}
|
|
955
|
+
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
956
|
+
if (sanitizedFileName) {
|
|
957
|
+
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
958
|
+
}
|
|
959
|
+
return null;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
const styleContent = (styleId) => {
|
|
963
|
+
return ComponentStylesPrefixContent + styleId;
|
|
964
|
+
};
|
|
965
|
+
function hasClassAttr(props) {
|
|
966
|
+
for (const key in props) {
|
|
967
|
+
if (Object.prototype.hasOwnProperty.call(props, key) && isClassAttr(key)) {
|
|
968
|
+
return true;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
function isClassAttr(key) {
|
|
974
|
+
return key === 'class' || key === 'className';
|
|
975
|
+
}
|
|
976
|
+
function convertScopedStyleIdsToArray(scopedStyleIds) {
|
|
977
|
+
return scopedStyleIds?.split(' ') ?? null;
|
|
978
|
+
}
|
|
979
|
+
function convertStyleIdsToString(scopedStyleIds) {
|
|
980
|
+
return Array.from(scopedStyleIds).join(' ');
|
|
981
|
+
}
|
|
982
|
+
const addComponentStylePrefix = (styleId) => {
|
|
983
|
+
if (styleId) {
|
|
984
|
+
let idx = 0;
|
|
985
|
+
do {
|
|
986
|
+
styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
|
|
987
|
+
} while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
|
|
988
|
+
}
|
|
989
|
+
return styleId || null;
|
|
990
|
+
};
|
|
991
|
+
|
|
853
992
|
/** CSS properties which accept numbers but are not in units of "px". */
|
|
854
993
|
const unitlessNumbers = new Set([
|
|
855
994
|
'animationIterationCount',
|
|
@@ -1008,36 +1147,6 @@ const styleKey = (qStyles, index) => {
|
|
|
1008
1147
|
assertQrl(qStyles);
|
|
1009
1148
|
return `${hashCode(qStyles.$hash$)}-${index}`;
|
|
1010
1149
|
};
|
|
1011
|
-
const styleContent = (styleId) => {
|
|
1012
|
-
return ComponentStylesPrefixContent + styleId;
|
|
1013
|
-
};
|
|
1014
|
-
|
|
1015
|
-
function hasClassAttr(props) {
|
|
1016
|
-
for (const key in props) {
|
|
1017
|
-
if (Object.prototype.hasOwnProperty.call(props, key) && isClassAttr(key)) {
|
|
1018
|
-
return true;
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
return false;
|
|
1022
|
-
}
|
|
1023
|
-
function isClassAttr(key) {
|
|
1024
|
-
return key === 'class' || key === 'className';
|
|
1025
|
-
}
|
|
1026
|
-
function convertScopedStyleIdsToArray(scopedStyleIds) {
|
|
1027
|
-
return scopedStyleIds?.split(' ') ?? null;
|
|
1028
|
-
}
|
|
1029
|
-
function convertStyleIdsToString(scopedStyleIds) {
|
|
1030
|
-
return Array.from(scopedStyleIds).join(' ');
|
|
1031
|
-
}
|
|
1032
|
-
const addComponentStylePrefix = (styleId) => {
|
|
1033
|
-
if (styleId) {
|
|
1034
|
-
let idx = 0;
|
|
1035
|
-
do {
|
|
1036
|
-
styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
|
|
1037
|
-
} while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
|
|
1038
|
-
}
|
|
1039
|
-
return styleId || null;
|
|
1040
|
-
};
|
|
1041
1150
|
|
|
1042
1151
|
const STORE_TARGET = Symbol('store.target');
|
|
1043
1152
|
const STORE_HANDLER = Symbol('store.handler');
|
|
@@ -1182,8 +1291,12 @@ class StoreHandler {
|
|
|
1182
1291
|
return Reflect.ownKeys(target);
|
|
1183
1292
|
}
|
|
1184
1293
|
getOwnPropertyDescriptor(target, prop) {
|
|
1294
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
1185
1295
|
if (Array.isArray(target) || typeof prop === 'symbol') {
|
|
1186
|
-
return
|
|
1296
|
+
return descriptor;
|
|
1297
|
+
}
|
|
1298
|
+
if (descriptor && !descriptor.configurable) {
|
|
1299
|
+
return descriptor;
|
|
1187
1300
|
}
|
|
1188
1301
|
return {
|
|
1189
1302
|
enumerable: true,
|
|
@@ -1191,39 +1304,185 @@ class StoreHandler {
|
|
|
1191
1304
|
};
|
|
1192
1305
|
}
|
|
1193
1306
|
}
|
|
1194
|
-
function addEffect(target, prop, store,
|
|
1195
|
-
const effectsMap = (store.$effects$ ||=
|
|
1196
|
-
|
|
1197
|
-
|
|
1307
|
+
function addEffect(target, prop, store, effectSubscription) {
|
|
1308
|
+
const effectsMap = (store.$effects$ ||= new Map());
|
|
1309
|
+
let effects = effectsMap.get(prop);
|
|
1310
|
+
if (!effects) {
|
|
1311
|
+
effects = new Set();
|
|
1312
|
+
effectsMap.set(prop, effects);
|
|
1313
|
+
}
|
|
1198
1314
|
// Let's make sure that we have a reference to this effect.
|
|
1199
1315
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
1200
1316
|
// changes we know who to notify.
|
|
1201
|
-
|
|
1317
|
+
ensureContainsSubscription(effects, effectSubscription);
|
|
1202
1318
|
// But when effect is scheduled in needs to be able to know which signals
|
|
1203
1319
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
1204
1320
|
// to this signal.
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
ensureEffectContainsSubscriber(effectSubscriber[EffectSubscriptionsProp.EFFECT], target, store.$container$);
|
|
1321
|
+
ensureContainsBackRef(effectSubscription, target);
|
|
1322
|
+
addQrlToSerializationCtx(effectSubscription, store.$container$);
|
|
1208
1323
|
}
|
|
1209
1324
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
1210
1325
|
target[prop] = value;
|
|
1211
1326
|
triggerEffects(currentStore.$container$, currentStore, getEffects(target, prop, currentStore.$effects$));
|
|
1212
1327
|
}
|
|
1213
1328
|
function getEffects(target, prop, storeEffects) {
|
|
1214
|
-
let effectsToTrigger
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1329
|
+
let effectsToTrigger;
|
|
1330
|
+
if (storeEffects) {
|
|
1331
|
+
if (Array.isArray(target)) {
|
|
1332
|
+
for (const effects of storeEffects.values()) {
|
|
1333
|
+
effectsToTrigger ||= new Set();
|
|
1334
|
+
for (const effect of effects) {
|
|
1335
|
+
effectsToTrigger.add(effect);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
else {
|
|
1340
|
+
effectsToTrigger = storeEffects.get(prop);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
const storeArrayValue = storeEffects?.get(STORE_ARRAY_PROP);
|
|
1220
1344
|
if (storeArrayValue) {
|
|
1221
|
-
effectsToTrigger ||=
|
|
1222
|
-
|
|
1345
|
+
effectsToTrigger ||= new Set();
|
|
1346
|
+
for (const effect of storeArrayValue) {
|
|
1347
|
+
effectsToTrigger.add(effect);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
return effectsToTrigger || null;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/**
|
|
1354
|
+
* Special value used to mark that a given signal needs to be computed. This is essentially a
|
|
1355
|
+
* "marked as dirty" flag.
|
|
1356
|
+
*/
|
|
1357
|
+
const NEEDS_COMPUTATION = Symbol('invalid');
|
|
1358
|
+
/** @internal */
|
|
1359
|
+
const _EFFECT_BACK_REF = Symbol('backRef');
|
|
1360
|
+
|
|
1361
|
+
/** Class for back reference to the EffectSubscription */
|
|
1362
|
+
class BackRef {
|
|
1363
|
+
[_EFFECT_BACK_REF] = null;
|
|
1364
|
+
}
|
|
1365
|
+
function clearAllEffects(container, consumer) {
|
|
1366
|
+
if (vnode_isVNode(consumer) && vnode_isElementVNode(consumer)) {
|
|
1367
|
+
ensureMaterialized(consumer);
|
|
1368
|
+
}
|
|
1369
|
+
const effects = consumer[_EFFECT_BACK_REF];
|
|
1370
|
+
if (!effects) {
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
for (const [, effect] of effects) {
|
|
1374
|
+
const backRefs = effect[EffectSubscriptionProp.BACK_REF];
|
|
1375
|
+
if (!backRefs) {
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
for (const producer of backRefs) {
|
|
1379
|
+
if (producer instanceof Signal) {
|
|
1380
|
+
clearSignal(container, producer, effect);
|
|
1381
|
+
}
|
|
1382
|
+
else if (container.$storeProxyMap$.has(producer)) {
|
|
1383
|
+
const target = container.$storeProxyMap$.get(producer);
|
|
1384
|
+
const storeHandler = getStoreHandler(target);
|
|
1385
|
+
clearStore(storeHandler, effect);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
function clearSignal(container, producer, effect) {
|
|
1391
|
+
const effects = producer.$effects$;
|
|
1392
|
+
if (effects) {
|
|
1393
|
+
effects.delete(effect);
|
|
1394
|
+
}
|
|
1395
|
+
if (producer instanceof WrappedSignal) {
|
|
1396
|
+
producer.$hostElement$ = null;
|
|
1397
|
+
clearAllEffects(container, producer);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
function clearStore(producer, effect) {
|
|
1401
|
+
const effects = producer?.$effects$;
|
|
1402
|
+
if (effects) {
|
|
1403
|
+
for (const propEffects of effects.values()) {
|
|
1404
|
+
propEffects.delete(effect);
|
|
1405
|
+
}
|
|
1223
1406
|
}
|
|
1224
|
-
return effectsToTrigger;
|
|
1225
1407
|
}
|
|
1226
1408
|
|
|
1409
|
+
// <docs markdown="../../readme.md#implicit$FirstArg">
|
|
1410
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
1411
|
+
// (edit ../../readme.md#implicit$FirstArg instead and run `pnpm docs.sync`)
|
|
1412
|
+
/**
|
|
1413
|
+
* Create a `____$(...)` convenience method from `___(...)`.
|
|
1414
|
+
*
|
|
1415
|
+
* It is very common for functions to take a lazy-loadable resource as a first argument. For this
|
|
1416
|
+
* reason, the Qwik Optimizer automatically extracts the first argument from any function which ends
|
|
1417
|
+
* in `$`.
|
|
1418
|
+
*
|
|
1419
|
+
* This means that `foo$(arg0)` and `foo($(arg0))` are equivalent with respect to Qwik Optimizer.
|
|
1420
|
+
* The former is just a shorthand for the latter.
|
|
1421
|
+
*
|
|
1422
|
+
* For example, these function calls are equivalent:
|
|
1423
|
+
*
|
|
1424
|
+
* - `component$(() => {...})` is same as `component($(() => {...}))`
|
|
1425
|
+
*
|
|
1426
|
+
* ```tsx
|
|
1427
|
+
* export function myApi(callback: QRL<() => void>): void {
|
|
1428
|
+
* // ...
|
|
1429
|
+
* }
|
|
1430
|
+
*
|
|
1431
|
+
* export const myApi$ = implicit$FirstArg(myApi);
|
|
1432
|
+
* // type of myApi$: (callback: () => void): void
|
|
1433
|
+
*
|
|
1434
|
+
* // can be used as:
|
|
1435
|
+
* myApi$(() => console.log('callback'));
|
|
1436
|
+
*
|
|
1437
|
+
* // will be transpiled to:
|
|
1438
|
+
* // FILE: <current file>
|
|
1439
|
+
* myApi(qrl('./chunk-abc.js', 'callback'));
|
|
1440
|
+
*
|
|
1441
|
+
* // FILE: chunk-abc.js
|
|
1442
|
+
* export const callback = () => console.log('callback');
|
|
1443
|
+
* ```
|
|
1444
|
+
*
|
|
1445
|
+
* @param fn - A function that should have its first argument automatically `$`.
|
|
1446
|
+
* @public
|
|
1447
|
+
*/
|
|
1448
|
+
// </docs>
|
|
1449
|
+
const implicit$FirstArg = (fn) => {
|
|
1450
|
+
return function (first, ...rest) {
|
|
1451
|
+
return fn.call(null, dollar(first), ...rest);
|
|
1452
|
+
};
|
|
1453
|
+
};
|
|
1454
|
+
|
|
1455
|
+
const createSignal$1 = (value) => {
|
|
1456
|
+
return new Signal(null, value);
|
|
1457
|
+
};
|
|
1458
|
+
const createComputedSignal = (qrl) => {
|
|
1459
|
+
throwIfQRLNotResolved(qrl);
|
|
1460
|
+
return new ComputedSignal(null, qrl);
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1463
|
+
/**
|
|
1464
|
+
* Creates a Signal with the given value. If no value is given, the signal is created with
|
|
1465
|
+
* `undefined`.
|
|
1466
|
+
*
|
|
1467
|
+
* @public
|
|
1468
|
+
*/
|
|
1469
|
+
const createSignal = createSignal$1;
|
|
1470
|
+
/** @internal */
|
|
1471
|
+
const createComputedQrl = createComputedSignal;
|
|
1472
|
+
/**
|
|
1473
|
+
* Create a computed signal which is calculated from the given QRL. A computed signal is a signal
|
|
1474
|
+
* which is calculated from other signals. When the signals change, the computed signal is
|
|
1475
|
+
* recalculated.
|
|
1476
|
+
*
|
|
1477
|
+
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
1478
|
+
* effects, and it mus be synchronous.
|
|
1479
|
+
*
|
|
1480
|
+
* If you need the function to be async, use `useSignal` and `useTask$` instead.
|
|
1481
|
+
*
|
|
1482
|
+
* @public
|
|
1483
|
+
*/
|
|
1484
|
+
const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedQrl);
|
|
1485
|
+
|
|
1227
1486
|
/**
|
|
1228
1487
|
* @internal
|
|
1229
1488
|
* The storage provider for hooks. Each invocation increases index i. Data is stored in an array.
|
|
@@ -1259,272 +1518,66 @@ const useSequentialScope = () => {
|
|
|
1259
1518
|
};
|
|
1260
1519
|
};
|
|
1261
1520
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
return value instanceof Subscriber || value instanceof WrappedSignal;
|
|
1267
|
-
}
|
|
1268
|
-
function clearVNodeEffectDependencies(container, value) {
|
|
1269
|
-
if (vnode_isElementVNode(value)) {
|
|
1270
|
-
ensureMaterialized(value);
|
|
1271
|
-
}
|
|
1272
|
-
const effects = vnode_getProp(value, QSubscribers, container.$getObjectById$);
|
|
1273
|
-
if (!effects) {
|
|
1274
|
-
return;
|
|
1275
|
-
}
|
|
1276
|
-
for (let i = effects.length - 1; i >= 0; i--) {
|
|
1277
|
-
const subscriber = effects[i];
|
|
1278
|
-
clearEffects(subscriber, value, effects, i, container);
|
|
1279
|
-
}
|
|
1280
|
-
if (effects.length === 0) {
|
|
1281
|
-
vnode_setProp(value, QSubscribers, null);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
function clearSubscriberEffectDependencies(container, value) {
|
|
1285
|
-
if (value.$effectDependencies$) {
|
|
1286
|
-
for (let i = value.$effectDependencies$.length - 1; i >= 0; i--) {
|
|
1287
|
-
const subscriber = value.$effectDependencies$[i];
|
|
1288
|
-
clearEffects(subscriber, value, value.$effectDependencies$, i, container);
|
|
1521
|
+
function getSubscriber(effect, prop, data) {
|
|
1522
|
+
if (!effect[_EFFECT_BACK_REF]) {
|
|
1523
|
+
if (isServer && isSsrNode(effect)) {
|
|
1524
|
+
effect.setProp(QBackRefs, new Map());
|
|
1289
1525
|
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1526
|
+
else {
|
|
1527
|
+
effect[_EFFECT_BACK_REF] = new Map();
|
|
1292
1528
|
}
|
|
1293
1529
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
subscriptionRemoved = clearSignalEffects(subscriber, value, seenSet);
|
|
1300
|
-
}
|
|
1301
|
-
else if (container.$storeProxyMap$.has(subscriber)) {
|
|
1302
|
-
const store = container.$storeProxyMap$.get(subscriber);
|
|
1303
|
-
const handler = getStoreHandler(store);
|
|
1304
|
-
subscriptionRemoved = clearStoreEffects(handler, value);
|
|
1530
|
+
const subMap = effect[_EFFECT_BACK_REF];
|
|
1531
|
+
let sub = subMap.get(prop);
|
|
1532
|
+
if (!sub) {
|
|
1533
|
+
sub = [effect, prop];
|
|
1534
|
+
subMap.set(prop, sub);
|
|
1305
1535
|
}
|
|
1306
|
-
if (
|
|
1307
|
-
|
|
1536
|
+
if (data) {
|
|
1537
|
+
sub[EffectSubscriptionProp.DATA] = data;
|
|
1308
1538
|
}
|
|
1539
|
+
return sub;
|
|
1309
1540
|
}
|
|
1310
|
-
function
|
|
1311
|
-
|
|
1312
|
-
let subscriptionRemoved = false;
|
|
1313
|
-
if (effectSubscriptions) {
|
|
1314
|
-
for (let i = effectSubscriptions.length - 1; i >= 0; i--) {
|
|
1315
|
-
const effect = effectSubscriptions[i];
|
|
1316
|
-
if (effect[EffectSubscriptionsProp.EFFECT] === value) {
|
|
1317
|
-
effectSubscriptions.splice(i, 1);
|
|
1318
|
-
subscriptionRemoved = true;
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
if (subscriber instanceof WrappedSignal) {
|
|
1323
|
-
const hostElement = subscriber.$hostElement$;
|
|
1324
|
-
if (hostElement && hostElement === value) {
|
|
1325
|
-
subscriber.$hostElement$ = null;
|
|
1326
|
-
}
|
|
1327
|
-
// clear the effects of the arguments
|
|
1328
|
-
const args = subscriber.$args$;
|
|
1329
|
-
if (args) {
|
|
1330
|
-
clearArgsEffects(args, subscriber, seenSet);
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
return subscriptionRemoved;
|
|
1334
|
-
}
|
|
1335
|
-
function clearStoreEffects(storeHandler, value) {
|
|
1336
|
-
const effectSubscriptions = storeHandler.$effects$;
|
|
1337
|
-
if (!effectSubscriptions) {
|
|
1338
|
-
return false;
|
|
1339
|
-
}
|
|
1340
|
-
let subscriptionRemoved = false;
|
|
1341
|
-
for (const key in effectSubscriptions) {
|
|
1342
|
-
const effects = effectSubscriptions[key];
|
|
1343
|
-
for (let i = effects.length - 1; i >= 0; i--) {
|
|
1344
|
-
const effect = effects[i];
|
|
1345
|
-
if (effect[EffectSubscriptionsProp.EFFECT] === value) {
|
|
1346
|
-
effects.splice(i, 1);
|
|
1347
|
-
subscriptionRemoved = true;
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
if (effects.length === 0) {
|
|
1351
|
-
delete effectSubscriptions[key];
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
return subscriptionRemoved;
|
|
1355
|
-
}
|
|
1356
|
-
function clearArgsEffects(args, subscriber, seenSet) {
|
|
1357
|
-
for (let i = args.length - 1; i >= 0; i--) {
|
|
1358
|
-
const arg = args[i];
|
|
1359
|
-
clearArgEffect(arg, subscriber, seenSet);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
function clearArgEffect(arg, subscriber, seenSet) {
|
|
1363
|
-
if (seenSet.has(arg)) {
|
|
1364
|
-
return;
|
|
1365
|
-
}
|
|
1366
|
-
seenSet.add(arg);
|
|
1367
|
-
if (isSignal(arg)) {
|
|
1368
|
-
clearSignalEffects(arg, subscriber, seenSet);
|
|
1369
|
-
}
|
|
1370
|
-
else if (typeof arg === 'object' && arg !== null) {
|
|
1371
|
-
if (isStore(arg)) {
|
|
1372
|
-
clearStoreEffects(getStoreHandler(arg), subscriber);
|
|
1373
|
-
}
|
|
1374
|
-
else {
|
|
1375
|
-
for (const key in arg) {
|
|
1376
|
-
clearArgEffect(arg[key], subscriber, seenSet);
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
else if (Array.isArray(arg)) {
|
|
1381
|
-
clearArgsEffects(arg, subscriber, seenSet);
|
|
1382
|
-
}
|
|
1383
|
-
else ;
|
|
1541
|
+
function isSsrNode(value) {
|
|
1542
|
+
return '__brand__' in value && 'currentComponentNode' in value;
|
|
1384
1543
|
}
|
|
1385
1544
|
|
|
1545
|
+
var TaskFlags;
|
|
1546
|
+
(function (TaskFlags) {
|
|
1547
|
+
TaskFlags[TaskFlags["VISIBLE_TASK"] = 1] = "VISIBLE_TASK";
|
|
1548
|
+
TaskFlags[TaskFlags["TASK"] = 2] = "TASK";
|
|
1549
|
+
TaskFlags[TaskFlags["RESOURCE"] = 4] = "RESOURCE";
|
|
1550
|
+
TaskFlags[TaskFlags["DIRTY"] = 8] = "DIRTY";
|
|
1551
|
+
})(TaskFlags || (TaskFlags = {}));
|
|
1386
1552
|
/** @internal */
|
|
1387
|
-
const
|
|
1388
|
-
const { val, set,
|
|
1389
|
-
if (val
|
|
1390
|
-
return
|
|
1553
|
+
const useTaskQrl = (qrl) => {
|
|
1554
|
+
const { val, set, iCtx, i } = useSequentialScope();
|
|
1555
|
+
if (val) {
|
|
1556
|
+
return;
|
|
1391
1557
|
}
|
|
1392
1558
|
assertQrl(qrl);
|
|
1559
|
+
set(1);
|
|
1560
|
+
const task = new Task(TaskFlags.DIRTY | TaskFlags.TASK, i, iCtx.$hostElement$, qrl, undefined, null);
|
|
1561
|
+
// In V2 we add the task to the sequential scope. We need to do this
|
|
1562
|
+
// in order to be able to retrieve it later when the parent element is
|
|
1563
|
+
// deleted and we need to be able to release the task subscriptions.
|
|
1564
|
+
set(task);
|
|
1393
1565
|
const container = iCtx.$container$;
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
set(resource);
|
|
1399
|
-
return resource;
|
|
1400
|
-
};
|
|
1401
|
-
// <docs markdown="../readme.md#useResource">
|
|
1402
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
1403
|
-
// (edit ../readme.md#useResource instead and run `pnpm docs.sync`)
|
|
1404
|
-
/**
|
|
1405
|
-
* This method works like an async memoized function that runs whenever some tracked value changes
|
|
1406
|
-
* and returns some data.
|
|
1407
|
-
*
|
|
1408
|
-
* `useResource` however returns immediate a `ResourceReturn` object that contains the data and a
|
|
1409
|
-
* state that indicates if the data is available or not.
|
|
1410
|
-
*
|
|
1411
|
-
* The status can be one of the following:
|
|
1412
|
-
*
|
|
1413
|
-
* - `pending` - the data is not yet available.
|
|
1414
|
-
* - `resolved` - the data is available.
|
|
1415
|
-
* - `rejected` - the data is not available due to an error or timeout.
|
|
1416
|
-
*
|
|
1417
|
-
* Be careful when using a `try/catch` statement in `useResource$`. If you catch the error and don't
|
|
1418
|
-
* re-throw it (or a new Error), the resource status will never be `rejected`.
|
|
1419
|
-
*
|
|
1420
|
-
* ### Example
|
|
1421
|
-
*
|
|
1422
|
-
* Example showing how `useResource` to perform a fetch to request the weather, whenever the input
|
|
1423
|
-
* city name changes.
|
|
1424
|
-
*
|
|
1425
|
-
* ```tsx
|
|
1426
|
-
* const Cmp = component$(() => {
|
|
1427
|
-
* const cityS = useSignal('');
|
|
1428
|
-
*
|
|
1429
|
-
* const weatherResource = useResource$(async ({ track, cleanup }) => {
|
|
1430
|
-
* const cityName = track(cityS);
|
|
1431
|
-
* const abortController = new AbortController();
|
|
1432
|
-
* cleanup(() => abortController.abort('cleanup'));
|
|
1433
|
-
* const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
|
|
1434
|
-
* signal: abortController.signal,
|
|
1435
|
-
* });
|
|
1436
|
-
* const data = await res.json();
|
|
1437
|
-
* return data as { temp: number };
|
|
1438
|
-
* });
|
|
1439
|
-
*
|
|
1440
|
-
* return (
|
|
1441
|
-
* <div>
|
|
1442
|
-
* <input name="city" bind:value={cityS} />
|
|
1443
|
-
* <Resource
|
|
1444
|
-
* value={weatherResource}
|
|
1445
|
-
* onResolved={(weather) => {
|
|
1446
|
-
* return <div>Temperature: {weather.temp}</div>;
|
|
1447
|
-
* }}
|
|
1448
|
-
* />
|
|
1449
|
-
* </div>
|
|
1450
|
-
* );
|
|
1451
|
-
* });
|
|
1452
|
-
* ```
|
|
1453
|
-
*
|
|
1454
|
-
* @public
|
|
1455
|
-
* @see Resource
|
|
1456
|
-
* @see ResourceReturn
|
|
1457
|
-
*/
|
|
1458
|
-
// </docs>
|
|
1459
|
-
const Resource = (props) => {
|
|
1460
|
-
// Resource path
|
|
1461
|
-
return _jsxSorted(Fragment, null, null, getResourceValueAsPromise(props), 0, null);
|
|
1462
|
-
};
|
|
1463
|
-
function getResourceValueAsPromise(props) {
|
|
1464
|
-
const resource = props.value;
|
|
1465
|
-
if (isResourceReturn(resource)) {
|
|
1466
|
-
const isBrowser = !isServerPlatform();
|
|
1467
|
-
if (isBrowser) {
|
|
1468
|
-
// create a subscription for the resource._state changes
|
|
1469
|
-
const state = resource._state;
|
|
1470
|
-
if (state === 'pending' && props.onPending) {
|
|
1471
|
-
return Promise.resolve().then(useBindInvokeContext(props.onPending));
|
|
1472
|
-
}
|
|
1473
|
-
else if (state === 'rejected' && props.onRejected) {
|
|
1474
|
-
return Promise.resolve(resource._error).then(useBindInvokeContext(props.onRejected));
|
|
1475
|
-
}
|
|
1476
|
-
else {
|
|
1477
|
-
const resolvedValue = untrack(() => resource._resolved);
|
|
1478
|
-
if (resolvedValue !== undefined) {
|
|
1479
|
-
// resolved, pending without onPending prop or rejected without onRejected prop
|
|
1480
|
-
return Promise.resolve(resolvedValue).then(useBindInvokeContext(props.onResolved));
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
return resource.value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1485
|
-
}
|
|
1486
|
-
else if (isPromise(resource)) {
|
|
1487
|
-
return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1488
|
-
}
|
|
1489
|
-
else if (isSignal(resource)) {
|
|
1490
|
-
return Promise.resolve(resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1566
|
+
const promise = container.$scheduler$(ChoreType.TASK, task);
|
|
1567
|
+
if (isPromise(promise)) {
|
|
1568
|
+
// TODO: should we handle this differently?
|
|
1569
|
+
promise.catch(() => { });
|
|
1491
1570
|
}
|
|
1492
|
-
else {
|
|
1493
|
-
return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
const _createResourceReturn = (opts) => {
|
|
1497
|
-
const resource = {
|
|
1498
|
-
__brand: 'resource',
|
|
1499
|
-
value: undefined,
|
|
1500
|
-
loading: isServerPlatform() ? false : true,
|
|
1501
|
-
_resolved: undefined,
|
|
1502
|
-
_error: undefined,
|
|
1503
|
-
_state: 'pending',
|
|
1504
|
-
_timeout: opts?.timeout ?? -1,
|
|
1505
|
-
_cache: 0,
|
|
1506
|
-
};
|
|
1507
|
-
return resource;
|
|
1508
1571
|
};
|
|
1509
|
-
const
|
|
1510
|
-
const result = _createResourceReturn(opts);
|
|
1511
|
-
result.value = initialPromise;
|
|
1512
|
-
return createStore(container, result, StoreFlags.RECURSIVE);
|
|
1513
|
-
};
|
|
1514
|
-
const isResourceReturn = (obj) => {
|
|
1515
|
-
return isObject(obj) && (getStoreTarget(obj) || obj).__brand === 'resource';
|
|
1516
|
-
};
|
|
1517
|
-
const runResource = (task, container, host) => {
|
|
1572
|
+
const runTask = (task, container, host) => {
|
|
1518
1573
|
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
1519
1574
|
cleanupTask(task);
|
|
1520
|
-
const iCtx = newInvokeContext(container.$locale$, host, undefined,
|
|
1575
|
+
const iCtx = newInvokeContext(container.$locale$, host, undefined, TaskEvent);
|
|
1521
1576
|
iCtx.$container$ = container;
|
|
1522
|
-
const taskFn = task.$qrl$.getFn(iCtx, () =>
|
|
1523
|
-
const resource = task.$state$;
|
|
1524
|
-
assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
|
|
1577
|
+
const taskFn = task.$qrl$.getFn(iCtx, () => clearAllEffects(container, task));
|
|
1525
1578
|
const track = (obj, prop) => {
|
|
1526
1579
|
const ctx = newInvokeContext();
|
|
1527
|
-
ctx.$effectSubscriber$ =
|
|
1580
|
+
ctx.$effectSubscriber$ = getSubscriber(task, EffectProperty.COMPONENT);
|
|
1528
1581
|
ctx.$container$ = container;
|
|
1529
1582
|
return invoke(ctx, () => {
|
|
1530
1583
|
if (isFunction(obj)) {
|
|
@@ -1537,115 +1590,85 @@ const runResource = (task, container, host) => {
|
|
|
1537
1590
|
return obj.value;
|
|
1538
1591
|
}
|
|
1539
1592
|
else {
|
|
1540
|
-
|
|
1593
|
+
throw qError(QError.trackObjectWithoutProp);
|
|
1541
1594
|
}
|
|
1542
1595
|
});
|
|
1543
1596
|
};
|
|
1544
1597
|
const handleError = (reason) => container.handleError(reason, host);
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
if (typeof fn === 'function') {
|
|
1562
|
-
cleanups.push(fn);
|
|
1563
|
-
}
|
|
1564
|
-
},
|
|
1565
|
-
cache(policy) {
|
|
1566
|
-
let milliseconds = 0;
|
|
1567
|
-
if (policy === 'immutable') {
|
|
1568
|
-
milliseconds = Infinity;
|
|
1569
|
-
}
|
|
1570
|
-
else {
|
|
1571
|
-
milliseconds = policy;
|
|
1572
|
-
}
|
|
1573
|
-
resource._cache = milliseconds;
|
|
1574
|
-
},
|
|
1575
|
-
previous: resourceTarget._resolved,
|
|
1576
|
-
};
|
|
1577
|
-
let resolve;
|
|
1578
|
-
let reject;
|
|
1579
|
-
let done = false;
|
|
1580
|
-
const setState = (resolved, value) => {
|
|
1581
|
-
if (!done) {
|
|
1582
|
-
done = true;
|
|
1583
|
-
if (resolved) {
|
|
1584
|
-
done = true;
|
|
1585
|
-
resource.loading = false;
|
|
1586
|
-
resource._state = 'resolved';
|
|
1587
|
-
resource._resolved = value;
|
|
1588
|
-
resource._error = undefined;
|
|
1589
|
-
resolve(value);
|
|
1590
|
-
}
|
|
1591
|
-
else {
|
|
1592
|
-
done = true;
|
|
1593
|
-
resource.loading = false;
|
|
1594
|
-
resource._state = 'rejected';
|
|
1595
|
-
resource._error = value;
|
|
1596
|
-
reject(value);
|
|
1598
|
+
let cleanupFns = null;
|
|
1599
|
+
const cleanup = (fn) => {
|
|
1600
|
+
if (typeof fn == 'function') {
|
|
1601
|
+
if (!cleanupFns) {
|
|
1602
|
+
cleanupFns = [];
|
|
1603
|
+
task.$destroy$ = noSerialize(() => {
|
|
1604
|
+
task.$destroy$ = null;
|
|
1605
|
+
cleanupFns.forEach((fn) => {
|
|
1606
|
+
try {
|
|
1607
|
+
fn();
|
|
1608
|
+
}
|
|
1609
|
+
catch (err) {
|
|
1610
|
+
handleError(err);
|
|
1611
|
+
}
|
|
1612
|
+
});
|
|
1613
|
+
});
|
|
1597
1614
|
}
|
|
1598
|
-
|
|
1615
|
+
cleanupFns.push(fn);
|
|
1599
1616
|
}
|
|
1600
|
-
return false;
|
|
1601
1617
|
};
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
*/
|
|
1606
|
-
cleanups.push(() => {
|
|
1607
|
-
if (untrack(() => resource.loading) === true) {
|
|
1608
|
-
const value = untrack(() => resource._resolved);
|
|
1609
|
-
setState(true, value);
|
|
1610
|
-
}
|
|
1611
|
-
});
|
|
1612
|
-
// Execute mutation inside empty invocation
|
|
1613
|
-
invoke(iCtx, () => {
|
|
1614
|
-
// console.log('RESOURCE.pending: ');
|
|
1615
|
-
resource._state = 'pending';
|
|
1616
|
-
resource.loading = !isServerPlatform();
|
|
1617
|
-
const promise = (resource.value = new Promise((r, re) => {
|
|
1618
|
-
resolve = r;
|
|
1619
|
-
reject = re;
|
|
1620
|
-
}));
|
|
1621
|
-
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
1622
|
-
});
|
|
1623
|
-
const promise = safeCall(() => Promise.resolve(taskFn(opts)), (value) => {
|
|
1624
|
-
setState(true, value);
|
|
1625
|
-
}, (err) => {
|
|
1618
|
+
const taskApi = { track, cleanup };
|
|
1619
|
+
const result = safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
1620
|
+
// If a Promise is thrown, that means we need to re-run the task.
|
|
1626
1621
|
if (isPromise(err)) {
|
|
1627
|
-
return err.then(() =>
|
|
1622
|
+
return err.then(() => runTask(task, container, host));
|
|
1628
1623
|
}
|
|
1629
1624
|
else {
|
|
1630
|
-
|
|
1625
|
+
throw err;
|
|
1631
1626
|
}
|
|
1632
1627
|
});
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1628
|
+
return result;
|
|
1629
|
+
};
|
|
1630
|
+
const cleanupTask = (task) => {
|
|
1631
|
+
const destroy = task.$destroy$;
|
|
1632
|
+
if (destroy) {
|
|
1633
|
+
task.$destroy$ = null;
|
|
1634
|
+
try {
|
|
1635
|
+
destroy();
|
|
1636
|
+
}
|
|
1637
|
+
catch (err) {
|
|
1638
|
+
logError(err);
|
|
1639
|
+
}
|
|
1643
1640
|
}
|
|
1644
|
-
return promise;
|
|
1645
1641
|
};
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1642
|
+
class Task extends BackRef {
|
|
1643
|
+
$flags$;
|
|
1644
|
+
$index$;
|
|
1645
|
+
$el$;
|
|
1646
|
+
$qrl$;
|
|
1647
|
+
$state$;
|
|
1648
|
+
$destroy$;
|
|
1649
|
+
constructor($flags$, $index$, $el$, $qrl$, $state$, $destroy$) {
|
|
1650
|
+
super();
|
|
1651
|
+
this.$flags$ = $flags$;
|
|
1652
|
+
this.$index$ = $index$;
|
|
1653
|
+
this.$el$ = $el$;
|
|
1654
|
+
this.$qrl$ = $qrl$;
|
|
1655
|
+
this.$state$ = $state$;
|
|
1656
|
+
this.$destroy$ = $destroy$;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
const isTask = (value) => {
|
|
1660
|
+
return value instanceof Task;
|
|
1661
|
+
};
|
|
1662
|
+
/**
|
|
1663
|
+
* Used internally as a qrl event handler to schedule a task.
|
|
1664
|
+
*
|
|
1665
|
+
* @internal
|
|
1666
|
+
*/
|
|
1667
|
+
const scheduleTask = (_event, element) => {
|
|
1668
|
+
const [task] = useLexicalScope();
|
|
1669
|
+
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
|
|
1670
|
+
const container = getDomContainer(element);
|
|
1671
|
+
container.$scheduler$(type, task);
|
|
1649
1672
|
};
|
|
1650
1673
|
|
|
1651
1674
|
/** @file Public types for the client deserialization */
|
|
@@ -1723,22 +1746,67 @@ var VirtualVNodeProps;
|
|
|
1723
1746
|
VirtualVNodeProps[VirtualVNodeProps["PROPS_OFFSET"] = 6] = "PROPS_OFFSET";
|
|
1724
1747
|
})(VirtualVNodeProps || (VirtualVNodeProps = {}));
|
|
1725
1748
|
|
|
1726
|
-
const
|
|
1749
|
+
const mapApp_findIndx = (elementVNode, key, start) => {
|
|
1750
|
+
assertTrue(start % 2 === 0, 'Expecting even number.');
|
|
1751
|
+
let bottom = start >> 1;
|
|
1752
|
+
let top = (elementVNode.length - 2) >> 1;
|
|
1753
|
+
while (bottom <= top) {
|
|
1754
|
+
const mid = bottom + ((top - bottom) >> 1);
|
|
1755
|
+
const midKey = elementVNode[mid << 1];
|
|
1756
|
+
if (midKey === key) {
|
|
1757
|
+
return mid << 1;
|
|
1758
|
+
}
|
|
1759
|
+
if (midKey < key) {
|
|
1760
|
+
bottom = mid + 1;
|
|
1761
|
+
}
|
|
1762
|
+
else {
|
|
1763
|
+
top = mid - 1;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
return (bottom << 1) ^ -1;
|
|
1767
|
+
};
|
|
1768
|
+
const mapArray_set = (elementVNode, key, value, start) => {
|
|
1769
|
+
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
1770
|
+
if (indx >= 0) {
|
|
1771
|
+
if (value == null) {
|
|
1772
|
+
elementVNode.splice(indx, 2);
|
|
1773
|
+
}
|
|
1774
|
+
else {
|
|
1775
|
+
elementVNode[indx + 1] = value;
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
else if (value != null) {
|
|
1779
|
+
elementVNode.splice(indx ^ -1, 0, key, value);
|
|
1780
|
+
}
|
|
1781
|
+
};
|
|
1782
|
+
const mapArray_get = (elementVNode, key, start) => {
|
|
1783
|
+
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
1784
|
+
if (indx >= 0) {
|
|
1785
|
+
return elementVNode[indx + 1];
|
|
1786
|
+
}
|
|
1787
|
+
else {
|
|
1788
|
+
return null;
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
|
|
1792
|
+
const isForeignObjectElement = (elementName) => {
|
|
1793
|
+
return isDev ? elementName.toLowerCase() === 'foreignobject' : elementName === 'foreignObject';
|
|
1794
|
+
};
|
|
1727
1795
|
const isSvgElement = (elementName) => elementName === 'svg' || isForeignObjectElement(elementName);
|
|
1728
1796
|
const isMathElement = (elementName) => elementName === 'math';
|
|
1729
1797
|
const vnode_isDefaultNamespace = (vnode) => {
|
|
1730
1798
|
const flags = vnode[VNodeProps.flags];
|
|
1731
1799
|
return (flags & VNodeFlags.NAMESPACE_MASK) === 0;
|
|
1732
1800
|
};
|
|
1733
|
-
const vnode_getElementNamespaceFlags = (
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1801
|
+
const vnode_getElementNamespaceFlags = (element) => {
|
|
1802
|
+
const namespace = fastNamespaceURI(element);
|
|
1803
|
+
switch (namespace) {
|
|
1804
|
+
case SVG_NS:
|
|
1805
|
+
return VNodeFlags.NS_svg;
|
|
1806
|
+
case MATH_NS:
|
|
1807
|
+
return VNodeFlags.NS_math;
|
|
1808
|
+
default:
|
|
1809
|
+
return VNodeFlags.NS_html;
|
|
1742
1810
|
}
|
|
1743
1811
|
};
|
|
1744
1812
|
function vnode_getDomChildrenWithCorrectNamespacesToInsert(journal, domParentVNode, newChild) {
|
|
@@ -2092,19 +2160,21 @@ const useOnEventsSequentialScope = () => {
|
|
|
2092
2160
|
* @returns
|
|
2093
2161
|
*/
|
|
2094
2162
|
const executeComponent = (container, renderHost, subscriptionHost, componentQRL, props) => {
|
|
2095
|
-
const iCtx = newInvokeContext(container.$locale$, subscriptionHost, undefined, RenderEvent);
|
|
2096
|
-
|
|
2097
|
-
|
|
2163
|
+
const iCtx = newInvokeContext(container.$locale$, subscriptionHost || undefined, undefined, RenderEvent);
|
|
2164
|
+
if (subscriptionHost) {
|
|
2165
|
+
iCtx.$effectSubscriber$ = getSubscriber(subscriptionHost, EffectProperty.COMPONENT);
|
|
2166
|
+
iCtx.$container$ = container;
|
|
2167
|
+
}
|
|
2098
2168
|
let componentFn;
|
|
2099
2169
|
container.ensureProjectionResolved(renderHost);
|
|
2100
2170
|
let isInlineComponent = false;
|
|
2101
2171
|
if (componentQRL === null) {
|
|
2102
|
-
componentQRL =
|
|
2172
|
+
componentQRL = container.getHostProp(renderHost, OnRenderProp);
|
|
2103
2173
|
assertDefined(componentQRL, 'No Component found at this location');
|
|
2104
2174
|
}
|
|
2105
|
-
if (isQrl(componentQRL)) {
|
|
2175
|
+
if (isQrl$1(componentQRL)) {
|
|
2106
2176
|
props = props || container.getHostProp(renderHost, ELEMENT_PROPS) || EMPTY_OBJ;
|
|
2107
|
-
if (props
|
|
2177
|
+
if (props.children) {
|
|
2108
2178
|
delete props.children;
|
|
2109
2179
|
}
|
|
2110
2180
|
componentFn = componentQRL.getFn(iCtx);
|
|
@@ -2122,18 +2192,16 @@ const executeComponent = (container, renderHost, subscriptionHost, componentQRL,
|
|
|
2122
2192
|
if (!isInlineComponent) {
|
|
2123
2193
|
container.setHostProp(renderHost, ELEMENT_SEQ_IDX, null);
|
|
2124
2194
|
container.setHostProp(renderHost, USE_ON_LOCAL_SEQ_IDX, null);
|
|
2125
|
-
|
|
2126
|
-
container.setHostProp(renderHost, ELEMENT_PROPS, props);
|
|
2127
|
-
}
|
|
2195
|
+
container.setHostProp(renderHost, ELEMENT_PROPS, props);
|
|
2128
2196
|
}
|
|
2129
2197
|
if (vnode_isVNode(renderHost)) {
|
|
2130
|
-
|
|
2198
|
+
clearAllEffects(container, renderHost);
|
|
2131
2199
|
}
|
|
2132
2200
|
return componentFn(props);
|
|
2133
2201
|
}, (jsx) => {
|
|
2134
2202
|
const useOnEvents = container.getHostProp(renderHost, USE_ON_LOCAL);
|
|
2135
2203
|
if (useOnEvents) {
|
|
2136
|
-
return
|
|
2204
|
+
return addUseOnEvents(jsx, useOnEvents);
|
|
2137
2205
|
}
|
|
2138
2206
|
return jsx;
|
|
2139
2207
|
}, (err) => {
|
|
@@ -2159,6 +2227,7 @@ const executeComponent = (container, renderHost, subscriptionHost, componentQRL,
|
|
|
2159
2227
|
*/
|
|
2160
2228
|
function addUseOnEvents(jsx, useOnEvents) {
|
|
2161
2229
|
const jsxElement = findFirstStringJSX(jsx);
|
|
2230
|
+
let jsxResult = jsx;
|
|
2162
2231
|
return maybeThen(jsxElement, (jsxElement) => {
|
|
2163
2232
|
let isInvisibleComponent = false;
|
|
2164
2233
|
if (!jsxElement) {
|
|
@@ -2177,13 +2246,15 @@ function addUseOnEvents(jsx, useOnEvents) {
|
|
|
2177
2246
|
if (Object.prototype.hasOwnProperty.call(useOnEvents, key)) {
|
|
2178
2247
|
if (isInvisibleComponent) {
|
|
2179
2248
|
if (key === 'onQvisible$') {
|
|
2180
|
-
jsxElement = addScriptNodeForInvisibleComponents(
|
|
2249
|
+
const [jsxElement, jsx] = addScriptNodeForInvisibleComponents(jsxResult);
|
|
2250
|
+
jsxResult = jsx;
|
|
2181
2251
|
if (jsxElement) {
|
|
2182
2252
|
addUseOnEvent(jsxElement, 'document:onQinit$', useOnEvents[key]);
|
|
2183
2253
|
}
|
|
2184
2254
|
}
|
|
2185
2255
|
else if (key.startsWith('document:') || key.startsWith('window:')) {
|
|
2186
|
-
jsxElement = addScriptNodeForInvisibleComponents(
|
|
2256
|
+
const [jsxElement, jsx] = addScriptNodeForInvisibleComponents(jsxResult);
|
|
2257
|
+
jsxResult = jsx;
|
|
2187
2258
|
if (jsxElement) {
|
|
2188
2259
|
addUseOnEvent(jsxElement, key, useOnEvents[key]);
|
|
2189
2260
|
}
|
|
@@ -2201,7 +2272,7 @@ function addUseOnEvents(jsx, useOnEvents) {
|
|
|
2201
2272
|
}
|
|
2202
2273
|
}
|
|
2203
2274
|
}
|
|
2204
|
-
return
|
|
2275
|
+
return jsxResult;
|
|
2205
2276
|
});
|
|
2206
2277
|
}
|
|
2207
2278
|
function addUseOnEvent(jsxElement, key, value) {
|
|
@@ -2247,6 +2318,9 @@ function addScriptNodeForInvisibleComponents(jsx) {
|
|
|
2247
2318
|
type: 'placeholder',
|
|
2248
2319
|
hidden: '',
|
|
2249
2320
|
}, null, 3);
|
|
2321
|
+
if (jsx.type === Slot) {
|
|
2322
|
+
return [jsxElement, _jsxSorted(Fragment, null, null, [jsx, jsxElement], 0, null)];
|
|
2323
|
+
}
|
|
2250
2324
|
if (jsx.children == null) {
|
|
2251
2325
|
jsx.children = jsxElement;
|
|
2252
2326
|
}
|
|
@@ -2256,15 +2330,23 @@ function addScriptNodeForInvisibleComponents(jsx) {
|
|
|
2256
2330
|
else {
|
|
2257
2331
|
jsx.children = [jsx.children, jsxElement];
|
|
2258
2332
|
}
|
|
2259
|
-
return jsxElement;
|
|
2333
|
+
return [jsxElement, jsx];
|
|
2260
2334
|
}
|
|
2261
2335
|
else if (Array.isArray(jsx) && jsx.length) {
|
|
2262
2336
|
// get first element
|
|
2263
|
-
|
|
2337
|
+
const [jsxElement, _] = addScriptNodeForInvisibleComponents(jsx[0]);
|
|
2338
|
+
return [jsxElement, jsx];
|
|
2264
2339
|
}
|
|
2265
|
-
return null;
|
|
2340
|
+
return [null, null];
|
|
2266
2341
|
}
|
|
2267
2342
|
|
|
2343
|
+
/** @internal */
|
|
2344
|
+
const _CONST_PROPS = Symbol('CONST');
|
|
2345
|
+
/** @internal */
|
|
2346
|
+
const _VAR_PROPS = Symbol('VAR');
|
|
2347
|
+
/** @internal @deprecated v1 compat */
|
|
2348
|
+
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
2349
|
+
|
|
2268
2350
|
function isSlotProp(prop) {
|
|
2269
2351
|
return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
|
|
2270
2352
|
}
|
|
@@ -2273,12 +2355,24 @@ function isParentSlotProp(prop) {
|
|
|
2273
2355
|
}
|
|
2274
2356
|
/** @internal */
|
|
2275
2357
|
const _restProps = (props, omit, target = {}) => {
|
|
2276
|
-
|
|
2358
|
+
let constPropsTarget = null;
|
|
2359
|
+
const constProps = props[_CONST_PROPS];
|
|
2360
|
+
if (constProps) {
|
|
2361
|
+
for (const key in constProps) {
|
|
2362
|
+
if (!omit.includes(key)) {
|
|
2363
|
+
constPropsTarget ||= {};
|
|
2364
|
+
constPropsTarget[key] = constProps[key];
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
const varPropsTarget = target;
|
|
2369
|
+
const varProps = props[_VAR_PROPS];
|
|
2370
|
+
for (const key in varProps) {
|
|
2277
2371
|
if (!omit.includes(key)) {
|
|
2278
|
-
|
|
2372
|
+
varPropsTarget[key] = varProps[key];
|
|
2279
2373
|
}
|
|
2280
2374
|
}
|
|
2281
|
-
return
|
|
2375
|
+
return createPropsProxy(varPropsTarget, constPropsTarget);
|
|
2282
2376
|
};
|
|
2283
2377
|
|
|
2284
2378
|
function escapeHTML(html) {
|
|
@@ -2320,17 +2414,6 @@ function escapeHTML(html) {
|
|
|
2320
2414
|
}
|
|
2321
2415
|
}
|
|
2322
2416
|
|
|
2323
|
-
function getFileLocationFromJsx(jsxDev) {
|
|
2324
|
-
if (!jsxDev) {
|
|
2325
|
-
return null;
|
|
2326
|
-
}
|
|
2327
|
-
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
2328
|
-
if (sanitizedFileName) {
|
|
2329
|
-
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
2330
|
-
}
|
|
2331
|
-
return null;
|
|
2332
|
-
}
|
|
2333
|
-
|
|
2334
2417
|
const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
2335
2418
|
let journal = container.$journal$;
|
|
2336
2419
|
/**
|
|
@@ -2349,9 +2432,9 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2349
2432
|
/// (Node can be null, if we are at the end of the list.)
|
|
2350
2433
|
let vCurrent = null;
|
|
2351
2434
|
/// When we insert new node we start it here so that we can descend into it.
|
|
2352
|
-
/// NOTE: it can't be stored in `vCurrent` because `
|
|
2435
|
+
/// NOTE: it can't be stored in `vCurrent` because `vNewNode` is in journal
|
|
2353
2436
|
/// and is not connected to the tree.
|
|
2354
|
-
let vNewNode = null;
|
|
2437
|
+
let vNewNode = null;
|
|
2355
2438
|
/// When elements have keys they can be consumed out of order and therefore we can't use nextSibling.
|
|
2356
2439
|
/// In such a case this array will contain the elements after the current location.
|
|
2357
2440
|
/// The array even indices will contains keys and odd indices the vNode.
|
|
@@ -2404,7 +2487,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2404
2487
|
}
|
|
2405
2488
|
else if (isSignal(jsxValue)) {
|
|
2406
2489
|
if (vCurrent) {
|
|
2407
|
-
|
|
2490
|
+
clearAllEffects(container, vCurrent);
|
|
2408
2491
|
}
|
|
2409
2492
|
expectVirtual(VirtualType.WrappedSignal, null);
|
|
2410
2493
|
descend(trackSignalAndAssignHost(jsxValue, (vNewNode || vCurrent), EffectProperty.VNODE, container), true);
|
|
@@ -2619,9 +2702,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2619
2702
|
};
|
|
2620
2703
|
const projections = [];
|
|
2621
2704
|
if (host) {
|
|
2705
|
+
const props = vnode_getProps(host);
|
|
2622
2706
|
// we need to create empty projections for all the slots to remove unused slots content
|
|
2623
|
-
for (let i =
|
|
2624
|
-
const prop =
|
|
2707
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
2708
|
+
const prop = props[i];
|
|
2625
2709
|
if (isSlotProp(prop)) {
|
|
2626
2710
|
const slotName = prop;
|
|
2627
2711
|
projections.push(slotName);
|
|
@@ -2789,10 +2873,19 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2789
2873
|
// But we need to mark them so that they don't get pulled into the diff.
|
|
2790
2874
|
const eventName = getEventNameFromJsxProp(key);
|
|
2791
2875
|
const scope = getEventNameScopeFromJsxProp(key);
|
|
2792
|
-
vnode_setProp(vNewNode, HANDLER_PREFIX + ':' + scope + ':' + eventName, value);
|
|
2793
2876
|
if (eventName) {
|
|
2877
|
+
vnode_setProp(vNewNode, HANDLER_PREFIX + ':' + scope + ':' + eventName, value);
|
|
2794
2878
|
registerQwikLoaderEvent(eventName);
|
|
2795
2879
|
}
|
|
2880
|
+
if (scope) {
|
|
2881
|
+
// add an event attr with empty value for qwikloader element selector.
|
|
2882
|
+
// We don't need value here. For ssr this value is a QRL,
|
|
2883
|
+
// but for CSR value should be just empty
|
|
2884
|
+
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
2885
|
+
if (htmlEvent) {
|
|
2886
|
+
vnode_setAttr(journal, vNewNode, htmlEvent, '');
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2796
2889
|
needsQDispatchEventPatch = true;
|
|
2797
2890
|
continue;
|
|
2798
2891
|
}
|
|
@@ -2805,12 +2898,15 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2805
2898
|
value(element);
|
|
2806
2899
|
continue;
|
|
2807
2900
|
}
|
|
2901
|
+
else if (value == null) {
|
|
2902
|
+
continue;
|
|
2903
|
+
}
|
|
2808
2904
|
else {
|
|
2809
2905
|
throw qError(QError.invalidRefValue, [currentFile]);
|
|
2810
2906
|
}
|
|
2811
2907
|
}
|
|
2812
2908
|
if (isSignal(value)) {
|
|
2813
|
-
const signalData = new
|
|
2909
|
+
const signalData = new SubscriptionData({
|
|
2814
2910
|
$scopedStyleIdPrefix$: scopedStyleIdPrefix,
|
|
2815
2911
|
$isConst$: true,
|
|
2816
2912
|
});
|
|
@@ -2914,7 +3010,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2914
3010
|
let returnValue = false;
|
|
2915
3011
|
qrls.flat(2).forEach((qrl) => {
|
|
2916
3012
|
if (qrl) {
|
|
2917
|
-
const value = qrl
|
|
3013
|
+
const value = container.$scheduler$(ChoreType.RUN_QRL, vNode, qrl, [event, element]);
|
|
2918
3014
|
returnValue = returnValue || value === true;
|
|
2919
3015
|
}
|
|
2920
3016
|
});
|
|
@@ -2926,10 +3022,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2926
3022
|
/** @param tag Returns true if `qDispatchEvent` needs patching */
|
|
2927
3023
|
function setBulkProps(vnode, srcAttrs, currentFile) {
|
|
2928
3024
|
vnode_ensureElementInflated(vnode);
|
|
2929
|
-
const dstAttrs = vnode;
|
|
3025
|
+
const dstAttrs = vnode_getProps(vnode);
|
|
2930
3026
|
let srcIdx = 0;
|
|
2931
3027
|
const srcLength = srcAttrs.length;
|
|
2932
|
-
let dstIdx =
|
|
3028
|
+
let dstIdx = 0;
|
|
2933
3029
|
let dstLength = dstAttrs.length;
|
|
2934
3030
|
let srcKey = srcIdx < srcLength ? srcAttrs[srcIdx++] : null;
|
|
2935
3031
|
let dstKey = dstIdx < dstLength ? dstAttrs[dstIdx++] : null;
|
|
@@ -2949,12 +3045,15 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2949
3045
|
value(element);
|
|
2950
3046
|
return;
|
|
2951
3047
|
}
|
|
3048
|
+
else if (value == null) {
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
2952
3051
|
else {
|
|
2953
3052
|
throw qError(QError.invalidRefValue, [currentFile]);
|
|
2954
3053
|
}
|
|
2955
3054
|
}
|
|
2956
3055
|
if (isSignal(value)) {
|
|
2957
|
-
const signalData = new
|
|
3056
|
+
const signalData = new SubscriptionData({
|
|
2958
3057
|
$scopedStyleIdPrefix$: scopedStyleIdPrefix,
|
|
2959
3058
|
$isConst$: false,
|
|
2960
3059
|
});
|
|
@@ -2968,21 +3067,21 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2968
3067
|
};
|
|
2969
3068
|
const recordJsxEvent = (key, value) => {
|
|
2970
3069
|
const eventName = getEventNameFromJsxProp(key);
|
|
3070
|
+
const scope = getEventNameScopeFromJsxProp(key);
|
|
2971
3071
|
if (eventName) {
|
|
2972
|
-
const scope = getEventNameScopeFromJsxProp(key);
|
|
2973
3072
|
record(':' + scope + ':' + eventName, value);
|
|
2974
|
-
|
|
2975
|
-
// add an event attr with empty value for qwikloader element selector.
|
|
2976
|
-
// We don't need value here. For ssr this value is a QRL,
|
|
2977
|
-
// but for CSR value should be just empty
|
|
2978
|
-
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
2979
|
-
if (htmlEvent) {
|
|
2980
|
-
record(htmlEvent, '');
|
|
2981
|
-
}
|
|
2982
|
-
// register an event for qwik loader
|
|
2983
|
-
if (eventName) {
|
|
3073
|
+
// register an event for qwik loader
|
|
2984
3074
|
registerQwikLoaderEvent(eventName);
|
|
2985
3075
|
}
|
|
3076
|
+
if (scope) {
|
|
3077
|
+
// add an event attr with empty value for qwikloader element selector.
|
|
3078
|
+
// We don't need value here. For ssr this value is a QRL,
|
|
3079
|
+
// but for CSR value should be just empty
|
|
3080
|
+
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
3081
|
+
if (htmlEvent) {
|
|
3082
|
+
record(htmlEvent, '');
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
2986
3085
|
};
|
|
2987
3086
|
while (srcKey !== null || dstKey !== null) {
|
|
2988
3087
|
if (dstKey?.startsWith(HANDLER_PREFIX) || dstKey?.startsWith(Q_PREFIX)) {
|
|
@@ -3178,10 +3277,6 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
3178
3277
|
else if (!hashesAreEqual) {
|
|
3179
3278
|
insertNewComponent(host, componentQRL, jsxProps);
|
|
3180
3279
|
if (vNewNode) {
|
|
3181
|
-
if (host) {
|
|
3182
|
-
// TODO(varixo): not sure why we need to copy flags here.
|
|
3183
|
-
vNewNode[VNodeProps.flags] = host[VNodeProps.flags];
|
|
3184
|
-
}
|
|
3185
3280
|
host = vNewNode;
|
|
3186
3281
|
shouldRender = true;
|
|
3187
3282
|
}
|
|
@@ -3234,7 +3329,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
3234
3329
|
}
|
|
3235
3330
|
function insertNewComponent(host, componentQRL, jsxProps) {
|
|
3236
3331
|
if (host) {
|
|
3237
|
-
|
|
3332
|
+
clearAllEffects(container, host);
|
|
3238
3333
|
}
|
|
3239
3334
|
vnode_insertBefore(journal, vParent, (vNewNode = vnode_newVirtual()), vCurrent && getInsertBefore());
|
|
3240
3335
|
const jsxNode = jsxValue;
|
|
@@ -3322,8 +3417,8 @@ function propsDiffer(src, dst) {
|
|
|
3322
3417
|
if (!src || !dst) {
|
|
3323
3418
|
return true;
|
|
3324
3419
|
}
|
|
3325
|
-
let srcKeys = removePropsKeys(Object.keys(src), ['children',
|
|
3326
|
-
let dstKeys = removePropsKeys(Object.keys(dst), ['children',
|
|
3420
|
+
let srcKeys = removePropsKeys(Object.keys(src), ['children', QBackRefs]);
|
|
3421
|
+
let dstKeys = removePropsKeys(Object.keys(dst), ['children', QBackRefs]);
|
|
3327
3422
|
if (srcKeys.length !== dstKeys.length) {
|
|
3328
3423
|
return true;
|
|
3329
3424
|
}
|
|
@@ -3369,7 +3464,7 @@ function cleanup(container, vNode) {
|
|
|
3369
3464
|
do {
|
|
3370
3465
|
const type = vCursor[VNodeProps.flags];
|
|
3371
3466
|
if (type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) {
|
|
3372
|
-
|
|
3467
|
+
clearAllEffects(container, vCursor);
|
|
3373
3468
|
markVNodeAsDeleted(vCursor);
|
|
3374
3469
|
// Only elements and virtual nodes need to be traversed for children
|
|
3375
3470
|
if (type & VNodeFlags.Virtual) {
|
|
@@ -3379,7 +3474,7 @@ function cleanup(container, vNode) {
|
|
|
3379
3474
|
const obj = seq[i];
|
|
3380
3475
|
if (isTask(obj)) {
|
|
3381
3476
|
const task = obj;
|
|
3382
|
-
|
|
3477
|
+
clearAllEffects(container, task);
|
|
3383
3478
|
if (task.$flags$ & TaskFlags.VISIBLE_TASK) {
|
|
3384
3479
|
container.$scheduler$(ChoreType.CLEANUP_VISIBLE, task);
|
|
3385
3480
|
}
|
|
@@ -3394,8 +3489,8 @@ function cleanup(container, vNode) {
|
|
|
3394
3489
|
vnode_getProp(vCursor, OnRenderProp, null) !== null;
|
|
3395
3490
|
if (isComponent) {
|
|
3396
3491
|
// SPECIAL CASE: If we are a component, we need to descend into the projected content and release the content.
|
|
3397
|
-
const attrs = vCursor;
|
|
3398
|
-
for (let i =
|
|
3492
|
+
const attrs = vnode_getProps(vCursor);
|
|
3493
|
+
for (let i = 0; i < attrs.length; i = i + 2) {
|
|
3399
3494
|
const key = attrs[i];
|
|
3400
3495
|
if (!isParentSlotProp(key) && isSlotProp(key)) {
|
|
3401
3496
|
const value = attrs[i + 1];
|
|
@@ -3455,130 +3550,420 @@ function cleanup(container, vNode) {
|
|
|
3455
3550
|
// We are back where we started, we are done.
|
|
3456
3551
|
return;
|
|
3457
3552
|
}
|
|
3458
|
-
const vNextParentSibling = vnode_getNextSibling(vParent);
|
|
3459
|
-
if (vNextParentSibling) {
|
|
3460
|
-
vCursor = vNextParentSibling;
|
|
3461
|
-
break;
|
|
3553
|
+
const vNextParentSibling = vnode_getNextSibling(vParent);
|
|
3554
|
+
if (vNextParentSibling) {
|
|
3555
|
+
vCursor = vNextParentSibling;
|
|
3556
|
+
break;
|
|
3557
|
+
}
|
|
3558
|
+
vParent = vnode_getParent(vParent);
|
|
3559
|
+
}
|
|
3560
|
+
if (vParent == null) {
|
|
3561
|
+
// We are done.
|
|
3562
|
+
return;
|
|
3563
|
+
}
|
|
3564
|
+
} while (true);
|
|
3565
|
+
}
|
|
3566
|
+
function cleanupStaleUnclaimedProjection(journal, projection) {
|
|
3567
|
+
// we are removing a node where the projection would go after slot render.
|
|
3568
|
+
// This is not needed, so we need to cleanup still unclaimed projection
|
|
3569
|
+
const projectionParent = vnode_getParent(projection);
|
|
3570
|
+
if (projectionParent) {
|
|
3571
|
+
const projectionParentType = projectionParent[VNodeProps.flags];
|
|
3572
|
+
if (projectionParentType & VNodeFlags.Element &&
|
|
3573
|
+
vnode_getElementName(projectionParent) === QTemplate) {
|
|
3574
|
+
// if parent is the q:template element then projection is still unclaimed - remove it
|
|
3575
|
+
vnode_remove(journal, projectionParent, projection, true);
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
function markVNodeAsDeleted(vCursor) {
|
|
3580
|
+
/**
|
|
3581
|
+
* Marks vCursor as deleted. We need to do this to prevent chores from running after the vnode is
|
|
3582
|
+
* removed. (for example signal subscriptions)
|
|
3583
|
+
*/
|
|
3584
|
+
vCursor[VNodeProps.flags] |= VNodeFlags.Deleted;
|
|
3585
|
+
}
|
|
3586
|
+
/**
|
|
3587
|
+
* This marks the property as immutable. It is needed for the QRLs so that QwikLoader can get a hold
|
|
3588
|
+
* of them. This character must be `:` so that the `vnode_getAttr` can ignore them.
|
|
3589
|
+
*/
|
|
3590
|
+
const HANDLER_PREFIX = ':';
|
|
3591
|
+
let count = 0;
|
|
3592
|
+
var SiblingsArray;
|
|
3593
|
+
(function (SiblingsArray) {
|
|
3594
|
+
SiblingsArray[SiblingsArray["Name"] = 0] = "Name";
|
|
3595
|
+
SiblingsArray[SiblingsArray["Key"] = 1] = "Key";
|
|
3596
|
+
SiblingsArray[SiblingsArray["VNode"] = 2] = "VNode";
|
|
3597
|
+
SiblingsArray[SiblingsArray["Size"] = 3] = "Size";
|
|
3598
|
+
SiblingsArray[SiblingsArray["NextVNode"] = 5] = "NextVNode";
|
|
3599
|
+
})(SiblingsArray || (SiblingsArray = {}));
|
|
3600
|
+
|
|
3601
|
+
/** @internal */
|
|
3602
|
+
const useResourceQrl = (qrl, opts) => {
|
|
3603
|
+
const { val, set, i, iCtx } = useSequentialScope();
|
|
3604
|
+
if (val != null) {
|
|
3605
|
+
return val;
|
|
3606
|
+
}
|
|
3607
|
+
assertQrl(qrl);
|
|
3608
|
+
const container = iCtx.$container$;
|
|
3609
|
+
const resource = createResourceReturn(container, opts);
|
|
3610
|
+
const el = iCtx.$hostElement$;
|
|
3611
|
+
const task = new Task(TaskFlags.DIRTY | TaskFlags.RESOURCE, i, el, qrl, resource, null);
|
|
3612
|
+
container.$scheduler$(ChoreType.TASK, task);
|
|
3613
|
+
set(resource);
|
|
3614
|
+
return resource;
|
|
3615
|
+
};
|
|
3616
|
+
// <docs markdown="../readme.md#useResource">
|
|
3617
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
3618
|
+
// (edit ../readme.md#useResource instead and run `pnpm docs.sync`)
|
|
3619
|
+
/**
|
|
3620
|
+
* This method works like an async memoized function that runs whenever some tracked value changes
|
|
3621
|
+
* and returns some data.
|
|
3622
|
+
*
|
|
3623
|
+
* `useResource` however returns immediate a `ResourceReturn` object that contains the data and a
|
|
3624
|
+
* state that indicates if the data is available or not.
|
|
3625
|
+
*
|
|
3626
|
+
* The status can be one of the following:
|
|
3627
|
+
*
|
|
3628
|
+
* - `pending` - the data is not yet available.
|
|
3629
|
+
* - `resolved` - the data is available.
|
|
3630
|
+
* - `rejected` - the data is not available due to an error or timeout.
|
|
3631
|
+
*
|
|
3632
|
+
* Be careful when using a `try/catch` statement in `useResource$`. If you catch the error and don't
|
|
3633
|
+
* re-throw it (or a new Error), the resource status will never be `rejected`.
|
|
3634
|
+
*
|
|
3635
|
+
* ### Example
|
|
3636
|
+
*
|
|
3637
|
+
* Example showing how `useResource` to perform a fetch to request the weather, whenever the input
|
|
3638
|
+
* city name changes.
|
|
3639
|
+
*
|
|
3640
|
+
* ```tsx
|
|
3641
|
+
* const Cmp = component$(() => {
|
|
3642
|
+
* const cityS = useSignal('');
|
|
3643
|
+
*
|
|
3644
|
+
* const weatherResource = useResource$(async ({ track, cleanup }) => {
|
|
3645
|
+
* const cityName = track(cityS);
|
|
3646
|
+
* const abortController = new AbortController();
|
|
3647
|
+
* cleanup(() => abortController.abort('cleanup'));
|
|
3648
|
+
* const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
|
|
3649
|
+
* signal: abortController.signal,
|
|
3650
|
+
* });
|
|
3651
|
+
* const data = await res.json();
|
|
3652
|
+
* return data as { temp: number };
|
|
3653
|
+
* });
|
|
3654
|
+
*
|
|
3655
|
+
* return (
|
|
3656
|
+
* <div>
|
|
3657
|
+
* <input name="city" bind:value={cityS} />
|
|
3658
|
+
* <Resource
|
|
3659
|
+
* value={weatherResource}
|
|
3660
|
+
* onResolved={(weather) => {
|
|
3661
|
+
* return <div>Temperature: {weather.temp}</div>;
|
|
3662
|
+
* }}
|
|
3663
|
+
* />
|
|
3664
|
+
* </div>
|
|
3665
|
+
* );
|
|
3666
|
+
* });
|
|
3667
|
+
* ```
|
|
3668
|
+
*
|
|
3669
|
+
* @public
|
|
3670
|
+
* @see Resource
|
|
3671
|
+
* @see ResourceReturn
|
|
3672
|
+
*/
|
|
3673
|
+
// </docs>
|
|
3674
|
+
const Resource = (props) => {
|
|
3675
|
+
// Resource path
|
|
3676
|
+
return _jsxSorted(Fragment, null, null, getResourceValueAsPromise(props), 0, null);
|
|
3677
|
+
};
|
|
3678
|
+
function getResourceValueAsPromise(props) {
|
|
3679
|
+
const resource = props.value;
|
|
3680
|
+
if (isResourceReturn(resource) && resource.value) {
|
|
3681
|
+
const isBrowser = !isServerPlatform();
|
|
3682
|
+
if (isBrowser) {
|
|
3683
|
+
// create a subscription for the resource._state changes
|
|
3684
|
+
const state = resource._state;
|
|
3685
|
+
if (state === 'pending' && props.onPending) {
|
|
3686
|
+
return Promise.resolve().then(useBindInvokeContext(props.onPending));
|
|
3687
|
+
}
|
|
3688
|
+
else if (state === 'rejected' && props.onRejected) {
|
|
3689
|
+
return Promise.resolve(resource._error).then(useBindInvokeContext(props.onRejected));
|
|
3690
|
+
}
|
|
3691
|
+
else {
|
|
3692
|
+
const resolvedValue = untrack(() => resource._resolved);
|
|
3693
|
+
if (resolvedValue !== undefined) {
|
|
3694
|
+
// resolved, pending without onPending prop or rejected without onRejected prop
|
|
3695
|
+
return Promise.resolve(resolvedValue).then(useBindInvokeContext(props.onResolved));
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
return resource.value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3700
|
+
}
|
|
3701
|
+
else if (isPromise(resource)) {
|
|
3702
|
+
return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3703
|
+
}
|
|
3704
|
+
else if (isSignal(resource)) {
|
|
3705
|
+
return Promise.resolve(resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3706
|
+
}
|
|
3707
|
+
else {
|
|
3708
|
+
return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
const _createResourceReturn = (opts) => {
|
|
3712
|
+
const resource = {
|
|
3713
|
+
__brand: 'resource',
|
|
3714
|
+
value: undefined,
|
|
3715
|
+
loading: isServerPlatform() ? false : true,
|
|
3716
|
+
_resolved: undefined,
|
|
3717
|
+
_error: undefined,
|
|
3718
|
+
_state: 'pending',
|
|
3719
|
+
_timeout: opts?.timeout ?? -1,
|
|
3720
|
+
_cache: 0,
|
|
3721
|
+
};
|
|
3722
|
+
return resource;
|
|
3723
|
+
};
|
|
3724
|
+
const createResourceReturn = (container, opts, initialPromise) => {
|
|
3725
|
+
const result = _createResourceReturn(opts);
|
|
3726
|
+
result.value = initialPromise;
|
|
3727
|
+
return createStore(container, result, StoreFlags.RECURSIVE);
|
|
3728
|
+
};
|
|
3729
|
+
const isResourceReturn = (obj) => {
|
|
3730
|
+
return isObject(obj) && (getStoreTarget(obj) || obj).__brand === 'resource';
|
|
3731
|
+
};
|
|
3732
|
+
const runResource = (task, container, host) => {
|
|
3733
|
+
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
3734
|
+
cleanupTask(task);
|
|
3735
|
+
const iCtx = newInvokeContext(container.$locale$, host, undefined, ResourceEvent);
|
|
3736
|
+
iCtx.$container$ = container;
|
|
3737
|
+
const taskFn = task.$qrl$.getFn(iCtx, () => clearAllEffects(container, task));
|
|
3738
|
+
const resource = task.$state$;
|
|
3739
|
+
assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
|
|
3740
|
+
const track = (obj, prop) => {
|
|
3741
|
+
const ctx = newInvokeContext();
|
|
3742
|
+
ctx.$effectSubscriber$ = getSubscriber(task, EffectProperty.COMPONENT);
|
|
3743
|
+
ctx.$container$ = container;
|
|
3744
|
+
return invoke(ctx, () => {
|
|
3745
|
+
if (isFunction(obj)) {
|
|
3746
|
+
return obj();
|
|
3747
|
+
}
|
|
3748
|
+
if (prop) {
|
|
3749
|
+
return obj[prop];
|
|
3750
|
+
}
|
|
3751
|
+
else if (isSignal(obj)) {
|
|
3752
|
+
return obj.value;
|
|
3753
|
+
}
|
|
3754
|
+
else {
|
|
3755
|
+
return obj;
|
|
3756
|
+
}
|
|
3757
|
+
});
|
|
3758
|
+
};
|
|
3759
|
+
const handleError = (reason) => container.handleError(reason, host);
|
|
3760
|
+
const cleanups = [];
|
|
3761
|
+
task.$destroy$ = noSerialize(() => {
|
|
3762
|
+
cleanups.forEach((fn) => {
|
|
3763
|
+
try {
|
|
3764
|
+
fn();
|
|
3765
|
+
}
|
|
3766
|
+
catch (err) {
|
|
3767
|
+
handleError(err);
|
|
3768
|
+
}
|
|
3769
|
+
});
|
|
3770
|
+
done = true;
|
|
3771
|
+
});
|
|
3772
|
+
const resourceTarget = unwrapStore(resource);
|
|
3773
|
+
const opts = {
|
|
3774
|
+
track,
|
|
3775
|
+
cleanup(fn) {
|
|
3776
|
+
if (typeof fn === 'function') {
|
|
3777
|
+
cleanups.push(fn);
|
|
3778
|
+
}
|
|
3779
|
+
},
|
|
3780
|
+
cache(policy) {
|
|
3781
|
+
let milliseconds = 0;
|
|
3782
|
+
if (policy === 'immutable') {
|
|
3783
|
+
milliseconds = Infinity;
|
|
3784
|
+
}
|
|
3785
|
+
else {
|
|
3786
|
+
milliseconds = policy;
|
|
3787
|
+
}
|
|
3788
|
+
resource._cache = milliseconds;
|
|
3789
|
+
},
|
|
3790
|
+
previous: resourceTarget._resolved,
|
|
3791
|
+
};
|
|
3792
|
+
let resolve;
|
|
3793
|
+
let reject;
|
|
3794
|
+
let done = false;
|
|
3795
|
+
const setState = (resolved, value) => {
|
|
3796
|
+
if (!done) {
|
|
3797
|
+
done = true;
|
|
3798
|
+
if (resolved) {
|
|
3799
|
+
done = true;
|
|
3800
|
+
resource.loading = false;
|
|
3801
|
+
resource._state = 'resolved';
|
|
3802
|
+
resource._resolved = value;
|
|
3803
|
+
resource._error = undefined;
|
|
3804
|
+
resolve(value);
|
|
3805
|
+
}
|
|
3806
|
+
else {
|
|
3807
|
+
done = true;
|
|
3808
|
+
resource.loading = false;
|
|
3809
|
+
resource._state = 'rejected';
|
|
3810
|
+
resource._error = value;
|
|
3811
|
+
reject(value);
|
|
3462
3812
|
}
|
|
3463
|
-
|
|
3813
|
+
return true;
|
|
3464
3814
|
}
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3815
|
+
return false;
|
|
3816
|
+
};
|
|
3817
|
+
/**
|
|
3818
|
+
* Add cleanup to resolve the resource if we are trying to run the same resource again while the
|
|
3819
|
+
* previous one is not resolved yet. The next `runResource` run will call this cleanup
|
|
3820
|
+
*/
|
|
3821
|
+
cleanups.push(() => {
|
|
3822
|
+
if (untrack(() => resource.loading) === true) {
|
|
3823
|
+
const value = untrack(() => resource._resolved);
|
|
3824
|
+
setState(true, value);
|
|
3468
3825
|
}
|
|
3469
|
-
}
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3826
|
+
});
|
|
3827
|
+
// Execute mutation inside empty invocation
|
|
3828
|
+
invoke(iCtx, () => {
|
|
3829
|
+
// console.log('RESOURCE.pending: ');
|
|
3830
|
+
resource._state = 'pending';
|
|
3831
|
+
resource.loading = !isServerPlatform();
|
|
3832
|
+
const promise = (resource.value = new Promise((r, re) => {
|
|
3833
|
+
resolve = r;
|
|
3834
|
+
reject = re;
|
|
3835
|
+
}));
|
|
3836
|
+
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
3837
|
+
});
|
|
3838
|
+
const promise = safeCall(() => Promise.resolve(taskFn(opts)), (value) => {
|
|
3839
|
+
setState(true, value);
|
|
3840
|
+
}, (err) => {
|
|
3841
|
+
if (isPromise(err)) {
|
|
3842
|
+
return err.then(() => runResource(task, container, host));
|
|
3481
3843
|
}
|
|
3844
|
+
else {
|
|
3845
|
+
setState(false, err);
|
|
3846
|
+
}
|
|
3847
|
+
});
|
|
3848
|
+
const timeout = resourceTarget._timeout;
|
|
3849
|
+
if (timeout > 0) {
|
|
3850
|
+
return Promise.race([
|
|
3851
|
+
promise,
|
|
3852
|
+
delay(timeout).then(() => {
|
|
3853
|
+
if (setState(false, new Error('timeout'))) {
|
|
3854
|
+
cleanupTask(task);
|
|
3855
|
+
}
|
|
3856
|
+
}),
|
|
3857
|
+
]);
|
|
3482
3858
|
}
|
|
3483
|
-
|
|
3484
|
-
function markVNodeAsDeleted(vCursor) {
|
|
3485
|
-
/**
|
|
3486
|
-
* Marks vCursor as deleted. We need to do this to prevent chores from running after the vnode is
|
|
3487
|
-
* removed. (for example signal subscriptions)
|
|
3488
|
-
*/
|
|
3489
|
-
vCursor[VNodeProps.flags] |= VNodeFlags.Deleted;
|
|
3490
|
-
}
|
|
3491
|
-
/**
|
|
3492
|
-
* This marks the property as immutable. It is needed for the QRLs so that QwikLoader can get a hold
|
|
3493
|
-
* of them. This character must be `:` so that the `vnode_getAttr` can ignore them.
|
|
3494
|
-
*/
|
|
3495
|
-
const HANDLER_PREFIX = ':';
|
|
3496
|
-
let count = 0;
|
|
3497
|
-
var SiblingsArray;
|
|
3498
|
-
(function (SiblingsArray) {
|
|
3499
|
-
SiblingsArray[SiblingsArray["Name"] = 0] = "Name";
|
|
3500
|
-
SiblingsArray[SiblingsArray["Key"] = 1] = "Key";
|
|
3501
|
-
SiblingsArray[SiblingsArray["VNode"] = 2] = "VNode";
|
|
3502
|
-
SiblingsArray[SiblingsArray["Size"] = 3] = "Size";
|
|
3503
|
-
SiblingsArray[SiblingsArray["NextVNode"] = 5] = "NextVNode";
|
|
3504
|
-
})(SiblingsArray || (SiblingsArray = {}));
|
|
3505
|
-
|
|
3506
|
-
// <docs markdown="../../readme.md#implicit$FirstArg">
|
|
3507
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
3508
|
-
// (edit ../../readme.md#implicit$FirstArg instead and run `pnpm docs.sync`)
|
|
3509
|
-
/**
|
|
3510
|
-
* Create a `____$(...)` convenience method from `___(...)`.
|
|
3511
|
-
*
|
|
3512
|
-
* It is very common for functions to take a lazy-loadable resource as a first argument. For this
|
|
3513
|
-
* reason, the Qwik Optimizer automatically extracts the first argument from any function which ends
|
|
3514
|
-
* in `$`.
|
|
3515
|
-
*
|
|
3516
|
-
* This means that `foo$(arg0)` and `foo($(arg0))` are equivalent with respect to Qwik Optimizer.
|
|
3517
|
-
* The former is just a shorthand for the latter.
|
|
3518
|
-
*
|
|
3519
|
-
* For example, these function calls are equivalent:
|
|
3520
|
-
*
|
|
3521
|
-
* - `component$(() => {...})` is same as `component($(() => {...}))`
|
|
3522
|
-
*
|
|
3523
|
-
* ```tsx
|
|
3524
|
-
* export function myApi(callback: QRL<() => void>): void {
|
|
3525
|
-
* // ...
|
|
3526
|
-
* }
|
|
3527
|
-
*
|
|
3528
|
-
* export const myApi$ = implicit$FirstArg(myApi);
|
|
3529
|
-
* // type of myApi$: (callback: () => void): void
|
|
3530
|
-
*
|
|
3531
|
-
* // can be used as:
|
|
3532
|
-
* myApi$(() => console.log('callback'));
|
|
3533
|
-
*
|
|
3534
|
-
* // will be transpiled to:
|
|
3535
|
-
* // FILE: <current file>
|
|
3536
|
-
* myApi(qrl('./chunk-abc.js', 'callback'));
|
|
3537
|
-
*
|
|
3538
|
-
* // FILE: chunk-abc.js
|
|
3539
|
-
* export const callback = () => console.log('callback');
|
|
3540
|
-
* ```
|
|
3541
|
-
*
|
|
3542
|
-
* @param fn - A function that should have its first argument automatically `$`.
|
|
3543
|
-
* @public
|
|
3544
|
-
*/
|
|
3545
|
-
// </docs>
|
|
3546
|
-
const implicit$FirstArg = (fn) => {
|
|
3547
|
-
return function (first, ...rest) {
|
|
3548
|
-
return fn.call(null, dollar(first), ...rest);
|
|
3549
|
-
};
|
|
3550
|
-
};
|
|
3551
|
-
|
|
3552
|
-
const createSignal$1 = (value) => {
|
|
3553
|
-
return new Signal(null, value);
|
|
3859
|
+
return promise;
|
|
3554
3860
|
};
|
|
3555
|
-
const
|
|
3556
|
-
|
|
3557
|
-
|
|
3861
|
+
const ignoreErrorToPreventNodeFromCrashing = (err) => {
|
|
3862
|
+
// ignore error to prevent node from crashing
|
|
3863
|
+
// node will crash in promise is rejected and no one is listening to the rejection.
|
|
3558
3864
|
};
|
|
3559
3865
|
|
|
3866
|
+
/// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
|
|
3867
|
+
const aVNodePath = [];
|
|
3868
|
+
const bVNodePath = [];
|
|
3560
3869
|
/**
|
|
3561
|
-
*
|
|
3562
|
-
* `undefined`.
|
|
3870
|
+
* Compare two VNodes and determine their document position relative to each other.
|
|
3563
3871
|
*
|
|
3564
|
-
* @
|
|
3872
|
+
* @param a VNode to compare
|
|
3873
|
+
* @param b VNode to compare
|
|
3874
|
+
* @param rootVNode - Root VNode of a container
|
|
3875
|
+
* @returns -1 if `a` is before `b`, 0 if `a` is the same as `b`, 1 if `a` is after `b`.
|
|
3565
3876
|
*/
|
|
3566
|
-
const
|
|
3567
|
-
|
|
3568
|
-
|
|
3877
|
+
const vnode_documentPosition = (a, b, rootVNode) => {
|
|
3878
|
+
if (a === b) {
|
|
3879
|
+
return 0;
|
|
3880
|
+
}
|
|
3881
|
+
let aDepth = -1;
|
|
3882
|
+
let bDepth = -1;
|
|
3883
|
+
while (a) {
|
|
3884
|
+
const vNode = (aVNodePath[++aDepth] = a);
|
|
3885
|
+
a = (vNode[VNodeProps.parent] ||
|
|
3886
|
+
(rootVNode && vnode_getProp(a, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
3887
|
+
}
|
|
3888
|
+
while (b) {
|
|
3889
|
+
const vNode = (bVNodePath[++bDepth] = b);
|
|
3890
|
+
b = (vNode[VNodeProps.parent] ||
|
|
3891
|
+
(rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
3892
|
+
}
|
|
3893
|
+
while (aDepth >= 0 && bDepth >= 0) {
|
|
3894
|
+
a = aVNodePath[aDepth];
|
|
3895
|
+
b = bVNodePath[bDepth];
|
|
3896
|
+
if (a === b) {
|
|
3897
|
+
// if the nodes are the same, we need to check the next level.
|
|
3898
|
+
aDepth--;
|
|
3899
|
+
bDepth--;
|
|
3900
|
+
}
|
|
3901
|
+
else {
|
|
3902
|
+
// We found a difference so we need to scan nodes at this level.
|
|
3903
|
+
let cursor = b;
|
|
3904
|
+
do {
|
|
3905
|
+
cursor = vnode_getNextSibling(cursor);
|
|
3906
|
+
if (cursor === a) {
|
|
3907
|
+
return 1;
|
|
3908
|
+
}
|
|
3909
|
+
} while (cursor);
|
|
3910
|
+
cursor = b;
|
|
3911
|
+
do {
|
|
3912
|
+
cursor = vnode_getPreviousSibling(cursor);
|
|
3913
|
+
if (cursor === a) {
|
|
3914
|
+
return -1;
|
|
3915
|
+
}
|
|
3916
|
+
} while (cursor);
|
|
3917
|
+
if (rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))) {
|
|
3918
|
+
// The "b" node is a projection, so we need to set it after "a" node,
|
|
3919
|
+
// because the "a" node could be a context provider.
|
|
3920
|
+
return -1;
|
|
3921
|
+
}
|
|
3922
|
+
// The node is not in the list of siblings, that means it must be disconnected.
|
|
3923
|
+
return 1;
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
return aDepth < bDepth ? -1 : 1;
|
|
3927
|
+
};
|
|
3928
|
+
/// These global variables are used to avoid creating new arrays for each call to `ssrNodeDocumentPosition`.
|
|
3929
|
+
const aSsrNodePath = [];
|
|
3930
|
+
const bSsrNodePath = [];
|
|
3569
3931
|
/**
|
|
3570
|
-
*
|
|
3571
|
-
*
|
|
3572
|
-
* recalculated.
|
|
3573
|
-
*
|
|
3574
|
-
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
3575
|
-
* effects, and it mus be synchronous.
|
|
3932
|
+
* Compare two SSR nodes and determine their document position relative to each other. Compares only
|
|
3933
|
+
* position between parent and child.
|
|
3576
3934
|
*
|
|
3577
|
-
*
|
|
3578
|
-
*
|
|
3579
|
-
* @
|
|
3935
|
+
* @param a SSR node to compare
|
|
3936
|
+
* @param b SSR node to compare
|
|
3937
|
+
* @returns -1 if `a` is before `b`, 0 if `a` is the same as `b`, 1 if `a` is after `b`.
|
|
3580
3938
|
*/
|
|
3581
|
-
const
|
|
3939
|
+
const ssrNodeDocumentPosition = (a, b) => {
|
|
3940
|
+
if (a === b) {
|
|
3941
|
+
return 0;
|
|
3942
|
+
}
|
|
3943
|
+
let aDepth = -1;
|
|
3944
|
+
let bDepth = -1;
|
|
3945
|
+
while (a) {
|
|
3946
|
+
const ssrNode = (aSsrNodePath[++aDepth] = a);
|
|
3947
|
+
a = ssrNode.currentComponentNode;
|
|
3948
|
+
}
|
|
3949
|
+
while (b) {
|
|
3950
|
+
const ssrNode = (bSsrNodePath[++bDepth] = b);
|
|
3951
|
+
b = ssrNode.currentComponentNode;
|
|
3952
|
+
}
|
|
3953
|
+
while (aDepth >= 0 && bDepth >= 0) {
|
|
3954
|
+
a = aSsrNodePath[aDepth];
|
|
3955
|
+
b = bSsrNodePath[bDepth];
|
|
3956
|
+
if (a === b) {
|
|
3957
|
+
// if the nodes are the same, we need to check the next level.
|
|
3958
|
+
aDepth--;
|
|
3959
|
+
bDepth--;
|
|
3960
|
+
}
|
|
3961
|
+
else {
|
|
3962
|
+
return 1;
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
return aDepth < bDepth ? -1 : 1;
|
|
3966
|
+
};
|
|
3582
3967
|
|
|
3583
3968
|
/**
|
|
3584
3969
|
* Scheduler is responsible for running application code in predictable order.
|
|
@@ -3661,38 +4046,29 @@ const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedQrl);
|
|
|
3661
4046
|
* - Visible Tasks are sorted afterJournalFlush, than depth first on component and finally in
|
|
3662
4047
|
* declaration order within component.
|
|
3663
4048
|
*/
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
ChoreType[ChoreType["MICRO"] = 15] = "MICRO";
|
|
3670
|
-
/** Ensure tha the QRL promise is resolved before processing next chores in the queue */
|
|
3671
|
-
ChoreType[ChoreType["QRL_RESOLVE"] = 1] = "QRL_RESOLVE";
|
|
3672
|
-
ChoreType[ChoreType["RESOURCE"] = 2] = "RESOURCE";
|
|
3673
|
-
ChoreType[ChoreType["TASK"] = 3] = "TASK";
|
|
3674
|
-
ChoreType[ChoreType["NODE_DIFF"] = 4] = "NODE_DIFF";
|
|
3675
|
-
ChoreType[ChoreType["NODE_PROP"] = 5] = "NODE_PROP";
|
|
3676
|
-
ChoreType[ChoreType["COMPONENT_SSR"] = 6] = "COMPONENT_SSR";
|
|
3677
|
-
ChoreType[ChoreType["COMPONENT"] = 7] = "COMPONENT";
|
|
3678
|
-
ChoreType[ChoreType["RECOMPUTE_AND_SCHEDULE_EFFECTS"] = 8] = "RECOMPUTE_AND_SCHEDULE_EFFECTS";
|
|
3679
|
-
ChoreType[ChoreType["JOURNAL_FLUSH"] = 16] = "JOURNAL_FLUSH";
|
|
3680
|
-
ChoreType[ChoreType["VISIBLE"] = 32] = "VISIBLE";
|
|
3681
|
-
ChoreType[ChoreType["CLEANUP_VISIBLE"] = 48] = "CLEANUP_VISIBLE";
|
|
3682
|
-
ChoreType[ChoreType["WAIT_FOR_ALL"] = 255] = "WAIT_FOR_ALL";
|
|
3683
|
-
})(ChoreType || (ChoreType = {}));
|
|
4049
|
+
// Turn this on to get debug output of what the scheduler is doing.
|
|
4050
|
+
const DEBUG$1 = false;
|
|
4051
|
+
const getPromise = (chore) => (chore.$promise$ ||= new Promise((resolve) => {
|
|
4052
|
+
chore.$resolve$ = resolve;
|
|
4053
|
+
}));
|
|
3684
4054
|
const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
3685
4055
|
const choreQueue = [];
|
|
4056
|
+
const qrlRuns = [];
|
|
3686
4057
|
let currentChore = null;
|
|
3687
|
-
let
|
|
4058
|
+
let drainScheduled = false;
|
|
3688
4059
|
return schedule;
|
|
3689
4060
|
///// IMPLEMENTATION /////
|
|
3690
4061
|
function schedule(type, hostOrTask = null, targetOrQrl = null, payload = null) {
|
|
3691
|
-
const
|
|
3692
|
-
const
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
4062
|
+
const isServer = !isDomContainer(container);
|
|
4063
|
+
const isComponentSsr = isServer && type === ChoreType.COMPONENT;
|
|
4064
|
+
const runLater = type !== ChoreType.WAIT_FOR_ALL && !isComponentSsr && type !== ChoreType.RUN_QRL;
|
|
4065
|
+
const isTask = type === ChoreType.TASK || type === ChoreType.VISIBLE || type === ChoreType.CLEANUP_VISIBLE;
|
|
4066
|
+
const isClientOnly = type === ChoreType.JOURNAL_FLUSH ||
|
|
4067
|
+
type === ChoreType.NODE_DIFF ||
|
|
4068
|
+
type === ChoreType.NODE_PROP;
|
|
4069
|
+
if (isServer && isClientOnly) {
|
|
4070
|
+
return;
|
|
4071
|
+
}
|
|
3696
4072
|
if (isTask) {
|
|
3697
4073
|
hostOrTask.$flags$ |= TaskFlags.DIRTY;
|
|
3698
4074
|
}
|
|
@@ -3711,184 +4087,234 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
3711
4087
|
$returnValue$: null,
|
|
3712
4088
|
$executed$: false,
|
|
3713
4089
|
};
|
|
3714
|
-
chore.$promise$ = new Promise((resolve) => (chore.$resolve$ = resolve));
|
|
3715
4090
|
chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
|
|
3716
|
-
if (!
|
|
4091
|
+
if (!drainScheduled && runLater) {
|
|
3717
4092
|
// If we are not currently draining, we need to schedule a drain.
|
|
3718
|
-
|
|
4093
|
+
drainScheduled = true;
|
|
3719
4094
|
schedule(ChoreType.JOURNAL_FLUSH);
|
|
3720
|
-
|
|
4095
|
+
// Catch here to avoid unhandled promise rejection
|
|
4096
|
+
scheduleDrain()?.catch?.(() => { });
|
|
3721
4097
|
}
|
|
4098
|
+
// TODO figure out what to do with chore errors
|
|
3722
4099
|
if (runLater) {
|
|
3723
|
-
return chore
|
|
4100
|
+
return getPromise(chore);
|
|
3724
4101
|
}
|
|
3725
4102
|
else {
|
|
3726
|
-
return drainUpTo(chore,
|
|
3727
|
-
}
|
|
3728
|
-
}
|
|
3729
|
-
/**
|
|
3730
|
-
* Execute all of the chores up to and including the given chore.
|
|
3731
|
-
*
|
|
3732
|
-
* @param runUptoChore
|
|
3733
|
-
*/
|
|
3734
|
-
function drainUpTo(runUptoChore, rootVNode) {
|
|
3735
|
-
// If it already ran, it's not in the queue
|
|
3736
|
-
if (runUptoChore.$executed$) {
|
|
3737
|
-
return runUptoChore.$returnValue$;
|
|
3738
|
-
}
|
|
3739
|
-
if (currentChore) {
|
|
3740
|
-
// Already running chore, which means we're waiting for async completion
|
|
3741
|
-
return runUptoChore.$promise$;
|
|
4103
|
+
return drainUpTo(chore, isServer);
|
|
3742
4104
|
}
|
|
4105
|
+
}
|
|
4106
|
+
/** Execute all of the chores up to and including the given chore. */
|
|
4107
|
+
function drainUpTo(runUptoChore, isServer) {
|
|
4108
|
+
let maxRetries = 5000;
|
|
3743
4109
|
while (choreQueue.length) {
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
if (order === null) {
|
|
3747
|
-
continue;
|
|
4110
|
+
if (maxRetries-- < 0) {
|
|
4111
|
+
throw new Error('drainUpTo: max retries reached');
|
|
3748
4112
|
}
|
|
3749
|
-
if (
|
|
3750
|
-
//
|
|
3751
|
-
|
|
4113
|
+
if (currentChore) {
|
|
4114
|
+
// Already running chore, which means we're waiting for async completion
|
|
4115
|
+
return getPromise(currentChore)
|
|
4116
|
+
.then(() => drainUpTo(runUptoChore, isServer))
|
|
4117
|
+
.catch((e) => {
|
|
4118
|
+
container.handleError(e, currentChore?.$host$);
|
|
4119
|
+
});
|
|
4120
|
+
}
|
|
4121
|
+
const nextChore = choreQueue[0];
|
|
4122
|
+
if (nextChore.$executed$) {
|
|
4123
|
+
choreQueue.shift();
|
|
4124
|
+
if (nextChore === runUptoChore) {
|
|
4125
|
+
break;
|
|
4126
|
+
}
|
|
4127
|
+
continue;
|
|
3752
4128
|
}
|
|
3753
|
-
|
|
3754
|
-
if (isDeletedVNode &&
|
|
4129
|
+
if (vNodeAlreadyDeleted(nextChore) &&
|
|
3755
4130
|
// we need to process cleanup tasks for deleted nodes
|
|
3756
4131
|
nextChore.$type$ !== ChoreType.CLEANUP_VISIBLE) {
|
|
4132
|
+
choreQueue.shift();
|
|
3757
4133
|
continue;
|
|
3758
4134
|
}
|
|
3759
|
-
|
|
3760
|
-
if (isPromise(returnValue)) {
|
|
3761
|
-
const promise = returnValue.then(() => drainUpTo(runUptoChore, rootVNode));
|
|
3762
|
-
return promise;
|
|
3763
|
-
}
|
|
4135
|
+
executeChore(nextChore, isServer);
|
|
3764
4136
|
}
|
|
3765
4137
|
return runUptoChore.$returnValue$;
|
|
3766
4138
|
}
|
|
3767
|
-
function executeChore(chore) {
|
|
4139
|
+
function executeChore(chore, isServer) {
|
|
3768
4140
|
const host = chore.$host$;
|
|
3769
4141
|
assertEqual(currentChore, null, 'Chore already running.');
|
|
3770
4142
|
currentChore = chore;
|
|
3771
4143
|
let returnValue = null;
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
3780
|
-
if (chore.$type$ === ChoreType.COMPONENT) {
|
|
3781
|
-
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
3782
|
-
return vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId));
|
|
4144
|
+
try {
|
|
4145
|
+
switch (chore.$type$) {
|
|
4146
|
+
case ChoreType.WAIT_FOR_ALL:
|
|
4147
|
+
{
|
|
4148
|
+
if (isServer) {
|
|
4149
|
+
drainScheduled = false;
|
|
4150
|
+
}
|
|
3783
4151
|
}
|
|
3784
|
-
|
|
3785
|
-
|
|
4152
|
+
break;
|
|
4153
|
+
case ChoreType.JOURNAL_FLUSH:
|
|
4154
|
+
{
|
|
4155
|
+
returnValue = journalFlush();
|
|
4156
|
+
drainScheduled = false;
|
|
4157
|
+
}
|
|
4158
|
+
break;
|
|
4159
|
+
case ChoreType.COMPONENT:
|
|
4160
|
+
{
|
|
4161
|
+
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
4162
|
+
if (isServer) {
|
|
4163
|
+
return jsx;
|
|
4164
|
+
}
|
|
4165
|
+
else {
|
|
4166
|
+
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
4167
|
+
return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
|
|
4168
|
+
}
|
|
4169
|
+
}, (err) => container.handleError(err, host));
|
|
4170
|
+
}
|
|
4171
|
+
break;
|
|
4172
|
+
case ChoreType.RUN_QRL:
|
|
4173
|
+
{
|
|
4174
|
+
const fn = chore.$target$.getFn();
|
|
4175
|
+
const result = retryOnPromise(() => fn(...chore.$payload$));
|
|
4176
|
+
if (isPromise(result)) {
|
|
4177
|
+
const handled = result
|
|
4178
|
+
.finally(() => {
|
|
4179
|
+
qrlRuns.splice(qrlRuns.indexOf(handled), 1);
|
|
4180
|
+
})
|
|
4181
|
+
.catch((error) => {
|
|
4182
|
+
container.handleError(error, chore.$host$);
|
|
4183
|
+
});
|
|
4184
|
+
// Don't wait for the promise to resolve
|
|
4185
|
+
// TODO come up with a better solution, we also want concurrent signal handling with tasks but serial tasks
|
|
4186
|
+
qrlRuns.push(handled);
|
|
4187
|
+
DEBUG$1 &&
|
|
4188
|
+
debugTrace('execute.DONE (but still running)', chore, currentChore, choreQueue);
|
|
4189
|
+
chore.$returnValue$ = handled;
|
|
4190
|
+
chore.$resolve$?.(handled);
|
|
4191
|
+
currentChore = null;
|
|
4192
|
+
chore.$executed$ = true;
|
|
4193
|
+
// early out so we don't call after()
|
|
4194
|
+
return;
|
|
4195
|
+
}
|
|
4196
|
+
returnValue = null;
|
|
4197
|
+
}
|
|
4198
|
+
break;
|
|
4199
|
+
case ChoreType.TASK:
|
|
4200
|
+
case ChoreType.VISIBLE:
|
|
4201
|
+
{
|
|
4202
|
+
const payload = chore.$payload$;
|
|
4203
|
+
if (payload.$flags$ & TaskFlags.RESOURCE) {
|
|
4204
|
+
const result = runResource(payload, container, host);
|
|
4205
|
+
// Don't await the return value of the resource, because async resources should not be awaited.
|
|
4206
|
+
// The reason for this is that we should be able to update for example a node with loading
|
|
4207
|
+
// text. If we await the resource, the loading text will not be displayed until the resource
|
|
4208
|
+
// is loaded.
|
|
4209
|
+
// Awaiting on the client also causes a deadlock.
|
|
4210
|
+
// In any case, the resource will never throw.
|
|
4211
|
+
returnValue = isServer ? result : null;
|
|
4212
|
+
}
|
|
4213
|
+
else {
|
|
4214
|
+
returnValue = runTask(payload, container, host);
|
|
4215
|
+
}
|
|
4216
|
+
}
|
|
4217
|
+
break;
|
|
4218
|
+
case ChoreType.CLEANUP_VISIBLE:
|
|
4219
|
+
{
|
|
4220
|
+
const task = chore.$payload$;
|
|
4221
|
+
cleanupTask(task);
|
|
4222
|
+
}
|
|
4223
|
+
break;
|
|
4224
|
+
case ChoreType.NODE_DIFF:
|
|
4225
|
+
{
|
|
4226
|
+
const parentVirtualNode = chore.$target$;
|
|
4227
|
+
let jsx = chore.$payload$;
|
|
4228
|
+
if (isSignal(jsx)) {
|
|
4229
|
+
jsx = jsx.value;
|
|
4230
|
+
}
|
|
4231
|
+
returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
|
|
4232
|
+
}
|
|
4233
|
+
break;
|
|
4234
|
+
case ChoreType.NODE_PROP:
|
|
4235
|
+
{
|
|
4236
|
+
const virtualNode = chore.$host$;
|
|
4237
|
+
const payload = chore.$payload$;
|
|
4238
|
+
let value = payload.$value$;
|
|
4239
|
+
if (isSignal(value)) {
|
|
4240
|
+
value = value.value;
|
|
4241
|
+
}
|
|
4242
|
+
const isConst = payload.$isConst$;
|
|
4243
|
+
const journal = container.$journal$;
|
|
4244
|
+
const property = chore.$idx$;
|
|
4245
|
+
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
4246
|
+
if (isConst) {
|
|
4247
|
+
const element = virtualNode[ElementVNodeProps.element];
|
|
4248
|
+
journal.push(VNodeJournalOpCode.SetAttribute, element, property, serializedValue);
|
|
4249
|
+
}
|
|
4250
|
+
else {
|
|
4251
|
+
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
4252
|
+
}
|
|
4253
|
+
}
|
|
4254
|
+
break;
|
|
4255
|
+
case ChoreType.QRL_RESOLVE: {
|
|
4256
|
+
{
|
|
4257
|
+
const target = chore.$target$;
|
|
4258
|
+
returnValue = !target.resolved ? target.resolve() : null;
|
|
3786
4259
|
}
|
|
3787
|
-
}, (err) => container.handleError(err, host));
|
|
3788
|
-
break;
|
|
3789
|
-
case ChoreType.RESOURCE:
|
|
3790
|
-
// Don't await the return value of the resource, because async resources should not be awaited.
|
|
3791
|
-
// The reason for this is that we should be able to update for example a node with loading
|
|
3792
|
-
// text. If we await the resource, the loading text will not be displayed until the resource
|
|
3793
|
-
// is loaded.
|
|
3794
|
-
const result = runResource(chore.$payload$, container, host);
|
|
3795
|
-
returnValue = isDomContainer(container) ? null : result;
|
|
3796
|
-
break;
|
|
3797
|
-
case ChoreType.TASK:
|
|
3798
|
-
returnValue = runTask(chore.$payload$, container, host);
|
|
3799
|
-
break;
|
|
3800
|
-
case ChoreType.VISIBLE:
|
|
3801
|
-
returnValue = runTask(chore.$payload$, container, host);
|
|
3802
|
-
break;
|
|
3803
|
-
case ChoreType.CLEANUP_VISIBLE:
|
|
3804
|
-
const task = chore.$payload$;
|
|
3805
|
-
cleanupTask(task);
|
|
3806
|
-
break;
|
|
3807
|
-
case ChoreType.NODE_DIFF:
|
|
3808
|
-
const parentVirtualNode = chore.$target$;
|
|
3809
|
-
let jsx = chore.$payload$;
|
|
3810
|
-
if (isSignal(jsx)) {
|
|
3811
|
-
jsx = jsx.value;
|
|
3812
|
-
}
|
|
3813
|
-
returnValue = vnode_diff(container, jsx, parentVirtualNode, null);
|
|
3814
|
-
break;
|
|
3815
|
-
case ChoreType.NODE_PROP:
|
|
3816
|
-
const virtualNode = chore.$host$;
|
|
3817
|
-
const payload = chore.$payload$;
|
|
3818
|
-
let value = payload.$value$;
|
|
3819
|
-
if (isSignal(value)) {
|
|
3820
|
-
value = value.value;
|
|
3821
|
-
}
|
|
3822
|
-
const isConst = payload.$isConst$;
|
|
3823
|
-
const journal = container.$journal$;
|
|
3824
|
-
const property = chore.$idx$;
|
|
3825
|
-
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
3826
|
-
if (isConst) {
|
|
3827
|
-
const element = virtualNode[ElementVNodeProps.element];
|
|
3828
|
-
journal.push(VNodeJournalOpCode.SetAttribute, element, property, serializedValue);
|
|
3829
|
-
}
|
|
3830
|
-
else {
|
|
3831
|
-
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
3832
|
-
}
|
|
3833
|
-
break;
|
|
3834
|
-
case ChoreType.QRL_RESOLVE: {
|
|
3835
|
-
const target = chore.$target$;
|
|
3836
|
-
returnValue = !target.resolved ? target.resolve() : null;
|
|
3837
|
-
break;
|
|
3838
|
-
}
|
|
3839
|
-
case ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS: {
|
|
3840
|
-
const target = chore.$target$;
|
|
3841
|
-
const forceRunEffects = target.$forceRunEffects$;
|
|
3842
|
-
target.$forceRunEffects$ = false;
|
|
3843
|
-
if (!target.$effects$?.length) {
|
|
3844
4260
|
break;
|
|
3845
4261
|
}
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
4262
|
+
case ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS: {
|
|
4263
|
+
{
|
|
4264
|
+
const target = chore.$target$;
|
|
4265
|
+
const forceRunEffects = target.$forceRunEffects$;
|
|
4266
|
+
target.$forceRunEffects$ = false;
|
|
4267
|
+
if (!target.$effects$?.size) {
|
|
4268
|
+
break;
|
|
4269
|
+
}
|
|
4270
|
+
returnValue = retryOnPromise(() => {
|
|
4271
|
+
if (target.$computeIfNeeded$() || forceRunEffects) {
|
|
4272
|
+
triggerEffects(container, target, target.$effects$);
|
|
4273
|
+
}
|
|
4274
|
+
});
|
|
3849
4275
|
}
|
|
3850
|
-
|
|
3851
|
-
|
|
4276
|
+
break;
|
|
4277
|
+
}
|
|
3852
4278
|
}
|
|
3853
4279
|
}
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
}
|
|
4280
|
+
catch (e) {
|
|
4281
|
+
returnValue = Promise.reject(e);
|
|
4282
|
+
}
|
|
4283
|
+
const after = (value, error) => {
|
|
3859
4284
|
currentChore = null;
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
}
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
}
|
|
3877
|
-
function vNodeAlreadyDeleted(chore) {
|
|
3878
|
-
return !!(chore.$host$ &&
|
|
3879
|
-
vnode_isVNode(chore.$host$) &&
|
|
3880
|
-
chore.$host$[VNodeProps.flags] & VNodeFlags.Deleted);
|
|
3881
|
-
}
|
|
3882
|
-
function choreComparator(a, b, rootVNode, shouldThrowOnHostMismatch) {
|
|
3883
|
-
const macroTypeDiff = (a.$type$ & ChoreType.MACRO) - (b.$type$ & ChoreType.MACRO);
|
|
3884
|
-
if (macroTypeDiff !== 0) {
|
|
3885
|
-
return macroTypeDiff;
|
|
4285
|
+
chore.$executed$ = true;
|
|
4286
|
+
if (error) {
|
|
4287
|
+
container.handleError(error, host);
|
|
4288
|
+
}
|
|
4289
|
+
else {
|
|
4290
|
+
chore.$returnValue$ = value;
|
|
4291
|
+
chore.$resolve$?.(value);
|
|
4292
|
+
}
|
|
4293
|
+
};
|
|
4294
|
+
if (isPromise(returnValue)) {
|
|
4295
|
+
chore.$promise$ = returnValue.then(after, (error) => after(undefined, error));
|
|
4296
|
+
chore.$resolve$?.(chore.$promise$);
|
|
4297
|
+
chore.$resolve$ = undefined;
|
|
4298
|
+
}
|
|
4299
|
+
else {
|
|
4300
|
+
after(returnValue);
|
|
4301
|
+
}
|
|
3886
4302
|
}
|
|
3887
|
-
|
|
3888
|
-
|
|
4303
|
+
/**
|
|
4304
|
+
* Compares two chores to determine their execution order in the scheduler's queue.
|
|
4305
|
+
*
|
|
4306
|
+
* @param a - The first chore to compare
|
|
4307
|
+
* @param b - The second chore to compare
|
|
4308
|
+
* @returns A number indicating the relative order of the chores. A negative number means `a` runs
|
|
4309
|
+
* before `b`.
|
|
4310
|
+
*/
|
|
4311
|
+
function choreComparator(a, b, rootVNode) {
|
|
4312
|
+
const macroTypeDiff = (a.$type$ & ChoreType.MACRO) - (b.$type$ & ChoreType.MACRO);
|
|
4313
|
+
if (macroTypeDiff !== 0) {
|
|
4314
|
+
return macroTypeDiff;
|
|
4315
|
+
}
|
|
3889
4316
|
const aHost = a.$host$;
|
|
3890
4317
|
const bHost = b.$host$;
|
|
3891
|
-
// QRL_RESOLVE does not have a host.
|
|
3892
4318
|
if (aHost !== bHost && aHost !== null && bHost !== null) {
|
|
3893
4319
|
if (vnode_isVNode(aHost) && vnode_isVNode(bHost)) {
|
|
3894
4320
|
// we are running on the client.
|
|
@@ -3898,6 +4324,8 @@ function choreComparator(a, b, rootVNode, shouldThrowOnHostMismatch) {
|
|
|
3898
4324
|
}
|
|
3899
4325
|
}
|
|
3900
4326
|
else {
|
|
4327
|
+
assertFalse(vnode_isVNode(aHost), 'expected aHost to be SSRNode but it is a VNode');
|
|
4328
|
+
assertFalse(vnode_isVNode(bHost), 'expected bHost to be SSRNode but it is a VNode');
|
|
3901
4329
|
// we are running on the server.
|
|
3902
4330
|
// On server we can't schedule task for a different host!
|
|
3903
4331
|
// Server is SSR, and therefore scheduling for anything but the current host
|
|
@@ -3906,258 +4334,125 @@ function choreComparator(a, b, rootVNode, shouldThrowOnHostMismatch) {
|
|
|
3906
4334
|
You are attempting to change a state that has already been streamed to the client.
|
|
3907
4335
|
This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
|
|
3908
4336
|
Problematic Node: ${aHost.toString()}`;
|
|
3909
|
-
if (shouldThrowOnHostMismatch) {
|
|
3910
|
-
throw qError(QError.serverHostMismatch, [errorMessage]);
|
|
3911
|
-
}
|
|
3912
4337
|
logWarn(errorMessage);
|
|
3913
|
-
|
|
4338
|
+
const hostDiff = ssrNodeDocumentPosition(aHost, bHost);
|
|
4339
|
+
if (hostDiff !== 0) {
|
|
4340
|
+
return hostDiff;
|
|
4341
|
+
}
|
|
3914
4342
|
}
|
|
3915
4343
|
}
|
|
3916
4344
|
const microTypeDiff = (a.$type$ & ChoreType.MICRO) - (b.$type$ & ChoreType.MICRO);
|
|
3917
4345
|
if (microTypeDiff !== 0) {
|
|
3918
4346
|
return microTypeDiff;
|
|
3919
4347
|
}
|
|
4348
|
+
// types are the same
|
|
3920
4349
|
const idxDiff = toNumber(a.$idx$) - toNumber(b.$idx$);
|
|
3921
4350
|
if (idxDiff !== 0) {
|
|
3922
4351
|
return idxDiff;
|
|
3923
4352
|
}
|
|
3924
|
-
// If the host is the same, we need to compare the target.
|
|
3925
|
-
if (a.$target$ !== b.$target$
|
|
3926
|
-
((a.$type$ === ChoreType.QRL_RESOLVE && b.$type$ === ChoreType.QRL_RESOLVE) ||
|
|
3927
|
-
(a.$type$ === ChoreType.NODE_PROP && b.$type$ === ChoreType.NODE_PROP) ||
|
|
3928
|
-
(a.$type$ === ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS &&
|
|
3929
|
-
b.$type$ === ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS))) {
|
|
4353
|
+
// If the host is the same (or missing), and the type is the same, we need to compare the target.
|
|
4354
|
+
if (a.$target$ !== b.$target$ || a.$payload$ !== b.$payload$) {
|
|
3930
4355
|
// 1 means that we are going to process chores as FIFO
|
|
3931
4356
|
return 1;
|
|
3932
4357
|
}
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
function sortedFindIndex(sortedArray, value, rootVNode) {
|
|
3937
|
-
/// We need to ensure that the `queue` is sorted by priority.
|
|
3938
|
-
/// 1. Find a place where to insert into.
|
|
3939
|
-
let bottom = 0;
|
|
3940
|
-
let top = sortedArray.length;
|
|
3941
|
-
while (bottom < top) {
|
|
3942
|
-
const middle = bottom + ((top - bottom) >> 1);
|
|
3943
|
-
const midChore = sortedArray[middle];
|
|
3944
|
-
const comp = choreComparator(value, midChore, rootVNode, true);
|
|
3945
|
-
if (comp < 0) {
|
|
3946
|
-
top = middle;
|
|
3947
|
-
}
|
|
3948
|
-
else if (comp > 0) {
|
|
3949
|
-
bottom = middle + 1;
|
|
3950
|
-
}
|
|
3951
|
-
else {
|
|
3952
|
-
// We already have the host in the queue.
|
|
3953
|
-
return middle;
|
|
4358
|
+
// If the chore is the same as the current chore, we will run it again
|
|
4359
|
+
if (b === currentChore) {
|
|
4360
|
+
return 1;
|
|
3954
4361
|
}
|
|
4362
|
+
// The chores are the same and will run only once
|
|
4363
|
+
return 0;
|
|
3955
4364
|
}
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
}
|
|
3971
|
-
|
|
3972
|
-
// <docs markdown="../readme.md#useLexicalScope">
|
|
3973
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
3974
|
-
// (edit ../readme.md#useLexicalScope instead and run `pnpm docs.sync`)
|
|
3975
|
-
/**
|
|
3976
|
-
* Used by the Qwik Optimizer to restore the lexically scoped variables.
|
|
3977
|
-
*
|
|
3978
|
-
* This method should not be present in the application source code.
|
|
3979
|
-
*
|
|
3980
|
-
* NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
|
|
3981
|
-
* (before any `await` statements.)
|
|
3982
|
-
*
|
|
3983
|
-
* @internal
|
|
3984
|
-
*/
|
|
3985
|
-
// </docs>
|
|
3986
|
-
const useLexicalScope = () => {
|
|
3987
|
-
const context = getInvokeContext();
|
|
3988
|
-
let qrl = context.$qrl$;
|
|
3989
|
-
if (!qrl) {
|
|
3990
|
-
const el = context.$element$;
|
|
3991
|
-
assertDefined(el, 'invoke: element must be defined inside useLexicalScope()', context);
|
|
3992
|
-
const containerElement = _getQContainerElement(el);
|
|
3993
|
-
assertDefined(containerElement, `invoke: cant find parent q:container of`, el);
|
|
3994
|
-
const container = getDomContainer(containerElement);
|
|
3995
|
-
qrl = container.parseQRL(decodeURIComponent(String(context.$url$)));
|
|
3996
|
-
}
|
|
3997
|
-
else {
|
|
3998
|
-
assertQrl(qrl);
|
|
3999
|
-
assertDefined(qrl.$captureRef$, 'invoke: qrl $captureRef$ must be defined inside useLexicalScope()', qrl);
|
|
4000
|
-
}
|
|
4001
|
-
return qrl.$captureRef$;
|
|
4002
|
-
};
|
|
4003
|
-
|
|
4004
|
-
var TaskFlags;
|
|
4005
|
-
(function (TaskFlags) {
|
|
4006
|
-
TaskFlags[TaskFlags["VISIBLE_TASK"] = 1] = "VISIBLE_TASK";
|
|
4007
|
-
TaskFlags[TaskFlags["TASK"] = 2] = "TASK";
|
|
4008
|
-
TaskFlags[TaskFlags["RESOURCE"] = 4] = "RESOURCE";
|
|
4009
|
-
TaskFlags[TaskFlags["DIRTY"] = 8] = "DIRTY";
|
|
4010
|
-
})(TaskFlags || (TaskFlags = {}));
|
|
4011
|
-
/** @internal */
|
|
4012
|
-
const useTaskQrl = (qrl, opts) => {
|
|
4013
|
-
const { val, set, iCtx, i } = useSequentialScope();
|
|
4014
|
-
if (val) {
|
|
4015
|
-
return;
|
|
4016
|
-
}
|
|
4017
|
-
assertQrl(qrl);
|
|
4018
|
-
set(1);
|
|
4019
|
-
const host = iCtx.$hostElement$;
|
|
4020
|
-
const task = new Task(TaskFlags.DIRTY | TaskFlags.TASK, i, iCtx.$hostElement$, qrl, undefined, null);
|
|
4021
|
-
// In V2 we add the task to the sequential scope. We need to do this
|
|
4022
|
-
// in order to be able to retrieve it later when the parent element is
|
|
4023
|
-
// deleted and we need to be able to release the task subscriptions.
|
|
4024
|
-
set(task);
|
|
4025
|
-
const result = runTask(task, iCtx.$container$, host);
|
|
4026
|
-
if (isPromise(result)) {
|
|
4027
|
-
throw result;
|
|
4028
|
-
}
|
|
4029
|
-
qrl.$resolveLazy$(iCtx.$element$);
|
|
4030
|
-
if (isServerPlatform()) {
|
|
4031
|
-
useRunTask(task, opts?.eagerness);
|
|
4032
|
-
}
|
|
4033
|
-
};
|
|
4034
|
-
const runTask = (task, container, host) => {
|
|
4035
|
-
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
4036
|
-
cleanupTask(task);
|
|
4037
|
-
const iCtx = newInvokeContext(container.$locale$, host, undefined, TaskEvent);
|
|
4038
|
-
iCtx.$container$ = container;
|
|
4039
|
-
const taskFn = task.$qrl$.getFn(iCtx, () => clearSubscriberEffectDependencies(container, task));
|
|
4040
|
-
const track = (obj, prop) => {
|
|
4041
|
-
const ctx = newInvokeContext();
|
|
4042
|
-
ctx.$effectSubscriber$ = [task, EffectProperty.COMPONENT];
|
|
4043
|
-
ctx.$container$ = container;
|
|
4044
|
-
return invoke(ctx, () => {
|
|
4045
|
-
if (isFunction(obj)) {
|
|
4046
|
-
return obj();
|
|
4047
|
-
}
|
|
4048
|
-
if (prop) {
|
|
4049
|
-
return obj[prop];
|
|
4050
|
-
}
|
|
4051
|
-
else if (isSignal(obj)) {
|
|
4052
|
-
return obj.value;
|
|
4365
|
+
function sortedFindIndex(sortedArray, value, rootVNode) {
|
|
4366
|
+
/// We need to ensure that the `queue` is sorted by priority.
|
|
4367
|
+
/// 1. Find a place where to insert into.
|
|
4368
|
+
let bottom = 0;
|
|
4369
|
+
let top = sortedArray.length;
|
|
4370
|
+
while (bottom < top) {
|
|
4371
|
+
const middle = bottom + ((top - bottom) >> 1);
|
|
4372
|
+
const midChore = sortedArray[middle];
|
|
4373
|
+
const comp = choreComparator(value, midChore, rootVNode);
|
|
4374
|
+
if (comp < 0) {
|
|
4375
|
+
top = middle;
|
|
4376
|
+
}
|
|
4377
|
+
else if (comp > 0) {
|
|
4378
|
+
bottom = middle + 1;
|
|
4053
4379
|
}
|
|
4054
4380
|
else {
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
});
|
|
4058
|
-
};
|
|
4059
|
-
const handleError = (reason) => container.handleError(reason, host);
|
|
4060
|
-
let cleanupFns = null;
|
|
4061
|
-
const cleanup = (fn) => {
|
|
4062
|
-
if (typeof fn == 'function') {
|
|
4063
|
-
if (!cleanupFns) {
|
|
4064
|
-
cleanupFns = [];
|
|
4065
|
-
task.$destroy$ = noSerialize(() => {
|
|
4066
|
-
task.$destroy$ = null;
|
|
4067
|
-
cleanupFns.forEach((fn) => {
|
|
4068
|
-
try {
|
|
4069
|
-
fn();
|
|
4070
|
-
}
|
|
4071
|
-
catch (err) {
|
|
4072
|
-
handleError(err);
|
|
4073
|
-
}
|
|
4074
|
-
});
|
|
4075
|
-
});
|
|
4381
|
+
// We already have the host in the queue.
|
|
4382
|
+
return middle;
|
|
4076
4383
|
}
|
|
4077
|
-
cleanupFns.push(fn);
|
|
4078
|
-
}
|
|
4079
|
-
};
|
|
4080
|
-
const taskApi = { track, cleanup };
|
|
4081
|
-
const result = safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
4082
|
-
if (isPromise(err)) {
|
|
4083
|
-
return err.then(() => runTask(task, container, host));
|
|
4084
|
-
}
|
|
4085
|
-
else {
|
|
4086
|
-
return handleError(err);
|
|
4087
4384
|
}
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4385
|
+
return ~bottom;
|
|
4386
|
+
}
|
|
4387
|
+
function sortedInsert(sortedArray, value, rootVNode) {
|
|
4388
|
+
/// We need to ensure that the `queue` is sorted by priority.
|
|
4389
|
+
/// 1. Find a place where to insert into.
|
|
4390
|
+
const idx = sortedFindIndex(sortedArray, value, rootVNode);
|
|
4391
|
+
if (idx < 0) {
|
|
4392
|
+
/// 2. Insert the chore into the queue.
|
|
4393
|
+
sortedArray.splice(~idx, 0, value);
|
|
4394
|
+
return value;
|
|
4097
4395
|
}
|
|
4098
|
-
|
|
4099
|
-
|
|
4396
|
+
const existing = sortedArray[idx];
|
|
4397
|
+
/**
|
|
4398
|
+
* When a derived signal is updated we need to run vnode_diff. However the signal can update
|
|
4399
|
+
* multiple times during component execution. For this reason it is necessary for us to update
|
|
4400
|
+
* the chore with the latest result of the signal.
|
|
4401
|
+
*/
|
|
4402
|
+
if (existing.$type$ === ChoreType.NODE_DIFF) {
|
|
4403
|
+
existing.$payload$ = value.$payload$;
|
|
4100
4404
|
}
|
|
4405
|
+
if (existing.$executed$) {
|
|
4406
|
+
existing.$executed$ = false;
|
|
4407
|
+
}
|
|
4408
|
+
return existing;
|
|
4101
4409
|
}
|
|
4102
4410
|
};
|
|
4103
|
-
const
|
|
4104
|
-
|
|
4105
|
-
useOn('qvisible', getTaskHandlerQrl(task));
|
|
4106
|
-
}
|
|
4107
|
-
else if (eagerness === 'load' || eagerness === 'document-ready') {
|
|
4108
|
-
useOnDocument('qinit', getTaskHandlerQrl(task));
|
|
4109
|
-
}
|
|
4110
|
-
else if (eagerness === 'idle' || eagerness === 'document-idle') {
|
|
4111
|
-
useOnDocument('qidle', getTaskHandlerQrl(task));
|
|
4112
|
-
}
|
|
4113
|
-
};
|
|
4114
|
-
const getTaskHandlerQrl = (task) => {
|
|
4115
|
-
const taskQrl = task.$qrl$;
|
|
4116
|
-
const taskHandler = createQRL(taskQrl.$chunk$, '_hW', _hW, null, null, [task], taskQrl.$symbol$);
|
|
4117
|
-
// Needed for chunk lookup in dev mode
|
|
4118
|
-
if (taskQrl.dev) {
|
|
4119
|
-
taskHandler.dev = taskQrl.dev;
|
|
4120
|
-
}
|
|
4121
|
-
return taskHandler;
|
|
4122
|
-
};
|
|
4123
|
-
class Task extends Subscriber {
|
|
4124
|
-
$flags$;
|
|
4125
|
-
$index$;
|
|
4126
|
-
$el$;
|
|
4127
|
-
$qrl$;
|
|
4128
|
-
$state$;
|
|
4129
|
-
$destroy$;
|
|
4130
|
-
constructor($flags$, $index$, $el$, $qrl$, $state$, $destroy$) {
|
|
4131
|
-
super();
|
|
4132
|
-
this.$flags$ = $flags$;
|
|
4133
|
-
this.$index$ = $index$;
|
|
4134
|
-
this.$el$ = $el$;
|
|
4135
|
-
this.$qrl$ = $qrl$;
|
|
4136
|
-
this.$state$ = $state$;
|
|
4137
|
-
this.$destroy$ = $destroy$;
|
|
4138
|
-
}
|
|
4139
|
-
}
|
|
4140
|
-
const isTask = (value) => {
|
|
4141
|
-
return value instanceof Task;
|
|
4142
|
-
};
|
|
4143
|
-
/**
|
|
4144
|
-
* Low-level API used by the Optimizer to process `useTask$()` API. This method is not intended to
|
|
4145
|
-
* be used by developers.
|
|
4146
|
-
*
|
|
4147
|
-
* @internal
|
|
4148
|
-
*/
|
|
4149
|
-
const _hW = () => {
|
|
4150
|
-
const [task] = useLexicalScope();
|
|
4151
|
-
const container = getDomContainer(task.$el$);
|
|
4152
|
-
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
|
|
4153
|
-
container.$scheduler$(type, task);
|
|
4411
|
+
const toNumber = (value) => {
|
|
4412
|
+
return typeof value === 'number' ? value : -1;
|
|
4154
4413
|
};
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4414
|
+
function vNodeAlreadyDeleted(chore) {
|
|
4415
|
+
return !!(chore.$host$ &&
|
|
4416
|
+
vnode_isVNode(chore.$host$) &&
|
|
4417
|
+
chore.$host$[VNodeProps.flags] & VNodeFlags.Deleted);
|
|
4418
|
+
}
|
|
4419
|
+
function debugChoreTypeToString(type) {
|
|
4420
|
+
return ({
|
|
4421
|
+
[ChoreType.QRL_RESOLVE]: 'QRL_RESOLVE',
|
|
4422
|
+
[ChoreType.RUN_QRL]: 'RUN_QRL',
|
|
4423
|
+
[ChoreType.TASK]: 'TASK',
|
|
4424
|
+
[ChoreType.NODE_DIFF]: 'NODE_DIFF',
|
|
4425
|
+
[ChoreType.NODE_PROP]: 'NODE_PROP',
|
|
4426
|
+
[ChoreType.COMPONENT]: 'COMPONENT',
|
|
4427
|
+
[ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS]: 'RECOMPUTE_SIGNAL',
|
|
4428
|
+
[ChoreType.JOURNAL_FLUSH]: 'JOURNAL_FLUSH',
|
|
4429
|
+
[ChoreType.VISIBLE]: 'VISIBLE',
|
|
4430
|
+
[ChoreType.CLEANUP_VISIBLE]: 'CLEANUP_VISIBLE',
|
|
4431
|
+
[ChoreType.WAIT_FOR_ALL]: 'WAIT_FOR_ALL',
|
|
4432
|
+
}[type] || 'UNKNOWN: ' + type);
|
|
4433
|
+
}
|
|
4434
|
+
function debugChoreToString(chore) {
|
|
4435
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
4436
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
4437
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
4438
|
+
return `Chore(${type} ${chore.$type$ === ChoreType.QRL_RESOLVE || chore.$type$ === ChoreType.RUN_QRL ? qrlTarget : host} ${chore.$idx$})`;
|
|
4439
|
+
}
|
|
4440
|
+
function debugTrace(action, arg, currentChore, queue) {
|
|
4441
|
+
const lines = ['===========================\nScheduler: ' + action];
|
|
4442
|
+
if (arg && !('$type$' in arg)) {
|
|
4443
|
+
lines.push(' arg: ' + String(arg).replaceAll(/\n.*/gim, ''));
|
|
4444
|
+
}
|
|
4445
|
+
if (queue) {
|
|
4446
|
+
queue.forEach((chore) => {
|
|
4447
|
+
const active = chore === arg ? '>>>' : ' ';
|
|
4448
|
+
lines.push(` ${active} > ` +
|
|
4449
|
+
(chore === currentChore ? '[running] ' : '') +
|
|
4450
|
+
debugChoreToString(chore));
|
|
4451
|
+
});
|
|
4452
|
+
}
|
|
4453
|
+
// eslint-disable-next-line no-console
|
|
4454
|
+
console.log(lines.join('\n') + '\n');
|
|
4455
|
+
}
|
|
4161
4456
|
|
|
4162
4457
|
/**
|
|
4163
4458
|
* @file
|
|
@@ -4191,18 +4486,19 @@ const isSignal = (value) => {
|
|
|
4191
4486
|
return value instanceof Signal;
|
|
4192
4487
|
};
|
|
4193
4488
|
/** @internal */
|
|
4194
|
-
class
|
|
4489
|
+
class SubscriptionData {
|
|
4195
4490
|
data;
|
|
4196
4491
|
constructor(data) {
|
|
4197
4492
|
this.data = data;
|
|
4198
4493
|
}
|
|
4199
4494
|
}
|
|
4200
|
-
var
|
|
4201
|
-
(function (
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4495
|
+
var EffectSubscriptionProp;
|
|
4496
|
+
(function (EffectSubscriptionProp) {
|
|
4497
|
+
EffectSubscriptionProp[EffectSubscriptionProp["CONSUMER"] = 0] = "CONSUMER";
|
|
4498
|
+
EffectSubscriptionProp[EffectSubscriptionProp["PROPERTY"] = 1] = "PROPERTY";
|
|
4499
|
+
EffectSubscriptionProp[EffectSubscriptionProp["BACK_REF"] = 2] = "BACK_REF";
|
|
4500
|
+
EffectSubscriptionProp[EffectSubscriptionProp["DATA"] = 3] = "DATA";
|
|
4501
|
+
})(EffectSubscriptionProp || (EffectSubscriptionProp = {}));
|
|
4206
4502
|
var EffectProperty;
|
|
4207
4503
|
(function (EffectProperty) {
|
|
4208
4504
|
EffectProperty["COMPONENT"] = ":";
|
|
@@ -4239,19 +4535,16 @@ class Signal {
|
|
|
4239
4535
|
}
|
|
4240
4536
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
4241
4537
|
if (effectSubscriber) {
|
|
4242
|
-
const effects = (this.$effects$ ||=
|
|
4538
|
+
const effects = (this.$effects$ ||= new Set());
|
|
4243
4539
|
// Let's make sure that we have a reference to this effect.
|
|
4244
4540
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
4245
4541
|
// changes we know who to notify.
|
|
4246
|
-
|
|
4542
|
+
ensureContainsSubscription(effects, effectSubscriber);
|
|
4247
4543
|
// But when effect is scheduled in needs to be able to know which signals
|
|
4248
4544
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
4249
4545
|
// to this signal.
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
// We need to add the subscriber to the effect so that we can clean it up later
|
|
4253
|
-
ensureEffectContainsSubscriber(effectSubscriber[EffectSubscriptionsProp.EFFECT], this, this.$container$);
|
|
4254
|
-
}
|
|
4546
|
+
ensureContainsBackRef(effectSubscriber, this);
|
|
4547
|
+
addQrlToSerializationCtx(effectSubscriber, this.$container$);
|
|
4255
4548
|
}
|
|
4256
4549
|
}
|
|
4257
4550
|
return this.untrackedValue;
|
|
@@ -4270,122 +4563,97 @@ class Signal {
|
|
|
4270
4563
|
}
|
|
4271
4564
|
toString() {
|
|
4272
4565
|
return (`[${this.constructor.name}${this.$invalid$ ? ' INVALID' : ''} ${String(this.$untrackedValue$)}]` +
|
|
4273
|
-
(this.$effects
|
|
4566
|
+
(Array.from(this.$effects$ || [])
|
|
4567
|
+
.map((e) => '\n -> ' + pad(qwikDebugToString(e[0]), ' '))
|
|
4568
|
+
.join('\n') || ''));
|
|
4274
4569
|
}
|
|
4275
4570
|
toJSON() {
|
|
4276
4571
|
return { value: this.$untrackedValue$ };
|
|
4277
4572
|
}
|
|
4278
4573
|
}
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
const isMissing = array.indexOf(value) === -1;
|
|
4282
|
-
if (isMissing) {
|
|
4283
|
-
array.push(value);
|
|
4284
|
-
}
|
|
4285
|
-
};
|
|
4286
|
-
const ensureContainsEffect = (array, effectSubscriptions) => {
|
|
4287
|
-
for (let i = 0; i < array.length; i++) {
|
|
4288
|
-
const existingEffect = array[i];
|
|
4289
|
-
if (existingEffect[0] === effectSubscriptions[0] &&
|
|
4290
|
-
existingEffect[1] === effectSubscriptions[1]) {
|
|
4291
|
-
return;
|
|
4292
|
-
}
|
|
4293
|
-
}
|
|
4294
|
-
array.push(effectSubscriptions);
|
|
4574
|
+
const ensureContainsSubscription = (array, effectSubscription) => {
|
|
4575
|
+
array.add(effectSubscription);
|
|
4295
4576
|
};
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4577
|
+
/** Ensure the item is in back refs set */
|
|
4578
|
+
const ensureContainsBackRef = (array, value) => {
|
|
4579
|
+
array[EffectSubscriptionProp.BACK_REF] ||= new Set();
|
|
4580
|
+
array[EffectSubscriptionProp.BACK_REF].add(value);
|
|
4581
|
+
};
|
|
4582
|
+
const addQrlToSerializationCtx = (effectSubscriber, container) => {
|
|
4583
|
+
if (!!container && !isDomContainer(container)) {
|
|
4584
|
+
const effect = effectSubscriber[EffectSubscriptionProp.CONSUMER];
|
|
4585
|
+
const property = effectSubscriber[EffectSubscriptionProp.PROPERTY];
|
|
4586
|
+
let qrl = null;
|
|
4587
|
+
if (isTask(effect)) {
|
|
4588
|
+
qrl = effect.$qrl$;
|
|
4301
4589
|
}
|
|
4302
|
-
effect
|
|
4303
|
-
|
|
4304
|
-
else if (vnode_isVNode(effect) && !vnode_isTextVNode(effect)) {
|
|
4305
|
-
let subscribers = vnode_getProp(effect, QSubscribers, container ? container.$getObjectById$ : null);
|
|
4306
|
-
subscribers ||= [];
|
|
4307
|
-
if (subscriberExistInSubscribers(subscribers, subscriber)) {
|
|
4308
|
-
return;
|
|
4590
|
+
else if (effect instanceof ComputedSignal) {
|
|
4591
|
+
qrl = effect.$computeQrl$;
|
|
4309
4592
|
}
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
}
|
|
4313
|
-
else if (isSSRNode(effect)) {
|
|
4314
|
-
let subscribers = effect.getProp(QSubscribers);
|
|
4315
|
-
subscribers ||= [];
|
|
4316
|
-
if (subscriberExistInSubscribers(subscribers, subscriber)) {
|
|
4317
|
-
return;
|
|
4593
|
+
else if (property === EffectProperty.COMPONENT) {
|
|
4594
|
+
qrl = container.getHostProp(effect, OnRenderProp);
|
|
4318
4595
|
}
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
}
|
|
4322
|
-
};
|
|
4323
|
-
const isSSRNode = (effect) => {
|
|
4324
|
-
return 'setProp' in effect && 'getProp' in effect && 'removeProp' in effect && 'id' in effect;
|
|
4325
|
-
};
|
|
4326
|
-
const subscriberExistInSubscribers = (subscribers, subscriber) => {
|
|
4327
|
-
for (let i = 0; i < subscribers.length; i++) {
|
|
4328
|
-
if (subscribers[i] === subscriber) {
|
|
4329
|
-
return true;
|
|
4596
|
+
if (qrl) {
|
|
4597
|
+
container.serializationCtx.$eventQrls$.add(qrl);
|
|
4330
4598
|
}
|
|
4331
4599
|
}
|
|
4332
|
-
return false;
|
|
4333
4600
|
};
|
|
4334
4601
|
const triggerEffects = (container, signal, effects) => {
|
|
4602
|
+
const isBrowser = isDomContainer(container);
|
|
4335
4603
|
if (effects) {
|
|
4336
|
-
const scheduleEffect = (
|
|
4337
|
-
const
|
|
4338
|
-
const property =
|
|
4604
|
+
const scheduleEffect = (effectSubscription) => {
|
|
4605
|
+
const consumer = effectSubscription[EffectSubscriptionProp.CONSUMER];
|
|
4606
|
+
const property = effectSubscription[EffectSubscriptionProp.PROPERTY];
|
|
4339
4607
|
assertDefined(container, 'Container must be defined.');
|
|
4340
|
-
if (isTask(
|
|
4341
|
-
|
|
4608
|
+
if (isTask(consumer)) {
|
|
4609
|
+
consumer.$flags$ |= TaskFlags.DIRTY;
|
|
4342
4610
|
let choreType = ChoreType.TASK;
|
|
4343
|
-
if (
|
|
4611
|
+
if (consumer.$flags$ & TaskFlags.VISIBLE_TASK) {
|
|
4344
4612
|
choreType = ChoreType.VISIBLE;
|
|
4345
4613
|
}
|
|
4346
|
-
|
|
4347
|
-
choreType = ChoreType.RESOURCE;
|
|
4348
|
-
}
|
|
4349
|
-
container.$scheduler$(choreType, effect);
|
|
4614
|
+
container.$scheduler$(choreType, consumer);
|
|
4350
4615
|
}
|
|
4351
|
-
else if (
|
|
4616
|
+
else if (consumer instanceof Signal) {
|
|
4352
4617
|
// we don't schedule ComputedSignal/DerivedSignal directly, instead we invalidate it and
|
|
4353
4618
|
// and schedule the signals effects (recursively)
|
|
4354
|
-
if (
|
|
4619
|
+
if (consumer instanceof ComputedSignal) {
|
|
4355
4620
|
// Ensure that the computed signal's QRL is resolved.
|
|
4356
4621
|
// If not resolved schedule it to be resolved.
|
|
4357
|
-
if (!
|
|
4358
|
-
container.$scheduler$(ChoreType.QRL_RESOLVE, null,
|
|
4622
|
+
if (!consumer.$computeQrl$.resolved) {
|
|
4623
|
+
container.$scheduler$(ChoreType.QRL_RESOLVE, null, consumer.$computeQrl$);
|
|
4359
4624
|
}
|
|
4360
4625
|
}
|
|
4361
|
-
|
|
4626
|
+
consumer.$invalidate$();
|
|
4362
4627
|
}
|
|
4363
4628
|
else if (property === EffectProperty.COMPONENT) {
|
|
4364
|
-
const host =
|
|
4629
|
+
const host = consumer;
|
|
4365
4630
|
const qrl = container.getHostProp(host, OnRenderProp);
|
|
4366
4631
|
assertDefined(qrl, 'Component must have QRL');
|
|
4367
4632
|
const props = container.getHostProp(host, ELEMENT_PROPS);
|
|
4368
4633
|
container.$scheduler$(ChoreType.COMPONENT, host, qrl, props);
|
|
4369
4634
|
}
|
|
4370
|
-
else if (
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4635
|
+
else if (isBrowser) {
|
|
4636
|
+
if (property === EffectProperty.VNODE) {
|
|
4637
|
+
const host = consumer;
|
|
4638
|
+
container.$scheduler$(ChoreType.NODE_DIFF, host, host, signal);
|
|
4639
|
+
}
|
|
4640
|
+
else {
|
|
4641
|
+
const host = consumer;
|
|
4642
|
+
const effectData = effectSubscription[EffectSubscriptionProp.DATA];
|
|
4643
|
+
if (effectData instanceof SubscriptionData) {
|
|
4644
|
+
const data = effectData.data;
|
|
4645
|
+
const payload = {
|
|
4646
|
+
...data,
|
|
4647
|
+
$value$: signal,
|
|
4648
|
+
};
|
|
4649
|
+
container.$scheduler$(ChoreType.NODE_PROP, host, property, payload);
|
|
4650
|
+
}
|
|
4385
4651
|
}
|
|
4386
4652
|
}
|
|
4387
4653
|
};
|
|
4388
|
-
effects
|
|
4654
|
+
for (const effect of effects) {
|
|
4655
|
+
scheduleEffect(effect);
|
|
4656
|
+
}
|
|
4389
4657
|
}
|
|
4390
4658
|
};
|
|
4391
4659
|
/**
|
|
@@ -4443,7 +4711,7 @@ class ComputedSignal extends Signal {
|
|
|
4443
4711
|
throwIfQRLNotResolved(computeQrl);
|
|
4444
4712
|
const ctx = tryGetInvokeContext();
|
|
4445
4713
|
const previousEffectSubscription = ctx?.$effectSubscriber$;
|
|
4446
|
-
ctx && (ctx.$effectSubscriber$ =
|
|
4714
|
+
ctx && (ctx.$effectSubscriber$ = getSubscriber(this, EffectProperty.VNODE));
|
|
4447
4715
|
try {
|
|
4448
4716
|
const untrackedValue = computeQrl.getFn(ctx)();
|
|
4449
4717
|
if (isPromise(untrackedValue)) {
|
|
@@ -4481,9 +4749,9 @@ class WrappedSignal extends Signal {
|
|
|
4481
4749
|
// We need a separate flag to know when the computation needs running because
|
|
4482
4750
|
// we need the old value to know if effects need running after computation
|
|
4483
4751
|
$invalid$ = true;
|
|
4484
|
-
$effectDependencies$ = null;
|
|
4485
4752
|
$hostElement$ = null;
|
|
4486
4753
|
$forceRunEffects$ = false;
|
|
4754
|
+
[_EFFECT_BACK_REF] = null;
|
|
4487
4755
|
constructor(container, fn, args, fnStr) {
|
|
4488
4756
|
super(container, NEEDS_COMPUTATION);
|
|
4489
4757
|
this.$args$ = args;
|
|
@@ -4551,7 +4819,7 @@ const applyQwikComponentBody = (ssr, jsx, component) => {
|
|
|
4551
4819
|
if (jsx.key !== null) {
|
|
4552
4820
|
host.setProp(ELEMENT_KEY, jsx.key);
|
|
4553
4821
|
}
|
|
4554
|
-
return scheduler(ChoreType.
|
|
4822
|
+
return scheduler(ChoreType.COMPONENT, host, componentQrl, srcProps);
|
|
4555
4823
|
};
|
|
4556
4824
|
|
|
4557
4825
|
class ParentComponentData {
|
|
@@ -4563,21 +4831,10 @@ class ParentComponentData {
|
|
|
4563
4831
|
}
|
|
4564
4832
|
}
|
|
4565
4833
|
/** @internal */
|
|
4566
|
-
function _walkJSX(ssr, value, options) {
|
|
4834
|
+
async function _walkJSX(ssr, value, options) {
|
|
4567
4835
|
const stack = [value];
|
|
4568
|
-
let resolveDrain;
|
|
4569
|
-
let rejectDrain;
|
|
4570
|
-
const drained = options.allowPromises &&
|
|
4571
|
-
new Promise((res, rej) => {
|
|
4572
|
-
resolveDrain = res;
|
|
4573
|
-
rejectDrain = rej;
|
|
4574
|
-
});
|
|
4575
4836
|
const enqueue = (value) => stack.push(value);
|
|
4576
|
-
const
|
|
4577
|
-
stack.push(value);
|
|
4578
|
-
drain();
|
|
4579
|
-
};
|
|
4580
|
-
const drain = () => {
|
|
4837
|
+
const drain = async () => {
|
|
4581
4838
|
while (stack.length) {
|
|
4582
4839
|
const value = stack.pop();
|
|
4583
4840
|
if (value instanceof ParentComponentData) {
|
|
@@ -4587,20 +4844,10 @@ function _walkJSX(ssr, value, options) {
|
|
|
4587
4844
|
}
|
|
4588
4845
|
else if (typeof value === 'function') {
|
|
4589
4846
|
if (value === Promise) {
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
}
|
|
4593
|
-
stack.pop().then(resolveValue, rejectDrain);
|
|
4594
|
-
return;
|
|
4595
|
-
}
|
|
4596
|
-
const waitOn = value.apply(ssr);
|
|
4597
|
-
if (waitOn) {
|
|
4598
|
-
if (!options.allowPromises) {
|
|
4599
|
-
throw qError(QError.promisesNotExpected);
|
|
4600
|
-
}
|
|
4601
|
-
waitOn.then(drain, rejectDrain);
|
|
4602
|
-
return;
|
|
4847
|
+
stack.push(await stack.pop());
|
|
4848
|
+
continue;
|
|
4603
4849
|
}
|
|
4850
|
+
await value.apply(ssr);
|
|
4604
4851
|
continue;
|
|
4605
4852
|
}
|
|
4606
4853
|
processJSXNode(ssr, enqueue, value, {
|
|
@@ -4608,12 +4855,8 @@ function _walkJSX(ssr, value, options) {
|
|
|
4608
4855
|
parentComponentFrame: options.parentComponentFrame,
|
|
4609
4856
|
});
|
|
4610
4857
|
}
|
|
4611
|
-
if (stack.length === 0 && options.allowPromises) {
|
|
4612
|
-
resolveDrain();
|
|
4613
|
-
}
|
|
4614
4858
|
};
|
|
4615
|
-
drain();
|
|
4616
|
-
return drained;
|
|
4859
|
+
await drain();
|
|
4617
4860
|
}
|
|
4618
4861
|
function processJSXNode(ssr, enqueue, value, options) {
|
|
4619
4862
|
// console.log('processJSXNode', value);
|
|
@@ -4652,7 +4895,6 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
4652
4895
|
enqueue(async () => {
|
|
4653
4896
|
for await (const chunk of value) {
|
|
4654
4897
|
await _walkJSX(ssr, chunk, {
|
|
4655
|
-
allowPromises: true,
|
|
4656
4898
|
currentStyleScoped: options.styleScoped,
|
|
4657
4899
|
parentComponentFrame: options.parentComponentFrame,
|
|
4658
4900
|
});
|
|
@@ -4739,7 +4981,6 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
4739
4981
|
value = generator({
|
|
4740
4982
|
async write(chunk) {
|
|
4741
4983
|
await _walkJSX(ssr, chunk, {
|
|
4742
|
-
allowPromises: true,
|
|
4743
4984
|
currentStyleScoped: options.styleScoped,
|
|
4744
4985
|
parentComponentFrame: options.parentComponentFrame,
|
|
4745
4986
|
});
|
|
@@ -4896,11 +5137,23 @@ function setEvent(serializationCtx, key, rawValue) {
|
|
|
4896
5137
|
const appendToValue = (valueToAppend) => {
|
|
4897
5138
|
value = (value == null ? '' : value + '\n') + valueToAppend;
|
|
4898
5139
|
};
|
|
5140
|
+
const getQrlString = (qrl) => {
|
|
5141
|
+
/**
|
|
5142
|
+
* If there are captures we need to schedule so everything is executed in the right order + qrls
|
|
5143
|
+
* are resolved.
|
|
5144
|
+
*
|
|
5145
|
+
* For internal qrls (starting with `_`) we assume that they do the right thing.
|
|
5146
|
+
*/
|
|
5147
|
+
if (!qrl.$symbol$.startsWith('_') && (qrl.$captureRef$ || qrl.$capture$)) {
|
|
5148
|
+
qrl = createQRL(null, '_run', queueQRL, null, null, [qrl]);
|
|
5149
|
+
}
|
|
5150
|
+
return qrlToString(serializationCtx, qrl);
|
|
5151
|
+
};
|
|
4899
5152
|
if (Array.isArray(qrls)) {
|
|
4900
5153
|
for (let i = 0; i <= qrls.length; i++) {
|
|
4901
5154
|
const qrl = qrls[i];
|
|
4902
|
-
if (isQrl(qrl)) {
|
|
4903
|
-
appendToValue(
|
|
5155
|
+
if (isQrl$1(qrl)) {
|
|
5156
|
+
appendToValue(getQrlString(qrl));
|
|
4904
5157
|
addQwikEventToSerializationContext(serializationCtx, key, qrl);
|
|
4905
5158
|
}
|
|
4906
5159
|
else if (qrl != null) {
|
|
@@ -4912,8 +5165,8 @@ function setEvent(serializationCtx, key, rawValue) {
|
|
|
4912
5165
|
}
|
|
4913
5166
|
}
|
|
4914
5167
|
}
|
|
4915
|
-
else if (isQrl(qrls)) {
|
|
4916
|
-
value =
|
|
5168
|
+
else if (isQrl$1(qrls)) {
|
|
5169
|
+
value = getQrlString(qrls);
|
|
4917
5170
|
addQwikEventToSerializationContext(serializationCtx, key, qrls);
|
|
4918
5171
|
}
|
|
4919
5172
|
return value;
|
|
@@ -4963,7 +5216,7 @@ function appendClassIfScopedStyleExists(jsx, styleScoped) {
|
|
|
4963
5216
|
*
|
|
4964
5217
|
* @public
|
|
4965
5218
|
*/
|
|
4966
|
-
const version = "2.0.0-alpha.
|
|
5219
|
+
const version = "2.0.0-alpha.7-dev+a26598a";
|
|
4967
5220
|
|
|
4968
5221
|
/** @internal */
|
|
4969
5222
|
class _SharedContainer {
|
|
@@ -4995,13 +5248,6 @@ class _SharedContainer {
|
|
|
4995
5248
|
}
|
|
4996
5249
|
}
|
|
4997
5250
|
|
|
4998
|
-
/** @internal */
|
|
4999
|
-
const _CONST_PROPS = Symbol('CONST');
|
|
5000
|
-
/** @internal */
|
|
5001
|
-
const _VAR_PROPS = Symbol('VAR');
|
|
5002
|
-
/** @internal @deprecated v1 compat */
|
|
5003
|
-
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
5004
|
-
|
|
5005
5251
|
// Keep these properties named like this so they're the same as from wrapSignal
|
|
5006
5252
|
const getValueProp = (p0) => p0.value;
|
|
5007
5253
|
const getProp = (p0, p1) => p0[p1];
|
|
@@ -5413,7 +5659,7 @@ function qwikDebugToString(value) {
|
|
|
5413
5659
|
else if (isTask(value)) {
|
|
5414
5660
|
return `Task(${qwikDebugToString(value.$qrl$)})`;
|
|
5415
5661
|
}
|
|
5416
|
-
else if (isQrl
|
|
5662
|
+
else if (isQrl(value)) {
|
|
5417
5663
|
return `Qrl(${value.$symbol$})`;
|
|
5418
5664
|
}
|
|
5419
5665
|
else if (typeof value === 'object' || typeof value === 'function') {
|
|
@@ -5567,14 +5813,21 @@ const VNodeDataChar = {
|
|
|
5567
5813
|
CONTEXT_CHAR: /* **** */ ']',
|
|
5568
5814
|
SEQ_IDX: /* ************ */ 94, // `^` - `q:seqIdx' - Sequential scope id
|
|
5569
5815
|
SEQ_IDX_CHAR: /* **** */ '^',
|
|
5570
|
-
|
|
5571
|
-
|
|
5816
|
+
BACK_REFS: /* ********** */ 96, // '`' - `q:brefs' - Effect dependencies/subscriptions
|
|
5817
|
+
BACK_REFS_CHAR: /* ** */ '`',
|
|
5572
5818
|
SEPARATOR: /* ********* */ 124, // `|` - Separator char to encode any key/value pairs.
|
|
5573
5819
|
SEPARATOR_CHAR: /* ** */ '|',
|
|
5574
5820
|
SLOT: /* ************** */ 126, // `~` - `q:slot' - Slot name
|
|
5575
5821
|
SLOT_CHAR: /* ******* */ '~',
|
|
5576
5822
|
};
|
|
5577
5823
|
|
|
5824
|
+
const mergeMaps = (map1, map2) => {
|
|
5825
|
+
for (const [k, v] of map2) {
|
|
5826
|
+
map1.set(k, v);
|
|
5827
|
+
}
|
|
5828
|
+
return map1;
|
|
5829
|
+
};
|
|
5830
|
+
|
|
5578
5831
|
/**
|
|
5579
5832
|
* @file
|
|
5580
5833
|
*
|
|
@@ -5830,6 +6083,7 @@ const vnode_ensureElementInflated = (vnode) => {
|
|
|
5830
6083
|
elementVNode[VNodeProps.flags] ^= VNodeFlags.Inflated;
|
|
5831
6084
|
const element = elementVNode[ElementVNodeProps.element];
|
|
5832
6085
|
const attributes = element.attributes;
|
|
6086
|
+
const props = vnode_getProps(elementVNode);
|
|
5833
6087
|
for (let idx = 0; idx < attributes.length; idx++) {
|
|
5834
6088
|
const attr = attributes[idx];
|
|
5835
6089
|
const key = attr.name;
|
|
@@ -5840,15 +6094,15 @@ const vnode_ensureElementInflated = (vnode) => {
|
|
|
5840
6094
|
}
|
|
5841
6095
|
else if (key.startsWith(QContainerAttr)) {
|
|
5842
6096
|
if (attr.value === QContainerValue.HTML) {
|
|
5843
|
-
mapArray_set(
|
|
6097
|
+
mapArray_set(props, dangerouslySetInnerHTML, element.innerHTML, 0);
|
|
5844
6098
|
}
|
|
5845
6099
|
else if (attr.value === QContainerValue.TEXT && 'value' in element) {
|
|
5846
|
-
mapArray_set(
|
|
6100
|
+
mapArray_set(props, 'value', element.value, 0);
|
|
5847
6101
|
}
|
|
5848
6102
|
}
|
|
5849
6103
|
else if (!key.startsWith('on:')) {
|
|
5850
6104
|
const value = attr.value;
|
|
5851
|
-
mapArray_set(
|
|
6105
|
+
mapArray_set(props, key, value, 0);
|
|
5852
6106
|
}
|
|
5853
6107
|
}
|
|
5854
6108
|
}
|
|
@@ -6284,54 +6538,16 @@ const vnode_applyJournal = (journal) => {
|
|
|
6284
6538
|
journal.length = 0;
|
|
6285
6539
|
};
|
|
6286
6540
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
6287
|
-
const mapApp_findIndx = (elementVNode, key, start) => {
|
|
6288
|
-
assertTrue(start % 2 === 0, 'Expecting even number.');
|
|
6289
|
-
let bottom = start >> 1;
|
|
6290
|
-
let top = (elementVNode.length - 2) >> 1;
|
|
6291
|
-
while (bottom <= top) {
|
|
6292
|
-
const mid = bottom + ((top - bottom) >> 1);
|
|
6293
|
-
const midKey = elementVNode[mid << 1];
|
|
6294
|
-
if (midKey === key) {
|
|
6295
|
-
return mid << 1;
|
|
6296
|
-
}
|
|
6297
|
-
if (midKey < key) {
|
|
6298
|
-
bottom = mid + 1;
|
|
6299
|
-
}
|
|
6300
|
-
else {
|
|
6301
|
-
top = mid - 1;
|
|
6302
|
-
}
|
|
6303
|
-
}
|
|
6304
|
-
return (bottom << 1) ^ -1;
|
|
6305
|
-
};
|
|
6306
|
-
const mapArray_set = (elementVNode, key, value, start) => {
|
|
6307
|
-
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
6308
|
-
if (indx >= 0) {
|
|
6309
|
-
if (value == null) {
|
|
6310
|
-
elementVNode.splice(indx, 2);
|
|
6311
|
-
}
|
|
6312
|
-
else {
|
|
6313
|
-
elementVNode[indx + 1] = value;
|
|
6314
|
-
}
|
|
6315
|
-
}
|
|
6316
|
-
else if (value != null) {
|
|
6317
|
-
elementVNode.splice(indx ^ -1, 0, key, value);
|
|
6318
|
-
}
|
|
6319
|
-
};
|
|
6320
|
-
const mapArray_get = (elementVNode, key, start) => {
|
|
6321
|
-
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
6322
|
-
if (indx >= 0) {
|
|
6323
|
-
return elementVNode[indx + 1];
|
|
6324
|
-
}
|
|
6325
|
-
else {
|
|
6326
|
-
return null;
|
|
6327
|
-
}
|
|
6328
|
-
};
|
|
6329
|
-
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
6330
6541
|
const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
|
|
6331
6542
|
ensureElementOrVirtualVNode(parent);
|
|
6332
6543
|
if (vnode_isElementVNode(parent)) {
|
|
6333
6544
|
ensureMaterialized(parent);
|
|
6334
6545
|
}
|
|
6546
|
+
if (newChild === insertBefore) {
|
|
6547
|
+
// invalid insertBefore. We can't insert before self reference
|
|
6548
|
+
// prevent infinity loop and putting self reference to next sibling
|
|
6549
|
+
insertBefore = null;
|
|
6550
|
+
}
|
|
6335
6551
|
let adjustedInsertBefore = null;
|
|
6336
6552
|
if (insertBefore == null) {
|
|
6337
6553
|
if (vnode_isVirtualVNode(parent)) {
|
|
@@ -6455,9 +6671,10 @@ const vnode_getElementName = (vnode) => {
|
|
|
6455
6671
|
const elementVNode = ensureElementVNode(vnode);
|
|
6456
6672
|
let elementName = elementVNode[ElementVNodeProps.elementName];
|
|
6457
6673
|
if (elementName === undefined) {
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
elementVNode[
|
|
6674
|
+
const element = elementVNode[ElementVNodeProps.element];
|
|
6675
|
+
const nodeName = isDev ? fastNodeName(element).toLowerCase() : fastNodeName(element);
|
|
6676
|
+
elementName = elementVNode[ElementVNodeProps.elementName] = nodeName;
|
|
6677
|
+
elementVNode[VNodeProps.flags] |= vnode_getElementNamespaceFlags(element);
|
|
6461
6678
|
}
|
|
6462
6679
|
return elementName;
|
|
6463
6680
|
};
|
|
@@ -6639,6 +6856,20 @@ const fastFirstChild = (node) => {
|
|
|
6639
6856
|
}
|
|
6640
6857
|
return node;
|
|
6641
6858
|
};
|
|
6859
|
+
let _fastNamespaceURI = null;
|
|
6860
|
+
const fastNamespaceURI = (element) => {
|
|
6861
|
+
if (!_fastNamespaceURI) {
|
|
6862
|
+
_fastNamespaceURI = fastGetter(element, 'namespaceURI');
|
|
6863
|
+
}
|
|
6864
|
+
return _fastNamespaceURI.call(element);
|
|
6865
|
+
};
|
|
6866
|
+
let _fastNodeName = null;
|
|
6867
|
+
const fastNodeName = (element) => {
|
|
6868
|
+
if (!_fastNodeName) {
|
|
6869
|
+
_fastNodeName = fastGetter(element, 'nodeName');
|
|
6870
|
+
}
|
|
6871
|
+
return _fastNodeName.call(element);
|
|
6872
|
+
};
|
|
6642
6873
|
const fastGetter = (prototype, name) => {
|
|
6643
6874
|
let getter;
|
|
6644
6875
|
while (prototype && !(getter = Object.getOwnPropertyDescriptor(prototype, name)?.get)) {
|
|
@@ -6705,8 +6936,11 @@ const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
|
6705
6936
|
container.$setRawState$(parseInt(id), vParent);
|
|
6706
6937
|
isDev && vnode_setAttr(null, vParent, ELEMENT_ID, id);
|
|
6707
6938
|
}
|
|
6708
|
-
else if (peek() === VNodeDataChar.
|
|
6709
|
-
|
|
6939
|
+
else if (peek() === VNodeDataChar.BACK_REFS) {
|
|
6940
|
+
if (!container) {
|
|
6941
|
+
container = getDomContainer(vParent[ElementVNodeProps.element]);
|
|
6942
|
+
}
|
|
6943
|
+
setEffectBackRefFromVNodeData(vParent, consumeValue(), container);
|
|
6710
6944
|
}
|
|
6711
6945
|
else {
|
|
6712
6946
|
// prevent infinity loop if there are some characters outside the range
|
|
@@ -6716,6 +6950,18 @@ const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
|
6716
6950
|
}
|
|
6717
6951
|
return vFirstChild;
|
|
6718
6952
|
};
|
|
6953
|
+
function setEffectBackRefFromVNodeData(vParent, value, container) {
|
|
6954
|
+
const deserializedSubMap = container.$getObjectById$(value);
|
|
6955
|
+
if (!vParent[_EFFECT_BACK_REF]) {
|
|
6956
|
+
Object.defineProperty(vParent, _EFFECT_BACK_REF, {
|
|
6957
|
+
value: deserializedSubMap,
|
|
6958
|
+
});
|
|
6959
|
+
}
|
|
6960
|
+
else {
|
|
6961
|
+
const subMap = vParent[_EFFECT_BACK_REF];
|
|
6962
|
+
mergeMaps(subMap, deserializedSubMap);
|
|
6963
|
+
}
|
|
6964
|
+
}
|
|
6719
6965
|
const processVNodeData$1 = (vData, callback) => {
|
|
6720
6966
|
let nextToConsumeIdx = 0;
|
|
6721
6967
|
let ch = 0;
|
|
@@ -6760,8 +7006,9 @@ const vnode_getAttrKeys = (vnode) => {
|
|
|
6760
7006
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6761
7007
|
vnode_ensureElementInflated(vnode);
|
|
6762
7008
|
const keys = [];
|
|
6763
|
-
|
|
6764
|
-
|
|
7009
|
+
const props = vnode_getProps(vnode);
|
|
7010
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
7011
|
+
const key = props[i];
|
|
6765
7012
|
if (!key.startsWith(Q_PROPS_SEPARATOR)) {
|
|
6766
7013
|
keys.push(key);
|
|
6767
7014
|
}
|
|
@@ -6774,22 +7021,23 @@ const vnode_setAttr = (journal, vnode, key, value) => {
|
|
|
6774
7021
|
const type = vnode[VNodeProps.flags];
|
|
6775
7022
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6776
7023
|
vnode_ensureElementInflated(vnode);
|
|
6777
|
-
const
|
|
7024
|
+
const props = vnode_getProps(vnode);
|
|
7025
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6778
7026
|
if (idx >= 0) {
|
|
6779
|
-
if (
|
|
7027
|
+
if (props[idx + 1] != value && (type & VNodeFlags.Element) !== 0) {
|
|
6780
7028
|
// Values are different, update DOM
|
|
6781
7029
|
const element = vnode[ElementVNodeProps.element];
|
|
6782
7030
|
journal && journal.push(VNodeJournalOpCode.SetAttribute, element, key, value);
|
|
6783
7031
|
}
|
|
6784
7032
|
if (value == null) {
|
|
6785
|
-
|
|
7033
|
+
props.splice(idx, 2);
|
|
6786
7034
|
}
|
|
6787
7035
|
else {
|
|
6788
|
-
|
|
7036
|
+
props[idx + 1] = value;
|
|
6789
7037
|
}
|
|
6790
7038
|
}
|
|
6791
7039
|
else if (value != null) {
|
|
6792
|
-
|
|
7040
|
+
props.splice(idx ^ -1, 0, key, value);
|
|
6793
7041
|
if ((type & VNodeFlags.Element) !== 0) {
|
|
6794
7042
|
// New value, update DOM
|
|
6795
7043
|
const element = vnode[ElementVNodeProps.element];
|
|
@@ -6802,7 +7050,8 @@ const vnode_getAttr = (vnode, key) => {
|
|
|
6802
7050
|
const type = vnode[VNodeProps.flags];
|
|
6803
7051
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6804
7052
|
vnode_ensureElementInflated(vnode);
|
|
6805
|
-
|
|
7053
|
+
const props = vnode_getProps(vnode);
|
|
7054
|
+
return mapArray_get(props, key, 0);
|
|
6806
7055
|
}
|
|
6807
7056
|
return null;
|
|
6808
7057
|
};
|
|
@@ -6810,11 +7059,12 @@ const vnode_getProp = (vnode, key, getObject) => {
|
|
|
6810
7059
|
const type = vnode[VNodeProps.flags];
|
|
6811
7060
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6812
7061
|
type & VNodeFlags.Element && vnode_ensureElementInflated(vnode);
|
|
6813
|
-
const
|
|
7062
|
+
const props = vnode_getProps(vnode);
|
|
7063
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6814
7064
|
if (idx >= 0) {
|
|
6815
|
-
let value =
|
|
7065
|
+
let value = props[idx + 1];
|
|
6816
7066
|
if (typeof value === 'string' && getObject) {
|
|
6817
|
-
|
|
7067
|
+
props[idx + 1] = value = getObject(value);
|
|
6818
7068
|
}
|
|
6819
7069
|
return value;
|
|
6820
7070
|
}
|
|
@@ -6823,12 +7073,13 @@ const vnode_getProp = (vnode, key, getObject) => {
|
|
|
6823
7073
|
};
|
|
6824
7074
|
const vnode_setProp = (vnode, key, value) => {
|
|
6825
7075
|
ensureElementOrVirtualVNode(vnode);
|
|
6826
|
-
const
|
|
7076
|
+
const props = vnode_getProps(vnode);
|
|
7077
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6827
7078
|
if (idx >= 0) {
|
|
6828
|
-
|
|
7079
|
+
props[idx + 1] = value;
|
|
6829
7080
|
}
|
|
6830
7081
|
else if (value != null) {
|
|
6831
|
-
|
|
7082
|
+
props.splice(idx ^ -1, 0, key, value);
|
|
6832
7083
|
}
|
|
6833
7084
|
};
|
|
6834
7085
|
const vnode_getPropStartIndex = (vnode) => {
|
|
@@ -6841,6 +7092,9 @@ const vnode_getPropStartIndex = (vnode) => {
|
|
|
6841
7092
|
}
|
|
6842
7093
|
throw qError(QError.invalidVNodeType, [type]);
|
|
6843
7094
|
};
|
|
7095
|
+
const vnode_getProps = (vnode) => {
|
|
7096
|
+
return vnode[vnode_getPropStartIndex(vnode)];
|
|
7097
|
+
};
|
|
6844
7098
|
const vnode_getParent = (vnode) => {
|
|
6845
7099
|
return vnode[VNodeProps.parent] || null;
|
|
6846
7100
|
};
|
|
@@ -7004,8 +7258,11 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
7004
7258
|
else if (peek() === VNodeDataChar.SEQ_IDX) {
|
|
7005
7259
|
vnode_setAttr(null, vParent, ELEMENT_SEQ_IDX, consumeValue());
|
|
7006
7260
|
}
|
|
7007
|
-
else if (peek() === VNodeDataChar.
|
|
7008
|
-
|
|
7261
|
+
else if (peek() === VNodeDataChar.BACK_REFS) {
|
|
7262
|
+
if (!container) {
|
|
7263
|
+
container = getDomContainer(element);
|
|
7264
|
+
}
|
|
7265
|
+
setEffectBackRefFromVNodeData(vParent, consumeValue(), container);
|
|
7009
7266
|
}
|
|
7010
7267
|
else if (peek() === VNodeDataChar.CONTEXT) {
|
|
7011
7268
|
vnode_setAttr(null, vParent, QCtxAttr, consumeValue());
|
|
@@ -7071,60 +7328,6 @@ const vnode_getType = (vnode) => {
|
|
|
7071
7328
|
throw qError(QError.invalidVNodeType, [type]);
|
|
7072
7329
|
};
|
|
7073
7330
|
const isElement = (node) => node && typeof node == 'object' && fastNodeType(node) === /** Node.ELEMENT_NODE* */ 1;
|
|
7074
|
-
/// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
|
|
7075
|
-
const aPath = [];
|
|
7076
|
-
const bPath = [];
|
|
7077
|
-
const vnode_documentPosition = (a, b, rootVNode) => {
|
|
7078
|
-
if (a === b) {
|
|
7079
|
-
return 0;
|
|
7080
|
-
}
|
|
7081
|
-
let aDepth = -1;
|
|
7082
|
-
let bDepth = -1;
|
|
7083
|
-
while (a) {
|
|
7084
|
-
const vNode = (aPath[++aDepth] = a);
|
|
7085
|
-
a = (vNode[VNodeProps.parent] ||
|
|
7086
|
-
(rootVNode && vnode_getProp(a, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
7087
|
-
}
|
|
7088
|
-
while (b) {
|
|
7089
|
-
const vNode = (bPath[++bDepth] = b);
|
|
7090
|
-
b = (vNode[VNodeProps.parent] ||
|
|
7091
|
-
(rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
7092
|
-
}
|
|
7093
|
-
while (aDepth >= 0 && bDepth >= 0) {
|
|
7094
|
-
a = aPath[aDepth];
|
|
7095
|
-
b = bPath[bDepth];
|
|
7096
|
-
if (a === b) {
|
|
7097
|
-
// if the nodes are the same, we need to check the next level.
|
|
7098
|
-
aDepth--;
|
|
7099
|
-
bDepth--;
|
|
7100
|
-
}
|
|
7101
|
-
else {
|
|
7102
|
-
// We found a difference so we need to scan nodes at this level.
|
|
7103
|
-
let cursor = b;
|
|
7104
|
-
do {
|
|
7105
|
-
cursor = vnode_getNextSibling(cursor);
|
|
7106
|
-
if (cursor === a) {
|
|
7107
|
-
return 1;
|
|
7108
|
-
}
|
|
7109
|
-
} while (cursor);
|
|
7110
|
-
cursor = b;
|
|
7111
|
-
do {
|
|
7112
|
-
cursor = vnode_getPreviousSibling(cursor);
|
|
7113
|
-
if (cursor === a) {
|
|
7114
|
-
return -1;
|
|
7115
|
-
}
|
|
7116
|
-
} while (cursor);
|
|
7117
|
-
if (rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))) {
|
|
7118
|
-
// The "b" node is a projection, so we need to set it after "a" node,
|
|
7119
|
-
// because the "a" node could be a context provider.
|
|
7120
|
-
return -1;
|
|
7121
|
-
}
|
|
7122
|
-
// The node is not in the list of siblings, that means it must be disconnected.
|
|
7123
|
-
return 1;
|
|
7124
|
-
}
|
|
7125
|
-
}
|
|
7126
|
-
return aDepth < bDepth ? -1 : 1;
|
|
7127
|
-
};
|
|
7128
7331
|
/**
|
|
7129
7332
|
* Use this method to find the parent component for projection.
|
|
7130
7333
|
*
|
|
@@ -7167,23 +7370,20 @@ const vnode_getProjectionParentComponent = (vHost, rootVNode) => {
|
|
|
7167
7370
|
};
|
|
7168
7371
|
const VNodeArray = class VNode extends Array {
|
|
7169
7372
|
static createElement(flags, parent, previousSibling, nextSibling, firstChild, lastChild, element, elementName) {
|
|
7170
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7171
|
-
vnode.push(firstChild, lastChild, element, elementName);
|
|
7373
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, firstChild, lastChild, element, elementName, []);
|
|
7172
7374
|
return vnode;
|
|
7173
7375
|
}
|
|
7174
7376
|
static createText(flags, parent, previousSibling, nextSibling, textNode, text) {
|
|
7175
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7176
|
-
vnode.push(textNode, text);
|
|
7377
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, textNode, text);
|
|
7177
7378
|
return vnode;
|
|
7178
7379
|
}
|
|
7179
7380
|
static createVirtual(flags, parent, previousSibling, nextSibling, firstChild, lastChild) {
|
|
7180
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7181
|
-
vnode.push(firstChild, lastChild);
|
|
7381
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, firstChild, lastChild, []);
|
|
7182
7382
|
return vnode;
|
|
7183
7383
|
}
|
|
7184
|
-
constructor(flags, parent, previousSibling, nextSibling) {
|
|
7185
|
-
|
|
7186
|
-
|
|
7384
|
+
constructor(flags, parent, previousSibling, nextSibling, ...rest) {
|
|
7385
|
+
// @ts-expect-error
|
|
7386
|
+
super(flags, parent, previousSibling, nextSibling, ...rest);
|
|
7187
7387
|
if (isDev) {
|
|
7188
7388
|
this.toString = vnode_toString;
|
|
7189
7389
|
}
|
|
@@ -7248,10 +7448,12 @@ function invokeApply(context, fn, args) {
|
|
|
7248
7448
|
return returnValue;
|
|
7249
7449
|
}
|
|
7250
7450
|
const newInvokeContextFromTuple = ([element, event, url]) => {
|
|
7251
|
-
const
|
|
7451
|
+
const domContainer = getDomContainer(element);
|
|
7452
|
+
const container = domContainer.element;
|
|
7453
|
+
const vNode = container ? vnode_locate(domContainer.rootVNode, element) : undefined;
|
|
7252
7454
|
const locale = container?.getAttribute(QLocaleAttr) || undefined;
|
|
7253
7455
|
locale && setLocale(locale);
|
|
7254
|
-
return newInvokeContext(locale,
|
|
7456
|
+
return newInvokeContext(locale, vNode, element, event, url);
|
|
7255
7457
|
};
|
|
7256
7458
|
// TODO how about putting url and locale (and event/custom?) in to a "static" object
|
|
7257
7459
|
const newInvokeContext = (locale, hostElement, element, event, url) => {
|
|
@@ -7286,16 +7488,14 @@ const trackInvocation = /*#__PURE__*/ newInvokeContext(undefined, undefined, und
|
|
|
7286
7488
|
* @param property `true` - subscriber is component `false` - subscriber is VNode `string` -
|
|
7287
7489
|
* subscriber is property
|
|
7288
7490
|
* @param container
|
|
7491
|
+
* @param data - Additional subscription data
|
|
7289
7492
|
* @returns
|
|
7290
7493
|
*/
|
|
7291
7494
|
const trackSignal = (fn, subscriber, property, container, data) => {
|
|
7292
7495
|
const previousSubscriber = trackInvocation.$effectSubscriber$;
|
|
7293
7496
|
const previousContainer = trackInvocation.$container$;
|
|
7294
7497
|
try {
|
|
7295
|
-
trackInvocation.$effectSubscriber$ =
|
|
7296
|
-
if (data) {
|
|
7297
|
-
trackInvocation.$effectSubscriber$.push(data);
|
|
7298
|
-
}
|
|
7498
|
+
trackInvocation.$effectSubscriber$ = getSubscriber(subscriber, property, data);
|
|
7299
7499
|
trackInvocation.$container$ = container;
|
|
7300
7500
|
return invoke(trackInvocation, fn);
|
|
7301
7501
|
}
|
|
@@ -7316,8 +7516,16 @@ const _getContextElement = () => {
|
|
|
7316
7516
|
if (iCtx) {
|
|
7317
7517
|
const hostElement = iCtx.$hostElement$;
|
|
7318
7518
|
let element = null;
|
|
7319
|
-
if (
|
|
7320
|
-
|
|
7519
|
+
if (hostElement != null) {
|
|
7520
|
+
if (vnode_isVNode(hostElement)) {
|
|
7521
|
+
if (vnode_isElementVNode(hostElement)) {
|
|
7522
|
+
element = vnode_getNode(hostElement);
|
|
7523
|
+
}
|
|
7524
|
+
}
|
|
7525
|
+
else {
|
|
7526
|
+
// isSSRnode
|
|
7527
|
+
element = hostElement;
|
|
7528
|
+
}
|
|
7321
7529
|
}
|
|
7322
7530
|
return element ?? iCtx.$qrl$?.$setContainer$(undefined);
|
|
7323
7531
|
}
|
|
@@ -7953,9 +8161,9 @@ class DomContainer extends _SharedContainer {
|
|
|
7953
8161
|
$storeProxyMap$ = new WeakMap();
|
|
7954
8162
|
$qFuncs$;
|
|
7955
8163
|
$instanceHash$;
|
|
7956
|
-
|
|
8164
|
+
vNodeLocate = (id) => vnode_locate(this.rootVNode, id);
|
|
8165
|
+
$stateData$;
|
|
7957
8166
|
$styleIds$ = null;
|
|
7958
|
-
$vnodeLocate$ = (id) => vnode_locate(this.rootVNode, id);
|
|
7959
8167
|
$renderCount$ = 0;
|
|
7960
8168
|
constructor(element) {
|
|
7961
8169
|
super(() => this.scheduleRender(), () => vnode_applyJournal(this.$journal$), {}, element.getAttribute('q:locale'));
|
|
@@ -7981,29 +8189,29 @@ class DomContainer extends _SharedContainer {
|
|
|
7981
8189
|
this.rootVNode = vnode_newUnMaterializedElement(this.element);
|
|
7982
8190
|
// These are here to initialize all properties at once for single class transition
|
|
7983
8191
|
this.$rawStateData$ = null;
|
|
7984
|
-
this
|
|
8192
|
+
this.$stateData$ = null;
|
|
7985
8193
|
const document = this.element.ownerDocument;
|
|
7986
8194
|
if (!document.qVNodeData) {
|
|
7987
8195
|
processVNodeData(document);
|
|
7988
8196
|
}
|
|
7989
8197
|
this.$rawStateData$ = [];
|
|
7990
|
-
this
|
|
8198
|
+
this.$stateData$ = [];
|
|
7991
8199
|
const qwikStates = element.querySelectorAll('script[type="qwik/state"]');
|
|
7992
8200
|
if (qwikStates.length !== 0) {
|
|
7993
8201
|
const lastState = qwikStates[qwikStates.length - 1];
|
|
7994
8202
|
this.$rawStateData$ = JSON.parse(lastState.textContent);
|
|
7995
|
-
this
|
|
8203
|
+
this.$stateData$ = wrapDeserializerProxy(this, this.$rawStateData$);
|
|
7996
8204
|
}
|
|
7997
8205
|
this.$qFuncs$ = getQFuncs(document, this.$instanceHash$) || EMPTY_ARRAY;
|
|
7998
8206
|
}
|
|
7999
8207
|
$setRawState$(id, vParent) {
|
|
8000
|
-
this
|
|
8208
|
+
this.$stateData$[id] = vParent;
|
|
8001
8209
|
}
|
|
8002
8210
|
parseQRL(qrl) {
|
|
8003
8211
|
return inflateQRL(this, parseQRL(qrl));
|
|
8004
8212
|
}
|
|
8005
8213
|
handleError(err, host) {
|
|
8006
|
-
if (qDev) {
|
|
8214
|
+
if (qDev && host) {
|
|
8007
8215
|
// Clean vdom
|
|
8008
8216
|
if (typeof document !== 'undefined') {
|
|
8009
8217
|
const vHost = host;
|
|
@@ -8027,7 +8235,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8027
8235
|
throw err;
|
|
8028
8236
|
}
|
|
8029
8237
|
}
|
|
8030
|
-
const errorStore = this.resolveContext(host, ERROR_CONTEXT);
|
|
8238
|
+
const errorStore = host && this.resolveContext(host, ERROR_CONTEXT);
|
|
8031
8239
|
if (!errorStore) {
|
|
8032
8240
|
throw err;
|
|
8033
8241
|
}
|
|
@@ -8063,7 +8271,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8063
8271
|
vNode =
|
|
8064
8272
|
vnode_getParent(vNode) ||
|
|
8065
8273
|
// If virtual node, than it could be a slot so we need to read its parent.
|
|
8066
|
-
vnode_getProp(vNode, QSlotParent, this
|
|
8274
|
+
vnode_getProp(vNode, QSlotParent, this.vNodeLocate);
|
|
8067
8275
|
}
|
|
8068
8276
|
else {
|
|
8069
8277
|
vNode = vnode_getParent(vNode);
|
|
@@ -8083,7 +8291,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8083
8291
|
case ELEMENT_PROPS:
|
|
8084
8292
|
case OnRenderProp:
|
|
8085
8293
|
case QCtxAttr:
|
|
8086
|
-
case
|
|
8294
|
+
case QBackRefs:
|
|
8087
8295
|
getObjectById = this.$getObjectById$;
|
|
8088
8296
|
break;
|
|
8089
8297
|
case ELEMENT_SEQ_IDX:
|
|
@@ -8096,7 +8304,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8096
8304
|
scheduleRender() {
|
|
8097
8305
|
this.$renderCount$++;
|
|
8098
8306
|
this.renderDone ||= getPlatform().nextTick(() => this.processChores());
|
|
8099
|
-
return this.renderDone;
|
|
8307
|
+
return this.renderDone.finally(() => emitEvent('qrender', { instanceHash: this.$instanceHash$, renderCount: this.$renderCount$ }));
|
|
8100
8308
|
}
|
|
8101
8309
|
processChores() {
|
|
8102
8310
|
let renderCount = this.$renderCount$;
|
|
@@ -8119,12 +8327,13 @@ class DomContainer extends _SharedContainer {
|
|
|
8119
8327
|
ensureProjectionResolved(vNode) {
|
|
8120
8328
|
if ((vNode[VNodeProps.flags] & VNodeFlags.Resolved) === 0) {
|
|
8121
8329
|
vNode[VNodeProps.flags] |= VNodeFlags.Resolved;
|
|
8122
|
-
|
|
8123
|
-
|
|
8330
|
+
const props = vnode_getProps(vNode);
|
|
8331
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
8332
|
+
const prop = props[i];
|
|
8124
8333
|
if (isSlotProp(prop)) {
|
|
8125
|
-
const value =
|
|
8334
|
+
const value = props[i + 1];
|
|
8126
8335
|
if (typeof value == 'string') {
|
|
8127
|
-
|
|
8336
|
+
props[i + 1] = this.vNodeLocate(value);
|
|
8128
8337
|
}
|
|
8129
8338
|
}
|
|
8130
8339
|
}
|
|
@@ -8135,7 +8344,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8135
8344
|
id = parseFloat(id);
|
|
8136
8345
|
}
|
|
8137
8346
|
assertTrue(id < this.$rawStateData$.length / 2, `Invalid reference: ${id} >= ${this.$rawStateData$.length / 2}`);
|
|
8138
|
-
return this
|
|
8347
|
+
return this.$stateData$[id];
|
|
8139
8348
|
};
|
|
8140
8349
|
getSyncFn(id) {
|
|
8141
8350
|
const fn = this.$qFuncs$[id];
|
|
@@ -8207,8 +8416,7 @@ class DeserializationHandler {
|
|
|
8207
8416
|
? parseInt(property, 10)
|
|
8208
8417
|
: NaN;
|
|
8209
8418
|
if (Number.isNaN(i) || i < 0 || i >= this.$length$) {
|
|
8210
|
-
|
|
8211
|
-
return out;
|
|
8419
|
+
return Reflect.get(target, property, receiver);
|
|
8212
8420
|
}
|
|
8213
8421
|
// The serialized data is an array with 2 values for each item
|
|
8214
8422
|
const idx = i * 2;
|
|
@@ -8274,6 +8482,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8274
8482
|
switch (typeId) {
|
|
8275
8483
|
case TypeIds.Object:
|
|
8276
8484
|
// We use getters for making complex values lazy
|
|
8485
|
+
// TODO scan the data for computeQRLs and schedule resolve chores
|
|
8277
8486
|
for (let i = 0; i < data.length; i += 4) {
|
|
8278
8487
|
const key = deserializeData(container, data[i], data[i + 1]);
|
|
8279
8488
|
const valType = data[i + 2];
|
|
@@ -8313,7 +8522,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8313
8522
|
task.$flags$ = v[1];
|
|
8314
8523
|
task.$index$ = v[2];
|
|
8315
8524
|
task.$el$ = v[3];
|
|
8316
|
-
task
|
|
8525
|
+
task[_EFFECT_BACK_REF] = v[4];
|
|
8317
8526
|
task.$state$ = v[5];
|
|
8318
8527
|
break;
|
|
8319
8528
|
case TypeIds.Resource:
|
|
@@ -8336,12 +8545,9 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8336
8545
|
break;
|
|
8337
8546
|
case TypeIds.Store:
|
|
8338
8547
|
case TypeIds.StoreArray: {
|
|
8339
|
-
const [value, flags, effects
|
|
8548
|
+
const [value, flags, effects] = data;
|
|
8340
8549
|
const store = getOrCreateStore(value, flags, container);
|
|
8341
8550
|
const storeHandler = getStoreHandler(store);
|
|
8342
|
-
if (storeEffect) {
|
|
8343
|
-
effects[STORE_ARRAY_PROP] = storeEffect;
|
|
8344
|
-
}
|
|
8345
8551
|
storeHandler.$effects$ = effects;
|
|
8346
8552
|
target = store;
|
|
8347
8553
|
break;
|
|
@@ -8350,7 +8556,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8350
8556
|
const signal = target;
|
|
8351
8557
|
const d = data;
|
|
8352
8558
|
signal.$untrackedValue$ = d[0];
|
|
8353
|
-
signal.$effects$ = d.slice(1);
|
|
8559
|
+
signal.$effects$ = new Set(d.slice(1));
|
|
8354
8560
|
break;
|
|
8355
8561
|
}
|
|
8356
8562
|
case TypeIds.WrappedSignal: {
|
|
@@ -8358,10 +8564,10 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8358
8564
|
const d = data;
|
|
8359
8565
|
signal.$func$ = container.getSyncFn(d[0]);
|
|
8360
8566
|
signal.$args$ = d[1];
|
|
8361
|
-
signal
|
|
8567
|
+
signal[_EFFECT_BACK_REF] = d[2];
|
|
8362
8568
|
signal.$untrackedValue$ = d[3];
|
|
8363
8569
|
signal.$hostElement$ = d[4];
|
|
8364
|
-
signal.$effects$ = d.slice(5);
|
|
8570
|
+
signal.$effects$ = new Set(d.slice(5));
|
|
8365
8571
|
break;
|
|
8366
8572
|
}
|
|
8367
8573
|
case TypeIds.ComputedSignal: {
|
|
@@ -8481,6 +8687,7 @@ const _constants = [
|
|
|
8481
8687
|
EMPTY_ARRAY,
|
|
8482
8688
|
EMPTY_OBJ,
|
|
8483
8689
|
NEEDS_COMPUTATION,
|
|
8690
|
+
STORE_ARRAY_PROP,
|
|
8484
8691
|
Slot,
|
|
8485
8692
|
Fragment,
|
|
8486
8693
|
NaN,
|
|
@@ -8561,6 +8768,8 @@ const allocate = (container, typeId, value) => {
|
|
|
8561
8768
|
reject = rej;
|
|
8562
8769
|
});
|
|
8563
8770
|
resolvers.set(promise, [resolve, reject]);
|
|
8771
|
+
// Don't leave unhandled promise rejections
|
|
8772
|
+
promise.catch(() => { });
|
|
8564
8773
|
return promise;
|
|
8565
8774
|
case TypeIds.Uint8Array:
|
|
8566
8775
|
const encodedLength = value.length;
|
|
@@ -8570,12 +8779,9 @@ const allocate = (container, typeId, value) => {
|
|
|
8570
8779
|
return new Uint8Array(decodedLength);
|
|
8571
8780
|
case TypeIds.PropsProxy:
|
|
8572
8781
|
return createPropsProxy(null, null);
|
|
8573
|
-
case TypeIds.RefVNode:
|
|
8574
8782
|
case TypeIds.VNode:
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
return vnodeOrDocument;
|
|
8578
|
-
}
|
|
8783
|
+
return retrieveVNodeOrDocument(container, value);
|
|
8784
|
+
case TypeIds.RefVNode:
|
|
8579
8785
|
const vNode = retrieveVNodeOrDocument(container, value);
|
|
8580
8786
|
if (vnode_isVNode(vNode)) {
|
|
8581
8787
|
return vnode_getNode(vNode);
|
|
@@ -8584,7 +8790,7 @@ const allocate = (container, typeId, value) => {
|
|
|
8584
8790
|
throw qError(QError.serializeErrorExpectedVNode, [typeof vNode]);
|
|
8585
8791
|
}
|
|
8586
8792
|
case TypeIds.EffectData:
|
|
8587
|
-
return new
|
|
8793
|
+
return new SubscriptionData({});
|
|
8588
8794
|
default:
|
|
8589
8795
|
throw qError(QError.serializeErrorCannotAllocate, [typeId]);
|
|
8590
8796
|
}
|
|
@@ -8616,7 +8822,7 @@ function parseQRL(qrl) {
|
|
|
8616
8822
|
assertDefined(backChannel, 'Missing QRL_RUNTIME_CHUNK');
|
|
8617
8823
|
qrlRef = backChannel.get(symbol);
|
|
8618
8824
|
}
|
|
8619
|
-
return createQRL(chunk, symbol, qrlRef, null, captureIds, null
|
|
8825
|
+
return createQRL(chunk, symbol, qrlRef, null, captureIds, null);
|
|
8620
8826
|
}
|
|
8621
8827
|
function inflateQRL(container, qrl) {
|
|
8622
8828
|
const captureIds = qrl.$capture$;
|
|
@@ -8734,7 +8940,7 @@ prepVNodeData) => {
|
|
|
8734
8940
|
/** Visit an object, adding anything that will be serialized as to scan */
|
|
8735
8941
|
const visit = (obj) => {
|
|
8736
8942
|
if (typeof obj === 'function') {
|
|
8737
|
-
if (isQrl(obj)) {
|
|
8943
|
+
if (isQrl$1(obj)) {
|
|
8738
8944
|
if (obj.$captureRef$) {
|
|
8739
8945
|
discoveredValues.push(...obj.$captureRef$);
|
|
8740
8946
|
}
|
|
@@ -8753,6 +8959,7 @@ prepVNodeData) => {
|
|
|
8753
8959
|
obj instanceof RegExp ||
|
|
8754
8960
|
obj instanceof Uint8Array ||
|
|
8755
8961
|
obj instanceof URLSearchParams ||
|
|
8962
|
+
vnode_isVNode(obj) ||
|
|
8756
8963
|
(typeof FormData !== 'undefined' && obj instanceof FormData) ||
|
|
8757
8964
|
// Ignore the no serialize objects
|
|
8758
8965
|
fastSkipSerialize(obj)) ;
|
|
@@ -8762,8 +8969,7 @@ prepVNodeData) => {
|
|
|
8762
8969
|
else if (isStore(obj)) {
|
|
8763
8970
|
const target = getStoreTarget(obj);
|
|
8764
8971
|
const effects = getStoreHandler(obj).$effects$;
|
|
8765
|
-
|
|
8766
|
-
discoveredValues.push(target, effects, storeEffect);
|
|
8972
|
+
discoveredValues.push(target, effects);
|
|
8767
8973
|
for (const prop in target) {
|
|
8768
8974
|
const propValue = target[prop];
|
|
8769
8975
|
if (storeProxyMap.has(propValue)) {
|
|
@@ -8797,9 +9003,7 @@ prepVNodeData) => {
|
|
|
8797
9003
|
}
|
|
8798
9004
|
// WrappedSignal uses syncQrl which has no captured refs
|
|
8799
9005
|
if (obj instanceof WrappedSignal) {
|
|
8800
|
-
|
|
8801
|
-
discoveredValues.push(...obj.$effectDependencies$);
|
|
8802
|
-
}
|
|
9006
|
+
discoverEffectBackRefs(obj[_EFFECT_BACK_REF], discoveredValues);
|
|
8803
9007
|
if (obj.$args$) {
|
|
8804
9008
|
discoveredValues.push(...obj.$args$);
|
|
8805
9009
|
}
|
|
@@ -8812,7 +9016,8 @@ prepVNodeData) => {
|
|
|
8812
9016
|
}
|
|
8813
9017
|
}
|
|
8814
9018
|
else if (obj instanceof Task) {
|
|
8815
|
-
discoveredValues.push(obj.$el$, obj.$qrl$, obj.$state
|
|
9019
|
+
discoveredValues.push(obj.$el$, obj.$qrl$, obj.$state$);
|
|
9020
|
+
discoverEffectBackRefs(obj[_EFFECT_BACK_REF], discoveredValues);
|
|
8816
9021
|
}
|
|
8817
9022
|
else if (isSsrNode(obj)) {
|
|
8818
9023
|
discoverValuesForVNodeData(obj.vnodeData, discoveredValues);
|
|
@@ -8831,7 +9036,7 @@ prepVNodeData) => {
|
|
|
8831
9036
|
else if (Array.isArray(obj)) {
|
|
8832
9037
|
discoveredValues.push(...obj);
|
|
8833
9038
|
}
|
|
8834
|
-
else if (isQrl(obj)) {
|
|
9039
|
+
else if (isQrl$1(obj)) {
|
|
8835
9040
|
obj.$captureRef$ && obj.$captureRef$.length && discoveredValues.push(...obj.$captureRef$);
|
|
8836
9041
|
}
|
|
8837
9042
|
else if (isPropsProxy(obj)) {
|
|
@@ -8847,7 +9052,7 @@ prepVNodeData) => {
|
|
|
8847
9052
|
});
|
|
8848
9053
|
promises.push(obj);
|
|
8849
9054
|
}
|
|
8850
|
-
else if (obj instanceof
|
|
9055
|
+
else if (obj instanceof SubscriptionData) {
|
|
8851
9056
|
discoveredValues.push(obj.data);
|
|
8852
9057
|
}
|
|
8853
9058
|
else if (isObjectLiteral(obj)) {
|
|
@@ -8892,15 +9097,31 @@ const discoverValuesForVNodeData = (vnodeData, discoveredValues) => {
|
|
|
8892
9097
|
for (const value of vnodeData) {
|
|
8893
9098
|
if (isSsrAttrs(value)) {
|
|
8894
9099
|
for (let i = 1; i < value.length; i += 2) {
|
|
8895
|
-
|
|
9100
|
+
const attrValue = value[i];
|
|
9101
|
+
if (typeof attrValue === 'string') {
|
|
8896
9102
|
continue;
|
|
8897
9103
|
}
|
|
8898
|
-
const attrValue = value[i];
|
|
8899
9104
|
discoveredValues.push(attrValue);
|
|
8900
9105
|
}
|
|
8901
9106
|
}
|
|
8902
9107
|
}
|
|
8903
9108
|
};
|
|
9109
|
+
const discoverEffectBackRefs = (effectsBackRefs, discoveredValues) => {
|
|
9110
|
+
if (effectsBackRefs) {
|
|
9111
|
+
// We need serialize effect subscriptions with back refs
|
|
9112
|
+
let hasBackRefs = false;
|
|
9113
|
+
for (const [, effect] of effectsBackRefs) {
|
|
9114
|
+
const backRefs = effect[EffectSubscriptionProp.BACK_REF];
|
|
9115
|
+
if (backRefs) {
|
|
9116
|
+
hasBackRefs = true;
|
|
9117
|
+
break;
|
|
9118
|
+
}
|
|
9119
|
+
}
|
|
9120
|
+
if (hasBackRefs) {
|
|
9121
|
+
discoveredValues.push(effectsBackRefs);
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9124
|
+
};
|
|
8904
9125
|
const promiseResults = new WeakMap();
|
|
8905
9126
|
/**
|
|
8906
9127
|
* Format:
|
|
@@ -8972,7 +9193,7 @@ function serialize(serializationContext) {
|
|
|
8972
9193
|
else if (value === Fragment) {
|
|
8973
9194
|
output(TypeIds.Constant, Constants.Fragment);
|
|
8974
9195
|
}
|
|
8975
|
-
else if (isQrl(value)) {
|
|
9196
|
+
else if (isQrl$1(value)) {
|
|
8976
9197
|
const qrl = qrlToString(serializationContext, value);
|
|
8977
9198
|
const id = serializationContext.$addRoot$(qrl);
|
|
8978
9199
|
output(TypeIds.QRL, id);
|
|
@@ -9047,6 +9268,9 @@ function serialize(serializationContext) {
|
|
|
9047
9268
|
else if (value === NEEDS_COMPUTATION) {
|
|
9048
9269
|
output(TypeIds.Constant, Constants.NEEDS_COMPUTATION);
|
|
9049
9270
|
}
|
|
9271
|
+
else if (value === STORE_ARRAY_PROP) {
|
|
9272
|
+
output(TypeIds.Constant, Constants.STORE_ARRAY_PROP);
|
|
9273
|
+
}
|
|
9050
9274
|
else {
|
|
9051
9275
|
throw qError(QError.serializeErrorUnknownType, [typeof value]);
|
|
9052
9276
|
}
|
|
@@ -9083,7 +9307,7 @@ function serialize(serializationContext) {
|
|
|
9083
9307
|
: 0;
|
|
9084
9308
|
output(TypeIds.PropsProxy, out);
|
|
9085
9309
|
}
|
|
9086
|
-
else if (value instanceof
|
|
9310
|
+
else if (value instanceof SubscriptionData) {
|
|
9087
9311
|
output(TypeIds.EffectData, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
|
|
9088
9312
|
}
|
|
9089
9313
|
else if (isStore(value)) {
|
|
@@ -9094,6 +9318,7 @@ function serialize(serializationContext) {
|
|
|
9094
9318
|
if (!res) {
|
|
9095
9319
|
throw qError(QError.serializeErrorUnvisited, ['resource']);
|
|
9096
9320
|
}
|
|
9321
|
+
// TODO the effects include the resourcereturn which has duplicate data
|
|
9097
9322
|
output(TypeIds.Resource, [...res, getStoreHandler(value).$effects$]);
|
|
9098
9323
|
}
|
|
9099
9324
|
else {
|
|
@@ -9101,7 +9326,6 @@ function serialize(serializationContext) {
|
|
|
9101
9326
|
const storeTarget = getStoreTarget(value);
|
|
9102
9327
|
const flags = storeHandler.$flags$;
|
|
9103
9328
|
const effects = storeHandler.$effects$;
|
|
9104
|
-
const storeEffect = effects?.[STORE_ARRAY_PROP] ?? null;
|
|
9105
9329
|
const innerStores = [];
|
|
9106
9330
|
for (const prop in storeTarget) {
|
|
9107
9331
|
const propValue = storeTarget[prop];
|
|
@@ -9111,7 +9335,7 @@ function serialize(serializationContext) {
|
|
|
9111
9335
|
serializationContext.$addRoot$(innerStore);
|
|
9112
9336
|
}
|
|
9113
9337
|
}
|
|
9114
|
-
const out = [storeTarget, flags, effects,
|
|
9338
|
+
const out = [storeTarget, flags, effects, ...innerStores];
|
|
9115
9339
|
while (out[out.length - 1] == null) {
|
|
9116
9340
|
out.pop();
|
|
9117
9341
|
}
|
|
@@ -9150,7 +9374,7 @@ function serialize(serializationContext) {
|
|
|
9150
9374
|
if (value instanceof WrappedSignal) {
|
|
9151
9375
|
output(TypeIds.WrappedSignal, [
|
|
9152
9376
|
...serializeWrappingFn(serializationContext, value),
|
|
9153
|
-
value
|
|
9377
|
+
filterEffectBackRefs(value[_EFFECT_BACK_REF]),
|
|
9154
9378
|
v,
|
|
9155
9379
|
value.$hostElement$,
|
|
9156
9380
|
...(value.$effects$ || []),
|
|
@@ -9257,7 +9481,7 @@ function serialize(serializationContext) {
|
|
|
9257
9481
|
value.$flags$,
|
|
9258
9482
|
value.$index$,
|
|
9259
9483
|
value.$el$,
|
|
9260
|
-
value
|
|
9484
|
+
value[_EFFECT_BACK_REF],
|
|
9261
9485
|
value.$state$,
|
|
9262
9486
|
];
|
|
9263
9487
|
while (out[out.length - 1] == null) {
|
|
@@ -9280,12 +9504,27 @@ function serialize(serializationContext) {
|
|
|
9280
9504
|
const out = btoa(buf).replace(/=+$/, '');
|
|
9281
9505
|
output(TypeIds.Uint8Array, out);
|
|
9282
9506
|
}
|
|
9507
|
+
else if (vnode_isVNode(value)) {
|
|
9508
|
+
output(TypeIds.Constant, Constants.Undefined);
|
|
9509
|
+
}
|
|
9283
9510
|
else {
|
|
9284
9511
|
throw qError(QError.serializeErrorUnknownType, [typeof value]);
|
|
9285
9512
|
}
|
|
9286
9513
|
};
|
|
9287
9514
|
writeValue(serializationContext.$roots$, -1);
|
|
9288
9515
|
}
|
|
9516
|
+
function filterEffectBackRefs(effectBackRef) {
|
|
9517
|
+
let effectBackRefToSerialize = null;
|
|
9518
|
+
if (effectBackRef) {
|
|
9519
|
+
for (const [effectProp, effect] of effectBackRef) {
|
|
9520
|
+
if (effect[EffectSubscriptionProp.BACK_REF]) {
|
|
9521
|
+
effectBackRefToSerialize ||= new Map();
|
|
9522
|
+
effectBackRefToSerialize.set(effectProp, effect);
|
|
9523
|
+
}
|
|
9524
|
+
}
|
|
9525
|
+
}
|
|
9526
|
+
return effectBackRefToSerialize;
|
|
9527
|
+
}
|
|
9289
9528
|
function serializeWrappingFn(serializationContext, value) {
|
|
9290
9529
|
// if value is an object then we need to wrap this in ()
|
|
9291
9530
|
if (value.$funcStr$ && value.$funcStr$[0] === '{') {
|
|
@@ -9298,15 +9537,12 @@ function serializeWrappingFn(serializationContext, value) {
|
|
|
9298
9537
|
function qrlToString(serializationContext, value) {
|
|
9299
9538
|
let symbol = value.$symbol$;
|
|
9300
9539
|
let chunk = value.$chunk$;
|
|
9301
|
-
const refSymbol = value.$refSymbol$ ?? symbol;
|
|
9302
9540
|
const platform = getPlatform();
|
|
9303
9541
|
if (platform) {
|
|
9304
|
-
const result = platform.chunkForSymbol(
|
|
9542
|
+
const result = platform.chunkForSymbol(symbol, chunk, value.dev?.file);
|
|
9305
9543
|
if (result) {
|
|
9306
9544
|
chunk = result[1];
|
|
9307
|
-
|
|
9308
|
-
symbol = result[0];
|
|
9309
|
-
}
|
|
9545
|
+
symbol = result[0];
|
|
9310
9546
|
}
|
|
9311
9547
|
}
|
|
9312
9548
|
const isSync = isSyncQrl(value);
|
|
@@ -9483,9 +9719,9 @@ const frameworkType = (obj) => {
|
|
|
9483
9719
|
return ((typeof obj === 'object' &&
|
|
9484
9720
|
obj !== null &&
|
|
9485
9721
|
(obj instanceof Signal || obj instanceof Task || isJSXNode(obj))) ||
|
|
9486
|
-
isQrl(obj));
|
|
9722
|
+
isQrl$1(obj));
|
|
9487
9723
|
};
|
|
9488
|
-
const canSerialize = (value) => {
|
|
9724
|
+
const canSerialize = (value, seen = new WeakSet()) => {
|
|
9489
9725
|
if (value == null ||
|
|
9490
9726
|
typeof value === 'string' ||
|
|
9491
9727
|
typeof value === 'number' ||
|
|
@@ -9494,6 +9730,10 @@ const canSerialize = (value) => {
|
|
|
9494
9730
|
return true;
|
|
9495
9731
|
}
|
|
9496
9732
|
else if (typeof value === 'object') {
|
|
9733
|
+
if (seen.has(value)) {
|
|
9734
|
+
return true;
|
|
9735
|
+
}
|
|
9736
|
+
seen.add(value);
|
|
9497
9737
|
const proto = Object.getPrototypeOf(value);
|
|
9498
9738
|
if (isStore(value)) {
|
|
9499
9739
|
value = getStoreTarget(value);
|
|
@@ -9502,7 +9742,7 @@ const canSerialize = (value) => {
|
|
|
9502
9742
|
for (const key in value) {
|
|
9503
9743
|
// if the value is a props proxy, then sometimes we could create a component-level subscription,
|
|
9504
9744
|
// so we should call untrack here to avoid tracking the value
|
|
9505
|
-
if (!canSerialize(untrack(() => value[key]))) {
|
|
9745
|
+
if (!canSerialize(untrack(() => value[key]), seen)) {
|
|
9506
9746
|
return false;
|
|
9507
9747
|
}
|
|
9508
9748
|
}
|
|
@@ -9510,7 +9750,7 @@ const canSerialize = (value) => {
|
|
|
9510
9750
|
}
|
|
9511
9751
|
else if (proto == Array.prototype) {
|
|
9512
9752
|
for (let i = 0; i < value.length; i++) {
|
|
9513
|
-
if (!canSerialize(value[i])) {
|
|
9753
|
+
if (!canSerialize(value[i], seen)) {
|
|
9514
9754
|
return false;
|
|
9515
9755
|
}
|
|
9516
9756
|
}
|
|
@@ -9560,7 +9800,7 @@ const canSerialize = (value) => {
|
|
|
9560
9800
|
}
|
|
9561
9801
|
}
|
|
9562
9802
|
else if (typeof value === 'function') {
|
|
9563
|
-
if (isQrl(value) || isQwikComponent(value)) {
|
|
9803
|
+
if (isQrl$1(value) || isQwikComponent(value)) {
|
|
9564
9804
|
return true;
|
|
9565
9805
|
}
|
|
9566
9806
|
}
|
|
@@ -9613,20 +9853,21 @@ var Constants;
|
|
|
9613
9853
|
Constants[Constants["EMPTY_ARRAY"] = 5] = "EMPTY_ARRAY";
|
|
9614
9854
|
Constants[Constants["EMPTY_OBJ"] = 6] = "EMPTY_OBJ";
|
|
9615
9855
|
Constants[Constants["NEEDS_COMPUTATION"] = 7] = "NEEDS_COMPUTATION";
|
|
9616
|
-
Constants[Constants["
|
|
9617
|
-
Constants[Constants["
|
|
9618
|
-
Constants[Constants["
|
|
9619
|
-
Constants[Constants["
|
|
9620
|
-
Constants[Constants["
|
|
9621
|
-
Constants[Constants["
|
|
9856
|
+
Constants[Constants["STORE_ARRAY_PROP"] = 8] = "STORE_ARRAY_PROP";
|
|
9857
|
+
Constants[Constants["Slot"] = 9] = "Slot";
|
|
9858
|
+
Constants[Constants["Fragment"] = 10] = "Fragment";
|
|
9859
|
+
Constants[Constants["NaN"] = 11] = "NaN";
|
|
9860
|
+
Constants[Constants["PositiveInfinity"] = 12] = "PositiveInfinity";
|
|
9861
|
+
Constants[Constants["NegativeInfinity"] = 13] = "NegativeInfinity";
|
|
9862
|
+
Constants[Constants["MaxSafeInt"] = 14] = "MaxSafeInt";
|
|
9622
9863
|
// used for close fragment
|
|
9623
|
-
Constants[Constants["AlmostMaxSafeInt"] =
|
|
9624
|
-
Constants[Constants["MinSafeInt"] =
|
|
9864
|
+
Constants[Constants["AlmostMaxSafeInt"] = 15] = "AlmostMaxSafeInt";
|
|
9865
|
+
Constants[Constants["MinSafeInt"] = 16] = "MinSafeInt";
|
|
9625
9866
|
})(Constants || (Constants = {}));
|
|
9626
9867
|
|
|
9627
9868
|
/** @internal */
|
|
9628
9869
|
const verifySerializable = (value, preMessage) => {
|
|
9629
|
-
const seen = new
|
|
9870
|
+
const seen = new WeakSet();
|
|
9630
9871
|
return _verifySerializable(value, seen, '_', preMessage);
|
|
9631
9872
|
};
|
|
9632
9873
|
const _verifySerializable = (value, seen, ctx, preMessage) => {
|
|
@@ -9635,10 +9876,12 @@ const _verifySerializable = (value, seen, ctx, preMessage) => {
|
|
|
9635
9876
|
return value;
|
|
9636
9877
|
}
|
|
9637
9878
|
if (shouldSerialize(unwrapped)) {
|
|
9638
|
-
if (
|
|
9639
|
-
|
|
9879
|
+
if (typeof unwrapped === 'object') {
|
|
9880
|
+
if (seen.has(unwrapped)) {
|
|
9881
|
+
return value;
|
|
9882
|
+
}
|
|
9883
|
+
seen.add(unwrapped);
|
|
9640
9884
|
}
|
|
9641
|
-
seen.add(unwrapped);
|
|
9642
9885
|
if (isSignal(unwrapped)) {
|
|
9643
9886
|
return value;
|
|
9644
9887
|
}
|
|
@@ -9742,16 +9985,7 @@ const _weakSerialize = (input) => {
|
|
|
9742
9985
|
return input;
|
|
9743
9986
|
};
|
|
9744
9987
|
|
|
9745
|
-
const
|
|
9746
|
-
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
9747
|
-
};
|
|
9748
|
-
// Make sure this value is same as value in `platform.ts`
|
|
9749
|
-
const SYNC_QRL = '<sync>';
|
|
9750
|
-
/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
|
|
9751
|
-
const isSyncQrl = (value) => {
|
|
9752
|
-
return isQrl(value) && value.$symbol$ == SYNC_QRL;
|
|
9753
|
-
};
|
|
9754
|
-
const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refSymbol) => {
|
|
9988
|
+
const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef) => {
|
|
9755
9989
|
if (qDev && qSerialize) {
|
|
9756
9990
|
if (captureRef) {
|
|
9757
9991
|
for (const item of captureRef) {
|
|
@@ -9773,9 +10007,14 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9773
10007
|
};
|
|
9774
10008
|
function bindFnToContext(currentCtx, beforeFn) {
|
|
9775
10009
|
// Note that we bind the current `this`
|
|
9776
|
-
|
|
9777
|
-
if (!
|
|
9778
|
-
|
|
10010
|
+
const bound = (...args) => {
|
|
10011
|
+
if (!qrl.resolved) {
|
|
10012
|
+
return qrl.resolve().then((fn) => {
|
|
10013
|
+
if (!isFunction(fn)) {
|
|
10014
|
+
throw qError(QError.qrlIsNotFunction);
|
|
10015
|
+
}
|
|
10016
|
+
return bound(...args);
|
|
10017
|
+
});
|
|
9779
10018
|
}
|
|
9780
10019
|
if (beforeFn && beforeFn() === false) {
|
|
9781
10020
|
return;
|
|
@@ -9788,13 +10027,14 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9788
10027
|
context.$qrl$ = qrl;
|
|
9789
10028
|
context.$event$ ||= this;
|
|
9790
10029
|
try {
|
|
9791
|
-
return invoke.call(this, context,
|
|
10030
|
+
return invoke.call(this, context, symbolRef, ...args);
|
|
9792
10031
|
}
|
|
9793
10032
|
finally {
|
|
9794
10033
|
context.$qrl$ = prevQrl;
|
|
9795
10034
|
context.$event$ = prevEvent;
|
|
9796
10035
|
}
|
|
9797
|
-
}
|
|
10036
|
+
};
|
|
10037
|
+
return bound;
|
|
9798
10038
|
}
|
|
9799
10039
|
const resolveLazy = (containerEl) => {
|
|
9800
10040
|
return symbolRef !== null ? symbolRef : resolve(containerEl);
|
|
@@ -9806,8 +10046,20 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9806
10046
|
}
|
|
9807
10047
|
return function (...args) {
|
|
9808
10048
|
let context = tryGetInvokeContext();
|
|
10049
|
+
// use the given qrl if it is the right one
|
|
9809
10050
|
if (context) {
|
|
9810
|
-
|
|
10051
|
+
// TODO check if this is necessary in production
|
|
10052
|
+
if (context.$qrl$?.$symbol$ === qrl.$symbol$) {
|
|
10053
|
+
return fn.apply(this, args);
|
|
10054
|
+
}
|
|
10055
|
+
const prevQrl = context.$qrl$;
|
|
10056
|
+
context.$qrl$ = qrl;
|
|
10057
|
+
try {
|
|
10058
|
+
return fn.apply(this, args);
|
|
10059
|
+
}
|
|
10060
|
+
finally {
|
|
10061
|
+
context.$qrl$ = prevQrl;
|
|
10062
|
+
}
|
|
9811
10063
|
}
|
|
9812
10064
|
context = newInvokeContext();
|
|
9813
10065
|
context.$qrl$ = qrl;
|
|
@@ -9835,11 +10087,11 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9835
10087
|
const start = now();
|
|
9836
10088
|
const ctx = tryGetInvokeContext();
|
|
9837
10089
|
if (symbolFn !== null) {
|
|
9838
|
-
symbolRef = symbolFn().then((module) => (qrl.resolved = symbolRef =
|
|
10090
|
+
symbolRef = symbolFn().then((module) => (qrl.resolved = wrapFn((symbolRef = module[symbol]))));
|
|
9839
10091
|
}
|
|
9840
10092
|
else {
|
|
9841
10093
|
const imported = getPlatform().importSymbol(_containerEl, chunk, symbol);
|
|
9842
|
-
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = symbolRef =
|
|
10094
|
+
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = wrapFn((symbolRef = ref))));
|
|
9843
10095
|
}
|
|
9844
10096
|
if (typeof symbolRef === 'object' && isPromise(symbolRef)) {
|
|
9845
10097
|
symbolRef.then(() => emitUsedSymbol(symbol, ctx?.$element$, start), (err) => {
|
|
@@ -9862,10 +10114,9 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9862
10114
|
return invoke;
|
|
9863
10115
|
}
|
|
9864
10116
|
};
|
|
9865
|
-
const
|
|
9866
|
-
const hash = getSymbolHash(resolvedSymbol);
|
|
10117
|
+
const hash = getSymbolHash(symbol);
|
|
9867
10118
|
Object.assign(qrl, {
|
|
9868
|
-
getSymbol: () =>
|
|
10119
|
+
getSymbol: () => symbol,
|
|
9869
10120
|
getHash: () => hash,
|
|
9870
10121
|
getCaptured: () => captureRef,
|
|
9871
10122
|
resolve,
|
|
@@ -9873,7 +10124,6 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9873
10124
|
$setContainer$: setContainer,
|
|
9874
10125
|
$chunk$: chunk,
|
|
9875
10126
|
$symbol$: symbol,
|
|
9876
|
-
$refSymbol$: refSymbol,
|
|
9877
10127
|
$hash$: hash,
|
|
9878
10128
|
getFn: bindFnToContext,
|
|
9879
10129
|
$capture$: capture,
|
|
@@ -9882,8 +10132,8 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9882
10132
|
resolved: undefined,
|
|
9883
10133
|
});
|
|
9884
10134
|
if (symbolRef) {
|
|
9885
|
-
//
|
|
9886
|
-
symbolRef = maybeThen(symbolRef, (resolved) => (qrl.resolved = symbolRef =
|
|
10135
|
+
// Unwrap any promises
|
|
10136
|
+
symbolRef = maybeThen(symbolRef, (resolved) => (qrl.resolved = wrapFn((symbolRef = resolved))));
|
|
9887
10137
|
}
|
|
9888
10138
|
if (isDev) {
|
|
9889
10139
|
Object.defineProperty(qrl, '_devOnlySymbolRef', {
|
|
@@ -9897,20 +10147,6 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9897
10147
|
}
|
|
9898
10148
|
return qrl;
|
|
9899
10149
|
};
|
|
9900
|
-
const getSymbolHash = (symbolName) => {
|
|
9901
|
-
const index = symbolName.lastIndexOf('_');
|
|
9902
|
-
if (index > -1) {
|
|
9903
|
-
return symbolName.slice(index + 1);
|
|
9904
|
-
}
|
|
9905
|
-
return symbolName;
|
|
9906
|
-
};
|
|
9907
|
-
function assertQrl(qrl) {
|
|
9908
|
-
if (qDev) {
|
|
9909
|
-
if (!isQrl(qrl)) {
|
|
9910
|
-
throw new Error('Not a QRL');
|
|
9911
|
-
}
|
|
9912
|
-
}
|
|
9913
|
-
}
|
|
9914
10150
|
const EMITTED = /*#__PURE__*/ new Set();
|
|
9915
10151
|
const emitUsedSymbol = (symbol, element, reqTime) => {
|
|
9916
10152
|
if (!EMITTED.has(symbol)) {
|
|
@@ -10023,7 +10259,7 @@ const $ = (expression) => {
|
|
|
10023
10259
|
if (!qRuntimeQrl && qDev) {
|
|
10024
10260
|
throw new Error('Optimizer should replace all usages of $() with some special syntax. If you need to create a QRL manually, use inlinedQrl() instead.');
|
|
10025
10261
|
}
|
|
10026
|
-
return createQRL(null, 's' + runtimeSymbolId++, expression, null, null, null
|
|
10262
|
+
return createQRL(null, 's' + runtimeSymbolId++, expression, null, null, null);
|
|
10027
10263
|
};
|
|
10028
10264
|
/** @private Use To avoid optimizer replacement */
|
|
10029
10265
|
const dollar = $;
|
|
@@ -10049,7 +10285,7 @@ const sync$ = (fn) => {
|
|
|
10049
10285
|
// eslint-disable-next-line no-new-func
|
|
10050
10286
|
fn = new Function('return ' + fn.toString())();
|
|
10051
10287
|
}
|
|
10052
|
-
return createQRL('', SYNC_QRL, fn, null, null, null
|
|
10288
|
+
return createQRL('', SYNC_QRL, fn, null, null, null);
|
|
10053
10289
|
};
|
|
10054
10290
|
/**
|
|
10055
10291
|
* Extract function into a synchronously loadable QRL.
|
|
@@ -10066,7 +10302,7 @@ const _qrlSync = function (fn, serializedFn) {
|
|
|
10066
10302
|
serializedFn = fn.toString();
|
|
10067
10303
|
}
|
|
10068
10304
|
fn.serialized = serializedFn;
|
|
10069
|
-
return createQRL('', SYNC_QRL, fn, null, null, null
|
|
10305
|
+
return createQRL('', SYNC_QRL, fn, null, null, null);
|
|
10070
10306
|
};
|
|
10071
10307
|
|
|
10072
10308
|
/** @internal */
|
|
@@ -10785,6 +11021,21 @@ const useVisibleTaskQrl = (qrl, opts) => {
|
|
|
10785
11021
|
iCtx.$container$.$scheduler$(ChoreType.VISIBLE, task);
|
|
10786
11022
|
}
|
|
10787
11023
|
};
|
|
11024
|
+
const useRunTask = (task, eagerness) => {
|
|
11025
|
+
if (eagerness === 'intersection-observer') {
|
|
11026
|
+
useOn('qvisible', getTaskHandlerQrl(task));
|
|
11027
|
+
}
|
|
11028
|
+
else if (eagerness === 'document-ready') {
|
|
11029
|
+
useOnDocument('qinit', getTaskHandlerQrl(task));
|
|
11030
|
+
}
|
|
11031
|
+
else if (eagerness === 'document-idle') {
|
|
11032
|
+
useOnDocument('qidle', getTaskHandlerQrl(task));
|
|
11033
|
+
}
|
|
11034
|
+
};
|
|
11035
|
+
const getTaskHandlerQrl = (task) => {
|
|
11036
|
+
const taskHandler = createQRL(null, '_task', scheduleTask, null, null, [task]);
|
|
11037
|
+
return taskHandler;
|
|
11038
|
+
};
|
|
10788
11039
|
|
|
10789
11040
|
// <docs markdown="../readme.md#useResource">
|
|
10790
11041
|
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
@@ -11095,5 +11346,5 @@ const PrefetchGraph = (opts = {}) => {
|
|
|
11095
11346
|
return _jsxSorted('script', null, props, null, 0, 'prefetch-graph');
|
|
11096
11347
|
};
|
|
11097
11348
|
|
|
11098
|
-
export { $, Fragment, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, EMPTY_ARRAY as _EMPTY_ARRAY,
|
|
11349
|
+
export { $, Fragment, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, SubscriptionData as _EffectData, _IMMUTABLE, _SharedContainer, _VAR_PROPS, _deserialize, _fnSignal, _getContextElement, _getContextEvent, getDomContainer as _getDomContainer, _getQContainerElement, isJSXNode as _isJSXNode, isStringifiable as _isStringifiable, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, _noopQrl, _noopQrlDEV, _qrlSync, _regSymbol, _restProps, queueQRL as _run, _serialize, scheduleTask as _task, verifySerializable as _verifySerializable, _waitUntilRendered, _walkJSX, _weakSerialize, _wrapProp, _wrapSignal, component$, componentQrl, createComputed$, createComputedQrl, createContextId, h as createElement, createSignal, event$, eventQrl, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsx as jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
|
|
11099
11350
|
//# sourceMappingURL=core.mjs.map
|