@qwik.dev/core 2.0.0-beta.1 → 2.0.0-beta.10
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/backpatch/index.cjs +6 -0
- package/dist/backpatch/index.d.ts +2 -0
- package/dist/backpatch/index.mjs +5 -0
- package/dist/backpatch/package.json +8 -0
- package/dist/backpatch-executor.debug.js +34 -0
- package/dist/backpatch-executor.js +1 -0
- package/dist/build/package.json +1 -1
- package/dist/cli.cjs +3031 -763
- package/dist/core-internal.d.ts +253 -78
- package/dist/core.cjs +1770 -957
- package/dist/core.cjs.map +1 -1
- package/dist/core.min.mjs +1 -1
- package/dist/core.mjs +1745 -955
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.cjs +1368 -949
- package/dist/core.prod.mjs +1435 -951
- package/dist/insights/vite/index.cjs +1 -1
- package/dist/insights/vite/index.mjs +10 -10
- 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 +201 -4016
- package/dist/optimizer.d.ts +12 -37
- package/dist/optimizer.mjs +2539 -3715
- package/dist/preloader.cjs +8 -11
- package/dist/preloader.mjs +8 -11
- package/dist/qwikloader.debug.js +1 -15
- package/dist/qwikloader.js +1 -1
- package/dist/server.cjs +309 -116
- package/dist/server.d.ts +17 -2
- package/dist/server.mjs +291 -103
- package/dist/starters/adapters/aws-lambda/adapters/aws-lambda/vite.config.mts +1 -1
- package/dist/starters/adapters/aws-lambda/package.json +1 -1
- package/dist/starters/adapters/aws-lambda/src/entry_aws-lambda.tsx +2 -6
- package/dist/starters/adapters/azure-swa/adapters/azure-swa/vite.config.mts +1 -1
- package/dist/starters/adapters/azure-swa/package.json +1 -1
- package/dist/starters/adapters/azure-swa/src/entry.azure-swa.tsx +2 -3
- package/dist/starters/adapters/bun/adapters/bun/vite.config.mts +2 -2
- package/dist/starters/adapters/bun/package.json +1 -1
- package/dist/starters/adapters/bun/src/entry.bun.ts +0 -2
- package/dist/starters/adapters/cloud-run/adapters/cloud-run/vite.config.mts +1 -1
- package/dist/starters/adapters/cloud-run/package.json +1 -1
- package/dist/starters/adapters/cloud-run/src/entry.cloud-run.tsx +1 -3
- package/dist/starters/adapters/cloudflare-pages/adapters/cloudflare-pages/vite.config.mts +1 -1
- package/dist/starters/adapters/cloudflare-pages/package.json +1 -1
- package/dist/starters/adapters/cloudflare-pages/src/entry.cloudflare-pages.tsx +2 -3
- package/dist/starters/adapters/deno/adapters/deno/vite.config.mts +1 -1
- package/dist/starters/adapters/deno/package.json +1 -1
- package/dist/starters/adapters/deno/src/entry.deno.ts +0 -2
- package/dist/starters/adapters/express/adapters/express/vite.config.mts +1 -1
- package/dist/starters/adapters/express/package.json +1 -1
- package/dist/starters/adapters/express/src/entry.express.tsx +1 -3
- package/dist/starters/adapters/fastify/adapters/fastify/vite.config.mts +1 -1
- package/dist/starters/adapters/fastify/package.json +1 -1
- package/dist/starters/adapters/fastify/src/entry.fastify.tsx +1 -1
- package/dist/starters/adapters/fastify/src/plugins/fastify-qwik.ts +1 -2
- package/dist/starters/adapters/firebase/adapters/firebase/vite.config.mts +1 -1
- package/dist/starters/adapters/firebase/package.json +1 -1
- package/dist/starters/adapters/firebase/src/entry-firebase.tsx +2 -3
- package/dist/starters/adapters/netlify-edge/adapters/netlify-edge/vite.config.mts +1 -1
- package/dist/starters/adapters/netlify-edge/package.json +1 -1
- package/dist/starters/adapters/netlify-edge/src/entry.netlify-edge.tsx +2 -3
- package/dist/starters/adapters/node-server/adapters/node-server/vite.config.mts +1 -1
- package/dist/starters/adapters/node-server/package.json +1 -1
- package/dist/starters/adapters/node-server/src/entry.node-server.tsx +0 -2
- package/dist/starters/adapters/{static/adapters/static → ssg/adapters/ssg}/vite.config.mts +2 -2
- package/dist/starters/adapters/ssg/package.json +19 -0
- package/dist/starters/adapters/vercel-edge/adapters/vercel-edge/vite.config.mts +1 -1
- package/dist/starters/adapters/vercel-edge/package.json +1 -1
- package/dist/starters/adapters/vercel-edge/src/entry.vercel-edge.tsx +2 -3
- package/dist/starters/adapters/vercel-edge/vercel.json +1 -1
- package/dist/starters/features/auth/package.json +1 -1
- package/dist/starters/features/csr/index.html +23 -0
- package/dist/starters/features/csr/package.json +29 -0
- package/dist/starters/features/csr/src/root.tsx +15 -0
- package/dist/starters/features/csr/vite.config.mts +13 -0
- package/dist/starters/features/localize/package.json +3 -3
- package/dist/starters/features/localize/src/entry.ssr.tsx +17 -21
- package/dist/starters/features/pandacss/package.json +1 -1
- package/dist/starters/features/playwright/playwright-report/index.html +953 -911
- package/dist/starters/features/postcss/postcss.config.js +1 -1
- package/dist/starters/features/tailwind/package.json +2 -2
- package/dist/starters/features/tailwind/prettier.config.js +10 -0
- package/dist/starters/features/tailwind-v3/package.json +1 -1
- package/dist/starters/features/tailwind-v3/prettier.config.js +10 -0
- package/dist/testing/index.cjs +7556 -5229
- package/dist/testing/index.d.ts +972 -1
- package/dist/testing/index.mjs +7456 -5140
- package/dist/testing/package.json +1 -1
- package/package.json +16 -10
- package/public.d.ts +1 -0
- package/dist/starters/adapters/static/package.json +0 -19
- package/dist/starters/features/tailwind/.prettierrc.js +0 -3
- /package/dist/starters/adapters/{static → ssg}/README.md +0 -0
package/dist/core.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* @qwik.dev/core 2.0.0-beta.
|
|
3
|
+
* @qwik.dev/core 2.0.0-beta.10-dev+4669425
|
|
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
|
|
@@ -9,6 +9,13 @@ import { isDev, isServer, isBrowser } from '@qwik.dev/core/build';
|
|
|
9
9
|
export { isBrowser, isDev, isServer } from '@qwik.dev/core/build';
|
|
10
10
|
import { p } from '@qwik.dev/core/preloader';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* QWIK_VERSION
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
const version = "2.0.0-beta.10-dev+4669425";
|
|
18
|
+
|
|
12
19
|
// same as isDev but separate so we can test
|
|
13
20
|
const qDev = globalThis.qDev !== false;
|
|
14
21
|
const qInspector = globalThis.qInspector === true;
|
|
@@ -72,6 +79,30 @@ const createAndLogError = (asyncThrow, message, ...optionalParams) => {
|
|
|
72
79
|
return err;
|
|
73
80
|
};
|
|
74
81
|
|
|
82
|
+
/** @private */
|
|
83
|
+
const isSerializableObject = (v) => {
|
|
84
|
+
const proto = Object.getPrototypeOf(v);
|
|
85
|
+
return proto === Object.prototype || proto === Array.prototype || proto === null;
|
|
86
|
+
};
|
|
87
|
+
const isObject = (v) => {
|
|
88
|
+
return typeof v === 'object' && v !== null;
|
|
89
|
+
};
|
|
90
|
+
const isArray = (v) => {
|
|
91
|
+
return Array.isArray(v);
|
|
92
|
+
};
|
|
93
|
+
const isString = (v) => {
|
|
94
|
+
return typeof v === 'string';
|
|
95
|
+
};
|
|
96
|
+
const isNumber$1 = (v) => {
|
|
97
|
+
return typeof v === 'number';
|
|
98
|
+
};
|
|
99
|
+
const isFunction = (v) => {
|
|
100
|
+
return typeof v === 'function';
|
|
101
|
+
};
|
|
102
|
+
const isPrimitive = (v) => {
|
|
103
|
+
return typeof v !== 'object' && typeof v !== 'function' && v !== null && v !== undefined;
|
|
104
|
+
};
|
|
105
|
+
|
|
75
106
|
const codeToText = (code, ...parts) => {
|
|
76
107
|
if (qDev) {
|
|
77
108
|
// Keep one error, one line to make it easier to search for the error message.
|
|
@@ -116,7 +147,7 @@ const codeToText = (code, ...parts) => {
|
|
|
116
147
|
if (parts.length) {
|
|
117
148
|
text = text.replaceAll(/{{(\d+)}}/g, (_, index) => {
|
|
118
149
|
let v = parts[index];
|
|
119
|
-
if (v &&
|
|
150
|
+
if (v && isObject(v) && v.constructor === Object) {
|
|
120
151
|
v = JSON.stringify(v).slice(0, 50);
|
|
121
152
|
}
|
|
122
153
|
return v;
|
|
@@ -195,9 +226,13 @@ const QContainerSelector = '[q\\:container]:not([q\\:container=' +
|
|
|
195
226
|
']):not([q\\:container=' +
|
|
196
227
|
"text" /* QContainerValue.TEXT */ +
|
|
197
228
|
'])';
|
|
229
|
+
// Node namespaces
|
|
198
230
|
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
|
199
231
|
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
200
232
|
const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
|
|
233
|
+
// Attributes namespaces
|
|
234
|
+
const XLINK_NS = 'http://www.w3.org/1999/xlink';
|
|
235
|
+
const XML_NS = 'http://www.w3.org/XML/1998/namespace';
|
|
201
236
|
const ResourceEvent = 'qResource';
|
|
202
237
|
const RenderEvent = 'qRender';
|
|
203
238
|
const TaskEvent = 'qTask';
|
|
@@ -263,13 +298,6 @@ const createPlatform = () => {
|
|
|
263
298
|
});
|
|
264
299
|
});
|
|
265
300
|
},
|
|
266
|
-
nextTick: (fn) => {
|
|
267
|
-
return new Promise((resolve) => {
|
|
268
|
-
setTimeout(() => {
|
|
269
|
-
resolve(fn());
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
},
|
|
273
301
|
chunkForSymbol(symbolName, chunk) {
|
|
274
302
|
return [symbolName, chunk ?? '_'];
|
|
275
303
|
},
|
|
@@ -377,7 +405,7 @@ const delay = (timeout) => {
|
|
|
377
405
|
setTimeout(resolve, timeout);
|
|
378
406
|
});
|
|
379
407
|
};
|
|
380
|
-
|
|
408
|
+
/** Retries a function that throws a promise. */
|
|
381
409
|
function retryOnPromise(fn, retryCount = 0) {
|
|
382
410
|
const retryOrThrow = (e) => {
|
|
383
411
|
if (isPromise(e) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
@@ -402,24 +430,6 @@ function retryOnPromise(fn, retryCount = 0) {
|
|
|
402
430
|
}
|
|
403
431
|
}
|
|
404
432
|
|
|
405
|
-
/** @private */
|
|
406
|
-
const isSerializableObject = (v) => {
|
|
407
|
-
const proto = Object.getPrototypeOf(v);
|
|
408
|
-
return proto === Object.prototype || proto === Array.prototype || proto === null;
|
|
409
|
-
};
|
|
410
|
-
const isObject = (v) => {
|
|
411
|
-
return !!v && typeof v === 'object';
|
|
412
|
-
};
|
|
413
|
-
const isArray = (v) => {
|
|
414
|
-
return Array.isArray(v);
|
|
415
|
-
};
|
|
416
|
-
const isString = (v) => {
|
|
417
|
-
return typeof v === 'string';
|
|
418
|
-
};
|
|
419
|
-
const isFunction = (v) => {
|
|
420
|
-
return typeof v === 'function';
|
|
421
|
-
};
|
|
422
|
-
|
|
423
433
|
const ASSERT_DISCLAIMER = 'Internal assert, this is likely caused by a bug in Qwik: ';
|
|
424
434
|
function assertDefined(value, text, ...parts) {
|
|
425
435
|
if (qDev) {
|
|
@@ -545,6 +555,13 @@ class SignalImpl {
|
|
|
545
555
|
this.$container$ = container;
|
|
546
556
|
this.$untrackedValue$ = value;
|
|
547
557
|
}
|
|
558
|
+
/**
|
|
559
|
+
* Use this to force running subscribers, for example when the calculated value has mutated but
|
|
560
|
+
* remained the same object
|
|
561
|
+
*/
|
|
562
|
+
force() {
|
|
563
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
|
|
564
|
+
}
|
|
548
565
|
get untrackedValue() {
|
|
549
566
|
return this.$untrackedValue$;
|
|
550
567
|
}
|
|
@@ -558,14 +575,7 @@ class SignalImpl {
|
|
|
558
575
|
set value(value) {
|
|
559
576
|
if (value !== this.$untrackedValue$) {
|
|
560
577
|
this.$untrackedValue$ = value;
|
|
561
|
-
|
|
562
|
-
triggerEffects(this.$container$, this, this.$effects$);
|
|
563
|
-
// this.$container$?.$scheduler$(
|
|
564
|
-
// ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
|
|
565
|
-
// null,
|
|
566
|
-
// this,
|
|
567
|
-
// this.$effects$
|
|
568
|
-
// );
|
|
578
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
|
|
569
579
|
}
|
|
570
580
|
}
|
|
571
581
|
// prevent accidental use as value
|
|
@@ -627,23 +637,19 @@ class WrappedSignalImpl extends SignalImpl {
|
|
|
627
637
|
$funcStr$;
|
|
628
638
|
$flags$;
|
|
629
639
|
$hostElement$ = null;
|
|
630
|
-
$forceRunEffects$ = false;
|
|
631
640
|
[_EFFECT_BACK_REF] = null;
|
|
632
641
|
constructor(container, fn, args, fnStr,
|
|
633
642
|
// We need a separate flag to know when the computation needs running because
|
|
634
643
|
// we need the old value to know if effects need running after computation
|
|
635
|
-
flags = 1 /* SignalFlags.INVALID */ |
|
|
644
|
+
flags = 1 /* SignalFlags.INVALID */ | 4 /* WrappedSignalFlags.UNWRAP */) {
|
|
636
645
|
super(container, NEEDS_COMPUTATION);
|
|
637
646
|
this.$args$ = args;
|
|
638
647
|
this.$func$ = fn;
|
|
639
648
|
this.$funcStr$ = fnStr;
|
|
640
649
|
this.$flags$ = flags;
|
|
641
650
|
}
|
|
642
|
-
|
|
651
|
+
invalidate() {
|
|
643
652
|
this.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
644
|
-
this.$forceRunEffects$ = false;
|
|
645
|
-
// We should only call subscribers if the calculation actually changed.
|
|
646
|
-
// Therefore, we need to calculate the value now.
|
|
647
653
|
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
|
|
648
654
|
}
|
|
649
655
|
/**
|
|
@@ -651,30 +657,26 @@ class WrappedSignalImpl extends SignalImpl {
|
|
|
651
657
|
* remained the same object.
|
|
652
658
|
*/
|
|
653
659
|
force() {
|
|
654
|
-
this.$flags$ |=
|
|
655
|
-
this.$
|
|
656
|
-
triggerEffects(this.$container$, this, this.$effects$);
|
|
660
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
661
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
|
|
657
662
|
}
|
|
658
663
|
get untrackedValue() {
|
|
659
|
-
|
|
660
|
-
if (didChange) {
|
|
661
|
-
this.$forceRunEffects$ = didChange;
|
|
662
|
-
}
|
|
664
|
+
this.$computeIfNeeded$();
|
|
663
665
|
assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
|
|
664
666
|
return this.$untrackedValue$;
|
|
665
667
|
}
|
|
666
668
|
$computeIfNeeded$() {
|
|
667
669
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
668
|
-
return
|
|
670
|
+
return;
|
|
669
671
|
}
|
|
670
672
|
const untrackedValue = trackSignal(() => this.$func$(...this.$args$), this, "." /* EffectProperty.VNODE */, this.$container$);
|
|
671
|
-
// TODO: we should remove invalid flag here
|
|
673
|
+
// TODO: we should remove invalid flag here, but some tests are failing
|
|
672
674
|
// this.$flags$ &= ~SignalFlags.INVALID;
|
|
673
675
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
674
676
|
if (didChange) {
|
|
677
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
675
678
|
this.$untrackedValue$ = untrackedValue;
|
|
676
679
|
}
|
|
677
|
-
return didChange;
|
|
678
680
|
}
|
|
679
681
|
// Make this signal read-only
|
|
680
682
|
set value(_) {
|
|
@@ -711,7 +713,6 @@ function isSsrNode(value) {
|
|
|
711
713
|
}
|
|
712
714
|
|
|
713
715
|
let _context;
|
|
714
|
-
/** @public */
|
|
715
716
|
const tryGetInvokeContext = () => {
|
|
716
717
|
if (!_context) {
|
|
717
718
|
const context = typeof document !== 'undefined' && document && document.__q_context__;
|
|
@@ -732,6 +733,7 @@ const getInvokeContext = () => {
|
|
|
732
733
|
}
|
|
733
734
|
return ctx;
|
|
734
735
|
};
|
|
736
|
+
/** @internal */
|
|
735
737
|
const useInvokeContext = () => {
|
|
736
738
|
const ctx = tryGetInvokeContext();
|
|
737
739
|
if (!ctx || ctx.$event$ !== RenderEvent) {
|
|
@@ -777,7 +779,7 @@ const newInvokeContextFromTuple = ([element, event, url]) => {
|
|
|
777
779
|
// TODO how about putting url and locale (and event/custom?) in to a "static" object
|
|
778
780
|
const newInvokeContext = (locale, hostElement, element, event, url) => {
|
|
779
781
|
// ServerRequestEvent has .locale, but it's not always defined.
|
|
780
|
-
const $locale$ = locale || (
|
|
782
|
+
const $locale$ = locale || (event && isObject(event) && 'locale' in event ? event.locale : undefined);
|
|
781
783
|
const ctx = {
|
|
782
784
|
$url$: url,
|
|
783
785
|
$i$: 0,
|
|
@@ -857,17 +859,38 @@ const _getContextEvent = () => {
|
|
|
857
859
|
}
|
|
858
860
|
};
|
|
859
861
|
/** @internal */
|
|
862
|
+
const _getContextContainer = () => {
|
|
863
|
+
const iCtx = tryGetInvokeContext();
|
|
864
|
+
if (iCtx) {
|
|
865
|
+
return iCtx.$container$;
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
/** @internal */
|
|
860
869
|
const _jsxBranch = (input) => {
|
|
861
870
|
return input;
|
|
862
871
|
};
|
|
863
872
|
/** @internal */
|
|
864
873
|
const _waitUntilRendered = (elm) => {
|
|
865
|
-
const
|
|
866
|
-
if (!
|
|
874
|
+
const container = _getQContainerElement(elm)?.qContainer;
|
|
875
|
+
if (!container) {
|
|
867
876
|
return Promise.resolve();
|
|
868
877
|
}
|
|
869
|
-
|
|
870
|
-
|
|
878
|
+
// Multi-cycle idle: loop WAIT_FOR_QUEUE until the flush epoch stays stable
|
|
879
|
+
// across an extra microtask, which signals that no new work re-scheduled.
|
|
880
|
+
return (async () => {
|
|
881
|
+
for (;;) {
|
|
882
|
+
await container.$scheduler$(255 /* ChoreType.WAIT_FOR_QUEUE */).$returnValue$;
|
|
883
|
+
const firstEpoch = container.$flushEpoch$ || 0;
|
|
884
|
+
// Give a microtask for any immediate follow-up scheduling to enqueue
|
|
885
|
+
await Promise.resolve();
|
|
886
|
+
const secondEpoch = container.$flushEpoch$ || 0;
|
|
887
|
+
// If no epoch change occurred during and after WAIT_FOR_QUEUE, we are idle.
|
|
888
|
+
if (firstEpoch === secondEpoch) {
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
// Continue loop if epoch advanced, meaning more work flushed.
|
|
892
|
+
}
|
|
893
|
+
})();
|
|
871
894
|
};
|
|
872
895
|
|
|
873
896
|
/**
|
|
@@ -945,7 +968,7 @@ function jsxEventToHtmlAttribute(jsxEvent) {
|
|
|
945
968
|
}
|
|
946
969
|
return null; // Return null if not matching expected format
|
|
947
970
|
}
|
|
948
|
-
function eventNameToJsxEvent(eventName, prefix
|
|
971
|
+
function eventNameToJsxEvent(eventName, prefix) {
|
|
949
972
|
eventName = eventName.charAt(0).toUpperCase() + eventName.substring(1);
|
|
950
973
|
return prefix + eventName + EVENT_SUFFIX;
|
|
951
974
|
}
|
|
@@ -1214,6 +1237,15 @@ const validateContext = (context) => {
|
|
|
1214
1237
|
throw qError(11 /* QError.invalidContext */, [context]);
|
|
1215
1238
|
}
|
|
1216
1239
|
};
|
|
1240
|
+
/** @internal */
|
|
1241
|
+
const _resolveContextWithoutSequentialScope = (context) => {
|
|
1242
|
+
const iCtx = getInvokeContext();
|
|
1243
|
+
const hostElement = iCtx.$hostElement$;
|
|
1244
|
+
if (!hostElement) {
|
|
1245
|
+
return undefined;
|
|
1246
|
+
}
|
|
1247
|
+
return iCtx.$container$?.resolveContext(hostElement, context);
|
|
1248
|
+
};
|
|
1217
1249
|
|
|
1218
1250
|
const ERROR_CONTEXT = /*#__PURE__*/ createContextId('qk-error');
|
|
1219
1251
|
const isRecoverable = (err) => {
|
|
@@ -1225,13 +1257,6 @@ const isRecoverable = (err) => {
|
|
|
1225
1257
|
return true;
|
|
1226
1258
|
};
|
|
1227
1259
|
|
|
1228
|
-
/**
|
|
1229
|
-
* QWIK_VERSION
|
|
1230
|
-
*
|
|
1231
|
-
* @public
|
|
1232
|
-
*/
|
|
1233
|
-
const version = "2.0.0-beta.1-dev+495e8d9";
|
|
1234
|
-
|
|
1235
1260
|
/** @internal */
|
|
1236
1261
|
const EMPTY_ARRAY = [];
|
|
1237
1262
|
const EMPTY_OBJ = {};
|
|
@@ -1372,7 +1397,7 @@ const useLexicalScope = () => {
|
|
|
1372
1397
|
*
|
|
1373
1398
|
* @internal
|
|
1374
1399
|
*/
|
|
1375
|
-
const
|
|
1400
|
+
const _run = (...args) => {
|
|
1376
1401
|
// This will already check container
|
|
1377
1402
|
const [runQrl] = useLexicalScope();
|
|
1378
1403
|
const context = getInvokeContext();
|
|
@@ -1386,7 +1411,58 @@ const queueQRL = (...args) => {
|
|
|
1386
1411
|
if (!scheduler) {
|
|
1387
1412
|
throw qError(1 /* QError.schedulerNotFound */);
|
|
1388
1413
|
}
|
|
1389
|
-
return
|
|
1414
|
+
// We don't return anything, the scheduler is in charge now
|
|
1415
|
+
const chore = scheduler(2 /* ChoreType.RUN_QRL */, hostElement, runQrl, args);
|
|
1416
|
+
return getChorePromise(chore);
|
|
1417
|
+
};
|
|
1418
|
+
|
|
1419
|
+
/** @internal */
|
|
1420
|
+
const mapApp_findIndx = (array, key, start) => {
|
|
1421
|
+
assertTrue(start % 2 === 0, 'Expecting even number.');
|
|
1422
|
+
let bottom = start >> 1;
|
|
1423
|
+
let top = (array.length - 2) >> 1;
|
|
1424
|
+
while (bottom <= top) {
|
|
1425
|
+
const mid = bottom + ((top - bottom) >> 1);
|
|
1426
|
+
const midKey = array[mid << 1];
|
|
1427
|
+
if (midKey === key) {
|
|
1428
|
+
return mid << 1;
|
|
1429
|
+
}
|
|
1430
|
+
if (midKey < key) {
|
|
1431
|
+
bottom = mid + 1;
|
|
1432
|
+
}
|
|
1433
|
+
else {
|
|
1434
|
+
top = mid - 1;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
return (bottom << 1) ^ -1;
|
|
1438
|
+
};
|
|
1439
|
+
/** @internal */
|
|
1440
|
+
const mapArray_set = (array, key, value, start, allowNullValue = false) => {
|
|
1441
|
+
const indx = mapApp_findIndx(array, key, start);
|
|
1442
|
+
if (indx >= 0) {
|
|
1443
|
+
if (value == null && !allowNullValue) {
|
|
1444
|
+
array.splice(indx, 2);
|
|
1445
|
+
}
|
|
1446
|
+
else {
|
|
1447
|
+
array[indx + 1] = value;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
else if (value != null || allowNullValue) {
|
|
1451
|
+
array.splice(indx ^ -1, 0, key, value);
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
/** @internal */
|
|
1455
|
+
const mapArray_get = (array, key, start) => {
|
|
1456
|
+
const indx = mapApp_findIndx(array, key, start);
|
|
1457
|
+
if (indx >= 0) {
|
|
1458
|
+
return array[indx + 1];
|
|
1459
|
+
}
|
|
1460
|
+
else {
|
|
1461
|
+
return null;
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
const mapArray_has = (array, key, start) => {
|
|
1465
|
+
return mapApp_findIndx(array, key, start) >= 0;
|
|
1390
1466
|
};
|
|
1391
1467
|
|
|
1392
1468
|
/** @internal */
|
|
@@ -1395,6 +1471,8 @@ const _CONST_PROPS = Symbol('CONST');
|
|
|
1395
1471
|
const _VAR_PROPS = Symbol('VAR');
|
|
1396
1472
|
/** @internal @deprecated v1 compat */
|
|
1397
1473
|
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
1474
|
+
/** @internal */
|
|
1475
|
+
const _UNINITIALIZED = Symbol('UNINITIALIZED');
|
|
1398
1476
|
|
|
1399
1477
|
// <docs markdown="../../readme.md#implicit$FirstArg">
|
|
1400
1478
|
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
@@ -1459,21 +1537,20 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
1459
1537
|
*/
|
|
1460
1538
|
$computeQrl$;
|
|
1461
1539
|
$flags$;
|
|
1462
|
-
$forceRunEffects$ = false;
|
|
1463
1540
|
[_EFFECT_BACK_REF] = null;
|
|
1464
1541
|
constructor(container, fn,
|
|
1465
1542
|
// We need a separate flag to know when the computation needs running because
|
|
1466
1543
|
// we need the old value to know if effects need running after computation
|
|
1467
|
-
flags = 1 /* SignalFlags.INVALID */
|
|
1544
|
+
flags = 1 /* SignalFlags.INVALID */ |
|
|
1545
|
+
32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */) {
|
|
1468
1546
|
// The value is used for comparison when signals trigger, which can only happen
|
|
1469
1547
|
// when it was calculated before. Therefore we can pass whatever we like.
|
|
1470
1548
|
super(container, NEEDS_COMPUTATION);
|
|
1471
1549
|
this.$computeQrl$ = fn;
|
|
1472
1550
|
this.$flags$ = flags;
|
|
1473
1551
|
}
|
|
1474
|
-
|
|
1552
|
+
invalidate() {
|
|
1475
1553
|
this.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
1476
|
-
this.$forceRunEffects$ = false;
|
|
1477
1554
|
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
|
|
1478
1555
|
}
|
|
1479
1556
|
/**
|
|
@@ -1481,20 +1558,17 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
1481
1558
|
* remained the same object
|
|
1482
1559
|
*/
|
|
1483
1560
|
force() {
|
|
1484
|
-
this.$
|
|
1485
|
-
|
|
1561
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1562
|
+
super.force();
|
|
1486
1563
|
}
|
|
1487
1564
|
get untrackedValue() {
|
|
1488
|
-
|
|
1489
|
-
if (didChange) {
|
|
1490
|
-
this.$forceRunEffects$ = didChange;
|
|
1491
|
-
}
|
|
1565
|
+
this.$computeIfNeeded$();
|
|
1492
1566
|
assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
|
|
1493
1567
|
return this.$untrackedValue$;
|
|
1494
1568
|
}
|
|
1495
1569
|
$computeIfNeeded$() {
|
|
1496
1570
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
1497
|
-
return
|
|
1571
|
+
return;
|
|
1498
1572
|
}
|
|
1499
1573
|
const computeQrl = this.$computeQrl$;
|
|
1500
1574
|
throwIfQRLNotResolved(computeQrl);
|
|
@@ -1513,9 +1587,12 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
1513
1587
|
this.$flags$ &= ~1 /* SignalFlags.INVALID */;
|
|
1514
1588
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
1515
1589
|
if (didChange) {
|
|
1590
|
+
// skip first computation when value is not changed
|
|
1591
|
+
if (this.$untrackedValue$ !== NEEDS_COMPUTATION) {
|
|
1592
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1593
|
+
}
|
|
1516
1594
|
this.$untrackedValue$ = untrackedValue;
|
|
1517
1595
|
}
|
|
1518
|
-
return didChange;
|
|
1519
1596
|
}
|
|
1520
1597
|
finally {
|
|
1521
1598
|
if (ctx) {
|
|
@@ -1541,12 +1618,12 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
1541
1618
|
*/
|
|
1542
1619
|
class SerializerSignalImpl extends ComputedSignalImpl {
|
|
1543
1620
|
constructor(container, argQrl) {
|
|
1544
|
-
super(container, argQrl);
|
|
1621
|
+
super(container, argQrl, 1 /* SignalFlags.INVALID */ | 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */);
|
|
1545
1622
|
}
|
|
1546
1623
|
$didInitialize$ = false;
|
|
1547
1624
|
$computeIfNeeded$() {
|
|
1548
1625
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
1549
|
-
return
|
|
1626
|
+
return;
|
|
1550
1627
|
}
|
|
1551
1628
|
throwIfQRLNotResolved(this.$computeQrl$);
|
|
1552
1629
|
let arg = this.$computeQrl$.resolved;
|
|
@@ -1557,16 +1634,16 @@ class SerializerSignalImpl extends ComputedSignalImpl {
|
|
|
1557
1634
|
const update = arg.update;
|
|
1558
1635
|
const currentValue = this.$untrackedValue$ === NEEDS_COMPUTATION ? initial : this.$untrackedValue$;
|
|
1559
1636
|
const untrackedValue = trackSignal(() => this.$didInitialize$
|
|
1560
|
-
? update?.(currentValue)
|
|
1637
|
+
? update?.(currentValue) || currentValue
|
|
1561
1638
|
: deserialize(currentValue), this, "." /* EffectProperty.VNODE */, this.$container$);
|
|
1562
1639
|
const didChange = (this.$didInitialize$ && untrackedValue !== 'undefined') ||
|
|
1563
1640
|
untrackedValue !== this.$untrackedValue$;
|
|
1564
1641
|
this.$flags$ &= -2 /* SignalFlags.INVALID */;
|
|
1565
1642
|
this.$didInitialize$ = true;
|
|
1566
1643
|
if (didChange) {
|
|
1644
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1567
1645
|
this.$untrackedValue$ = untrackedValue;
|
|
1568
1646
|
}
|
|
1569
|
-
return didChange;
|
|
1570
1647
|
}
|
|
1571
1648
|
}
|
|
1572
1649
|
|
|
@@ -1576,6 +1653,28 @@ const getStoreHandler = (value) => {
|
|
|
1576
1653
|
const getStoreTarget = (value) => {
|
|
1577
1654
|
return value?.[STORE_TARGET] || null;
|
|
1578
1655
|
};
|
|
1656
|
+
/**
|
|
1657
|
+
* Force a store to recompute and schedule effects.
|
|
1658
|
+
*
|
|
1659
|
+
* @public
|
|
1660
|
+
*/
|
|
1661
|
+
const forceStoreEffects = (value, prop) => {
|
|
1662
|
+
const handler = getStoreHandler(value);
|
|
1663
|
+
if (handler) {
|
|
1664
|
+
handler.force(prop);
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
/**
|
|
1668
|
+
* @returns True if the store has effects for the given prop
|
|
1669
|
+
* @internal
|
|
1670
|
+
*/
|
|
1671
|
+
const _hasStoreEffects = (value, prop) => {
|
|
1672
|
+
const handler = getStoreHandler(value);
|
|
1673
|
+
if (handler) {
|
|
1674
|
+
return (handler.$effects$?.get(prop)?.size ?? 0) > 0;
|
|
1675
|
+
}
|
|
1676
|
+
return false;
|
|
1677
|
+
};
|
|
1579
1678
|
/**
|
|
1580
1679
|
* Get the original object that was wrapped by the store. Useful if you want to clone a store
|
|
1581
1680
|
* (structuredClone, IndexedDB,...)
|
|
@@ -1585,6 +1684,7 @@ const getStoreTarget = (value) => {
|
|
|
1585
1684
|
const unwrapStore = (value) => {
|
|
1586
1685
|
return getStoreTarget(value) || value;
|
|
1587
1686
|
};
|
|
1687
|
+
/** @internal */
|
|
1588
1688
|
const isStore = (value) => {
|
|
1589
1689
|
return STORE_TARGET in value;
|
|
1590
1690
|
};
|
|
@@ -1613,7 +1713,12 @@ class StoreHandler {
|
|
|
1613
1713
|
toString() {
|
|
1614
1714
|
return '[Store]';
|
|
1615
1715
|
}
|
|
1716
|
+
force(prop) {
|
|
1717
|
+
const target = getStoreTarget(this);
|
|
1718
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, getEffects(target, prop, this.$effects$));
|
|
1719
|
+
}
|
|
1616
1720
|
get(target, prop) {
|
|
1721
|
+
// TODO(perf): handle better `slice` calls
|
|
1617
1722
|
if (typeof prop === 'symbol') {
|
|
1618
1723
|
if (prop === STORE_TARGET) {
|
|
1619
1724
|
return target;
|
|
@@ -1646,8 +1751,7 @@ class StoreHandler {
|
|
|
1646
1751
|
}
|
|
1647
1752
|
const flags = this.$flags$;
|
|
1648
1753
|
if (flags & 1 /* StoreFlags.RECURSIVE */ &&
|
|
1649
|
-
|
|
1650
|
-
value !== null &&
|
|
1754
|
+
isObject(value) &&
|
|
1651
1755
|
!Object.isFrozen(value) &&
|
|
1652
1756
|
!isStore(value) &&
|
|
1653
1757
|
!Object.isFrozen(target)) {
|
|
@@ -1677,7 +1781,11 @@ class StoreHandler {
|
|
|
1677
1781
|
if (typeof prop != 'string' || !delete target[prop]) {
|
|
1678
1782
|
return false;
|
|
1679
1783
|
}
|
|
1680
|
-
|
|
1784
|
+
if (!Array.isArray(target)) {
|
|
1785
|
+
// If the target is an array, we don't need to trigger effects.
|
|
1786
|
+
// Changing the length property will trigger effects.
|
|
1787
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, getEffects(target, prop, this.$effects$));
|
|
1788
|
+
}
|
|
1681
1789
|
return true;
|
|
1682
1790
|
}
|
|
1683
1791
|
has(target, prop) {
|
|
@@ -1736,8 +1844,10 @@ function addStoreEffect(target, prop, store, effectSubscription) {
|
|
|
1736
1844
|
}
|
|
1737
1845
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
1738
1846
|
target[prop] = value;
|
|
1739
|
-
|
|
1740
|
-
|
|
1847
|
+
const effects = getEffects(target, prop, currentStore.$effects$);
|
|
1848
|
+
if (effects) {
|
|
1849
|
+
currentStore.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, currentStore, effects);
|
|
1850
|
+
}
|
|
1741
1851
|
}
|
|
1742
1852
|
function getEffects(target, prop, storeEffects) {
|
|
1743
1853
|
let effectsToTrigger;
|
|
@@ -1825,7 +1935,7 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
|
1825
1935
|
$loadingEffects$ = null;
|
|
1826
1936
|
$errorEffects$ = null;
|
|
1827
1937
|
$destroy$;
|
|
1828
|
-
$promiseValue$ =
|
|
1938
|
+
$promiseValue$ = NEEDS_COMPUTATION;
|
|
1829
1939
|
[_EFFECT_BACK_REF] = null;
|
|
1830
1940
|
constructor(container, fn, flags = 1 /* SignalFlags.INVALID */) {
|
|
1831
1941
|
super(container, fn, flags);
|
|
@@ -1859,18 +1969,23 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
|
1859
1969
|
get untrackedError() {
|
|
1860
1970
|
return this.$untrackedError$;
|
|
1861
1971
|
}
|
|
1972
|
+
invalidate() {
|
|
1973
|
+
super.invalidate();
|
|
1974
|
+
this.$promiseValue$ = NEEDS_COMPUTATION;
|
|
1975
|
+
}
|
|
1862
1976
|
$computeIfNeeded$() {
|
|
1863
1977
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
1864
|
-
return
|
|
1978
|
+
return;
|
|
1865
1979
|
}
|
|
1866
1980
|
const computeQrl = this.$computeQrl$;
|
|
1867
1981
|
throwIfQRLNotResolved(computeQrl);
|
|
1868
1982
|
const [cleanup] = cleanupFn(this, (err) => this.$container$?.handleError(err, null));
|
|
1869
|
-
const untrackedValue = this.$promiseValue$
|
|
1870
|
-
computeQrl.getFn()({
|
|
1983
|
+
const untrackedValue = this.$promiseValue$ === NEEDS_COMPUTATION
|
|
1984
|
+
? computeQrl.getFn()({
|
|
1871
1985
|
track: trackFn(this, this.$container$),
|
|
1872
1986
|
cleanup,
|
|
1873
|
-
})
|
|
1987
|
+
})
|
|
1988
|
+
: this.$promiseValue$;
|
|
1874
1989
|
if (isPromise(untrackedValue)) {
|
|
1875
1990
|
this.untrackedLoading = true;
|
|
1876
1991
|
this.untrackedError = null;
|
|
@@ -1881,14 +1996,16 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
|
1881
1996
|
this.untrackedError = null;
|
|
1882
1997
|
})
|
|
1883
1998
|
.catch((err) => {
|
|
1999
|
+
this.$promiseValue$ = err;
|
|
1884
2000
|
this.untrackedLoading = false;
|
|
1885
2001
|
this.untrackedError = err;
|
|
1886
2002
|
});
|
|
1887
2003
|
}
|
|
1888
|
-
this.$promiseValue$ =
|
|
2004
|
+
this.$promiseValue$ = NEEDS_COMPUTATION;
|
|
1889
2005
|
this.$flags$ &= -2 /* SignalFlags.INVALID */;
|
|
1890
2006
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
1891
2007
|
if (didChange) {
|
|
2008
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1892
2009
|
this.$untrackedValue$ = untrackedValue;
|
|
1893
2010
|
}
|
|
1894
2011
|
return didChange;
|
|
@@ -1900,13 +2017,15 @@ const createSignal$1 = (value) => {
|
|
|
1900
2017
|
return new SignalImpl(null, value);
|
|
1901
2018
|
};
|
|
1902
2019
|
/** @internal */
|
|
1903
|
-
const createComputedSignal = (qrl) => {
|
|
1904
|
-
|
|
1905
|
-
|
|
2020
|
+
const createComputedSignal = (qrl, options) => {
|
|
2021
|
+
return new ComputedSignalImpl(options?.container || null, qrl, getComputedSignalFlags(options?.serializationStrategy || 'always'));
|
|
2022
|
+
};
|
|
2023
|
+
/** @internal */
|
|
2024
|
+
const createAsyncComputedSignal = (qrl, options) => {
|
|
2025
|
+
return new AsyncComputedSignalImpl(options?.container || null, qrl, getComputedSignalFlags(options?.serializationStrategy || 'never'));
|
|
1906
2026
|
};
|
|
1907
2027
|
/** @internal */
|
|
1908
2028
|
const createSerializerSignal = (arg) => {
|
|
1909
|
-
throwIfQRLNotResolved(arg);
|
|
1910
2029
|
return new SerializerSignalImpl(null, arg);
|
|
1911
2030
|
};
|
|
1912
2031
|
|
|
@@ -1925,11 +2044,22 @@ const createSignal = createSignal$1;
|
|
|
1925
2044
|
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
1926
2045
|
* effects, and it must be synchronous.
|
|
1927
2046
|
*
|
|
1928
|
-
* If you need the function to be async, use `
|
|
2047
|
+
* If you need the function to be async, use `useAsyncComputed$` instead.
|
|
1929
2048
|
*
|
|
1930
2049
|
* @public
|
|
1931
2050
|
*/
|
|
1932
2051
|
const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedSignal);
|
|
2052
|
+
/**
|
|
2053
|
+
* Create an async computed signal which is calculated from the given QRL. A computed signal is a
|
|
2054
|
+
* signal which is calculated from other signals or async operation. When the signals change, the
|
|
2055
|
+
* computed signal is recalculated.
|
|
2056
|
+
*
|
|
2057
|
+
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
2058
|
+
* effects, and it can be async.
|
|
2059
|
+
*
|
|
2060
|
+
* @public
|
|
2061
|
+
*/
|
|
2062
|
+
const createAsyncComputed$ = /*#__PURE__*/ implicit$FirstArg(createAsyncComputedSignal);
|
|
1933
2063
|
/**
|
|
1934
2064
|
* Create a signal that holds a custom serializable value. See {@link useSerializer$} for more
|
|
1935
2065
|
* details.
|
|
@@ -1963,7 +2093,7 @@ const _wrapProp = (...args) => {
|
|
|
1963
2093
|
if (!(obj instanceof AsyncComputedSignalImpl)) {
|
|
1964
2094
|
assertEqual(prop, 'value', 'Left side is a signal, prop must be value');
|
|
1965
2095
|
}
|
|
1966
|
-
if (obj instanceof WrappedSignalImpl && obj.flags &
|
|
2096
|
+
if (obj instanceof WrappedSignalImpl && obj.flags & 4 /* WrappedSignalFlags.UNWRAP */) {
|
|
1967
2097
|
return obj;
|
|
1968
2098
|
}
|
|
1969
2099
|
return getWrapped(args);
|
|
@@ -1989,17 +2119,6 @@ const _wrapProp = (...args) => {
|
|
|
1989
2119
|
// the object is not reactive, so we can just return the value
|
|
1990
2120
|
return obj[prop];
|
|
1991
2121
|
};
|
|
1992
|
-
/** @internal */
|
|
1993
|
-
const _wrapStore = (obj, prop) => {
|
|
1994
|
-
const target = getStoreTarget(obj);
|
|
1995
|
-
const value = target[prop];
|
|
1996
|
-
if (isSignal(value)) {
|
|
1997
|
-
return value;
|
|
1998
|
-
}
|
|
1999
|
-
else {
|
|
2000
|
-
return new WrappedSignalImpl(null, getProp, [obj, prop], null, 1 /* SignalFlags.INVALID */);
|
|
2001
|
-
}
|
|
2002
|
-
};
|
|
2003
2122
|
/** @internal @deprecated v1 compat */
|
|
2004
2123
|
const _wrapSignal = (obj, prop) => {
|
|
2005
2124
|
const r = _wrapProp(obj, prop);
|
|
@@ -2035,7 +2154,7 @@ function isSlotProp(prop) {
|
|
|
2035
2154
|
return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
|
|
2036
2155
|
}
|
|
2037
2156
|
/** @internal */
|
|
2038
|
-
const _restProps = (props, omit, target = {}) => {
|
|
2157
|
+
const _restProps = (props, omit = [], target = {}) => {
|
|
2039
2158
|
let constPropsTarget = null;
|
|
2040
2159
|
const constProps = props[_CONST_PROPS];
|
|
2041
2160
|
if (constProps) {
|
|
@@ -2421,7 +2540,6 @@ const executeComponent = (container, renderHost, subscriptionHost, componentQRL,
|
|
|
2421
2540
|
if (!isInlineComponent) {
|
|
2422
2541
|
container.setHostProp(renderHost, ELEMENT_SEQ_IDX, null);
|
|
2423
2542
|
container.setHostProp(renderHost, USE_ON_LOCAL_SEQ_IDX, null);
|
|
2424
|
-
container.setHostProp(renderHost, ELEMENT_PROPS, props);
|
|
2425
2543
|
}
|
|
2426
2544
|
if (vnode_isVNode(renderHost)) {
|
|
2427
2545
|
clearAllEffects(container, renderHost);
|
|
@@ -2435,75 +2553,83 @@ const executeComponent = (container, renderHost, subscriptionHost, componentQRL,
|
|
|
2435
2553
|
return jsx;
|
|
2436
2554
|
}, (err) => {
|
|
2437
2555
|
if (isPromise(err) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
2438
|
-
return err.then(() => executeComponentWithPromiseExceptionRetry(retryCount
|
|
2556
|
+
return err.then(() => executeComponentWithPromiseExceptionRetry(++retryCount));
|
|
2439
2557
|
}
|
|
2440
2558
|
else {
|
|
2559
|
+
if (retryCount >= MAX_RETRY_ON_PROMISE_COUNT) {
|
|
2560
|
+
throw new Error(`Max retry count of component execution reached`);
|
|
2561
|
+
}
|
|
2441
2562
|
throw err;
|
|
2442
2563
|
}
|
|
2443
2564
|
});
|
|
2444
2565
|
return executeComponentWithPromiseExceptionRetry();
|
|
2445
2566
|
};
|
|
2446
2567
|
/**
|
|
2447
|
-
*
|
|
2448
|
-
*
|
|
2449
|
-
* Component can execute multiple times because:
|
|
2450
|
-
*
|
|
2451
|
-
* - Component can have multiple tasks
|
|
2452
|
-
* - Tasks can track signals
|
|
2453
|
-
* - Task A can change signal which causes Task B to rerun.
|
|
2568
|
+
* Adds `useOn` events to the JSX output.
|
|
2454
2569
|
*
|
|
2455
|
-
*
|
|
2570
|
+
* @param jsx The JSX output to modify.
|
|
2571
|
+
* @param useOnEvents The `useOn` events to add.
|
|
2572
|
+
* @returns The modified JSX output.
|
|
2456
2573
|
*/
|
|
2457
2574
|
function addUseOnEvents(jsx, useOnEvents) {
|
|
2458
|
-
const jsxElement =
|
|
2575
|
+
const jsxElement = findFirstElementNode(jsx);
|
|
2459
2576
|
let jsxResult = jsx;
|
|
2577
|
+
const qVisibleEvent = 'onQvisible$';
|
|
2460
2578
|
return maybeThen(jsxElement, (jsxElement) => {
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
*
|
|
2466
|
-
* ```html
|
|
2467
|
-
* <script type="placeholder" hidden on-document:qinit="..."></script>
|
|
2468
|
-
* ```
|
|
2469
|
-
*
|
|
2470
|
-
* This is needed because use on events should have a node to attach them to.
|
|
2471
|
-
*/
|
|
2472
|
-
isInvisibleComponent = true;
|
|
2473
|
-
}
|
|
2579
|
+
// headless components are components that don't render a real DOM element
|
|
2580
|
+
const isHeadless = !jsxElement;
|
|
2581
|
+
// placeholder element is a <script> element that is used to add events to the document or window
|
|
2582
|
+
let placeholderElement = null;
|
|
2474
2583
|
for (const key in useOnEvents) {
|
|
2475
2584
|
if (Object.prototype.hasOwnProperty.call(useOnEvents, key)) {
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2585
|
+
let targetElement = jsxElement;
|
|
2586
|
+
let eventKey = key;
|
|
2587
|
+
if (isHeadless) {
|
|
2588
|
+
// if the component is headless, we need to add the event to the placeholder element
|
|
2589
|
+
if (key === qVisibleEvent ||
|
|
2590
|
+
key.startsWith("document:on" /* EventNameJSXScope.document */) ||
|
|
2591
|
+
key.startsWith("window:on" /* EventNameJSXScope.window */)) {
|
|
2592
|
+
if (!placeholderElement) {
|
|
2593
|
+
const [createdElement, newJsx] = injectPlaceholderElement(jsxResult);
|
|
2594
|
+
jsxResult = newJsx;
|
|
2595
|
+
placeholderElement = createdElement;
|
|
2482
2596
|
}
|
|
2597
|
+
targetElement = placeholderElement;
|
|
2483
2598
|
}
|
|
2484
|
-
else
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2599
|
+
else {
|
|
2600
|
+
if (isDev) {
|
|
2601
|
+
logWarn('You are trying to add an event "' +
|
|
2602
|
+
key +
|
|
2603
|
+
'" using `useOn` hook, ' +
|
|
2604
|
+
'but a node to which you can add an event is not found. ' +
|
|
2605
|
+
'Please make sure that the component has a valid element node. ');
|
|
2489
2606
|
}
|
|
2607
|
+
continue;
|
|
2490
2608
|
}
|
|
2491
|
-
|
|
2609
|
+
}
|
|
2610
|
+
if (targetElement) {
|
|
2611
|
+
if (targetElement.type === 'script' && key === qVisibleEvent) {
|
|
2612
|
+
eventKey = 'document:onQInit$';
|
|
2492
2613
|
logWarn('You are trying to add an event "' +
|
|
2493
2614
|
key +
|
|
2494
|
-
'" using `
|
|
2615
|
+
'" using `useVisibleTask$` hook, ' +
|
|
2495
2616
|
'but a node to which you can add an event is not found. ' +
|
|
2496
|
-
'
|
|
2617
|
+
'Using document:onQInit$ instead.');
|
|
2497
2618
|
}
|
|
2498
|
-
|
|
2499
|
-
else if (jsxElement) {
|
|
2500
|
-
addUseOnEvent(jsxElement, key, useOnEvents[key]);
|
|
2619
|
+
addUseOnEvent(targetElement, eventKey, useOnEvents[key]);
|
|
2501
2620
|
}
|
|
2502
2621
|
}
|
|
2503
2622
|
}
|
|
2504
2623
|
return jsxResult;
|
|
2505
2624
|
});
|
|
2506
2625
|
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Adds an event to the JSX element.
|
|
2628
|
+
*
|
|
2629
|
+
* @param jsxElement The JSX element to add the event to.
|
|
2630
|
+
* @param key The event name.
|
|
2631
|
+
* @param value The event value.
|
|
2632
|
+
*/
|
|
2507
2633
|
function addUseOnEvent(jsxElement, key, value) {
|
|
2508
2634
|
let props = jsxElement.props;
|
|
2509
2635
|
if (props === EMPTY_OBJ) {
|
|
@@ -2519,7 +2645,13 @@ function addUseOnEvent(jsxElement, key, value) {
|
|
|
2519
2645
|
propValue.push(...value);
|
|
2520
2646
|
props[key] = propValue;
|
|
2521
2647
|
}
|
|
2522
|
-
|
|
2648
|
+
/**
|
|
2649
|
+
* Finds the first element node in the JSX output.
|
|
2650
|
+
*
|
|
2651
|
+
* @param jsx The JSX output to search.
|
|
2652
|
+
* @returns The first element node or null if no element node is found.
|
|
2653
|
+
*/
|
|
2654
|
+
function findFirstElementNode(jsx) {
|
|
2523
2655
|
const queue = [jsx];
|
|
2524
2656
|
while (queue.length) {
|
|
2525
2657
|
const jsx = queue.shift();
|
|
@@ -2529,44 +2661,69 @@ function findFirstStringJSX(jsx) {
|
|
|
2529
2661
|
}
|
|
2530
2662
|
queue.push(jsx.children);
|
|
2531
2663
|
}
|
|
2532
|
-
else if (
|
|
2664
|
+
else if (isArray(jsx)) {
|
|
2533
2665
|
queue.push(...jsx);
|
|
2534
2666
|
}
|
|
2535
2667
|
else if (isPromise(jsx)) {
|
|
2536
|
-
return maybeThen(jsx, (jsx) =>
|
|
2668
|
+
return maybeThen(jsx, (jsx) => findFirstElementNode(jsx));
|
|
2537
2669
|
}
|
|
2538
2670
|
else if (isSignal(jsx)) {
|
|
2539
|
-
return
|
|
2671
|
+
return findFirstElementNode(untrack(() => jsx.value));
|
|
2540
2672
|
}
|
|
2541
2673
|
}
|
|
2542
2674
|
return null;
|
|
2543
2675
|
}
|
|
2544
|
-
|
|
2676
|
+
/**
|
|
2677
|
+
* Injects a placeholder <script> element into the JSX output.
|
|
2678
|
+
*
|
|
2679
|
+
* This is necessary for headless components (components that don't render a real DOM element) to
|
|
2680
|
+
* have an anchor point for `useOn` event listeners that target the document or window.
|
|
2681
|
+
*
|
|
2682
|
+
* @param jsx The JSX output to modify.
|
|
2683
|
+
* @returns A tuple containing the created placeholder element and the modified JSX output.
|
|
2684
|
+
*/
|
|
2685
|
+
function injectPlaceholderElement(jsx) {
|
|
2686
|
+
// For regular JSX nodes, we can append the placeholder to its children.
|
|
2545
2687
|
if (isJSXNode(jsx)) {
|
|
2546
|
-
const
|
|
2547
|
-
|
|
2548
|
-
hidden: '',
|
|
2549
|
-
}, null, 3);
|
|
2688
|
+
const placeholder = createPlaceholderScriptNode();
|
|
2689
|
+
// For slots, we can't add children, so we wrap them in a fragment.
|
|
2550
2690
|
if (jsx.type === Slot) {
|
|
2551
|
-
return [
|
|
2691
|
+
return [placeholder, _jsxSorted(Fragment, null, null, [jsx, placeholder], 0, null)];
|
|
2552
2692
|
}
|
|
2553
2693
|
if (jsx.children == null) {
|
|
2554
|
-
jsx.children =
|
|
2694
|
+
jsx.children = placeholder;
|
|
2555
2695
|
}
|
|
2556
|
-
else if (
|
|
2557
|
-
jsx.children.push(
|
|
2696
|
+
else if (isArray(jsx.children)) {
|
|
2697
|
+
jsx.children.push(placeholder);
|
|
2558
2698
|
}
|
|
2559
2699
|
else {
|
|
2560
|
-
jsx.children = [jsx.children,
|
|
2700
|
+
jsx.children = [jsx.children, placeholder];
|
|
2561
2701
|
}
|
|
2562
|
-
return [
|
|
2702
|
+
return [placeholder, jsx];
|
|
2703
|
+
}
|
|
2704
|
+
// For primitives, we can't add children, so we wrap them in a fragment.
|
|
2705
|
+
if (isPrimitive(jsx)) {
|
|
2706
|
+
const placeholder = createPlaceholderScriptNode();
|
|
2707
|
+
return [placeholder, _jsxSorted(Fragment, null, null, [jsx, placeholder], 0, null)];
|
|
2563
2708
|
}
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
const [
|
|
2567
|
-
return [
|
|
2709
|
+
// For an array of nodes, we inject the placeholder into the first element.
|
|
2710
|
+
if (isArray(jsx) && jsx.length > 0) {
|
|
2711
|
+
const [createdElement, _] = injectPlaceholderElement(jsx[0]);
|
|
2712
|
+
return [createdElement, jsx];
|
|
2568
2713
|
}
|
|
2569
|
-
|
|
2714
|
+
// For anything else we do nothing.
|
|
2715
|
+
return [null, jsx];
|
|
2716
|
+
}
|
|
2717
|
+
/**
|
|
2718
|
+
* Creates a <script> element with a placeholder type.
|
|
2719
|
+
*
|
|
2720
|
+
* @returns A <script> element with a placeholder type.
|
|
2721
|
+
*/
|
|
2722
|
+
function createPlaceholderScriptNode() {
|
|
2723
|
+
return new JSXNodeImpl('script', {}, {
|
|
2724
|
+
type: 'placeholder',
|
|
2725
|
+
hidden: '',
|
|
2726
|
+
}, null, 3);
|
|
2570
2727
|
}
|
|
2571
2728
|
|
|
2572
2729
|
const applyInlineComponent = (ssr, componentHost, inlineComponentFunction, jsx) => {
|
|
@@ -2580,13 +2737,13 @@ const applyQwikComponentBody = (ssr, jsx, component) => {
|
|
|
2580
2737
|
if (srcProps && srcProps.children) {
|
|
2581
2738
|
delete srcProps.children;
|
|
2582
2739
|
}
|
|
2583
|
-
const scheduler = ssr.$scheduler$;
|
|
2584
2740
|
host.setProp(OnRenderProp, componentQrl);
|
|
2585
2741
|
host.setProp(ELEMENT_PROPS, srcProps);
|
|
2586
2742
|
if (jsx.key !== null) {
|
|
2587
2743
|
host.setProp(ELEMENT_KEY, jsx.key);
|
|
2588
2744
|
}
|
|
2589
|
-
|
|
2745
|
+
const componentChore = ssr.$scheduler$(6 /* ChoreType.COMPONENT */, host, componentQrl, srcProps);
|
|
2746
|
+
return getChorePromise(componentChore);
|
|
2590
2747
|
};
|
|
2591
2748
|
|
|
2592
2749
|
class ParentComponentData {
|
|
@@ -2694,7 +2851,14 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
2694
2851
|
appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue);
|
|
2695
2852
|
}
|
|
2696
2853
|
}
|
|
2697
|
-
const innerHTML = ssr.openElement(type, varPropsToSsrAttrs(jsx.varProps, jsx.constProps,
|
|
2854
|
+
const innerHTML = ssr.openElement(type, varPropsToSsrAttrs(jsx.varProps, jsx.constProps, {
|
|
2855
|
+
serializationCtx: ssr.serializationCtx,
|
|
2856
|
+
styleScopedId: options.styleScoped,
|
|
2857
|
+
key: jsx.key,
|
|
2858
|
+
}), constPropsToSsrAttrs(jsx.constProps, jsx.varProps, {
|
|
2859
|
+
serializationCtx: ssr.serializationCtx,
|
|
2860
|
+
styleScopedId: options.styleScoped,
|
|
2861
|
+
}), qwikInspectorAttrValue);
|
|
2698
2862
|
if (innerHTML) {
|
|
2699
2863
|
ssr.htmlNode(innerHTML);
|
|
2700
2864
|
}
|
|
@@ -2810,16 +2974,17 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
2810
2974
|
}
|
|
2811
2975
|
}
|
|
2812
2976
|
}
|
|
2813
|
-
function varPropsToSsrAttrs(varProps, constProps,
|
|
2814
|
-
return toSsrAttrs(varProps, constProps,
|
|
2977
|
+
function varPropsToSsrAttrs(varProps, constProps, options) {
|
|
2978
|
+
return toSsrAttrs(varProps, constProps, false, options);
|
|
2815
2979
|
}
|
|
2816
|
-
function constPropsToSsrAttrs(constProps, varProps,
|
|
2817
|
-
return toSsrAttrs(constProps, varProps,
|
|
2980
|
+
function constPropsToSsrAttrs(constProps, varProps, options) {
|
|
2981
|
+
return toSsrAttrs(constProps, varProps, true, options);
|
|
2818
2982
|
}
|
|
2819
|
-
function toSsrAttrs(record, anotherRecord,
|
|
2983
|
+
function toSsrAttrs(record, anotherRecord, isConst, options) {
|
|
2820
2984
|
if (record == null) {
|
|
2821
2985
|
return null;
|
|
2822
2986
|
}
|
|
2987
|
+
const pushMergedEventProps = !isConst;
|
|
2823
2988
|
const ssrAttrs = [];
|
|
2824
2989
|
for (const key in record) {
|
|
2825
2990
|
let value = record[key];
|
|
@@ -2856,7 +3021,7 @@ function toSsrAttrs(record, anotherRecord, serializationCtx, pushMergedEventProp
|
|
|
2856
3021
|
}
|
|
2857
3022
|
}
|
|
2858
3023
|
}
|
|
2859
|
-
const eventValue = setEvent(serializationCtx, key, value);
|
|
3024
|
+
const eventValue = setEvent(options.serializationCtx, key, value);
|
|
2860
3025
|
if (eventValue) {
|
|
2861
3026
|
ssrAttrs.push(jsxEventToHtmlAttribute(key), eventValue);
|
|
2862
3027
|
}
|
|
@@ -2866,7 +3031,7 @@ function toSsrAttrs(record, anotherRecord, serializationCtx, pushMergedEventProp
|
|
|
2866
3031
|
// write signal as is. We will track this signal inside `writeAttrs`
|
|
2867
3032
|
if (isClassAttr(key)) {
|
|
2868
3033
|
// additionally append styleScopedId for class attr
|
|
2869
|
-
ssrAttrs.push(key, [value, styleScopedId]);
|
|
3034
|
+
ssrAttrs.push(key, [value, options.styleScopedId]);
|
|
2870
3035
|
}
|
|
2871
3036
|
else {
|
|
2872
3037
|
ssrAttrs.push(key, value);
|
|
@@ -2874,13 +3039,13 @@ function toSsrAttrs(record, anotherRecord, serializationCtx, pushMergedEventProp
|
|
|
2874
3039
|
continue;
|
|
2875
3040
|
}
|
|
2876
3041
|
if (isPreventDefault(key)) {
|
|
2877
|
-
addPreventDefaultEventToSerializationContext(serializationCtx, key);
|
|
3042
|
+
addPreventDefaultEventToSerializationContext(options.serializationCtx, key);
|
|
2878
3043
|
}
|
|
2879
|
-
value = serializeAttribute(key, value, styleScopedId);
|
|
3044
|
+
value = serializeAttribute(key, value, options.styleScopedId);
|
|
2880
3045
|
ssrAttrs.push(key, value);
|
|
2881
3046
|
}
|
|
2882
|
-
if (key != null) {
|
|
2883
|
-
ssrAttrs.push(ELEMENT_KEY, key);
|
|
3047
|
+
if (options.key != null) {
|
|
3048
|
+
ssrAttrs.push(ELEMENT_KEY, options.key);
|
|
2884
3049
|
}
|
|
2885
3050
|
return ssrAttrs;
|
|
2886
3051
|
}
|
|
@@ -2929,7 +3094,7 @@ function setEvent(serializationCtx, key, rawValue) {
|
|
|
2929
3094
|
* For internal qrls (starting with `_`) we assume that they do the right thing.
|
|
2930
3095
|
*/
|
|
2931
3096
|
if (!qrl.$symbol$.startsWith('_') && (qrl.$captureRef$ || qrl.$capture$)) {
|
|
2932
|
-
qrl = createQRL(null, '_run',
|
|
3097
|
+
qrl = createQRL(null, '_run', _run, null, null, [qrl]);
|
|
2933
3098
|
}
|
|
2934
3099
|
return qrlToString(serializationCtx, qrl);
|
|
2935
3100
|
};
|
|
@@ -3009,10 +3174,9 @@ const useTaskQrl = (qrl) => {
|
|
|
3009
3174
|
// deleted and we need to be able to release the task subscriptions.
|
|
3010
3175
|
set(task);
|
|
3011
3176
|
const container = iCtx.$container$;
|
|
3012
|
-
const
|
|
3013
|
-
if (isPromise(
|
|
3014
|
-
|
|
3015
|
-
promise.catch(() => { });
|
|
3177
|
+
const result = runTask(task, container, iCtx.$hostElement$);
|
|
3178
|
+
if (isPromise(result)) {
|
|
3179
|
+
throw result;
|
|
3016
3180
|
}
|
|
3017
3181
|
};
|
|
3018
3182
|
const runTask = (task, container, host) => {
|
|
@@ -3024,7 +3188,7 @@ const runTask = (task, container, host) => {
|
|
|
3024
3188
|
const track = trackFn(task, container);
|
|
3025
3189
|
const [cleanup] = cleanupFn(task, (reason) => container.handleError(reason, host));
|
|
3026
3190
|
const taskApi = { track, cleanup };
|
|
3027
|
-
|
|
3191
|
+
return safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
3028
3192
|
// If a Promise is thrown, that means we need to re-run the task.
|
|
3029
3193
|
if (isPromise(err)) {
|
|
3030
3194
|
return err.then(() => runTask(task, container, host));
|
|
@@ -3033,7 +3197,6 @@ const runTask = (task, container, host) => {
|
|
|
3033
3197
|
throw err;
|
|
3034
3198
|
}
|
|
3035
3199
|
});
|
|
3036
|
-
return result;
|
|
3037
3200
|
};
|
|
3038
3201
|
const cleanupTask = (task) => {
|
|
3039
3202
|
const destroy = task.$destroy$;
|
|
@@ -3064,6 +3227,7 @@ class Task extends BackRef {
|
|
|
3064
3227
|
this.$destroy$ = $destroy$;
|
|
3065
3228
|
}
|
|
3066
3229
|
}
|
|
3230
|
+
/** @internal */
|
|
3067
3231
|
const isTask = (value) => {
|
|
3068
3232
|
return value instanceof Task;
|
|
3069
3233
|
};
|
|
@@ -3074,7 +3238,7 @@ const isTask = (value) => {
|
|
|
3074
3238
|
*/
|
|
3075
3239
|
const scheduleTask = (_event, element) => {
|
|
3076
3240
|
const [task] = useLexicalScope();
|
|
3077
|
-
const type = task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */ ?
|
|
3241
|
+
const type = task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */ ? 16 /* ChoreType.VISIBLE */ : 3 /* ChoreType.TASK */;
|
|
3078
3242
|
const container = getDomContainer(element);
|
|
3079
3243
|
container.$scheduler$(type, task);
|
|
3080
3244
|
};
|
|
@@ -3326,7 +3490,7 @@ class PropsProxyHandler {
|
|
|
3326
3490
|
? this.$constProps$[prop]
|
|
3327
3491
|
: this.$varProps$[prop];
|
|
3328
3492
|
// a proxied value that the optimizer made
|
|
3329
|
-
return value instanceof WrappedSignalImpl && value.$flags$ &
|
|
3493
|
+
return value instanceof WrappedSignalImpl && value.$flags$ & 4 /* WrappedSignalFlags.UNWRAP */
|
|
3330
3494
|
? value.value
|
|
3331
3495
|
: value;
|
|
3332
3496
|
}
|
|
@@ -3402,48 +3566,23 @@ class PropsProxyHandler {
|
|
|
3402
3566
|
const directGetPropsProxyProp = (jsx, prop) => {
|
|
3403
3567
|
return (jsx.constProps && prop in jsx.constProps ? jsx.constProps[prop] : jsx.varProps[prop]);
|
|
3404
3568
|
};
|
|
3405
|
-
|
|
3406
|
-
const
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
let top = (array.length - 2) >> 1;
|
|
3410
|
-
while (bottom <= top) {
|
|
3411
|
-
const mid = bottom + ((top - bottom) >> 1);
|
|
3412
|
-
const midKey = array[mid << 1];
|
|
3413
|
-
if (midKey === key) {
|
|
3414
|
-
return mid << 1;
|
|
3415
|
-
}
|
|
3416
|
-
if (midKey < key) {
|
|
3417
|
-
bottom = mid + 1;
|
|
3418
|
-
}
|
|
3419
|
-
else {
|
|
3420
|
-
top = mid - 1;
|
|
3421
|
-
}
|
|
3422
|
-
}
|
|
3423
|
-
return (bottom << 1) ^ -1;
|
|
3424
|
-
};
|
|
3425
|
-
const mapArray_set = (array, key, value, start) => {
|
|
3426
|
-
const indx = mapApp_findIndx(array, key, start);
|
|
3427
|
-
if (indx >= 0) {
|
|
3428
|
-
if (value == null) {
|
|
3429
|
-
array.splice(indx, 2);
|
|
3430
|
-
}
|
|
3431
|
-
else {
|
|
3432
|
-
array[indx + 1] = value;
|
|
3433
|
-
}
|
|
3434
|
-
}
|
|
3435
|
-
else if (value != null) {
|
|
3436
|
-
array.splice(indx ^ -1, 0, key, value);
|
|
3569
|
+
/** @internal */
|
|
3570
|
+
const _getVarProps = (props) => {
|
|
3571
|
+
if (!props) {
|
|
3572
|
+
return null;
|
|
3437
3573
|
}
|
|
3574
|
+
return _VAR_PROPS in props
|
|
3575
|
+
? 'children' in props
|
|
3576
|
+
? { ...props[_VAR_PROPS], children: props.children }
|
|
3577
|
+
: props[_VAR_PROPS]
|
|
3578
|
+
: props;
|
|
3438
3579
|
};
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
if (
|
|
3442
|
-
return array[indx + 1];
|
|
3443
|
-
}
|
|
3444
|
-
else {
|
|
3580
|
+
/** @internal */
|
|
3581
|
+
const _getConstProps = (props) => {
|
|
3582
|
+
if (!props) {
|
|
3445
3583
|
return null;
|
|
3446
3584
|
}
|
|
3585
|
+
return _CONST_PROPS in props ? props[_CONST_PROPS] : null;
|
|
3447
3586
|
};
|
|
3448
3587
|
|
|
3449
3588
|
const isForeignObjectElement = (elementName) => {
|
|
@@ -3649,6 +3788,24 @@ function getNewElementNamespaceData(domParentVNode, tagOrVNode) {
|
|
|
3649
3788
|
elementNamespaceFlag,
|
|
3650
3789
|
};
|
|
3651
3790
|
}
|
|
3791
|
+
function getAttributeNamespace(attributeName) {
|
|
3792
|
+
switch (attributeName) {
|
|
3793
|
+
case 'xlink:href':
|
|
3794
|
+
case 'xlink:actuate':
|
|
3795
|
+
case 'xlink:arcrole':
|
|
3796
|
+
case 'xlink:role':
|
|
3797
|
+
case 'xlink:show':
|
|
3798
|
+
case 'xlink:title':
|
|
3799
|
+
case 'xlink:type':
|
|
3800
|
+
return XLINK_NS;
|
|
3801
|
+
case 'xml:base':
|
|
3802
|
+
case 'xml:lang':
|
|
3803
|
+
case 'xml:space':
|
|
3804
|
+
return XML_NS;
|
|
3805
|
+
default:
|
|
3806
|
+
return null;
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3652
3809
|
|
|
3653
3810
|
function escapeHTML(html) {
|
|
3654
3811
|
let escapedHTML = '';
|
|
@@ -3747,6 +3904,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
3747
3904
|
vNewNode = null;
|
|
3748
3905
|
vCurrent = vnode_getFirstChild(vStartNode);
|
|
3749
3906
|
stackPush(jsxNode, true);
|
|
3907
|
+
if (vParent[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */) {
|
|
3908
|
+
// Ignore diff if the parent is deleted.
|
|
3909
|
+
return;
|
|
3910
|
+
}
|
|
3750
3911
|
while (stack.length) {
|
|
3751
3912
|
while (jsxIdx < jsxCount) {
|
|
3752
3913
|
assertFalse(vParent === vCurrent, "Parent and current can't be the same");
|
|
@@ -4175,8 +4336,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
4175
4336
|
value = trackSignalAndAssignHost(value, vNewNode, key, container, signalData);
|
|
4176
4337
|
}
|
|
4177
4338
|
if (key === dangerouslySetInnerHTML) {
|
|
4178
|
-
|
|
4179
|
-
|
|
4339
|
+
if (value) {
|
|
4340
|
+
element.innerHTML = String(value);
|
|
4341
|
+
element.setAttribute(QContainerAttr, "html" /* QContainerValue.HTML */);
|
|
4342
|
+
}
|
|
4180
4343
|
continue;
|
|
4181
4344
|
}
|
|
4182
4345
|
if (elementName === 'textarea' && key === 'value') {
|
|
@@ -4191,6 +4354,14 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
4191
4354
|
}
|
|
4192
4355
|
value = serializeAttribute(key, value, scopedStyleIdPrefix);
|
|
4193
4356
|
if (value != null) {
|
|
4357
|
+
if (vNewNode[0 /* VNodeProps.flags */] & 64 /* VNodeFlags.NS_svg */) {
|
|
4358
|
+
// only svg elements can have namespace attributes
|
|
4359
|
+
const namespace = getAttributeNamespace(key);
|
|
4360
|
+
if (namespace) {
|
|
4361
|
+
element.setAttributeNS(namespace, key, String(value));
|
|
4362
|
+
continue;
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4194
4365
|
element.setAttribute(key, String(value));
|
|
4195
4366
|
}
|
|
4196
4367
|
}
|
|
@@ -4269,8 +4440,13 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
4269
4440
|
let returnValue = false;
|
|
4270
4441
|
qrls.flat(2).forEach((qrl) => {
|
|
4271
4442
|
if (qrl) {
|
|
4272
|
-
|
|
4273
|
-
|
|
4443
|
+
if (isSyncQrl(qrl)) {
|
|
4444
|
+
qrl(event, element);
|
|
4445
|
+
}
|
|
4446
|
+
else {
|
|
4447
|
+
const value = container.$scheduler$(2 /* ChoreType.RUN_QRL */, vNode, qrl, [event, element]);
|
|
4448
|
+
returnValue = returnValue || value === true;
|
|
4449
|
+
}
|
|
4274
4450
|
}
|
|
4275
4451
|
});
|
|
4276
4452
|
return returnValue;
|
|
@@ -4540,16 +4716,36 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
4540
4716
|
shouldRender = true;
|
|
4541
4717
|
}
|
|
4542
4718
|
if (host) {
|
|
4543
|
-
|
|
4544
|
-
|
|
4719
|
+
let vNodeProps = vnode_getProp(host, ELEMENT_PROPS, container.$getObjectById$);
|
|
4720
|
+
const propsAreDifferent = propsDiffer(jsxProps, vNodeProps);
|
|
4721
|
+
shouldRender = shouldRender || propsAreDifferent;
|
|
4545
4722
|
if (shouldRender) {
|
|
4723
|
+
if (propsAreDifferent) {
|
|
4724
|
+
if (vNodeProps) {
|
|
4725
|
+
// Reuse the same props instance, qrls can use the current props instance
|
|
4726
|
+
// as a capture ref, so we can't change it.
|
|
4727
|
+
// We need to do this directly, because normally we would subscribe to the signals
|
|
4728
|
+
// if any signal is there.
|
|
4729
|
+
vNodeProps[_CONST_PROPS] = jsxProps[_CONST_PROPS];
|
|
4730
|
+
vNodeProps[_VAR_PROPS] = jsxProps[_VAR_PROPS];
|
|
4731
|
+
}
|
|
4732
|
+
else if (jsxProps) {
|
|
4733
|
+
// If there is no props instance, create a new one.
|
|
4734
|
+
// We can do this because we are not using the props instance for anything else.
|
|
4735
|
+
vnode_setProp(host, ELEMENT_PROPS, jsxProps);
|
|
4736
|
+
vNodeProps = jsxProps;
|
|
4737
|
+
}
|
|
4738
|
+
}
|
|
4739
|
+
// Assign the new QRL instance to the host.
|
|
4740
|
+
// Unfortunately it is created every time, something to fix in the optimizer.
|
|
4741
|
+
vnode_setProp(host, OnRenderProp, componentQRL);
|
|
4546
4742
|
/**
|
|
4547
4743
|
* Mark host as not deleted. The host could have been marked as deleted if it there was a
|
|
4548
4744
|
* cleanup run. Now we found it and want to reuse it, so we need to mark it as not
|
|
4549
4745
|
* deleted.
|
|
4550
4746
|
*/
|
|
4551
4747
|
host[0 /* VNodeProps.flags */] &= -33 /* VNodeFlags.Deleted */;
|
|
4552
|
-
container.$scheduler$(6 /* ChoreType.COMPONENT */, host, componentQRL,
|
|
4748
|
+
container.$scheduler$(6 /* ChoreType.COMPONENT */, host, componentQRL, vNodeProps);
|
|
4553
4749
|
}
|
|
4554
4750
|
}
|
|
4555
4751
|
descendContentToProject(jsxNode.children, host);
|
|
@@ -4752,7 +4948,7 @@ function cleanup(container, vNode) {
|
|
|
4752
4948
|
const task = obj;
|
|
4753
4949
|
clearAllEffects(container, task);
|
|
4754
4950
|
if (task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
|
|
4755
|
-
container.$scheduler$(
|
|
4951
|
+
container.$scheduler$(32 /* ChoreType.CLEANUP_VISIBLE */, task);
|
|
4756
4952
|
}
|
|
4757
4953
|
else {
|
|
4758
4954
|
cleanupTask(task);
|
|
@@ -4803,7 +4999,16 @@ function cleanup(container, vNode) {
|
|
|
4803
4999
|
*/
|
|
4804
5000
|
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
4805
5001
|
if (vFirstChild) {
|
|
4806
|
-
vnode_walkVNode(vFirstChild)
|
|
5002
|
+
vnode_walkVNode(vFirstChild, (vNode) => {
|
|
5003
|
+
/**
|
|
5004
|
+
* Instead of an ID, we store a direct reference to the VNode. This is necessary to
|
|
5005
|
+
* locate the slot's parent in a detached subtree, as the ID would become invalid.
|
|
5006
|
+
*/
|
|
5007
|
+
if (vNode[0 /* VNodeProps.flags */] & 2 /* VNodeFlags.Virtual */) {
|
|
5008
|
+
// The QSlotParent is used to find the slot parent during scheduling
|
|
5009
|
+
vnode_getProp(vNode, QSlotParent, (id) => vnode_locate(container.rootVNode, id));
|
|
5010
|
+
}
|
|
5011
|
+
});
|
|
4807
5012
|
return;
|
|
4808
5013
|
}
|
|
4809
5014
|
}
|
|
@@ -4880,8 +5085,8 @@ const useResourceQrl = (qrl, opts) => {
|
|
|
4880
5085
|
const resource = createResourceReturn(container, opts);
|
|
4881
5086
|
const el = iCtx.$hostElement$;
|
|
4882
5087
|
const task = new Task(8 /* TaskFlags.DIRTY */ | 4 /* TaskFlags.RESOURCE */, i, el, qrl, resource, null);
|
|
4883
|
-
container.$scheduler$(3 /* ChoreType.TASK */, task);
|
|
4884
5088
|
set(resource);
|
|
5089
|
+
runResource(task, container, el);
|
|
4885
5090
|
return resource;
|
|
4886
5091
|
};
|
|
4887
5092
|
// <docs markdown="../readme.md#useResource">
|
|
@@ -4949,10 +5154,10 @@ const Resource = (props) => {
|
|
|
4949
5154
|
function getResourceValueAsPromise(props) {
|
|
4950
5155
|
const resource = props.value;
|
|
4951
5156
|
if (isResourceReturn(resource)) {
|
|
5157
|
+
// create a subscription for the resource._state changes
|
|
5158
|
+
const state = resource._state;
|
|
4952
5159
|
const isBrowser = !isServerPlatform();
|
|
4953
5160
|
if (isBrowser) {
|
|
4954
|
-
// create a subscription for the resource._state changes
|
|
4955
|
-
const state = resource._state;
|
|
4956
5161
|
if (state === 'pending' && props.onPending) {
|
|
4957
5162
|
return Promise.resolve().then(useBindInvokeContext(props.onPending));
|
|
4958
5163
|
}
|
|
@@ -4967,30 +5172,25 @@ function getResourceValueAsPromise(props) {
|
|
|
4967
5172
|
}
|
|
4968
5173
|
}
|
|
4969
5174
|
}
|
|
4970
|
-
|
|
4971
|
-
if (value) {
|
|
4972
|
-
return value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
4973
|
-
}
|
|
4974
|
-
else {
|
|
4975
|
-
// this is temporary value until the `runResource` is executed and promise is assigned to the value
|
|
4976
|
-
return Promise.resolve(undefined);
|
|
4977
|
-
}
|
|
5175
|
+
return untrack(() => resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
4978
5176
|
}
|
|
4979
5177
|
else if (isPromise(resource)) {
|
|
4980
5178
|
return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
4981
5179
|
}
|
|
4982
5180
|
else if (isSignal(resource)) {
|
|
4983
|
-
|
|
5181
|
+
const value = retryOnPromise(() => resource.value);
|
|
5182
|
+
const promise = isPromise(value) ? value : Promise.resolve(value);
|
|
5183
|
+
return promise.then(useBindInvokeContext(props.onResolved));
|
|
4984
5184
|
}
|
|
4985
5185
|
else {
|
|
4986
|
-
return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved)
|
|
5186
|
+
return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved));
|
|
4987
5187
|
}
|
|
4988
5188
|
}
|
|
4989
5189
|
const _createResourceReturn = (opts) => {
|
|
4990
5190
|
const resource = {
|
|
4991
5191
|
__brand: 'resource',
|
|
4992
5192
|
value: undefined,
|
|
4993
|
-
loading: isServerPlatform()
|
|
5193
|
+
loading: !isServerPlatform(),
|
|
4994
5194
|
_resolved: undefined,
|
|
4995
5195
|
_error: undefined,
|
|
4996
5196
|
_state: 'pending',
|
|
@@ -5041,19 +5241,22 @@ const runResource = (task, container, host) => {
|
|
|
5041
5241
|
done = true;
|
|
5042
5242
|
if (resolved) {
|
|
5043
5243
|
done = true;
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5244
|
+
resourceTarget.loading = false;
|
|
5245
|
+
resourceTarget._state = 'resolved';
|
|
5246
|
+
resourceTarget._resolved = value;
|
|
5247
|
+
resourceTarget._error = undefined;
|
|
5048
5248
|
resolve(value);
|
|
5049
5249
|
}
|
|
5050
5250
|
else {
|
|
5051
5251
|
done = true;
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5252
|
+
resourceTarget.loading = false;
|
|
5253
|
+
resourceTarget._state = 'rejected';
|
|
5254
|
+
resourceTarget._error = value;
|
|
5055
5255
|
reject(value);
|
|
5056
5256
|
}
|
|
5257
|
+
if (!isServerPlatform()) {
|
|
5258
|
+
forceStoreEffects(resource, '_state');
|
|
5259
|
+
}
|
|
5057
5260
|
return true;
|
|
5058
5261
|
}
|
|
5059
5262
|
return false;
|
|
@@ -5069,17 +5272,17 @@ const runResource = (task, container, host) => {
|
|
|
5069
5272
|
}
|
|
5070
5273
|
});
|
|
5071
5274
|
// Execute mutation inside empty invocation
|
|
5275
|
+
// TODO: is it right? why we need to invoke inside context and trigger effects?
|
|
5072
5276
|
invoke(iCtx, () => {
|
|
5073
5277
|
// console.log('RESOURCE.pending: ');
|
|
5074
5278
|
resource._state = 'pending';
|
|
5075
5279
|
resource.loading = !isServerPlatform();
|
|
5076
|
-
|
|
5280
|
+
resource.value = new Promise((r, re) => {
|
|
5077
5281
|
resolve = r;
|
|
5078
5282
|
reject = re;
|
|
5079
|
-
})
|
|
5080
|
-
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
5283
|
+
});
|
|
5081
5284
|
});
|
|
5082
|
-
const promise = safeCall(() =>
|
|
5285
|
+
const promise = safeCall(() => taskFn(opts), (value) => {
|
|
5083
5286
|
setState(true, value);
|
|
5084
5287
|
}, (err) => {
|
|
5085
5288
|
if (isPromise(err)) {
|
|
@@ -5102,10 +5305,6 @@ const runResource = (task, container, host) => {
|
|
|
5102
5305
|
}
|
|
5103
5306
|
return promise;
|
|
5104
5307
|
};
|
|
5105
|
-
const ignoreErrorToPreventNodeFromCrashing = (err) => {
|
|
5106
|
-
// ignore error to prevent node from crashing
|
|
5107
|
-
// node will crash in promise is rejected and no one is listening to the rejection.
|
|
5108
|
-
};
|
|
5109
5308
|
|
|
5110
5309
|
/// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
|
|
5111
5310
|
const aVNodePath = [];
|
|
@@ -5188,11 +5387,11 @@ const ssrNodeDocumentPosition = (a, b) => {
|
|
|
5188
5387
|
let bDepth = -1;
|
|
5189
5388
|
while (a) {
|
|
5190
5389
|
const ssrNode = (aSsrNodePath[++aDepth] = a);
|
|
5191
|
-
a = ssrNode.
|
|
5390
|
+
a = ssrNode.parentComponent;
|
|
5192
5391
|
}
|
|
5193
5392
|
while (b) {
|
|
5194
5393
|
const ssrNode = (bSsrNodePath[++bDepth] = b);
|
|
5195
|
-
b = ssrNode.
|
|
5394
|
+
b = ssrNode.parentComponent;
|
|
5196
5395
|
}
|
|
5197
5396
|
while (aDepth >= 0 && bDepth >= 0) {
|
|
5198
5397
|
a = aSsrNodePath[aDepth];
|
|
@@ -5209,6 +5408,210 @@ const ssrNodeDocumentPosition = (a, b) => {
|
|
|
5209
5408
|
return aDepth < bDepth ? -1 : 1;
|
|
5210
5409
|
};
|
|
5211
5410
|
|
|
5411
|
+
/**
|
|
5412
|
+
* Rules for determining if a chore is blocked by another chore. Some chores can block other chores.
|
|
5413
|
+
* They cannot run until the blocking chore has completed.
|
|
5414
|
+
*
|
|
5415
|
+
* The match function is used to determine if the blocked chore is blocked by the blocking chore.
|
|
5416
|
+
* The match function is called with the blocked chore, the blocking chore, and the container.
|
|
5417
|
+
*/
|
|
5418
|
+
const VISIBLE_BLOCKING_RULES = [
|
|
5419
|
+
// NODE_DIFF blocks VISIBLE on same host,
|
|
5420
|
+
// if the blocked chore is a child of the blocking chore
|
|
5421
|
+
// or the blocked chore is a sibling of the blocking chore
|
|
5422
|
+
{
|
|
5423
|
+
blockedType: 16 /* ChoreType.VISIBLE */,
|
|
5424
|
+
blockingType: 4 /* ChoreType.NODE_DIFF */,
|
|
5425
|
+
match: (blocked, blocking, container) => isDescendant(blocked, blocking, container) || isDescendant(blocking, blocked, container),
|
|
5426
|
+
},
|
|
5427
|
+
// COMPONENT blocks VISIBLE on same host
|
|
5428
|
+
// if the blocked chore is a child of the blocking chore
|
|
5429
|
+
// or the blocked chore is a sibling of the blocking chore
|
|
5430
|
+
{
|
|
5431
|
+
blockedType: 16 /* ChoreType.VISIBLE */,
|
|
5432
|
+
blockingType: 6 /* ChoreType.COMPONENT */,
|
|
5433
|
+
match: (blocked, blocking, container) => isDescendant(blocked, blocking, container) || isDescendant(blocking, blocked, container),
|
|
5434
|
+
},
|
|
5435
|
+
];
|
|
5436
|
+
const BLOCKING_RULES = [
|
|
5437
|
+
// QRL_RESOLVE blocks RUN_QRL, TASK, VISIBLE on same host
|
|
5438
|
+
{
|
|
5439
|
+
blockedType: 2 /* ChoreType.RUN_QRL */,
|
|
5440
|
+
blockingType: 1 /* ChoreType.QRL_RESOLVE */,
|
|
5441
|
+
match: (blocked, blocking) => {
|
|
5442
|
+
const blockedQrl = blocked.$target$;
|
|
5443
|
+
const blockingQrl = blocking.$target$;
|
|
5444
|
+
return isSameHost(blocked, blocking) && isSameQrl(blockedQrl, blockingQrl);
|
|
5445
|
+
},
|
|
5446
|
+
},
|
|
5447
|
+
{
|
|
5448
|
+
blockedType: 3 /* ChoreType.TASK */,
|
|
5449
|
+
blockingType: 1 /* ChoreType.QRL_RESOLVE */,
|
|
5450
|
+
match: (blocked, blocking) => {
|
|
5451
|
+
const blockedTask = blocked.$payload$;
|
|
5452
|
+
const blockingQrl = blocking.$target$;
|
|
5453
|
+
return isSameHost(blocked, blocking) && isSameQrl(blockedTask.$qrl$, blockingQrl);
|
|
5454
|
+
},
|
|
5455
|
+
},
|
|
5456
|
+
{
|
|
5457
|
+
blockedType: 16 /* ChoreType.VISIBLE */,
|
|
5458
|
+
blockingType: 1 /* ChoreType.QRL_RESOLVE */,
|
|
5459
|
+
match: (blocked, blocking) => {
|
|
5460
|
+
const blockedTask = blocked.$payload$;
|
|
5461
|
+
const blockingQrl = blocking.$target$;
|
|
5462
|
+
return isSameHost(blocked, blocking) && isSameQrl(blockedTask.$qrl$, blockingQrl);
|
|
5463
|
+
},
|
|
5464
|
+
},
|
|
5465
|
+
// COMPONENT blocks NODE_DIFF, NODE_PROP on same host
|
|
5466
|
+
{
|
|
5467
|
+
blockedType: 4 /* ChoreType.NODE_DIFF */,
|
|
5468
|
+
blockingType: 6 /* ChoreType.COMPONENT */,
|
|
5469
|
+
match: (blocked, blocking) => blocked.$host$ === blocking.$host$,
|
|
5470
|
+
},
|
|
5471
|
+
{
|
|
5472
|
+
blockedType: 5 /* ChoreType.NODE_PROP */,
|
|
5473
|
+
blockingType: 6 /* ChoreType.COMPONENT */,
|
|
5474
|
+
match: (blocked, blocking) => blocked.$host$ === blocking.$host$,
|
|
5475
|
+
},
|
|
5476
|
+
...VISIBLE_BLOCKING_RULES,
|
|
5477
|
+
// TASK blocks subsequent TASKs in the same component
|
|
5478
|
+
{
|
|
5479
|
+
blockedType: 3 /* ChoreType.TASK */,
|
|
5480
|
+
blockingType: 3 /* ChoreType.TASK */,
|
|
5481
|
+
match: (blocked, blocking, container) => {
|
|
5482
|
+
if (blocked.$host$ !== blocking.$host$) {
|
|
5483
|
+
return false;
|
|
5484
|
+
}
|
|
5485
|
+
const blockedIdx = blocked.$idx$;
|
|
5486
|
+
if (!isNumber$1(blockedIdx) || blockedIdx <= 0) {
|
|
5487
|
+
return false;
|
|
5488
|
+
}
|
|
5489
|
+
const previousTask = findPreviousTaskInComponent(blocked.$host$, blockedIdx, container);
|
|
5490
|
+
return previousTask === blocking.$payload$;
|
|
5491
|
+
},
|
|
5492
|
+
},
|
|
5493
|
+
];
|
|
5494
|
+
function isDescendant(descendantChore, ancestorChore, container) {
|
|
5495
|
+
const descendantHost = descendantChore.$host$;
|
|
5496
|
+
const ancestorHost = ancestorChore.$host$;
|
|
5497
|
+
if (!vnode_isVNode(descendantHost) || !vnode_isVNode(ancestorHost)) {
|
|
5498
|
+
return false;
|
|
5499
|
+
}
|
|
5500
|
+
return vnode_isDescendantOf(descendantHost, ancestorHost, container.rootVNode);
|
|
5501
|
+
}
|
|
5502
|
+
function isSameHost(a, b) {
|
|
5503
|
+
return a.$host$ === b.$host$;
|
|
5504
|
+
}
|
|
5505
|
+
function isSameQrl(a, b) {
|
|
5506
|
+
return a.$symbol$ === b.$symbol$;
|
|
5507
|
+
}
|
|
5508
|
+
function findBlockingChoreInQueue(chore, choreQueue, container) {
|
|
5509
|
+
for (const candidate of choreQueue) {
|
|
5510
|
+
// everything after VISIBLE is not blocking. Visible task, task and resource should not block anything in this rule.
|
|
5511
|
+
if (candidate.$type$ >= 16 /* ChoreType.VISIBLE */ || candidate.$type$ === 3 /* ChoreType.TASK */) {
|
|
5512
|
+
continue;
|
|
5513
|
+
}
|
|
5514
|
+
if (isDescendant(chore, candidate, container)) {
|
|
5515
|
+
return candidate;
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
return null;
|
|
5519
|
+
}
|
|
5520
|
+
function findBlockingChore(chore, choreQueue, blockedChores, runningChores, container) {
|
|
5521
|
+
const blockingChoreInChoreQueue = findBlockingChoreInQueue(chore, choreQueue, container);
|
|
5522
|
+
if (blockingChoreInChoreQueue) {
|
|
5523
|
+
return blockingChoreInChoreQueue;
|
|
5524
|
+
}
|
|
5525
|
+
const blockingChoreInBlockedChores = findBlockingChoreInQueue(chore, Array.from(blockedChores), container);
|
|
5526
|
+
if (blockingChoreInBlockedChores) {
|
|
5527
|
+
return blockingChoreInBlockedChores;
|
|
5528
|
+
}
|
|
5529
|
+
const blockingChoreInRunningChores = findBlockingChoreInQueue(chore, Array.from(runningChores), container);
|
|
5530
|
+
if (blockingChoreInRunningChores) {
|
|
5531
|
+
return blockingChoreInRunningChores;
|
|
5532
|
+
}
|
|
5533
|
+
for (const rule of BLOCKING_RULES) {
|
|
5534
|
+
if (chore.$type$ !== rule.blockedType) {
|
|
5535
|
+
continue;
|
|
5536
|
+
}
|
|
5537
|
+
// Check in choreQueue
|
|
5538
|
+
// TODO(perf): better to iterate in reverse order?
|
|
5539
|
+
for (const candidate of choreQueue) {
|
|
5540
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5541
|
+
return candidate;
|
|
5542
|
+
}
|
|
5543
|
+
}
|
|
5544
|
+
// Check in blockedChores
|
|
5545
|
+
for (const candidate of blockedChores) {
|
|
5546
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5547
|
+
return candidate;
|
|
5548
|
+
}
|
|
5549
|
+
}
|
|
5550
|
+
// Check in runningChores
|
|
5551
|
+
for (const candidate of runningChores) {
|
|
5552
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5553
|
+
return candidate;
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5556
|
+
}
|
|
5557
|
+
return null;
|
|
5558
|
+
}
|
|
5559
|
+
function findPreviousTaskInComponent(host, currentTaskIdx, container) {
|
|
5560
|
+
const elementSeq = container.getHostProp(host, ELEMENT_SEQ);
|
|
5561
|
+
if (!elementSeq || elementSeq.length <= currentTaskIdx) {
|
|
5562
|
+
return null;
|
|
5563
|
+
}
|
|
5564
|
+
for (let i = currentTaskIdx - 1; i >= 0; i--) {
|
|
5565
|
+
const candidate = elementSeq[i];
|
|
5566
|
+
if (candidate instanceof Task && candidate.$flags$ & 2 /* TaskFlags.TASK */) {
|
|
5567
|
+
return candidate;
|
|
5568
|
+
}
|
|
5569
|
+
}
|
|
5570
|
+
return null;
|
|
5571
|
+
}
|
|
5572
|
+
function findBlockingChoreForVisible(chore, runningChores, container) {
|
|
5573
|
+
for (const rule of VISIBLE_BLOCKING_RULES) {
|
|
5574
|
+
if (chore.$type$ !== rule.blockedType) {
|
|
5575
|
+
continue;
|
|
5576
|
+
}
|
|
5577
|
+
for (const candidate of runningChores) {
|
|
5578
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5579
|
+
return candidate;
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
return null;
|
|
5584
|
+
}
|
|
5585
|
+
|
|
5586
|
+
// This can't be in platform.ts because it uses MessageChannel which cannot post messages with functions
|
|
5587
|
+
// TODO: move this to platform.ts somehow
|
|
5588
|
+
const createNextTick = (fn) => {
|
|
5589
|
+
let nextTick;
|
|
5590
|
+
// according to the https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate#notes
|
|
5591
|
+
if (typeof setImmediate === 'function') {
|
|
5592
|
+
// setImmediate is the fastest way to schedule a task, but works only in node.js
|
|
5593
|
+
nextTick = () => {
|
|
5594
|
+
setImmediate(fn);
|
|
5595
|
+
};
|
|
5596
|
+
}
|
|
5597
|
+
else if (typeof MessageChannel !== 'undefined') {
|
|
5598
|
+
const channel = new MessageChannel();
|
|
5599
|
+
channel.port1.onmessage = () => {
|
|
5600
|
+
fn();
|
|
5601
|
+
};
|
|
5602
|
+
nextTick = () => {
|
|
5603
|
+
channel.port2.postMessage(null);
|
|
5604
|
+
};
|
|
5605
|
+
}
|
|
5606
|
+
else {
|
|
5607
|
+
// setTimeout is a fallback, creates 4ms delay
|
|
5608
|
+
nextTick = () => {
|
|
5609
|
+
setTimeout(fn);
|
|
5610
|
+
};
|
|
5611
|
+
}
|
|
5612
|
+
return nextTick;
|
|
5613
|
+
};
|
|
5614
|
+
|
|
5212
5615
|
/**
|
|
5213
5616
|
* Scheduler is responsible for running application code in predictable order.
|
|
5214
5617
|
*
|
|
@@ -5292,29 +5695,43 @@ const ssrNodeDocumentPosition = (a, b) => {
|
|
|
5292
5695
|
*/
|
|
5293
5696
|
// Turn this on to get debug output of what the scheduler is doing.
|
|
5294
5697
|
const DEBUG = false;
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5698
|
+
var ChoreState;
|
|
5699
|
+
(function (ChoreState) {
|
|
5700
|
+
ChoreState[ChoreState["NONE"] = 0] = "NONE";
|
|
5701
|
+
ChoreState[ChoreState["RUNNING"] = 1] = "RUNNING";
|
|
5702
|
+
ChoreState[ChoreState["FAILED"] = 2] = "FAILED";
|
|
5703
|
+
ChoreState[ChoreState["DONE"] = 3] = "DONE";
|
|
5704
|
+
})(ChoreState || (ChoreState = {}));
|
|
5705
|
+
const getChorePromise = (chore) => chore.$state$ === ChoreState.NONE
|
|
5706
|
+
? (chore.$returnValue$ ||= new Promise((resolve, reject) => {
|
|
5707
|
+
chore.$resolve$ = resolve;
|
|
5708
|
+
chore.$reject$ = reject;
|
|
5709
|
+
}))
|
|
5710
|
+
: chore.$returnValue$;
|
|
5711
|
+
const createScheduler = (container, journalFlush, choreQueue = [], blockedChores = new Set(), runningChores = new Set()) => {
|
|
5712
|
+
let drainChore = null;
|
|
5302
5713
|
let drainScheduled = false;
|
|
5714
|
+
let isDraining = false;
|
|
5715
|
+
let isJournalFlushRunning = false;
|
|
5716
|
+
let flushBudgetStart = 0;
|
|
5717
|
+
let currentTime = performance.now();
|
|
5718
|
+
const nextTick = createNextTick(drainChoreQueue);
|
|
5719
|
+
function drainInNextTick() {
|
|
5720
|
+
if (!drainScheduled) {
|
|
5721
|
+
drainScheduled = true;
|
|
5722
|
+
nextTick();
|
|
5723
|
+
}
|
|
5724
|
+
}
|
|
5725
|
+
// Drain for ~16.67ms, then apply journal flush for ~16.67ms, then repeat
|
|
5726
|
+
// We divide by 60 because we want to run at 60fps
|
|
5727
|
+
const FREQUENCY_MS = Math.floor(1000 / 60);
|
|
5303
5728
|
return schedule;
|
|
5304
5729
|
///// IMPLEMENTATION /////
|
|
5305
5730
|
function schedule(type, hostOrTask = null, targetOrQrl = null, payload = null) {
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
const runLater = type !== 255 /* ChoreType.WAIT_FOR_ALL */ && !isComponentSsr && type !== 2 /* ChoreType.RUN_QRL */;
|
|
5309
|
-
const isTask = type === 3 /* ChoreType.TASK */ || type === 32 /* ChoreType.VISIBLE */ || type === 48 /* ChoreType.CLEANUP_VISIBLE */;
|
|
5310
|
-
const isClientOnly = type === 16 /* ChoreType.JOURNAL_FLUSH */ ||
|
|
5311
|
-
type === 4 /* ChoreType.NODE_DIFF */ ||
|
|
5312
|
-
type === 5 /* ChoreType.NODE_PROP */ ||
|
|
5313
|
-
type === 1 /* ChoreType.QRL_RESOLVE */ ||
|
|
5314
|
-
type === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */;
|
|
5315
|
-
if (isServer && isClientOnly) {
|
|
5316
|
-
return;
|
|
5731
|
+
if (type === 255 /* ChoreType.WAIT_FOR_QUEUE */ && drainChore) {
|
|
5732
|
+
return drainChore;
|
|
5317
5733
|
}
|
|
5734
|
+
const isTask = type === 3 /* ChoreType.TASK */ || type === 16 /* ChoreType.VISIBLE */ || type === 32 /* ChoreType.CLEANUP_VISIBLE */;
|
|
5318
5735
|
if (isTask) {
|
|
5319
5736
|
hostOrTask.$flags$ |= 8 /* TaskFlags.DIRTY */;
|
|
5320
5737
|
}
|
|
@@ -5328,167 +5745,310 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
5328
5745
|
$host$: isTask ? hostOrTask.$el$ : hostOrTask,
|
|
5329
5746
|
$target$: targetOrQrl,
|
|
5330
5747
|
$payload$: isTask ? hostOrTask : payload,
|
|
5331
|
-
$
|
|
5332
|
-
$
|
|
5748
|
+
$state$: ChoreState.NONE,
|
|
5749
|
+
$blockedChores$: null,
|
|
5750
|
+
$startTime$: undefined,
|
|
5751
|
+
$endTime$: undefined,
|
|
5752
|
+
$resolve$: undefined,
|
|
5753
|
+
$reject$: undefined,
|
|
5333
5754
|
$returnValue$: null,
|
|
5334
|
-
$executed$: false,
|
|
5335
5755
|
};
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5756
|
+
if (type === 255 /* ChoreType.WAIT_FOR_QUEUE */) {
|
|
5757
|
+
getChorePromise(chore);
|
|
5758
|
+
drainChore = chore;
|
|
5759
|
+
drainInNextTick();
|
|
5760
|
+
return chore;
|
|
5761
|
+
}
|
|
5762
|
+
const isServer = isServerPlatform();
|
|
5763
|
+
const isClientOnly = type === 4 /* ChoreType.NODE_DIFF */ || type === 1 /* ChoreType.QRL_RESOLVE */;
|
|
5764
|
+
if (isServer && isClientOnly) {
|
|
5765
|
+
// Mark skipped client-only chores as completed on the server
|
|
5766
|
+
finishChore(chore, undefined);
|
|
5767
|
+
return chore;
|
|
5768
|
+
}
|
|
5769
|
+
if (isServer && chore.$host$ && isSsrNode(chore.$host$)) {
|
|
5770
|
+
const isUpdatable = !!(chore.$host$.flags & 1 /* SsrNodeFlags.Updatable */);
|
|
5771
|
+
if (!isUpdatable) {
|
|
5772
|
+
if (
|
|
5773
|
+
// backpatching exceptions:
|
|
5774
|
+
// - node prop is allowed because it is used to update the node property
|
|
5775
|
+
// - recompute and schedule effects because it triggers effects (so node prop too)
|
|
5776
|
+
chore.$type$ !== 5 /* ChoreType.NODE_PROP */ &&
|
|
5777
|
+
chore.$type$ !== 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */) {
|
|
5778
|
+
// We are running on the server.
|
|
5779
|
+
// On server we can't schedule task for a different host!
|
|
5780
|
+
// Server is SSR, and therefore scheduling for anything but the current host
|
|
5781
|
+
// implies that things need to be re-run and that is not supported because of streaming.
|
|
5782
|
+
const warningMessage = `A '${choreTypeToName(chore.$type$)}' chore was scheduled on a host element that has already been streamed to the client.
|
|
5783
|
+
This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
|
|
5784
|
+
|
|
5785
|
+
Problematic chore:
|
|
5786
|
+
- Type: ${choreTypeToName(chore.$type$)}
|
|
5787
|
+
- Host: ${chore.$host$.toString()}
|
|
5788
|
+
- Nearest element location: ${chore.$host$.currentFile}
|
|
5789
|
+
|
|
5790
|
+
This is often caused by modifying a signal in an already rendered component during SSR.`;
|
|
5791
|
+
logWarn(warningMessage);
|
|
5792
|
+
return chore;
|
|
5793
|
+
}
|
|
5794
|
+
}
|
|
5343
5795
|
}
|
|
5344
|
-
|
|
5345
|
-
if (
|
|
5346
|
-
|
|
5796
|
+
const blockingChore = findBlockingChore(chore, choreQueue, blockedChores, runningChores, container);
|
|
5797
|
+
if (blockingChore) {
|
|
5798
|
+
addBlockedChore(chore, blockingChore, blockedChores);
|
|
5799
|
+
return chore;
|
|
5800
|
+
}
|
|
5801
|
+
chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
|
|
5802
|
+
const runImmediately = (isServer && type === 6 /* ChoreType.COMPONENT */) || type === 2 /* ChoreType.RUN_QRL */;
|
|
5803
|
+
if (runImmediately && !isDraining) {
|
|
5804
|
+
immediateDrain();
|
|
5347
5805
|
}
|
|
5348
5806
|
else {
|
|
5349
|
-
|
|
5350
|
-
}
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
function
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5807
|
+
drainInNextTick();
|
|
5808
|
+
}
|
|
5809
|
+
return chore;
|
|
5810
|
+
}
|
|
5811
|
+
function immediateDrain() {
|
|
5812
|
+
drainScheduled = true;
|
|
5813
|
+
drainChoreQueue();
|
|
5814
|
+
}
|
|
5815
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
5816
|
+
// Drain queue helpers
|
|
5817
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
5818
|
+
function applyJournalFlush() {
|
|
5819
|
+
if (!isJournalFlushRunning) {
|
|
5820
|
+
// prevent multiple journal flushes from running at the same time
|
|
5821
|
+
isJournalFlushRunning = true;
|
|
5822
|
+
journalFlush();
|
|
5823
|
+
isJournalFlushRunning = false;
|
|
5824
|
+
flushBudgetStart = performance.now();
|
|
5825
|
+
}
|
|
5826
|
+
}
|
|
5827
|
+
function shouldApplyJournalFlush(isServer) {
|
|
5828
|
+
return !isServer && currentTime - flushBudgetStart >= FREQUENCY_MS;
|
|
5829
|
+
}
|
|
5830
|
+
function drainChoreQueue() {
|
|
5831
|
+
const isServer = isServerPlatform();
|
|
5832
|
+
drainScheduled = false;
|
|
5833
|
+
if (isDraining) {
|
|
5834
|
+
return;
|
|
5835
|
+
}
|
|
5836
|
+
// early return if the queue is empty
|
|
5837
|
+
if (!choreQueue.length) {
|
|
5838
|
+
applyJournalFlush();
|
|
5839
|
+
if (drainChore && !runningChores.size) {
|
|
5840
|
+
// resolve drainChore only if there are no running chores, because
|
|
5841
|
+
// we are sure that we are done
|
|
5842
|
+
drainChore.$resolve$(null);
|
|
5843
|
+
drainChore = null;
|
|
5366
5844
|
}
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5845
|
+
return;
|
|
5846
|
+
}
|
|
5847
|
+
isDraining = true;
|
|
5848
|
+
flushBudgetStart = performance.now();
|
|
5849
|
+
const maybeFinishDrain = () => {
|
|
5850
|
+
if (choreQueue.length) {
|
|
5851
|
+
drainInNextTick();
|
|
5852
|
+
return false;
|
|
5853
|
+
}
|
|
5854
|
+
if (drainChore && runningChores.size) {
|
|
5855
|
+
if (shouldApplyJournalFlush(isServer)) {
|
|
5856
|
+
// apply journal flush even if we are not finished draining the queue
|
|
5857
|
+
applyJournalFlush();
|
|
5372
5858
|
}
|
|
5373
|
-
|
|
5859
|
+
return false;
|
|
5374
5860
|
}
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5861
|
+
currentChore = null;
|
|
5862
|
+
applyJournalFlush();
|
|
5863
|
+
drainChore?.$resolve$(null);
|
|
5864
|
+
drainChore = null;
|
|
5865
|
+
return true;
|
|
5866
|
+
};
|
|
5867
|
+
const scheduleBlockedChoresAndDrainIfNeeded = (chore) => {
|
|
5868
|
+
let blockedChoresScheduled = false;
|
|
5869
|
+
if (chore.$blockedChores$) {
|
|
5870
|
+
for (const blockedChore of chore.$blockedChores$) {
|
|
5871
|
+
const blockingChore = findBlockingChore(blockedChore, choreQueue, blockedChores, runningChores, container);
|
|
5872
|
+
if (blockingChore) {
|
|
5873
|
+
addBlockedChore(blockedChore, blockingChore, blockedChores);
|
|
5874
|
+
}
|
|
5875
|
+
else {
|
|
5876
|
+
blockedChores.delete(blockedChore);
|
|
5877
|
+
sortedInsert(choreQueue, blockedChore, container.rootVNode || null);
|
|
5878
|
+
blockedChoresScheduled = true;
|
|
5879
|
+
}
|
|
5880
|
+
}
|
|
5881
|
+
chore.$blockedChores$ = null;
|
|
5380
5882
|
}
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
const host = chore.$host$;
|
|
5387
|
-
assertEqual(currentChore, null, 'Chore already running.');
|
|
5388
|
-
currentChore = chore;
|
|
5389
|
-
let returnValue = null;
|
|
5883
|
+
if (blockedChoresScheduled && !isDraining) {
|
|
5884
|
+
drainInNextTick();
|
|
5885
|
+
}
|
|
5886
|
+
};
|
|
5887
|
+
let currentChore = null;
|
|
5390
5888
|
try {
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5889
|
+
while (choreQueue.length) {
|
|
5890
|
+
currentTime = performance.now();
|
|
5891
|
+
const chore = (currentChore = choreQueue.shift());
|
|
5892
|
+
if (chore.$state$ !== ChoreState.NONE) {
|
|
5893
|
+
continue;
|
|
5894
|
+
}
|
|
5895
|
+
if (vNodeAlreadyDeleted(chore) &&
|
|
5896
|
+
// we need to process cleanup tasks for deleted nodes
|
|
5897
|
+
chore.$type$ !== 32 /* ChoreType.CLEANUP_VISIBLE */) {
|
|
5898
|
+
// skip deleted chore
|
|
5899
|
+
DEBUG && debugTrace('skip chore', chore, choreQueue, blockedChores);
|
|
5900
|
+
continue;
|
|
5901
|
+
}
|
|
5902
|
+
if (chore.$type$ === 16 /* ChoreType.VISIBLE */) {
|
|
5903
|
+
// ensure that the journal flush is applied before the visible chore is executed
|
|
5904
|
+
// so that the visible chore can see the latest DOM changes
|
|
5905
|
+
applyJournalFlush();
|
|
5906
|
+
const blockingChore = findBlockingChoreForVisible(chore, runningChores, container);
|
|
5907
|
+
if (blockingChore && blockingChore.$state$ === ChoreState.RUNNING) {
|
|
5908
|
+
addBlockedChore(chore, blockingChore, blockedChores);
|
|
5909
|
+
continue;
|
|
5403
5910
|
}
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5911
|
+
}
|
|
5912
|
+
// Note that this never throws
|
|
5913
|
+
chore.$startTime$ = performance.now();
|
|
5914
|
+
const result = executeChore(chore, isServer);
|
|
5915
|
+
chore.$returnValue$ = result;
|
|
5916
|
+
if (isPromise(result)) {
|
|
5917
|
+
runningChores.add(chore);
|
|
5918
|
+
chore.$state$ = ChoreState.RUNNING;
|
|
5919
|
+
result
|
|
5920
|
+
.then((value) => {
|
|
5921
|
+
finishChore(chore, value);
|
|
5922
|
+
})
|
|
5923
|
+
.catch((e) => {
|
|
5924
|
+
if (chore.$state$ !== ChoreState.RUNNING) {
|
|
5925
|
+
// we already handled the error
|
|
5926
|
+
return;
|
|
5927
|
+
}
|
|
5928
|
+
handleError(chore, e);
|
|
5929
|
+
})
|
|
5930
|
+
.finally(() => {
|
|
5931
|
+
runningChores.delete(chore);
|
|
5932
|
+
// Note that we ignore failed chores so the app keeps working
|
|
5933
|
+
// TODO decide if this is ok and document it
|
|
5934
|
+
scheduleBlockedChoresAndDrainIfNeeded(chore);
|
|
5935
|
+
// If drainChore is not null, we are waiting for it to finish.
|
|
5936
|
+
// If there are no running chores, we can finish the drain.
|
|
5937
|
+
if (!runningChores.size) {
|
|
5938
|
+
let finished = false;
|
|
5939
|
+
if (drainChore) {
|
|
5940
|
+
finished = maybeFinishDrain();
|
|
5410
5941
|
}
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5942
|
+
if (!finished && !isDraining) {
|
|
5943
|
+
// if finished, then journal flush is already applied
|
|
5944
|
+
applyJournalFlush();
|
|
5414
5945
|
}
|
|
5415
|
-
}, (err) => container.handleError(err, host));
|
|
5416
|
-
}
|
|
5417
|
-
break;
|
|
5418
|
-
case 2 /* ChoreType.RUN_QRL */:
|
|
5419
|
-
{
|
|
5420
|
-
const fn = chore.$target$.getFn();
|
|
5421
|
-
const result = retryOnPromise(() => fn(...chore.$payload$));
|
|
5422
|
-
if (isPromise(result)) {
|
|
5423
|
-
const handled = result
|
|
5424
|
-
.finally(() => {
|
|
5425
|
-
qrlRuns.splice(qrlRuns.indexOf(handled), 1);
|
|
5426
|
-
})
|
|
5427
|
-
.catch((error) => {
|
|
5428
|
-
container.handleError(error, chore.$host$);
|
|
5429
|
-
});
|
|
5430
|
-
// Don't wait for the promise to resolve
|
|
5431
|
-
// TODO come up with a better solution, we also want concurrent signal handling with tasks but serial tasks
|
|
5432
|
-
qrlRuns.push(handled);
|
|
5433
|
-
DEBUG &&
|
|
5434
|
-
debugTrace('execute.DONE (but still running)', chore, currentChore, choreQueue);
|
|
5435
|
-
chore.$returnValue$ = handled;
|
|
5436
|
-
chore.$resolve$?.(handled);
|
|
5437
|
-
currentChore = null;
|
|
5438
|
-
chore.$executed$ = true;
|
|
5439
|
-
// early out so we don't call after()
|
|
5440
|
-
return;
|
|
5441
5946
|
}
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5947
|
+
});
|
|
5948
|
+
}
|
|
5949
|
+
else {
|
|
5950
|
+
finishChore(chore, result);
|
|
5951
|
+
scheduleBlockedChoresAndDrainIfNeeded(chore);
|
|
5952
|
+
}
|
|
5953
|
+
if (shouldApplyJournalFlush(isServer)) {
|
|
5954
|
+
applyJournalFlush();
|
|
5955
|
+
drainInNextTick();
|
|
5956
|
+
return;
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
}
|
|
5960
|
+
catch (e) {
|
|
5961
|
+
handleError(currentChore, e);
|
|
5962
|
+
scheduleBlockedChoresAndDrainIfNeeded(currentChore);
|
|
5963
|
+
}
|
|
5964
|
+
finally {
|
|
5965
|
+
isDraining = false;
|
|
5966
|
+
maybeFinishDrain();
|
|
5967
|
+
}
|
|
5968
|
+
}
|
|
5969
|
+
function finishChore(chore, value) {
|
|
5970
|
+
chore.$endTime$ = performance.now();
|
|
5971
|
+
chore.$state$ = ChoreState.DONE;
|
|
5972
|
+
chore.$returnValue$ = value;
|
|
5973
|
+
chore.$resolve$?.(value);
|
|
5974
|
+
}
|
|
5975
|
+
function handleError(chore, e) {
|
|
5976
|
+
chore.$endTime$ = performance.now();
|
|
5977
|
+
chore.$state$ = ChoreState.FAILED;
|
|
5978
|
+
// If we used the result as promise, this won't exist
|
|
5979
|
+
chore.$reject$?.(e);
|
|
5980
|
+
container.handleError(e, chore.$host$);
|
|
5981
|
+
}
|
|
5982
|
+
function executeChore(chore, isServer) {
|
|
5983
|
+
const host = chore.$host$;
|
|
5984
|
+
let returnValue;
|
|
5985
|
+
switch (chore.$type$) {
|
|
5986
|
+
case 6 /* ChoreType.COMPONENT */:
|
|
5987
|
+
{
|
|
5988
|
+
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
5989
|
+
if (isServer) {
|
|
5990
|
+
return jsx;
|
|
5458
5991
|
}
|
|
5459
5992
|
else {
|
|
5460
|
-
|
|
5993
|
+
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
5994
|
+
return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
|
|
5461
5995
|
}
|
|
5996
|
+
}, (err) => {
|
|
5997
|
+
handleError(chore, err);
|
|
5998
|
+
});
|
|
5999
|
+
}
|
|
6000
|
+
break;
|
|
6001
|
+
case 2 /* ChoreType.RUN_QRL */:
|
|
6002
|
+
{
|
|
6003
|
+
const fn = chore.$target$.getFn();
|
|
6004
|
+
returnValue = retryOnPromise(() => fn(...chore.$payload$));
|
|
6005
|
+
}
|
|
6006
|
+
break;
|
|
6007
|
+
case 3 /* ChoreType.TASK */:
|
|
6008
|
+
case 16 /* ChoreType.VISIBLE */:
|
|
6009
|
+
{
|
|
6010
|
+
const payload = chore.$payload$;
|
|
6011
|
+
if (payload.$flags$ & 4 /* TaskFlags.RESOURCE */) {
|
|
6012
|
+
returnValue = runResource(payload, container, host);
|
|
5462
6013
|
}
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
{
|
|
5466
|
-
const task = chore.$payload$;
|
|
5467
|
-
cleanupTask(task);
|
|
6014
|
+
else {
|
|
6015
|
+
returnValue = runTask(payload, container, host);
|
|
5468
6016
|
}
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
6017
|
+
}
|
|
6018
|
+
break;
|
|
6019
|
+
case 32 /* ChoreType.CLEANUP_VISIBLE */:
|
|
6020
|
+
{
|
|
6021
|
+
const task = chore.$payload$;
|
|
6022
|
+
cleanupTask(task);
|
|
6023
|
+
}
|
|
6024
|
+
break;
|
|
6025
|
+
case 4 /* ChoreType.NODE_DIFF */:
|
|
6026
|
+
{
|
|
6027
|
+
const parentVirtualNode = chore.$target$;
|
|
6028
|
+
let jsx = chore.$payload$;
|
|
6029
|
+
if (isSignal(jsx)) {
|
|
6030
|
+
jsx = jsx.value;
|
|
5478
6031
|
}
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
6032
|
+
returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
|
|
6033
|
+
}
|
|
6034
|
+
break;
|
|
6035
|
+
case 5 /* ChoreType.NODE_PROP */:
|
|
6036
|
+
{
|
|
6037
|
+
const virtualNode = chore.$host$;
|
|
6038
|
+
const payload = chore.$payload$;
|
|
6039
|
+
let value = payload.$value$;
|
|
6040
|
+
if (isSignal(value)) {
|
|
6041
|
+
value = value.value;
|
|
6042
|
+
}
|
|
6043
|
+
const isConst = payload.$isConst$;
|
|
6044
|
+
const journal = container.$journal$;
|
|
6045
|
+
const property = chore.$idx$;
|
|
6046
|
+
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
6047
|
+
if (isServer) {
|
|
6048
|
+
container.addBackpatchEntry(chore.$host$.id, property, serializedValue);
|
|
6049
|
+
returnValue = null;
|
|
6050
|
+
}
|
|
6051
|
+
else {
|
|
5492
6052
|
if (isConst) {
|
|
5493
6053
|
const element = virtualNode[6 /* ElementVNodeProps.element */];
|
|
5494
6054
|
journal.push(2 /* VNodeJournalOpCode.SetAttribute */, element, property, serializedValue);
|
|
@@ -5496,63 +6056,49 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
5496
6056
|
else {
|
|
5497
6057
|
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
5498
6058
|
}
|
|
6059
|
+
returnValue = undefined;
|
|
5499
6060
|
}
|
|
5500
|
-
break;
|
|
5501
|
-
case 1 /* ChoreType.QRL_RESOLVE */: {
|
|
5502
|
-
{
|
|
5503
|
-
const target = chore.$target$;
|
|
5504
|
-
returnValue = !target.resolved ? target.resolve() : null;
|
|
5505
|
-
}
|
|
5506
|
-
break;
|
|
5507
6061
|
}
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
6062
|
+
break;
|
|
6063
|
+
case 1 /* ChoreType.QRL_RESOLVE */: {
|
|
6064
|
+
{
|
|
6065
|
+
const target = chore.$target$;
|
|
6066
|
+
returnValue = (!target.resolved ? target.resolve() : null);
|
|
6067
|
+
}
|
|
6068
|
+
break;
|
|
6069
|
+
}
|
|
6070
|
+
case 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */: {
|
|
6071
|
+
{
|
|
6072
|
+
const target = chore.$target$;
|
|
6073
|
+
const effects = chore.$payload$;
|
|
6074
|
+
if (!effects?.size) {
|
|
6075
|
+
break;
|
|
6076
|
+
}
|
|
6077
|
+
let shouldCompute = target instanceof ComputedSignalImpl || target instanceof WrappedSignalImpl;
|
|
6078
|
+
if (target instanceof AsyncComputedSignalImpl && effects !== target.$effects$) {
|
|
6079
|
+
shouldCompute = false;
|
|
6080
|
+
}
|
|
6081
|
+
if (shouldCompute) {
|
|
6082
|
+
const ctx = newInvokeContext();
|
|
6083
|
+
ctx.$container$ = container;
|
|
6084
|
+
// needed for computed signals and throwing QRLs
|
|
6085
|
+
returnValue = maybeThen(retryOnPromise(() => invoke.call(target, ctx, target.$computeIfNeeded$)), () => {
|
|
6086
|
+
if (target.$flags$ & 2 /* SignalFlags.RUN_EFFECTS */) {
|
|
6087
|
+
target.$flags$ &= -3 /* SignalFlags.RUN_EFFECTS */;
|
|
6088
|
+
return retryOnPromise(() => triggerEffects(container, target, effects));
|
|
5517
6089
|
}
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
}
|
|
5524
|
-
else {
|
|
5525
|
-
returnValue = retryOnPromise(() => {
|
|
5526
|
-
triggerEffects(container, target, effects);
|
|
5527
|
-
});
|
|
5528
|
-
}
|
|
6090
|
+
});
|
|
6091
|
+
}
|
|
6092
|
+
else {
|
|
6093
|
+
returnValue = retryOnPromise(() => {
|
|
6094
|
+
triggerEffects(container, target, effects);
|
|
6095
|
+
});
|
|
5529
6096
|
}
|
|
5530
|
-
break;
|
|
5531
6097
|
}
|
|
6098
|
+
break;
|
|
5532
6099
|
}
|
|
5533
6100
|
}
|
|
5534
|
-
|
|
5535
|
-
returnValue = Promise.reject(e);
|
|
5536
|
-
}
|
|
5537
|
-
const after = (value, error) => {
|
|
5538
|
-
currentChore = null;
|
|
5539
|
-
chore.$executed$ = true;
|
|
5540
|
-
if (error) {
|
|
5541
|
-
container.handleError(error, host);
|
|
5542
|
-
}
|
|
5543
|
-
else {
|
|
5544
|
-
chore.$returnValue$ = value;
|
|
5545
|
-
chore.$resolve$?.(value);
|
|
5546
|
-
}
|
|
5547
|
-
};
|
|
5548
|
-
if (isPromise(returnValue)) {
|
|
5549
|
-
chore.$promise$ = returnValue.then(after, (error) => after(undefined, error));
|
|
5550
|
-
chore.$resolve$?.(chore.$promise$);
|
|
5551
|
-
chore.$resolve$ = undefined;
|
|
5552
|
-
}
|
|
5553
|
-
else {
|
|
5554
|
-
after(returnValue);
|
|
5555
|
-
}
|
|
6101
|
+
return returnValue;
|
|
5556
6102
|
}
|
|
5557
6103
|
/**
|
|
5558
6104
|
* Compares two chores to determine their execution order in the scheduler's queue.
|
|
@@ -5581,15 +6127,6 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
5581
6127
|
else {
|
|
5582
6128
|
assertFalse(vnode_isVNode(aHost), 'expected aHost to be SSRNode but it is a VNode');
|
|
5583
6129
|
assertFalse(vnode_isVNode(bHost), 'expected bHost to be SSRNode but it is a VNode');
|
|
5584
|
-
// we are running on the server.
|
|
5585
|
-
// On server we can't schedule task for a different host!
|
|
5586
|
-
// Server is SSR, and therefore scheduling for anything but the current host
|
|
5587
|
-
// implies that things need to be re-run nad that is not supported because of streaming.
|
|
5588
|
-
const errorMessage = `SERVER: during HTML streaming, re-running tasks on a different host is not allowed.
|
|
5589
|
-
You are attempting to change a state that has already been streamed to the client.
|
|
5590
|
-
This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
|
|
5591
|
-
Problematic Node: ${aHost.toString()}`;
|
|
5592
|
-
logWarn(errorMessage);
|
|
5593
6130
|
const hostDiff = ssrNodeDocumentPosition(aHost, bHost);
|
|
5594
6131
|
if (hostDiff !== 0) {
|
|
5595
6132
|
return hostDiff;
|
|
@@ -5606,12 +6143,21 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
5606
6143
|
return idxDiff;
|
|
5607
6144
|
}
|
|
5608
6145
|
// If the host is the same (or missing), and the type is the same, we need to compare the target.
|
|
5609
|
-
if (a.$target$ !== b.$target$
|
|
6146
|
+
if (a.$target$ !== b.$target$) {
|
|
6147
|
+
if (isQrl(a.$target$) && isQrl(b.$target$) && a.$target$.$hash$ === b.$target$.$hash$) {
|
|
6148
|
+
return 0;
|
|
6149
|
+
}
|
|
5610
6150
|
// 1 means that we are going to process chores as FIFO
|
|
5611
6151
|
return 1;
|
|
5612
6152
|
}
|
|
5613
|
-
//
|
|
5614
|
-
|
|
6153
|
+
// ensure that the effect chores are scheduled for the same target
|
|
6154
|
+
// TODO: can we do this better?
|
|
6155
|
+
if (a.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
|
|
6156
|
+
b.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
|
|
6157
|
+
((a.$target$ instanceof StoreHandler && b.$target$ instanceof StoreHandler) ||
|
|
6158
|
+
(a.$target$ instanceof AsyncComputedSignalImpl &&
|
|
6159
|
+
b.$target$ instanceof AsyncComputedSignalImpl)) &&
|
|
6160
|
+
a.$payload$ !== b.$payload$) {
|
|
5615
6161
|
return 1;
|
|
5616
6162
|
}
|
|
5617
6163
|
// The chores are the same and will run only once
|
|
@@ -5643,6 +6189,15 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
5643
6189
|
/// We need to ensure that the `queue` is sorted by priority.
|
|
5644
6190
|
/// 1. Find a place where to insert into.
|
|
5645
6191
|
const idx = sortedFindIndex(sortedArray, value, rootVNode);
|
|
6192
|
+
if (idx < 0 && runningChores.size) {
|
|
6193
|
+
// 1.1. Check if the chore is already running.
|
|
6194
|
+
for (const chore of runningChores) {
|
|
6195
|
+
const comp = choreComparator(value, chore, rootVNode);
|
|
6196
|
+
if (comp === 0) {
|
|
6197
|
+
return chore;
|
|
6198
|
+
}
|
|
6199
|
+
}
|
|
6200
|
+
}
|
|
5646
6201
|
if (idx < 0) {
|
|
5647
6202
|
/// 2. Insert the chore into the queue.
|
|
5648
6203
|
sortedArray.splice(~idx, 0, value);
|
|
@@ -5654,12 +6209,9 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
5654
6209
|
* multiple times during component execution. For this reason it is necessary for us to update
|
|
5655
6210
|
* the chore with the latest result of the signal.
|
|
5656
6211
|
*/
|
|
5657
|
-
if (existing.$
|
|
6212
|
+
if (existing.$payload$ !== value.$payload$) {
|
|
5658
6213
|
existing.$payload$ = value.$payload$;
|
|
5659
6214
|
}
|
|
5660
|
-
if (existing.$executed$) {
|
|
5661
|
-
existing.$executed$ = false;
|
|
5662
|
-
}
|
|
5663
6215
|
return existing;
|
|
5664
6216
|
}
|
|
5665
6217
|
};
|
|
@@ -5671,6 +6223,25 @@ function vNodeAlreadyDeleted(chore) {
|
|
|
5671
6223
|
vnode_isVNode(chore.$host$) &&
|
|
5672
6224
|
chore.$host$[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */);
|
|
5673
6225
|
}
|
|
6226
|
+
function addBlockedChore(blockedChore, blockingChore, blockedChores) {
|
|
6227
|
+
blockingChore.$blockedChores$ ||= [];
|
|
6228
|
+
blockingChore.$blockedChores$.push(blockedChore);
|
|
6229
|
+
blockedChores.add(blockedChore);
|
|
6230
|
+
}
|
|
6231
|
+
function choreTypeToName(type) {
|
|
6232
|
+
return ({
|
|
6233
|
+
[1 /* ChoreType.QRL_RESOLVE */]: 'Resolve QRL',
|
|
6234
|
+
[2 /* ChoreType.RUN_QRL */]: 'Run QRL',
|
|
6235
|
+
[3 /* ChoreType.TASK */]: 'Task',
|
|
6236
|
+
[4 /* ChoreType.NODE_DIFF */]: 'Changes diffing',
|
|
6237
|
+
[5 /* ChoreType.NODE_PROP */]: 'Updating node property',
|
|
6238
|
+
[6 /* ChoreType.COMPONENT */]: 'Component',
|
|
6239
|
+
[7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */]: 'Signal recompute',
|
|
6240
|
+
[16 /* ChoreType.VISIBLE */]: 'Visible',
|
|
6241
|
+
[32 /* ChoreType.CLEANUP_VISIBLE */]: 'Cleanup visible',
|
|
6242
|
+
[255 /* ChoreType.WAIT_FOR_QUEUE */]: 'Wait for queue',
|
|
6243
|
+
}[type] || 'Unknown: ' + type);
|
|
6244
|
+
}
|
|
5674
6245
|
function debugChoreTypeToString(type) {
|
|
5675
6246
|
return ({
|
|
5676
6247
|
[1 /* ChoreType.QRL_RESOLVE */]: 'QRL_RESOLVE',
|
|
@@ -5680,31 +6251,87 @@ function debugChoreTypeToString(type) {
|
|
|
5680
6251
|
[5 /* ChoreType.NODE_PROP */]: 'NODE_PROP',
|
|
5681
6252
|
[6 /* ChoreType.COMPONENT */]: 'COMPONENT',
|
|
5682
6253
|
[7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */]: 'RECOMPUTE_SIGNAL',
|
|
5683
|
-
[16 /* ChoreType.
|
|
5684
|
-
[32 /* ChoreType.
|
|
5685
|
-
[
|
|
5686
|
-
[255 /* ChoreType.WAIT_FOR_ALL */]: 'WAIT_FOR_ALL',
|
|
6254
|
+
[16 /* ChoreType.VISIBLE */]: 'VISIBLE',
|
|
6255
|
+
[32 /* ChoreType.CLEANUP_VISIBLE */]: 'CLEANUP_VISIBLE',
|
|
6256
|
+
[255 /* ChoreType.WAIT_FOR_QUEUE */]: 'WAIT_FOR_QUEUE',
|
|
5687
6257
|
}[type] || 'UNKNOWN: ' + type);
|
|
5688
6258
|
}
|
|
5689
|
-
function
|
|
5690
|
-
const
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
6259
|
+
function debugTrace(action, arg, queue, blockedChores) {
|
|
6260
|
+
const lines = [];
|
|
6261
|
+
// Header
|
|
6262
|
+
lines.push(`Scheduler: ${action}`);
|
|
6263
|
+
// Argument section
|
|
6264
|
+
if (arg) {
|
|
6265
|
+
lines.push('');
|
|
6266
|
+
if (arg && '$type$' in arg) {
|
|
6267
|
+
const chore = arg;
|
|
6268
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
6269
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
6270
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
6271
|
+
const targetOrHost = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
|
|
6272
|
+
? qrlTarget
|
|
6273
|
+
: host;
|
|
6274
|
+
lines.push(`🎯 Current Chore:`);
|
|
6275
|
+
lines.push(` Type: ${type}`);
|
|
6276
|
+
lines.push(` Host: ${targetOrHost}`);
|
|
6277
|
+
// Show execution time if available
|
|
6278
|
+
if (chore.$startTime$ && chore.$endTime$) {
|
|
6279
|
+
const executionTime = chore.$endTime$ - chore.$startTime$;
|
|
6280
|
+
lines.push(` Time: ${executionTime.toFixed(2)}ms`);
|
|
6281
|
+
}
|
|
6282
|
+
else if (chore.$startTime$) {
|
|
6283
|
+
const elapsedTime = performance.now() - chore.$startTime$;
|
|
6284
|
+
lines.push(` Time: ${elapsedTime.toFixed(2)}ms (running)`);
|
|
6285
|
+
}
|
|
6286
|
+
// Show blocked chores for this chore
|
|
6287
|
+
if (chore.$blockedChores$ && chore.$blockedChores$.length > 0) {
|
|
6288
|
+
lines.push(` ⛔ Blocked Chores:`);
|
|
6289
|
+
chore.$blockedChores$.forEach((blockedChore, index) => {
|
|
6290
|
+
const blockedType = debugChoreTypeToString(blockedChore.$type$);
|
|
6291
|
+
const blockedTarget = String(blockedChore.$host$).replaceAll(/\n.*/gim, '');
|
|
6292
|
+
lines.push(` ${index + 1}. ${blockedType} ${blockedTarget} ${blockedChore.$idx$}`);
|
|
6293
|
+
});
|
|
6294
|
+
}
|
|
6295
|
+
}
|
|
6296
|
+
else {
|
|
6297
|
+
lines.push(`📝 Argument: ${String(arg).replaceAll(/\n.*/gim, '')}`);
|
|
6298
|
+
}
|
|
6299
|
+
}
|
|
6300
|
+
// Queue section
|
|
6301
|
+
if (queue && queue.length > 0) {
|
|
6302
|
+
lines.push('');
|
|
6303
|
+
lines.push(`📋 Queue (${queue.length} items):`);
|
|
6304
|
+
queue.forEach((chore, index) => {
|
|
6305
|
+
const isActive = chore === arg;
|
|
6306
|
+
const activeMarker = isActive ? `▶ ` : ' ';
|
|
6307
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
6308
|
+
const state = chore.$state$ ? `[${ChoreState[chore.$state$]}]` : '';
|
|
6309
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
6310
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
6311
|
+
const target = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
|
|
6312
|
+
? qrlTarget
|
|
6313
|
+
: host;
|
|
6314
|
+
const line = `${activeMarker}${state} ${type} ${target} ${chore.$idx$}`;
|
|
6315
|
+
lines.push(line);
|
|
5706
6316
|
});
|
|
5707
6317
|
}
|
|
6318
|
+
// Blocked chores section
|
|
6319
|
+
if (blockedChores && blockedChores.size > 0) {
|
|
6320
|
+
lines.push('');
|
|
6321
|
+
lines.push(`🚫 Blocked Chores (${blockedChores.size} items):`);
|
|
6322
|
+
Array.from(blockedChores).forEach((chore, index) => {
|
|
6323
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
6324
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
6325
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
6326
|
+
const target = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
|
|
6327
|
+
? qrlTarget
|
|
6328
|
+
: host;
|
|
6329
|
+
lines.push(` ${index + 1}. ${type} ${target} ${chore.$idx$}`);
|
|
6330
|
+
});
|
|
6331
|
+
}
|
|
6332
|
+
// Footer
|
|
6333
|
+
lines.push('');
|
|
6334
|
+
lines.push('─'.repeat(60));
|
|
5708
6335
|
// eslint-disable-next-line no-console
|
|
5709
6336
|
console.log(lines.join('\n') + '\n');
|
|
5710
6337
|
}
|
|
@@ -5722,7 +6349,8 @@ class _SharedContainer {
|
|
|
5722
6349
|
$currentUniqueId$ = 0;
|
|
5723
6350
|
$instanceHash$ = null;
|
|
5724
6351
|
$buildBase$ = null;
|
|
5725
|
-
|
|
6352
|
+
$flushEpoch$ = 0;
|
|
6353
|
+
constructor(journalFlush, serverData, locale) {
|
|
5726
6354
|
this.$serverData$ = serverData;
|
|
5727
6355
|
this.$locale$ = locale;
|
|
5728
6356
|
this.$version$ = version;
|
|
@@ -5730,7 +6358,7 @@ class _SharedContainer {
|
|
|
5730
6358
|
this.$getObjectById$ = (_id) => {
|
|
5731
6359
|
throw Error('Not implemented');
|
|
5732
6360
|
};
|
|
5733
|
-
this.$scheduler$ = createScheduler(this,
|
|
6361
|
+
this.$scheduler$ = createScheduler(this, journalFlush);
|
|
5734
6362
|
}
|
|
5735
6363
|
trackSignalValue(signal, subscriber, property, data) {
|
|
5736
6364
|
return trackSignalAndAssignHost(signal, subscriber, property, this, data);
|
|
@@ -5878,7 +6506,7 @@ function processVNodeData$1(document) {
|
|
|
5878
6506
|
const qContainer = getAttribute.call(node, Q_CONTAINER);
|
|
5879
6507
|
if (qContainer === null) {
|
|
5880
6508
|
if (hasAttribute.call(node, Q_SHADOW_ROOT)) {
|
|
5881
|
-
return 6 /* NodeType.
|
|
6509
|
+
return 6 /* NodeType.ELEMENT_SHADOW_ROOT_WRAPPER */;
|
|
5882
6510
|
}
|
|
5883
6511
|
const isQElement = hasAttribute.call(node, Q_PROPS_SEPARATOR);
|
|
5884
6512
|
return isQElement ? 2 /* NodeType.ELEMENT */ : 0 /* NodeType.OTHER */;
|
|
@@ -5896,10 +6524,10 @@ function processVNodeData$1(document) {
|
|
|
5896
6524
|
return 16 /* NodeType.COMMENT_IGNORE_START */;
|
|
5897
6525
|
}
|
|
5898
6526
|
else if (nodeValue.startsWith(Q_CONTAINER)) {
|
|
5899
|
-
return
|
|
6527
|
+
return 9 /* NodeType.COMMENT_SKIP_START */;
|
|
5900
6528
|
}
|
|
5901
6529
|
else if (nodeValue.startsWith(Q_CONTAINER_ISLAND_END)) {
|
|
5902
|
-
return
|
|
6530
|
+
return 64 /* NodeType.COMMENT_ISLAND_END */;
|
|
5903
6531
|
}
|
|
5904
6532
|
else if (nodeValue.startsWith(Q_IGNORE_END)) {
|
|
5905
6533
|
return 32 /* NodeType.COMMENT_IGNORE_END */;
|
|
@@ -5946,11 +6574,6 @@ function processVNodeData$1(document) {
|
|
|
5946
6574
|
while (node && (node = node.nextSibling) && getFastNodeType(node) === 0 /* NodeType.OTHER */) { }
|
|
5947
6575
|
return node;
|
|
5948
6576
|
};
|
|
5949
|
-
const firstChild = (node) => {
|
|
5950
|
-
// eslint-disable-next-line no-empty
|
|
5951
|
-
while (node && (node = node.firstChild) && getFastNodeType(node) === 0 /* NodeType.OTHER */) { }
|
|
5952
|
-
return node;
|
|
5953
|
-
};
|
|
5954
6577
|
/**
|
|
5955
6578
|
* Process the container
|
|
5956
6579
|
*
|
|
@@ -6011,7 +6634,7 @@ function processVNodeData$1(document) {
|
|
|
6011
6634
|
} while (getFastNodeType(islandNode) !== 65 /* NodeType.COMMENT_ISLAND_START */);
|
|
6012
6635
|
nextNode = null;
|
|
6013
6636
|
}
|
|
6014
|
-
else if (nodeType ===
|
|
6637
|
+
else if (nodeType === 64 /* NodeType.COMMENT_ISLAND_END */) {
|
|
6015
6638
|
nextNode = node;
|
|
6016
6639
|
do {
|
|
6017
6640
|
nextNode = walker.nextNode();
|
|
@@ -6021,7 +6644,7 @@ function processVNodeData$1(document) {
|
|
|
6021
6644
|
} while (getFastNodeType(nextNode) !== 32 /* NodeType.COMMENT_IGNORE_END */);
|
|
6022
6645
|
nextNode = null;
|
|
6023
6646
|
}
|
|
6024
|
-
else if (nodeType ===
|
|
6647
|
+
else if (nodeType === 9 /* NodeType.COMMENT_SKIP_START */) {
|
|
6025
6648
|
// If we are in a container, we need to skip the children.
|
|
6026
6649
|
nextNode = node;
|
|
6027
6650
|
do {
|
|
@@ -6033,7 +6656,7 @@ function processVNodeData$1(document) {
|
|
|
6033
6656
|
// console.log('EXIT', nextNode?.outerHTML);
|
|
6034
6657
|
walkContainer(walker, node, node, nextNode, '', null);
|
|
6035
6658
|
}
|
|
6036
|
-
else if (nodeType === 6 /* NodeType.
|
|
6659
|
+
else if (nodeType === 6 /* NodeType.ELEMENT_SHADOW_ROOT_WRAPPER */) {
|
|
6037
6660
|
// If we are in a shadow root, we need to get the shadow root element.
|
|
6038
6661
|
nextNode = nextSibling(node);
|
|
6039
6662
|
const shadowRootContainer = node;
|
|
@@ -6041,7 +6664,7 @@ function processVNodeData$1(document) {
|
|
|
6041
6664
|
if (shadowRoot) {
|
|
6042
6665
|
walkContainer(
|
|
6043
6666
|
// we need to create a new walker for the shadow root
|
|
6044
|
-
document.createTreeWalker(shadowRoot, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */), null,
|
|
6667
|
+
document.createTreeWalker(shadowRoot, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */), null, shadowRoot, null, '', null);
|
|
6045
6668
|
}
|
|
6046
6669
|
}
|
|
6047
6670
|
if ((nodeType & 2 /* NodeType.ELEMENT */) === 2 /* NodeType.ELEMENT */) {
|
|
@@ -6098,6 +6721,7 @@ function processVNodeData$1(document) {
|
|
|
6098
6721
|
}
|
|
6099
6722
|
|
|
6100
6723
|
/** @file Public APIs for the SSR */
|
|
6724
|
+
// @ts-expect-error we don't have types for the preloader
|
|
6101
6725
|
/** @public */
|
|
6102
6726
|
function getDomContainer(element) {
|
|
6103
6727
|
const qContainerElement = _getQContainerElement(element);
|
|
@@ -6117,7 +6741,7 @@ function getDomContainerFromQContainerElement(qContainerElement) {
|
|
|
6117
6741
|
/** @internal */
|
|
6118
6742
|
function _getQContainerElement(element) {
|
|
6119
6743
|
const qContainerElement = Array.isArray(element)
|
|
6120
|
-
? vnode_getDomParent(element)
|
|
6744
|
+
? vnode_getDomParent(element, true)
|
|
6121
6745
|
: element;
|
|
6122
6746
|
return qContainerElement.closest(QContainerSelector);
|
|
6123
6747
|
}
|
|
@@ -6132,19 +6756,20 @@ class DomContainer extends _SharedContainer {
|
|
|
6132
6756
|
rootVNode;
|
|
6133
6757
|
document;
|
|
6134
6758
|
$journal$;
|
|
6135
|
-
renderDone = null;
|
|
6136
6759
|
$rawStateData$;
|
|
6137
6760
|
$storeProxyMap$ = new WeakMap();
|
|
6138
6761
|
$qFuncs$;
|
|
6139
6762
|
$instanceHash$;
|
|
6140
6763
|
$forwardRefs$ = null;
|
|
6141
|
-
$
|
|
6764
|
+
$initialQRLs$ = null;
|
|
6142
6765
|
vNodeLocate = (id) => vnode_locate(this.rootVNode, id);
|
|
6143
6766
|
$stateData$;
|
|
6144
6767
|
$styleIds$ = null;
|
|
6145
|
-
$renderCount$ = 0;
|
|
6146
6768
|
constructor(element) {
|
|
6147
|
-
super(() =>
|
|
6769
|
+
super(() => {
|
|
6770
|
+
this.$flushEpoch$++;
|
|
6771
|
+
vnode_applyJournal(this.$journal$);
|
|
6772
|
+
}, {}, element.getAttribute(QLocaleAttr));
|
|
6148
6773
|
this.qContainer = element.getAttribute(QContainerAttr);
|
|
6149
6774
|
if (!this.qContainer) {
|
|
6150
6775
|
throw qError(25 /* QError.elementWithoutContainer */);
|
|
@@ -6186,20 +6811,17 @@ class DomContainer extends _SharedContainer {
|
|
|
6186
6811
|
}
|
|
6187
6812
|
handleError(err, host) {
|
|
6188
6813
|
if (qDev && host) {
|
|
6189
|
-
// Clean vdom
|
|
6190
6814
|
if (typeof document !== 'undefined') {
|
|
6191
6815
|
const vHost = host;
|
|
6192
|
-
const errorDiv = document.createElement('errored-host');
|
|
6193
|
-
if (err && err instanceof Error) {
|
|
6194
|
-
errorDiv.props = { error: err };
|
|
6195
|
-
}
|
|
6196
|
-
errorDiv.setAttribute('q:key', '_error_');
|
|
6197
6816
|
const journal = [];
|
|
6198
|
-
const
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6817
|
+
const vHostParent = vnode_getParent(vHost);
|
|
6818
|
+
const vHostNextSibling = vnode_getNextSibling(vHost);
|
|
6819
|
+
const vErrorDiv = vnode_createErrorDiv(document, vHost, err, journal);
|
|
6820
|
+
// If the host is an element node, we need to insert the error div into its parent.
|
|
6821
|
+
const insertHost = vnode_isElementVNode(vHost) ? vHostParent || vHost : vHost;
|
|
6822
|
+
// If the host is different then we need to insert errored-host in the same position as the host.
|
|
6823
|
+
const insertBefore = insertHost === vHost ? null : vHostNextSibling;
|
|
6824
|
+
vnode_insertBefore(journal, insertHost, vErrorDiv, insertBefore);
|
|
6203
6825
|
vnode_applyJournal(journal);
|
|
6204
6826
|
}
|
|
6205
6827
|
if (err && err instanceof Error) {
|
|
@@ -6219,19 +6841,16 @@ class DomContainer extends _SharedContainer {
|
|
|
6219
6841
|
}
|
|
6220
6842
|
setContext(host, context, value) {
|
|
6221
6843
|
let ctx = this.getHostProp(host, QCtxAttr);
|
|
6222
|
-
if (
|
|
6844
|
+
if (ctx == null) {
|
|
6223
6845
|
this.setHostProp(host, QCtxAttr, (ctx = []));
|
|
6224
6846
|
}
|
|
6225
|
-
mapArray_set(ctx, context.id, value, 0);
|
|
6847
|
+
mapArray_set(ctx, context.id, value, 0, true);
|
|
6226
6848
|
}
|
|
6227
6849
|
resolveContext(host, contextId) {
|
|
6228
6850
|
while (host) {
|
|
6229
6851
|
const ctx = this.getHostProp(host, QCtxAttr);
|
|
6230
|
-
if (ctx) {
|
|
6231
|
-
|
|
6232
|
-
if (value) {
|
|
6233
|
-
return value;
|
|
6234
|
-
}
|
|
6852
|
+
if (ctx != null && mapArray_has(ctx, contextId.id, 0)) {
|
|
6853
|
+
return mapArray_get(ctx, contextId.id, 0);
|
|
6235
6854
|
}
|
|
6236
6855
|
host = this.getParentHost(host);
|
|
6237
6856
|
}
|
|
@@ -6277,29 +6896,6 @@ class DomContainer extends _SharedContainer {
|
|
|
6277
6896
|
}
|
|
6278
6897
|
return vnode_getProp(vNode, name, getObjectById);
|
|
6279
6898
|
}
|
|
6280
|
-
scheduleRender() {
|
|
6281
|
-
this.$renderCount$++;
|
|
6282
|
-
this.renderDone ||= getPlatform().nextTick(() => this.processChores());
|
|
6283
|
-
return this.renderDone.finally(() => emitEvent('qrender', { instanceHash: this.$instanceHash$, renderCount: this.$renderCount$ }));
|
|
6284
|
-
}
|
|
6285
|
-
processChores() {
|
|
6286
|
-
let renderCount = this.$renderCount$;
|
|
6287
|
-
const result = this.$scheduler$(255 /* ChoreType.WAIT_FOR_ALL */);
|
|
6288
|
-
if (isPromise(result)) {
|
|
6289
|
-
return result.then(async () => {
|
|
6290
|
-
while (renderCount !== this.$renderCount$) {
|
|
6291
|
-
renderCount = this.$renderCount$;
|
|
6292
|
-
await this.$scheduler$(255 /* ChoreType.WAIT_FOR_ALL */);
|
|
6293
|
-
}
|
|
6294
|
-
this.renderDone = null;
|
|
6295
|
-
});
|
|
6296
|
-
}
|
|
6297
|
-
if (renderCount !== this.$renderCount$) {
|
|
6298
|
-
this.processChores();
|
|
6299
|
-
return;
|
|
6300
|
-
}
|
|
6301
|
-
this.renderDone = null;
|
|
6302
|
-
}
|
|
6303
6899
|
ensureProjectionResolved(vNode) {
|
|
6304
6900
|
if ((vNode[0 /* VNodeProps.flags */] & 16 /* VNodeFlags.Resolved */) === 0) {
|
|
6305
6901
|
vNode[0 /* VNodeProps.flags */] |= 16 /* VNodeFlags.Resolved */;
|
|
@@ -6309,7 +6905,9 @@ class DomContainer extends _SharedContainer {
|
|
|
6309
6905
|
if (isSlotProp(prop)) {
|
|
6310
6906
|
const value = props[i + 1];
|
|
6311
6907
|
if (typeof value == 'string') {
|
|
6312
|
-
|
|
6908
|
+
const projection = this.vNodeLocate(value);
|
|
6909
|
+
props[i + 1] = projection;
|
|
6910
|
+
vnode_getProp(projection, QSlotParent, (id) => this.vNodeLocate(id));
|
|
6313
6911
|
}
|
|
6314
6912
|
}
|
|
6315
6913
|
}
|
|
@@ -6378,11 +6976,14 @@ class DomContainer extends _SharedContainer {
|
|
|
6378
6976
|
* ```
|
|
6379
6977
|
*/
|
|
6380
6978
|
$scheduleInitialQRLs$() {
|
|
6381
|
-
if (this.$
|
|
6382
|
-
for (const
|
|
6383
|
-
|
|
6979
|
+
if (this.$initialQRLs$) {
|
|
6980
|
+
for (const qrl of this.$initialQRLs$) {
|
|
6981
|
+
const match = /#(.*)_([a-zA-Z0-9]+)(\[|$)/.exec(qrl);
|
|
6982
|
+
if (match) {
|
|
6983
|
+
p(match[2], 0.3);
|
|
6984
|
+
}
|
|
6384
6985
|
}
|
|
6385
|
-
this.$
|
|
6986
|
+
this.$initialQRLs$ = null;
|
|
6386
6987
|
}
|
|
6387
6988
|
}
|
|
6388
6989
|
}
|
|
@@ -6430,7 +7031,7 @@ const addQrlToSerializationCtx = (effectSubscriber, container) => {
|
|
|
6430
7031
|
}
|
|
6431
7032
|
};
|
|
6432
7033
|
const triggerEffects = (container, signal, effects) => {
|
|
6433
|
-
const isBrowser =
|
|
7034
|
+
const isBrowser = !isServerPlatform();
|
|
6434
7035
|
if (effects) {
|
|
6435
7036
|
const scheduleEffect = (effectSubscription) => {
|
|
6436
7037
|
const consumer = effectSubscription[0 /* EffectSubscriptionProp.CONSUMER */];
|
|
@@ -6440,7 +7041,7 @@ const triggerEffects = (container, signal, effects) => {
|
|
|
6440
7041
|
consumer.$flags$ |= 8 /* TaskFlags.DIRTY */;
|
|
6441
7042
|
let choreType = 3 /* ChoreType.TASK */;
|
|
6442
7043
|
if (consumer.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
|
|
6443
|
-
choreType =
|
|
7044
|
+
choreType = 16 /* ChoreType.VISIBLE */;
|
|
6444
7045
|
}
|
|
6445
7046
|
container.$scheduler$(choreType, consumer);
|
|
6446
7047
|
}
|
|
@@ -6454,7 +7055,7 @@ const triggerEffects = (container, signal, effects) => {
|
|
|
6454
7055
|
container.$scheduler$(1 /* ChoreType.QRL_RESOLVE */, null, consumer.$computeQrl$);
|
|
6455
7056
|
}
|
|
6456
7057
|
}
|
|
6457
|
-
consumer
|
|
7058
|
+
consumer.invalidate();
|
|
6458
7059
|
}
|
|
6459
7060
|
else if (property === ":" /* EffectProperty.COMPONENT */) {
|
|
6460
7061
|
const host = consumer;
|
|
@@ -6463,22 +7064,22 @@ const triggerEffects = (container, signal, effects) => {
|
|
|
6463
7064
|
const props = container.getHostProp(host, ELEMENT_PROPS);
|
|
6464
7065
|
container.$scheduler$(6 /* ChoreType.COMPONENT */, host, qrl, props);
|
|
6465
7066
|
}
|
|
6466
|
-
else if (
|
|
6467
|
-
if (
|
|
7067
|
+
else if (property === "." /* EffectProperty.VNODE */) {
|
|
7068
|
+
if (isBrowser) {
|
|
6468
7069
|
const host = consumer;
|
|
6469
7070
|
container.$scheduler$(4 /* ChoreType.NODE_DIFF */, host, host, signal);
|
|
6470
7071
|
}
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
7072
|
+
}
|
|
7073
|
+
else {
|
|
7074
|
+
const host = consumer;
|
|
7075
|
+
const effectData = effectSubscription[3 /* EffectSubscriptionProp.DATA */];
|
|
7076
|
+
if (effectData instanceof SubscriptionData) {
|
|
7077
|
+
const data = effectData.data;
|
|
7078
|
+
const payload = {
|
|
7079
|
+
...data,
|
|
7080
|
+
$value$: signal,
|
|
7081
|
+
};
|
|
7082
|
+
container.$scheduler$(5 /* ChoreType.NODE_PROP */, host, property, payload);
|
|
6482
7083
|
}
|
|
6483
7084
|
}
|
|
6484
7085
|
};
|
|
@@ -6489,7 +7090,23 @@ const triggerEffects = (container, signal, effects) => {
|
|
|
6489
7090
|
};
|
|
6490
7091
|
/** @internal */
|
|
6491
7092
|
const isSerializerObj = (obj) => {
|
|
6492
|
-
return (
|
|
7093
|
+
return isObject(obj) && typeof obj[SerializerSymbol] === 'function';
|
|
7094
|
+
};
|
|
7095
|
+
const getComputedSignalFlags = (serializationStrategy) => {
|
|
7096
|
+
let flags = 1 /* SignalFlags.INVALID */;
|
|
7097
|
+
switch (serializationStrategy) {
|
|
7098
|
+
// TODO: implement this in the future
|
|
7099
|
+
// case 'auto':
|
|
7100
|
+
// flags |= ComputedSignalFlags.SERIALIZATION_STRATEGY_AUTO;
|
|
7101
|
+
// break;
|
|
7102
|
+
case 'never':
|
|
7103
|
+
flags |= 16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
|
|
7104
|
+
break;
|
|
7105
|
+
case 'always':
|
|
7106
|
+
flags |= 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
|
|
7107
|
+
break;
|
|
7108
|
+
}
|
|
7109
|
+
return flags;
|
|
6493
7110
|
};
|
|
6494
7111
|
|
|
6495
7112
|
const stringifyPath = [];
|
|
@@ -6784,6 +7401,7 @@ const vnode_isElementOrTextVNode = (vNode) => {
|
|
|
6784
7401
|
const flag = vNode[0 /* VNodeProps.flags */];
|
|
6785
7402
|
return (flag & 5 /* VNodeFlags.ELEMENT_OR_TEXT_MASK */) !== 0;
|
|
6786
7403
|
};
|
|
7404
|
+
/** @internal */
|
|
6787
7405
|
const vnode_isMaterialized = (vNode) => {
|
|
6788
7406
|
assertDefined(vNode, 'Missing vNode');
|
|
6789
7407
|
const flag = vNode[0 /* VNodeProps.flags */];
|
|
@@ -6791,11 +7409,13 @@ const vnode_isMaterialized = (vNode) => {
|
|
|
6791
7409
|
vNode[4 /* ElementVNodeProps.firstChild */] !== undefined &&
|
|
6792
7410
|
vNode[5 /* ElementVNodeProps.lastChild */] !== undefined);
|
|
6793
7411
|
};
|
|
7412
|
+
/** @internal */
|
|
6794
7413
|
const vnode_isTextVNode = (vNode) => {
|
|
6795
7414
|
assertDefined(vNode, 'Missing vNode');
|
|
6796
7415
|
const flag = vNode[0 /* VNodeProps.flags */];
|
|
6797
7416
|
return (flag & 4 /* VNodeFlags.Text */) === 4 /* VNodeFlags.Text */;
|
|
6798
7417
|
};
|
|
7418
|
+
/** @internal */
|
|
6799
7419
|
const vnode_isVirtualVNode = (vNode) => {
|
|
6800
7420
|
assertDefined(vNode, 'Missing vNode');
|
|
6801
7421
|
const flag = vNode[0 /* VNodeProps.flags */];
|
|
@@ -6833,6 +7453,7 @@ const vnode_getNodeTypeName = (vNode) => {
|
|
|
6833
7453
|
}
|
|
6834
7454
|
return '<unknown>';
|
|
6835
7455
|
};
|
|
7456
|
+
/** @internal */
|
|
6836
7457
|
const vnode_ensureElementInflated = (vnode) => {
|
|
6837
7458
|
const flags = vnode[0 /* VNodeProps.flags */];
|
|
6838
7459
|
if ((flags & 15 /* VNodeFlags.INFLATED_TYPE_MASK */) === 1 /* VNodeFlags.Element */) {
|
|
@@ -6874,6 +7495,9 @@ function vnode_walkVNode(vNode, callback) {
|
|
|
6874
7495
|
}
|
|
6875
7496
|
let vParent = null;
|
|
6876
7497
|
do {
|
|
7498
|
+
if (callback?.(vCursor, vParent)) {
|
|
7499
|
+
return;
|
|
7500
|
+
}
|
|
6877
7501
|
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
6878
7502
|
if (vFirstChild) {
|
|
6879
7503
|
vCursor = vFirstChild;
|
|
@@ -7042,6 +7666,7 @@ const vnode_ensureTextInflated = (journal, vnode) => {
|
|
|
7042
7666
|
const flags = textVNode[0 /* VNodeProps.flags */];
|
|
7043
7667
|
if ((flags & 8 /* VNodeFlags.Inflated */) === 0) {
|
|
7044
7668
|
const parentNode = vnode_getDomParent(vnode);
|
|
7669
|
+
assertDefined(parentNode, 'Missing parent node.');
|
|
7045
7670
|
const sharedTextNode = textVNode[4 /* TextVNodeProps.node */];
|
|
7046
7671
|
const doc = parentNode.ownerDocument;
|
|
7047
7672
|
// Walk the previous siblings and inflate them.
|
|
@@ -7200,6 +7825,18 @@ const indexOfAlphanumeric = (id, length) => {
|
|
|
7200
7825
|
}
|
|
7201
7826
|
return length;
|
|
7202
7827
|
};
|
|
7828
|
+
const vnode_createErrorDiv = (document, host, err, journal) => {
|
|
7829
|
+
const errorDiv = document.createElement('errored-host');
|
|
7830
|
+
if (err && err instanceof Error) {
|
|
7831
|
+
errorDiv.props = { error: err };
|
|
7832
|
+
}
|
|
7833
|
+
errorDiv.setAttribute('q:key', '_error_');
|
|
7834
|
+
const vErrorDiv = vnode_newElement(errorDiv, 'errored-host');
|
|
7835
|
+
vnode_getDOMChildNodes(journal, host, true).forEach((child) => {
|
|
7836
|
+
vnode_insertBefore(journal, vErrorDiv, child, null);
|
|
7837
|
+
});
|
|
7838
|
+
return vErrorDiv;
|
|
7839
|
+
};
|
|
7203
7840
|
const parseBoolean = (value) => {
|
|
7204
7841
|
if (value === 'false') {
|
|
7205
7842
|
return false;
|
|
@@ -7338,7 +7975,7 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
|
|
|
7338
7975
|
* unlink the previous or next sibling, we don't know that after "a" node is "b". So we need to
|
|
7339
7976
|
* find children first (and inflate them).
|
|
7340
7977
|
*/
|
|
7341
|
-
const domParentVNode = vnode_getDomParentVNode(parent);
|
|
7978
|
+
const domParentVNode = vnode_getDomParentVNode(parent, false);
|
|
7342
7979
|
const parentNode = domParentVNode && domParentVNode[6 /* ElementVNodeProps.element */];
|
|
7343
7980
|
let domChildren = null;
|
|
7344
7981
|
if (domParentVNode) {
|
|
@@ -7387,27 +8024,31 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
|
|
|
7387
8024
|
newChildCurrentParent !== parent)) {
|
|
7388
8025
|
vnode_remove(journal, newChildCurrentParent, newChild, false);
|
|
7389
8026
|
}
|
|
7390
|
-
|
|
7391
|
-
if
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
8027
|
+
const parentIsDeleted = parent[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */;
|
|
8028
|
+
// if the parent is deleted, then we don't need to insert the new child
|
|
8029
|
+
if (!parentIsDeleted) {
|
|
8030
|
+
let adjustedInsertBefore = null;
|
|
8031
|
+
if (insertBefore == null) {
|
|
8032
|
+
if (vnode_isVirtualVNode(parent)) {
|
|
8033
|
+
// If `insertBefore` is null, than we need to insert at the end of the list.
|
|
8034
|
+
// Well, not quite. If the parent is a virtual node, our "last node" is not the same
|
|
8035
|
+
// as the DOM "last node". So in that case we need to look for the "next node" from
|
|
8036
|
+
// our parent.
|
|
8037
|
+
adjustedInsertBefore = vnode_getDomSibling(parent, true, false);
|
|
8038
|
+
}
|
|
8039
|
+
}
|
|
8040
|
+
else if (vnode_isVirtualVNode(insertBefore)) {
|
|
8041
|
+
// If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
|
|
8042
|
+
adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
|
|
8043
|
+
}
|
|
8044
|
+
else {
|
|
8045
|
+
adjustedInsertBefore = insertBefore;
|
|
8046
|
+
}
|
|
8047
|
+
adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
|
|
8048
|
+
// Here we know the insertBefore node
|
|
8049
|
+
if (domChildren && domChildren.length) {
|
|
8050
|
+
journal.push(5 /* VNodeJournalOpCode.Insert */, parentNode, vnode_getNode(adjustedInsertBefore), ...domChildren);
|
|
7398
8051
|
}
|
|
7399
|
-
}
|
|
7400
|
-
else if (vnode_isVirtualVNode(insertBefore)) {
|
|
7401
|
-
// If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
|
|
7402
|
-
adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
|
|
7403
|
-
}
|
|
7404
|
-
else {
|
|
7405
|
-
adjustedInsertBefore = insertBefore;
|
|
7406
|
-
}
|
|
7407
|
-
adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
|
|
7408
|
-
// Here we know the insertBefore node
|
|
7409
|
-
if (domChildren && domChildren.length) {
|
|
7410
|
-
journal.push(5 /* VNodeJournalOpCode.Insert */, parentNode, vnode_getNode(adjustedInsertBefore), ...domChildren);
|
|
7411
8052
|
}
|
|
7412
8053
|
// link newChild into the previous/next list
|
|
7413
8054
|
const vNext = insertBefore;
|
|
@@ -7429,14 +8070,22 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
|
|
|
7429
8070
|
newChild[2 /* VNodeProps.previousSibling */] = vPrevious;
|
|
7430
8071
|
newChild[3 /* VNodeProps.nextSibling */] = vNext;
|
|
7431
8072
|
newChild[1 /* VNodeProps.parent */] = parent;
|
|
8073
|
+
if (parentIsDeleted) {
|
|
8074
|
+
// if the parent is deleted, then the new child is also deleted
|
|
8075
|
+
newChild[0 /* VNodeProps.flags */] |= 32 /* VNodeFlags.Deleted */;
|
|
8076
|
+
}
|
|
7432
8077
|
};
|
|
7433
|
-
const vnode_getDomParent = (vnode) => {
|
|
7434
|
-
vnode = vnode_getDomParentVNode(vnode);
|
|
8078
|
+
const vnode_getDomParent = (vnode, includeProjection = true) => {
|
|
8079
|
+
vnode = vnode_getDomParentVNode(vnode, includeProjection);
|
|
7435
8080
|
return (vnode && vnode[6 /* ElementVNodeProps.element */]);
|
|
7436
8081
|
};
|
|
7437
|
-
const vnode_getDomParentVNode = (vnode) => {
|
|
8082
|
+
const vnode_getDomParentVNode = (vnode, includeProjection = true) => {
|
|
7438
8083
|
while (vnode && !vnode_isElementVNode(vnode)) {
|
|
7439
|
-
vnode =
|
|
8084
|
+
vnode =
|
|
8085
|
+
vnode[1 /* VNodeProps.parent */] ||
|
|
8086
|
+
(includeProjection
|
|
8087
|
+
? vnode_getProp(vnode, QSlotParent, (id) => (vnode_isVNode(id) ? id : null))
|
|
8088
|
+
: null);
|
|
7440
8089
|
}
|
|
7441
8090
|
return vnode;
|
|
7442
8091
|
};
|
|
@@ -7446,7 +8095,7 @@ const vnode_remove = (journal, vParent, vToRemove, removeDOM) => {
|
|
|
7446
8095
|
vnode_ensureTextInflated(journal, vToRemove);
|
|
7447
8096
|
}
|
|
7448
8097
|
if (removeDOM) {
|
|
7449
|
-
const domParent = vnode_getDomParent(vParent);
|
|
8098
|
+
const domParent = vnode_getDomParent(vParent, false);
|
|
7450
8099
|
const isInnerHTMLParent = vnode_getAttr(vParent, dangerouslySetInnerHTML);
|
|
7451
8100
|
if (isInnerHTMLParent) {
|
|
7452
8101
|
// ignore children, as they are inserted via innerHTML
|
|
@@ -7511,6 +8160,7 @@ const vnode_setText = (journal, textVNode, text) => {
|
|
|
7511
8160
|
const textNode = textVNode[4 /* TextVNodeProps.node */];
|
|
7512
8161
|
journal.push(1 /* VNodeJournalOpCode.SetText */, textNode, (textVNode[5 /* TextVNodeProps.text */] = text));
|
|
7513
8162
|
};
|
|
8163
|
+
/** @internal */
|
|
7514
8164
|
const vnode_getFirstChild = (vnode) => {
|
|
7515
8165
|
if (vnode_isTextVNode(vnode)) {
|
|
7516
8166
|
return null;
|
|
@@ -7771,27 +8421,46 @@ const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
|
7771
8421
|
return vFirstChild;
|
|
7772
8422
|
};
|
|
7773
8423
|
function setEffectBackRefFromVNodeData(vParent, value, container) {
|
|
7774
|
-
const deserializedSubMap = container.$getObjectById$(value);
|
|
7775
8424
|
if (!vParent[_EFFECT_BACK_REF]) {
|
|
8425
|
+
// get data lazily
|
|
8426
|
+
// this is because effects back refs can point to vnodes which are not yet materialized
|
|
8427
|
+
// (are after the current vnode)
|
|
7776
8428
|
Object.defineProperty(vParent, _EFFECT_BACK_REF, {
|
|
7777
|
-
|
|
8429
|
+
get() {
|
|
8430
|
+
const subMap = container.$getObjectById$(value);
|
|
8431
|
+
vParent[_EFFECT_BACK_REF] = subMap;
|
|
8432
|
+
return subMap;
|
|
8433
|
+
},
|
|
8434
|
+
set(value) {
|
|
8435
|
+
Object.defineProperty(vParent, _EFFECT_BACK_REF, {
|
|
8436
|
+
value,
|
|
8437
|
+
writable: true,
|
|
8438
|
+
enumerable: true,
|
|
8439
|
+
configurable: true,
|
|
8440
|
+
});
|
|
8441
|
+
},
|
|
8442
|
+
enumerable: true,
|
|
8443
|
+
configurable: true,
|
|
7778
8444
|
});
|
|
7779
8445
|
}
|
|
7780
8446
|
else {
|
|
7781
8447
|
const subMap = vParent[_EFFECT_BACK_REF];
|
|
7782
|
-
mergeMaps(subMap,
|
|
8448
|
+
mergeMaps(subMap, container.$getObjectById$(value));
|
|
7783
8449
|
}
|
|
7784
8450
|
}
|
|
7785
8451
|
const processVNodeData = (vData, callback) => {
|
|
7786
8452
|
let nextToConsumeIdx = 0;
|
|
7787
8453
|
let ch = 0;
|
|
7788
8454
|
let peekCh = 0;
|
|
8455
|
+
const getChar = (idx) => {
|
|
8456
|
+
return idx < vData.length ? vData.charCodeAt(idx) : 0;
|
|
8457
|
+
};
|
|
7789
8458
|
const peek = () => {
|
|
7790
8459
|
if (peekCh !== 0) {
|
|
7791
8460
|
return peekCh;
|
|
7792
8461
|
}
|
|
7793
8462
|
else {
|
|
7794
|
-
return (peekCh =
|
|
8463
|
+
return (peekCh = getChar(nextToConsumeIdx));
|
|
7795
8464
|
}
|
|
7796
8465
|
};
|
|
7797
8466
|
const consume = () => {
|
|
@@ -7812,15 +8481,17 @@ const processVNodeData = (vData, callback) => {
|
|
|
7812
8481
|
return vData.substring(start, nextToConsumeIdx);
|
|
7813
8482
|
};
|
|
7814
8483
|
while (peek() !== 0) {
|
|
7815
|
-
callback(peek, consumeValue, consume, nextToConsumeIdx);
|
|
8484
|
+
callback(peek, consumeValue, consume, getChar, nextToConsumeIdx);
|
|
7816
8485
|
}
|
|
7817
8486
|
};
|
|
8487
|
+
/** @internal */
|
|
7818
8488
|
const vnode_getNextSibling = (vnode) => {
|
|
7819
8489
|
return vnode[3 /* VNodeProps.nextSibling */];
|
|
7820
8490
|
};
|
|
7821
8491
|
const vnode_getPreviousSibling = (vnode) => {
|
|
7822
8492
|
return vnode[2 /* VNodeProps.previousSibling */];
|
|
7823
8493
|
};
|
|
8494
|
+
/** @internal */
|
|
7824
8495
|
const vnode_getAttrKeys = (vnode) => {
|
|
7825
8496
|
const type = vnode[0 /* VNodeProps.flags */];
|
|
7826
8497
|
if ((type & 3 /* VNodeFlags.ELEMENT_OR_VIRTUAL_MASK */) !== 0) {
|
|
@@ -7866,6 +8537,7 @@ const vnode_setAttr = (journal, vnode, key, value) => {
|
|
|
7866
8537
|
}
|
|
7867
8538
|
}
|
|
7868
8539
|
};
|
|
8540
|
+
/** @internal */
|
|
7869
8541
|
const vnode_getAttr = (vnode, key) => {
|
|
7870
8542
|
const type = vnode[0 /* VNodeProps.flags */];
|
|
7871
8543
|
if ((type & 3 /* VNodeFlags.ELEMENT_OR_VIRTUAL_MASK */) !== 0) {
|
|
@@ -7902,6 +8574,7 @@ const vnode_setProp = (vnode, key, value) => {
|
|
|
7902
8574
|
props.splice(idx ^ -1, 0, key, value);
|
|
7903
8575
|
}
|
|
7904
8576
|
};
|
|
8577
|
+
/** @internal */
|
|
7905
8578
|
const vnode_getPropStartIndex = (vnode) => {
|
|
7906
8579
|
const type = vnode[0 /* VNodeProps.flags */] & 7 /* VNodeFlags.TYPE_MASK */;
|
|
7907
8580
|
if (type === 1 /* VNodeFlags.Element */) {
|
|
@@ -7912,12 +8585,33 @@ const vnode_getPropStartIndex = (vnode) => {
|
|
|
7912
8585
|
}
|
|
7913
8586
|
throw qError(26 /* QError.invalidVNodeType */, [type]);
|
|
7914
8587
|
};
|
|
8588
|
+
/** @internal */
|
|
7915
8589
|
const vnode_getProps = (vnode) => {
|
|
7916
8590
|
return vnode[vnode_getPropStartIndex(vnode)];
|
|
7917
8591
|
};
|
|
7918
8592
|
const vnode_getParent = (vnode) => {
|
|
7919
8593
|
return vnode[1 /* VNodeProps.parent */] || null;
|
|
7920
8594
|
};
|
|
8595
|
+
const vnode_isDescendantOf = (vnode, ancestor, rootVNode) => {
|
|
8596
|
+
let parent = vnode_getParentOrProjectionParent(vnode, rootVNode);
|
|
8597
|
+
while (parent) {
|
|
8598
|
+
if (parent === ancestor) {
|
|
8599
|
+
return true;
|
|
8600
|
+
}
|
|
8601
|
+
parent = vnode_getParentOrProjectionParent(parent, rootVNode);
|
|
8602
|
+
}
|
|
8603
|
+
return false;
|
|
8604
|
+
};
|
|
8605
|
+
const vnode_getParentOrProjectionParent = (vnode, rootVNode) => {
|
|
8606
|
+
if (rootVNode) {
|
|
8607
|
+
const parentProjection = vnode_getProp(vnode, QSlotParent, (id) => vnode_locate(rootVNode, id));
|
|
8608
|
+
if (parentProjection) {
|
|
8609
|
+
// This is a projection, so we need to check the parent of the projection
|
|
8610
|
+
return parentProjection;
|
|
8611
|
+
}
|
|
8612
|
+
}
|
|
8613
|
+
return vnode_getParent(vnode);
|
|
8614
|
+
};
|
|
7921
8615
|
const vnode_getNode = (vnode) => {
|
|
7922
8616
|
if (vnode === null || vnode_isVirtualVNode(vnode)) {
|
|
7923
8617
|
return null;
|
|
@@ -8026,21 +8720,19 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
8026
8720
|
let textIdx = 0;
|
|
8027
8721
|
let combinedText = null;
|
|
8028
8722
|
let container = null;
|
|
8029
|
-
processVNodeData(vData, (peek, consumeValue, consume, nextToConsumeIdx) => {
|
|
8723
|
+
processVNodeData(vData, (peek, consumeValue, consume, getChar, nextToConsumeIdx) => {
|
|
8030
8724
|
if (isNumber(peek())) {
|
|
8031
8725
|
// Element counts get encoded as numbers.
|
|
8032
|
-
while (!isElement(child)
|
|
8726
|
+
while (!isElement(child) ||
|
|
8727
|
+
// We pretend that style element's don't exist as they can get moved out.
|
|
8728
|
+
// skip over style elements, as those need to be moved to the head
|
|
8729
|
+
// and are not included in the counts.
|
|
8730
|
+
isQStyleElement(child)) {
|
|
8033
8731
|
child = fastNextSibling(child);
|
|
8034
8732
|
if (!child) {
|
|
8035
8733
|
throw qError(27 /* QError.materializeVNodeDataError */, [vData, peek(), nextToConsumeIdx]);
|
|
8036
8734
|
}
|
|
8037
8735
|
}
|
|
8038
|
-
// We pretend that style element's don't exist as they can get moved out.
|
|
8039
|
-
while (isQStyleElement(child)) {
|
|
8040
|
-
// skip over style elements, as those need to be moved to the head
|
|
8041
|
-
// and are not included in the counts.
|
|
8042
|
-
child = fastNextSibling(child);
|
|
8043
|
-
}
|
|
8044
8736
|
combinedText = null;
|
|
8045
8737
|
previousTextNode = null;
|
|
8046
8738
|
let value = 0;
|
|
@@ -8072,7 +8764,17 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
8072
8764
|
vnode_setAttr(null, vParent, ELEMENT_PROPS, consumeValue());
|
|
8073
8765
|
}
|
|
8074
8766
|
else if (peek() === VNodeDataChar.KEY) {
|
|
8075
|
-
|
|
8767
|
+
const isEscapedValue = getChar(nextToConsumeIdx + 1) === VNodeDataChar.SEPARATOR;
|
|
8768
|
+
let value;
|
|
8769
|
+
if (isEscapedValue) {
|
|
8770
|
+
consume();
|
|
8771
|
+
value = decodeURI(consumeValue());
|
|
8772
|
+
consume();
|
|
8773
|
+
}
|
|
8774
|
+
else {
|
|
8775
|
+
value = consumeValue();
|
|
8776
|
+
}
|
|
8777
|
+
vnode_setAttr(null, vParent, ELEMENT_KEY, value);
|
|
8076
8778
|
}
|
|
8077
8779
|
else if (peek() === VNodeDataChar.SEQ) {
|
|
8078
8780
|
vnode_setAttr(null, vParent, ELEMENT_SEQ, consumeValue());
|
|
@@ -8118,6 +8820,10 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
8118
8820
|
vnode_setAttr(null, vParent, QSlot, consumeValue());
|
|
8119
8821
|
}
|
|
8120
8822
|
else {
|
|
8823
|
+
// skip over style elements in front of text nodes, where text node is the first child (except the style node)
|
|
8824
|
+
while (isQStyleElement(child)) {
|
|
8825
|
+
child = fastNextSibling(child);
|
|
8826
|
+
}
|
|
8121
8827
|
const textNode = child && fastNodeType(child) === /* Node.TEXT_NODE */ 3 ? child : null;
|
|
8122
8828
|
// must be alphanumeric
|
|
8123
8829
|
if (combinedText === null) {
|
|
@@ -8212,9 +8918,11 @@ const VNodeArray = class VNode extends Array {
|
|
|
8212
8918
|
};
|
|
8213
8919
|
|
|
8214
8920
|
/** There's [documentation](./serialization.md) */
|
|
8921
|
+
/** Arrays/Objects are special-cased so their identifiers is a single digit. */
|
|
8922
|
+
const needsInflation = (typeId) => typeId >= 14 /* TypeIds.Error */ || typeId === 4 /* TypeIds.Array */ || typeId === 5 /* TypeIds.Object */;
|
|
8215
8923
|
const deserializedProxyMap = new WeakMap();
|
|
8216
8924
|
const isDeserializerProxy = (value) => {
|
|
8217
|
-
return
|
|
8925
|
+
return isObject(value) && SERIALIZER_PROXY_UNWRAP in value;
|
|
8218
8926
|
};
|
|
8219
8927
|
const SERIALIZER_PROXY_UNWRAP = Symbol('UNWRAP');
|
|
8220
8928
|
/** Call this on the serialized root state */
|
|
@@ -8259,19 +8967,19 @@ class DeserializationHandler {
|
|
|
8259
8967
|
const idx = i * 2;
|
|
8260
8968
|
const typeId = this.$data$[idx];
|
|
8261
8969
|
const value = this.$data$[idx + 1];
|
|
8262
|
-
if (typeId ===
|
|
8970
|
+
if (typeId === 0 /* TypeIds.Plain */) {
|
|
8263
8971
|
// The value is already cached
|
|
8264
8972
|
return value;
|
|
8265
8973
|
}
|
|
8266
8974
|
const container = this.$container$;
|
|
8267
|
-
|
|
8268
|
-
/** We stored the reference, so now we can inflate, allowing cycles. */
|
|
8269
|
-
if (typeId >= 14 /* TypeIds.Error */) {
|
|
8270
|
-
propValue = inflate(container, propValue, typeId, value);
|
|
8271
|
-
}
|
|
8975
|
+
const propValue = allocate(container, typeId, value);
|
|
8272
8976
|
Reflect.set(target, property, propValue);
|
|
8273
|
-
this.$data$[idx] =
|
|
8977
|
+
this.$data$[idx] = 0 /* TypeIds.Plain */;
|
|
8274
8978
|
this.$data$[idx + 1] = propValue;
|
|
8979
|
+
/** We stored the reference, so now we can inflate, allowing cycles */
|
|
8980
|
+
if (needsInflation(typeId)) {
|
|
8981
|
+
inflate(container, propValue, typeId, value);
|
|
8982
|
+
}
|
|
8275
8983
|
return propValue;
|
|
8276
8984
|
}
|
|
8277
8985
|
has(target, property) {
|
|
@@ -8290,7 +8998,7 @@ class DeserializationHandler {
|
|
|
8290
8998
|
return out;
|
|
8291
8999
|
}
|
|
8292
9000
|
const idx = i * 2;
|
|
8293
|
-
this.$data$[idx] =
|
|
9001
|
+
this.$data$[idx] = 0 /* TypeIds.Plain */;
|
|
8294
9002
|
this.$data$[idx + 1] = value;
|
|
8295
9003
|
return true;
|
|
8296
9004
|
}
|
|
@@ -8308,51 +9016,33 @@ const _eagerDeserializeArray = (container, data) => {
|
|
|
8308
9016
|
};
|
|
8309
9017
|
const resolvers = new WeakMap();
|
|
8310
9018
|
const inflate = (container, target, typeId, data) => {
|
|
8311
|
-
if (typeId ===
|
|
9019
|
+
if (typeId === 0 /* TypeIds.Plain */) {
|
|
8312
9020
|
// Already processed
|
|
8313
|
-
return
|
|
9021
|
+
return;
|
|
8314
9022
|
}
|
|
8315
|
-
//
|
|
8316
|
-
if (
|
|
9023
|
+
// Restore the complex data
|
|
9024
|
+
if (Array.isArray(data)) {
|
|
8317
9025
|
data = _eagerDeserializeArray(container, data);
|
|
8318
9026
|
}
|
|
8319
9027
|
switch (typeId) {
|
|
8320
|
-
case
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
target[key] = value;
|
|
8332
|
-
return value;
|
|
8333
|
-
},
|
|
8334
|
-
set(value) {
|
|
8335
|
-
Object.defineProperty(target, key, {
|
|
8336
|
-
value,
|
|
8337
|
-
writable: true,
|
|
8338
|
-
enumerable: true,
|
|
8339
|
-
configurable: true,
|
|
8340
|
-
});
|
|
8341
|
-
},
|
|
8342
|
-
enumerable: true,
|
|
8343
|
-
configurable: true,
|
|
8344
|
-
});
|
|
8345
|
-
}
|
|
8346
|
-
else {
|
|
8347
|
-
target[key] = deserializeData(container, valType, valData);
|
|
8348
|
-
}
|
|
9028
|
+
case 4 /* TypeIds.Array */:
|
|
9029
|
+
for (let i = 0; i < target.length; i++) {
|
|
9030
|
+
// read the value to trigger lazy deserialization
|
|
9031
|
+
target[i];
|
|
9032
|
+
}
|
|
9033
|
+
break;
|
|
9034
|
+
case 5 /* TypeIds.Object */:
|
|
9035
|
+
for (let i = 0; i < data.length; i += 2) {
|
|
9036
|
+
const key = data[i];
|
|
9037
|
+
const value = data[i + 1];
|
|
9038
|
+
target[key] = value;
|
|
8349
9039
|
}
|
|
8350
9040
|
break;
|
|
8351
|
-
case
|
|
8352
|
-
case
|
|
9041
|
+
case 19 /* TypeIds.QRL */:
|
|
9042
|
+
case 20 /* TypeIds.PreloadQRL */:
|
|
8353
9043
|
inflateQRL(container, target);
|
|
8354
9044
|
break;
|
|
8355
|
-
case
|
|
9045
|
+
case 21 /* TypeIds.Task */:
|
|
8356
9046
|
const task = target;
|
|
8357
9047
|
const v = data;
|
|
8358
9048
|
task.$qrl$ = inflateQRL(container, v[0]);
|
|
@@ -8362,7 +9052,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8362
9052
|
task[_EFFECT_BACK_REF] = v[4];
|
|
8363
9053
|
task.$state$ = v[5];
|
|
8364
9054
|
break;
|
|
8365
|
-
case
|
|
9055
|
+
case 22 /* TypeIds.Resource */:
|
|
8366
9056
|
const [resolved, result, effects] = data;
|
|
8367
9057
|
const resource = target;
|
|
8368
9058
|
if (resolved) {
|
|
@@ -8377,26 +9067,31 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8377
9067
|
}
|
|
8378
9068
|
getStoreHandler(target).$effects$ = effects;
|
|
8379
9069
|
break;
|
|
8380
|
-
case
|
|
9070
|
+
case 23 /* TypeIds.Component */:
|
|
8381
9071
|
target[SERIALIZABLE_STATE][0] = data[0];
|
|
8382
9072
|
break;
|
|
8383
|
-
case
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
9073
|
+
case 29 /* TypeIds.Store */: {
|
|
9074
|
+
/**
|
|
9075
|
+
* Note that cycles between stores and their targets can cause this inflation to happen on
|
|
9076
|
+
* already inflated stores, but that's ok because the flags and effects are still the same.
|
|
9077
|
+
*
|
|
9078
|
+
* Also note that we don't do anything with the innerstores we added during serialization,
|
|
9079
|
+
* because they are already inflated in the first step of inflate().
|
|
9080
|
+
*/
|
|
9081
|
+
const [, flags, effects] = data;
|
|
9082
|
+
const storeHandler = getStoreHandler(target);
|
|
9083
|
+
storeHandler.$flags$ = flags;
|
|
8388
9084
|
storeHandler.$effects$ = effects;
|
|
8389
|
-
target = store;
|
|
8390
9085
|
break;
|
|
8391
9086
|
}
|
|
8392
|
-
case
|
|
9087
|
+
case 24 /* TypeIds.Signal */: {
|
|
8393
9088
|
const signal = target;
|
|
8394
9089
|
const d = data;
|
|
8395
9090
|
signal.$untrackedValue$ = d[0];
|
|
8396
9091
|
signal.$effects$ = new Set(d.slice(1));
|
|
8397
9092
|
break;
|
|
8398
9093
|
}
|
|
8399
|
-
case
|
|
9094
|
+
case 25 /* TypeIds.WrappedSignal */: {
|
|
8400
9095
|
const signal = target;
|
|
8401
9096
|
const d = data;
|
|
8402
9097
|
signal.$func$ = container.getSyncFn(d[0]);
|
|
@@ -8409,7 +9104,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8409
9104
|
signal.$effects$ = new Set(d.slice(5));
|
|
8410
9105
|
break;
|
|
8411
9106
|
}
|
|
8412
|
-
case
|
|
9107
|
+
case 27 /* TypeIds.AsyncComputedSignal */: {
|
|
8413
9108
|
const asyncComputed = target;
|
|
8414
9109
|
const d = data;
|
|
8415
9110
|
asyncComputed.$computeQrl$ = d[0];
|
|
@@ -8422,14 +9117,12 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8422
9117
|
if (hasValue) {
|
|
8423
9118
|
asyncComputed.$untrackedValue$ = d[6];
|
|
8424
9119
|
}
|
|
8425
|
-
|
|
8426
|
-
asyncComputed.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
8427
|
-
}
|
|
9120
|
+
asyncComputed.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
8428
9121
|
break;
|
|
8429
9122
|
}
|
|
8430
9123
|
// Inflating a SerializerSignal is the same as inflating a ComputedSignal
|
|
8431
|
-
case
|
|
8432
|
-
case
|
|
9124
|
+
case 28 /* TypeIds.SerializerSignal */:
|
|
9125
|
+
case 26 /* TypeIds.ComputedSignal */: {
|
|
8433
9126
|
const computed = target;
|
|
8434
9127
|
const d = data;
|
|
8435
9128
|
computed.$computeQrl$ = d[0];
|
|
@@ -8438,7 +9131,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8438
9131
|
if (hasValue) {
|
|
8439
9132
|
computed.$untrackedValue$ = d[2];
|
|
8440
9133
|
// The serialized signal is always invalid so it can recreate the custom object
|
|
8441
|
-
if (typeId ===
|
|
9134
|
+
if (typeId === 28 /* TypeIds.SerializerSignal */) {
|
|
8442
9135
|
computed.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
8443
9136
|
}
|
|
8444
9137
|
}
|
|
@@ -8452,7 +9145,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8452
9145
|
*/
|
|
8453
9146
|
// try to download qrl in this tick
|
|
8454
9147
|
computed.$computeQrl$.resolve();
|
|
8455
|
-
container.$scheduler
|
|
9148
|
+
container.$scheduler$(1 /* ChoreType.QRL_RESOLVE */, null, computed.$computeQrl$);
|
|
8456
9149
|
}
|
|
8457
9150
|
break;
|
|
8458
9151
|
}
|
|
@@ -8464,7 +9157,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8464
9157
|
}
|
|
8465
9158
|
break;
|
|
8466
9159
|
}
|
|
8467
|
-
case
|
|
9160
|
+
case 30 /* TypeIds.FormData */: {
|
|
8468
9161
|
const formData = target;
|
|
8469
9162
|
const d = data;
|
|
8470
9163
|
for (let i = 0; i < d.length; i++) {
|
|
@@ -8472,7 +9165,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8472
9165
|
}
|
|
8473
9166
|
break;
|
|
8474
9167
|
}
|
|
8475
|
-
case
|
|
9168
|
+
case 31 /* TypeIds.JSXNode */: {
|
|
8476
9169
|
const jsx = target;
|
|
8477
9170
|
const [type, varProps, constProps, children, flags, key] = data;
|
|
8478
9171
|
jsx.type = type;
|
|
@@ -8483,7 +9176,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8483
9176
|
jsx.key = key;
|
|
8484
9177
|
break;
|
|
8485
9178
|
}
|
|
8486
|
-
case
|
|
9179
|
+
case 16 /* TypeIds.Set */: {
|
|
8487
9180
|
const set = target;
|
|
8488
9181
|
const d = data;
|
|
8489
9182
|
for (let i = 0; i < d.length; i++) {
|
|
@@ -8491,7 +9184,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8491
9184
|
}
|
|
8492
9185
|
break;
|
|
8493
9186
|
}
|
|
8494
|
-
case
|
|
9187
|
+
case 17 /* TypeIds.Map */: {
|
|
8495
9188
|
const map = target;
|
|
8496
9189
|
const d = data;
|
|
8497
9190
|
for (let i = 0; i < d.length; i++) {
|
|
@@ -8499,7 +9192,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8499
9192
|
}
|
|
8500
9193
|
break;
|
|
8501
9194
|
}
|
|
8502
|
-
case
|
|
9195
|
+
case 15 /* TypeIds.Promise */: {
|
|
8503
9196
|
const promise = target;
|
|
8504
9197
|
const [resolved, result] = data;
|
|
8505
9198
|
const [resolve, reject] = resolvers.get(promise);
|
|
@@ -8511,7 +9204,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8511
9204
|
}
|
|
8512
9205
|
break;
|
|
8513
9206
|
}
|
|
8514
|
-
case
|
|
9207
|
+
case 18 /* TypeIds.Uint8Array */:
|
|
8515
9208
|
const bytes = target;
|
|
8516
9209
|
const buf = atob(data);
|
|
8517
9210
|
let i = 0;
|
|
@@ -8519,12 +9212,12 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8519
9212
|
bytes[i++] = s.charCodeAt(0);
|
|
8520
9213
|
}
|
|
8521
9214
|
break;
|
|
8522
|
-
case
|
|
9215
|
+
case 32 /* TypeIds.PropsProxy */:
|
|
8523
9216
|
const propsProxy = target;
|
|
8524
9217
|
propsProxy[_VAR_PROPS] = data === 0 ? {} : data[0];
|
|
8525
9218
|
propsProxy[_CONST_PROPS] = data[1];
|
|
8526
9219
|
break;
|
|
8527
|
-
case
|
|
9220
|
+
case 33 /* TypeIds.SubscriptionData */: {
|
|
8528
9221
|
const effectData = target;
|
|
8529
9222
|
effectData.data.$scopedStyleIdPrefix$ = data[0];
|
|
8530
9223
|
effectData.data.$isConst$ = data[1];
|
|
@@ -8533,7 +9226,6 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8533
9226
|
default:
|
|
8534
9227
|
throw qError(16 /* QError.serializeErrorNotImplemented */, [typeId]);
|
|
8535
9228
|
}
|
|
8536
|
-
return target;
|
|
8537
9229
|
};
|
|
8538
9230
|
const _constants = [
|
|
8539
9231
|
undefined,
|
|
@@ -8545,6 +9237,7 @@ const _constants = [
|
|
|
8545
9237
|
EMPTY_OBJ,
|
|
8546
9238
|
NEEDS_COMPUTATION,
|
|
8547
9239
|
STORE_ALL_PROPS,
|
|
9240
|
+
_UNINITIALIZED,
|
|
8548
9241
|
Slot,
|
|
8549
9242
|
Fragment,
|
|
8550
9243
|
NaN,
|
|
@@ -8564,6 +9257,7 @@ const _constantNames = [
|
|
|
8564
9257
|
'EMPTY_OBJ',
|
|
8565
9258
|
'NEEDS_COMPUTATION',
|
|
8566
9259
|
'STORE_ALL_PROPS',
|
|
9260
|
+
'_UNINITIALIZED',
|
|
8567
9261
|
'Slot',
|
|
8568
9262
|
'Fragment',
|
|
8569
9263
|
'NaN',
|
|
@@ -8574,84 +9268,96 @@ const _constantNames = [
|
|
|
8574
9268
|
'MIN_SAFE_INTEGER',
|
|
8575
9269
|
];
|
|
8576
9270
|
const allocate = (container, typeId, value) => {
|
|
8577
|
-
if (
|
|
8578
|
-
|
|
8579
|
-
return typeId;
|
|
9271
|
+
if (typeId === 0 /* TypeIds.Plain */) {
|
|
9272
|
+
return value;
|
|
8580
9273
|
}
|
|
8581
9274
|
switch (typeId) {
|
|
8582
|
-
case
|
|
9275
|
+
case 1 /* TypeIds.RootRef */:
|
|
8583
9276
|
return container.$getObjectById$(value);
|
|
8584
|
-
case
|
|
9277
|
+
case 2 /* TypeIds.ForwardRef */:
|
|
8585
9278
|
if (!container.$forwardRefs$) {
|
|
8586
9279
|
throw qError(18 /* QError.serializeErrorCannotAllocate */, ['forward ref']);
|
|
8587
9280
|
}
|
|
8588
|
-
|
|
8589
|
-
|
|
9281
|
+
const rootRef = container.$forwardRefs$[value];
|
|
9282
|
+
if (rootRef === -1) {
|
|
9283
|
+
return _UNINITIALIZED;
|
|
9284
|
+
}
|
|
9285
|
+
else {
|
|
9286
|
+
return container.$getObjectById$(rootRef);
|
|
9287
|
+
}
|
|
9288
|
+
case 13 /* TypeIds.ForwardRefs */:
|
|
8590
9289
|
return value;
|
|
8591
9290
|
case 3 /* TypeIds.Constant */:
|
|
8592
9291
|
return _constants[value];
|
|
8593
|
-
case 4 /* TypeIds.
|
|
8594
|
-
|
|
8595
|
-
case 6 /* TypeIds.Array */:
|
|
9292
|
+
case 4 /* TypeIds.Array */:
|
|
9293
|
+
// Wrap while inflating so we can handle cyclic references
|
|
8596
9294
|
return wrapDeserializerProxy(container, value);
|
|
8597
|
-
case
|
|
9295
|
+
case 5 /* TypeIds.Object */:
|
|
8598
9296
|
return {};
|
|
8599
|
-
case
|
|
8600
|
-
case
|
|
9297
|
+
case 19 /* TypeIds.QRL */:
|
|
9298
|
+
case 20 /* TypeIds.PreloadQRL */:
|
|
8601
9299
|
const qrl = typeof value === 'number'
|
|
8602
9300
|
? // root reference
|
|
8603
9301
|
container.$getObjectById$(value)
|
|
8604
9302
|
: value;
|
|
8605
9303
|
return parseQRL(qrl);
|
|
8606
|
-
case
|
|
9304
|
+
case 21 /* TypeIds.Task */:
|
|
8607
9305
|
return new Task(-1, -1, null, null, null, null);
|
|
8608
|
-
case
|
|
9306
|
+
case 22 /* TypeIds.Resource */: {
|
|
8609
9307
|
const res = createResourceReturn(container,
|
|
8610
9308
|
// we don't care about the timeout value
|
|
8611
9309
|
undefined, undefined);
|
|
8612
9310
|
res.loading = false;
|
|
8613
9311
|
return res;
|
|
8614
9312
|
}
|
|
8615
|
-
case
|
|
9313
|
+
case 6 /* TypeIds.URL */:
|
|
8616
9314
|
return new URL(value);
|
|
8617
|
-
case
|
|
9315
|
+
case 7 /* TypeIds.Date */:
|
|
8618
9316
|
return new Date(value);
|
|
8619
|
-
case
|
|
9317
|
+
case 8 /* TypeIds.Regex */:
|
|
8620
9318
|
const idx = value.lastIndexOf('/');
|
|
8621
9319
|
return new RegExp(value.slice(1, idx), value.slice(idx + 1));
|
|
8622
9320
|
case 14 /* TypeIds.Error */:
|
|
8623
9321
|
return new Error();
|
|
8624
|
-
case
|
|
9322
|
+
case 23 /* TypeIds.Component */:
|
|
8625
9323
|
return componentQrl(null);
|
|
8626
|
-
case
|
|
9324
|
+
case 24 /* TypeIds.Signal */:
|
|
8627
9325
|
return new SignalImpl(container, 0);
|
|
8628
|
-
case
|
|
9326
|
+
case 25 /* TypeIds.WrappedSignal */:
|
|
8629
9327
|
return new WrappedSignalImpl(container, null, null, null);
|
|
8630
|
-
case
|
|
9328
|
+
case 26 /* TypeIds.ComputedSignal */:
|
|
8631
9329
|
return new ComputedSignalImpl(container, null);
|
|
8632
|
-
case
|
|
9330
|
+
case 27 /* TypeIds.AsyncComputedSignal */:
|
|
8633
9331
|
return new AsyncComputedSignalImpl(container, null);
|
|
8634
|
-
case
|
|
9332
|
+
case 28 /* TypeIds.SerializerSignal */:
|
|
8635
9333
|
return new SerializerSignalImpl(container, null);
|
|
8636
|
-
case
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
9334
|
+
case 29 /* TypeIds.Store */:
|
|
9335
|
+
/**
|
|
9336
|
+
* We have a problem here: In theory, both the store and the target need to be present at
|
|
9337
|
+
* allocate time before inflation can happen. However, that makes the code really complex.
|
|
9338
|
+
* Instead, we deserialize the target here, which will already allocate and inflate this store
|
|
9339
|
+
* if there is a cycle (because the original allocation for the store didn't complete yet).
|
|
9340
|
+
* Because we have a map of target -> store, we will reuse the same store instance after
|
|
9341
|
+
* target deserialization. So in that case, we will be running inflation twice on the same
|
|
9342
|
+
* store, but that is not a problem, very little overhead and the code is way simpler.
|
|
9343
|
+
*/
|
|
9344
|
+
const storeValue = deserializeData(container, value[0], value[1]);
|
|
9345
|
+
value[0] = 0 /* TypeIds.Plain */;
|
|
9346
|
+
value[1] = storeValue;
|
|
9347
|
+
return getOrCreateStore(storeValue, 0 /* StoreFlags.NONE */, container);
|
|
9348
|
+
case 12 /* TypeIds.URLSearchParams */:
|
|
8641
9349
|
return new URLSearchParams(value);
|
|
8642
|
-
case
|
|
9350
|
+
case 30 /* TypeIds.FormData */:
|
|
8643
9351
|
return new FormData();
|
|
8644
|
-
case
|
|
9352
|
+
case 31 /* TypeIds.JSXNode */:
|
|
8645
9353
|
return new JSXNodeImpl(null, null, null, null, -1, null);
|
|
8646
|
-
case
|
|
9354
|
+
case 11 /* TypeIds.BigInt */:
|
|
8647
9355
|
return BigInt(value);
|
|
8648
|
-
case
|
|
9356
|
+
case 16 /* TypeIds.Set */:
|
|
8649
9357
|
return new Set();
|
|
8650
|
-
case
|
|
9358
|
+
case 17 /* TypeIds.Map */:
|
|
8651
9359
|
return new Map();
|
|
8652
|
-
case
|
|
8653
|
-
return value;
|
|
8654
|
-
case 16 /* TypeIds.Promise */:
|
|
9360
|
+
case 15 /* TypeIds.Promise */:
|
|
8655
9361
|
let resolve;
|
|
8656
9362
|
let reject;
|
|
8657
9363
|
const promise = new Promise((res, rej) => {
|
|
@@ -8662,25 +9368,51 @@ const allocate = (container, typeId, value) => {
|
|
|
8662
9368
|
// Don't leave unhandled promise rejections
|
|
8663
9369
|
promise.catch(() => { });
|
|
8664
9370
|
return promise;
|
|
8665
|
-
case
|
|
9371
|
+
case 18 /* TypeIds.Uint8Array */:
|
|
8666
9372
|
const encodedLength = value.length;
|
|
8667
9373
|
const blocks = encodedLength >>> 2;
|
|
8668
9374
|
const rest = encodedLength & 3;
|
|
8669
9375
|
const decodedLength = blocks * 3 + (rest ? rest - 1 : 0);
|
|
8670
9376
|
return new Uint8Array(decodedLength);
|
|
8671
|
-
case
|
|
9377
|
+
case 32 /* TypeIds.PropsProxy */:
|
|
8672
9378
|
return createPropsProxy(null, null);
|
|
8673
|
-
case
|
|
9379
|
+
case 9 /* TypeIds.VNode */:
|
|
8674
9380
|
return retrieveVNodeOrDocument(container, value);
|
|
8675
|
-
case
|
|
9381
|
+
case 10 /* TypeIds.RefVNode */:
|
|
8676
9382
|
const vNode = retrieveVNodeOrDocument(container, value);
|
|
8677
9383
|
if (vnode_isVNode(vNode)) {
|
|
9384
|
+
/**
|
|
9385
|
+
* If we have a ref, we need to ensure the element is materialized.
|
|
9386
|
+
*
|
|
9387
|
+
* Example:
|
|
9388
|
+
*
|
|
9389
|
+
* ```
|
|
9390
|
+
* const Cmp = component$(() => {
|
|
9391
|
+
* const element = useSignal<HTMLDivElement>();
|
|
9392
|
+
*
|
|
9393
|
+
* useVisibleTask$(() => {
|
|
9394
|
+
* element.value!.innerHTML = 'I am the innerHTML content!';
|
|
9395
|
+
* });
|
|
9396
|
+
*
|
|
9397
|
+
* return (
|
|
9398
|
+
* <div ref={element} />
|
|
9399
|
+
* );
|
|
9400
|
+
* });
|
|
9401
|
+
* ```
|
|
9402
|
+
*
|
|
9403
|
+
* If we don't materialize early element with ref property, and change element innerHTML it
|
|
9404
|
+
* will be applied to a vnode tree during the lazy materialization, and it is wrong.
|
|
9405
|
+
*
|
|
9406
|
+
* Next if we rerender component it will remove applied innerHTML, because the system thinks
|
|
9407
|
+
* it is a part of the vnode tree.
|
|
9408
|
+
*/
|
|
9409
|
+
ensureMaterialized(vNode);
|
|
8678
9410
|
return vnode_getNode(vNode);
|
|
8679
9411
|
}
|
|
8680
9412
|
else {
|
|
8681
9413
|
throw qError(17 /* QError.serializeErrorExpectedVNode */, [typeof vNode]);
|
|
8682
9414
|
}
|
|
8683
|
-
case
|
|
9415
|
+
case 33 /* TypeIds.SubscriptionData */:
|
|
8684
9416
|
return new SubscriptionData({});
|
|
8685
9417
|
default:
|
|
8686
9418
|
throw qError(18 /* QError.serializeErrorCannotAllocate */, [typeId]);
|
|
@@ -8742,7 +9474,7 @@ DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, write
|
|
|
8742
9474
|
};
|
|
8743
9475
|
}
|
|
8744
9476
|
const seenObjsMap = new Map();
|
|
8745
|
-
const
|
|
9477
|
+
const objectPathStringCache = new Map();
|
|
8746
9478
|
const syncFnMap = new Map();
|
|
8747
9479
|
const syncFns = [];
|
|
8748
9480
|
const roots = [];
|
|
@@ -8751,7 +9483,7 @@ DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, write
|
|
|
8751
9483
|
return seenObjsMap.set(obj, { $parent$: parent, $index$: index, $rootIndex$: -1 });
|
|
8752
9484
|
};
|
|
8753
9485
|
const $addRootPath$ = (obj) => {
|
|
8754
|
-
const rootPath =
|
|
9486
|
+
const rootPath = objectPathStringCache.get(obj);
|
|
8755
9487
|
if (rootPath) {
|
|
8756
9488
|
return rootPath;
|
|
8757
9489
|
}
|
|
@@ -8770,7 +9502,7 @@ DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, write
|
|
|
8770
9502
|
current = seenObjsMap.get(current.$parent$);
|
|
8771
9503
|
}
|
|
8772
9504
|
const pathStr = path.length > 1 ? path.join(' ') : path.length ? path[0] : seen.$index$;
|
|
8773
|
-
|
|
9505
|
+
objectPathStringCache.set(obj, pathStr);
|
|
8774
9506
|
return pathStr;
|
|
8775
9507
|
};
|
|
8776
9508
|
const $addRoot$ = (obj, parent = null) => {
|
|
@@ -8837,7 +9569,7 @@ DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, write
|
|
|
8837
9569
|
$storeProxyMap$: storeProxyMap,
|
|
8838
9570
|
$getProp$: getProp,
|
|
8839
9571
|
$setProp$: setProp,
|
|
8840
|
-
$
|
|
9572
|
+
$objectPathStringCache$: objectPathStringCache,
|
|
8841
9573
|
};
|
|
8842
9574
|
};
|
|
8843
9575
|
function $discoverRoots$(serializationContext, obj, parent, index) {
|
|
@@ -8861,7 +9593,8 @@ const discoverValuesForVNodeData = (vnodeData, callback) => {
|
|
|
8861
9593
|
for (let i = 1; i < value.length; i += 2) {
|
|
8862
9594
|
const keyValue = value[i - 1];
|
|
8863
9595
|
const attrValue = value[i];
|
|
8864
|
-
if (
|
|
9596
|
+
if (attrValue == null ||
|
|
9597
|
+
typeof attrValue === 'string' ||
|
|
8865
9598
|
// skip empty props
|
|
8866
9599
|
(keyValue === ELEMENT_PROPS &&
|
|
8867
9600
|
Object.keys(attrValue).length === 0)) {
|
|
@@ -8886,6 +9619,14 @@ class PromiseResult {
|
|
|
8886
9619
|
this.$qrl$ = $qrl$;
|
|
8887
9620
|
}
|
|
8888
9621
|
}
|
|
9622
|
+
class SerializationWeakRef {
|
|
9623
|
+
$obj$;
|
|
9624
|
+
constructor($obj$) {
|
|
9625
|
+
this.$obj$ = $obj$;
|
|
9626
|
+
}
|
|
9627
|
+
}
|
|
9628
|
+
/** @internal */
|
|
9629
|
+
const _serializationWeakRef = (obj) => new SerializationWeakRef(obj);
|
|
8889
9630
|
/**
|
|
8890
9631
|
* Format:
|
|
8891
9632
|
*
|
|
@@ -8896,12 +9637,14 @@ class PromiseResult {
|
|
|
8896
9637
|
* - Therefore root indexes need to be doubled to get the actual index.
|
|
8897
9638
|
*/
|
|
8898
9639
|
async function serialize(serializationContext) {
|
|
8899
|
-
const { $writer$, $isSsrNode$, $isDomRef$, $storeProxyMap$, $addRoot$, $
|
|
9640
|
+
const { $writer$, $isSsrNode$, $isDomRef$, $storeProxyMap$, $addRoot$, $objectPathStringCache$, $wasSeen$, } = serializationContext;
|
|
8900
9641
|
let depth = 0;
|
|
9642
|
+
let rootIdx = 0;
|
|
8901
9643
|
const forwardRefs = [];
|
|
8902
9644
|
let forwardRefsId = 0;
|
|
8903
9645
|
const promises = new Set();
|
|
8904
9646
|
const preloadQrls = new Set();
|
|
9647
|
+
const s11nWeakRefs = new Map();
|
|
8905
9648
|
let parent = null;
|
|
8906
9649
|
const isRootObject = () => depth === 0;
|
|
8907
9650
|
const outputArray = (value, writeFn) => {
|
|
@@ -8946,19 +9689,41 @@ async function serialize(serializationContext) {
|
|
|
8946
9689
|
};
|
|
8947
9690
|
const addPreloadQrl = (qrl) => {
|
|
8948
9691
|
preloadQrls.add(qrl);
|
|
8949
|
-
serializationContext.$addRoot$(qrl
|
|
9692
|
+
serializationContext.$addRoot$(qrl);
|
|
8950
9693
|
};
|
|
8951
|
-
const
|
|
9694
|
+
const outputAsRootRef = (value, rootDepth = 0) => {
|
|
8952
9695
|
const seen = $wasSeen$(value);
|
|
8953
|
-
const rootRefPath = $
|
|
9696
|
+
const rootRefPath = $objectPathStringCache$.get(value);
|
|
9697
|
+
// Objects are the only way to create circular dependencies.
|
|
9698
|
+
// So the first thing to to is to see if we have a circular dependency.
|
|
9699
|
+
// (NOTE: For root objects we need to serialize them regardless if we have seen
|
|
9700
|
+
// them before, otherwise the root object reference will point to itself.)
|
|
9701
|
+
// Also note that depth will be 1 for objects in root
|
|
8954
9702
|
if (rootDepth === depth && seen && seen.$parent$ !== null && rootRefPath) {
|
|
8955
|
-
output(
|
|
9703
|
+
output(1 /* TypeIds.RootRef */, rootRefPath);
|
|
8956
9704
|
return true;
|
|
8957
9705
|
}
|
|
8958
9706
|
else if (depth > rootDepth && seen && seen.$rootIndex$ !== -1) {
|
|
8959
|
-
|
|
9707
|
+
// We have seen this object before, so we can serialize it as a reference.
|
|
9708
|
+
// Otherwise serialize as normal
|
|
9709
|
+
output(1 /* TypeIds.RootRef */, seen.$rootIndex$);
|
|
8960
9710
|
return true;
|
|
8961
9711
|
}
|
|
9712
|
+
else if (s11nWeakRefs.has(value)) {
|
|
9713
|
+
const forwardRefId = s11nWeakRefs.get(value);
|
|
9714
|
+
// We see the object again, we must now make it a root and update the forward ref
|
|
9715
|
+
if (rootDepth === depth) {
|
|
9716
|
+
// It's already a root
|
|
9717
|
+
forwardRefs[forwardRefId] = rootIdx;
|
|
9718
|
+
}
|
|
9719
|
+
else {
|
|
9720
|
+
// ref
|
|
9721
|
+
const rootRef = $addRoot$(value);
|
|
9722
|
+
output(1 /* TypeIds.RootRef */, rootRef);
|
|
9723
|
+
forwardRefs[forwardRefId] = rootRef;
|
|
9724
|
+
return true;
|
|
9725
|
+
}
|
|
9726
|
+
}
|
|
8962
9727
|
return false;
|
|
8963
9728
|
};
|
|
8964
9729
|
const writeValue = (value) => {
|
|
@@ -8966,22 +9731,22 @@ async function serialize(serializationContext) {
|
|
|
8966
9731
|
output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
|
|
8967
9732
|
}
|
|
8968
9733
|
else if (typeof value === 'bigint') {
|
|
8969
|
-
output(
|
|
9734
|
+
output(11 /* TypeIds.BigInt */, value.toString());
|
|
8970
9735
|
}
|
|
8971
9736
|
else if (typeof value === 'boolean') {
|
|
8972
9737
|
output(3 /* TypeIds.Constant */, value ? 2 /* Constants.True */ : 3 /* Constants.False */);
|
|
8973
9738
|
}
|
|
8974
9739
|
else if (typeof value === 'function') {
|
|
8975
9740
|
if (value === Slot) {
|
|
8976
|
-
output(3 /* TypeIds.Constant */,
|
|
9741
|
+
output(3 /* TypeIds.Constant */, 10 /* Constants.Slot */);
|
|
8977
9742
|
}
|
|
8978
9743
|
else if (value === Fragment) {
|
|
8979
|
-
output(3 /* TypeIds.Constant */,
|
|
9744
|
+
output(3 /* TypeIds.Constant */, 11 /* Constants.Fragment */);
|
|
8980
9745
|
}
|
|
8981
9746
|
else if (isQrl(value)) {
|
|
8982
|
-
if (!
|
|
9747
|
+
if (!outputAsRootRef(value)) {
|
|
8983
9748
|
const qrl = qrlToString(serializationContext, value);
|
|
8984
|
-
const type = preloadQrls.has(value) ?
|
|
9749
|
+
const type = preloadQrls.has(value) ? 20 /* TypeIds.PreloadQRL */ : 19 /* TypeIds.QRL */;
|
|
8985
9750
|
if (isRootObject()) {
|
|
8986
9751
|
output(type, qrl);
|
|
8987
9752
|
}
|
|
@@ -8994,7 +9759,7 @@ async function serialize(serializationContext) {
|
|
|
8994
9759
|
else if (isQwikComponent(value)) {
|
|
8995
9760
|
const [qrl] = value[SERIALIZABLE_STATE];
|
|
8996
9761
|
serializationContext.$renderSymbols$.add(qrl.$symbol$);
|
|
8997
|
-
output(
|
|
9762
|
+
output(23 /* TypeIds.Component */, [qrl]);
|
|
8998
9763
|
}
|
|
8999
9764
|
else {
|
|
9000
9765
|
throw qError(34 /* QError.serializeErrorCannotSerializeFunction */, [value.toString()]);
|
|
@@ -9002,22 +9767,22 @@ async function serialize(serializationContext) {
|
|
|
9002
9767
|
}
|
|
9003
9768
|
else if (typeof value === 'number') {
|
|
9004
9769
|
if (Number.isNaN(value)) {
|
|
9005
|
-
output(3 /* TypeIds.Constant */,
|
|
9770
|
+
output(3 /* TypeIds.Constant */, 12 /* Constants.NaN */);
|
|
9006
9771
|
}
|
|
9007
9772
|
else if (!Number.isFinite(value)) {
|
|
9008
|
-
output(3 /* TypeIds.Constant */, value < 0 ?
|
|
9773
|
+
output(3 /* TypeIds.Constant */, value < 0 ? 14 /* Constants.NegativeInfinity */ : 13 /* Constants.PositiveInfinity */);
|
|
9009
9774
|
}
|
|
9010
9775
|
else if (value === Number.MAX_SAFE_INTEGER) {
|
|
9011
|
-
output(3 /* TypeIds.Constant */,
|
|
9776
|
+
output(3 /* TypeIds.Constant */, 15 /* Constants.MaxSafeInt */);
|
|
9012
9777
|
}
|
|
9013
9778
|
else if (value === Number.MAX_SAFE_INTEGER - 1) {
|
|
9014
|
-
output(3 /* TypeIds.Constant */,
|
|
9779
|
+
output(3 /* TypeIds.Constant */, 16 /* Constants.AlmostMaxSafeInt */);
|
|
9015
9780
|
}
|
|
9016
9781
|
else if (value === Number.MIN_SAFE_INTEGER) {
|
|
9017
|
-
output(3 /* TypeIds.Constant */,
|
|
9782
|
+
output(3 /* TypeIds.Constant */, 17 /* Constants.MinSafeInt */);
|
|
9018
9783
|
}
|
|
9019
9784
|
else {
|
|
9020
|
-
output(
|
|
9785
|
+
output(0 /* TypeIds.Plain */, value);
|
|
9021
9786
|
}
|
|
9022
9787
|
}
|
|
9023
9788
|
else if (typeof value === 'object') {
|
|
@@ -9044,8 +9809,8 @@ async function serialize(serializationContext) {
|
|
|
9044
9809
|
output(3 /* TypeIds.Constant */, 4 /* Constants.EmptyString */);
|
|
9045
9810
|
}
|
|
9046
9811
|
else {
|
|
9047
|
-
if (!
|
|
9048
|
-
output(
|
|
9812
|
+
if (!outputAsRootRef(value)) {
|
|
9813
|
+
output(0 /* TypeIds.Plain */, value);
|
|
9049
9814
|
}
|
|
9050
9815
|
}
|
|
9051
9816
|
}
|
|
@@ -9058,6 +9823,9 @@ async function serialize(serializationContext) {
|
|
|
9058
9823
|
else if (value === STORE_ALL_PROPS) {
|
|
9059
9824
|
output(3 /* TypeIds.Constant */, 8 /* Constants.STORE_ALL_PROPS */);
|
|
9060
9825
|
}
|
|
9826
|
+
else if (value === _UNINITIALIZED) {
|
|
9827
|
+
output(3 /* TypeIds.Constant */, 9 /* Constants.UNINITIALIZED */);
|
|
9828
|
+
}
|
|
9061
9829
|
else {
|
|
9062
9830
|
throw qError(20 /* QError.serializeErrorUnknownType */, [typeof value]);
|
|
9063
9831
|
}
|
|
@@ -9067,14 +9835,11 @@ async function serialize(serializationContext) {
|
|
|
9067
9835
|
* The object writer outputs an array object (without type prefix) and this increases the depth
|
|
9068
9836
|
* for the objects within (depth 1).
|
|
9069
9837
|
*/
|
|
9070
|
-
|
|
9071
|
-
// So the first thing to to is to see if we have a circular dependency.
|
|
9072
|
-
// (NOTE: For root objects we need to serialize them regardless if we have seen
|
|
9073
|
-
// them before, otherwise the root object reference will point to itself.)
|
|
9074
|
-
// Also note that depth will be 1 for objects in root
|
|
9075
|
-
if (outputRootRef(value, 1)) {
|
|
9838
|
+
if (outputAsRootRef(value, 1)) {
|
|
9076
9839
|
return;
|
|
9077
9840
|
}
|
|
9841
|
+
// handle custom serializers
|
|
9842
|
+
// add to the seen map
|
|
9078
9843
|
if (isPropsProxy(value)) {
|
|
9079
9844
|
const varProps = value[_VAR_PROPS];
|
|
9080
9845
|
const constProps = value[_CONST_PROPS];
|
|
@@ -9083,10 +9848,10 @@ async function serialize(serializationContext) {
|
|
|
9083
9848
|
: Object.keys(varProps).length
|
|
9084
9849
|
? [varProps]
|
|
9085
9850
|
: 0;
|
|
9086
|
-
output(
|
|
9851
|
+
output(32 /* TypeIds.PropsProxy */, out);
|
|
9087
9852
|
}
|
|
9088
9853
|
else if (value instanceof SubscriptionData) {
|
|
9089
|
-
output(
|
|
9854
|
+
output(33 /* TypeIds.SubscriptionData */, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
|
|
9090
9855
|
}
|
|
9091
9856
|
else if (isStore(value)) {
|
|
9092
9857
|
if (isResource(value)) {
|
|
@@ -9094,38 +9859,38 @@ async function serialize(serializationContext) {
|
|
|
9094
9859
|
serializationContext.$resources$.add(value);
|
|
9095
9860
|
// TODO the effects include the resource return which has duplicate data
|
|
9096
9861
|
const forwardRefId = $resolvePromise$(value.value, $addRoot$, (resolved, resolvedValue) => {
|
|
9097
|
-
return new PromiseResult(
|
|
9862
|
+
return new PromiseResult(22 /* TypeIds.Resource */, resolved, resolvedValue, getStoreHandler(value).$effects$);
|
|
9098
9863
|
});
|
|
9099
|
-
output(
|
|
9864
|
+
output(2 /* TypeIds.ForwardRef */, forwardRefId);
|
|
9100
9865
|
}
|
|
9101
9866
|
else {
|
|
9102
9867
|
const storeHandler = getStoreHandler(value);
|
|
9103
9868
|
const storeTarget = getStoreTarget(value);
|
|
9104
9869
|
const flags = storeHandler.$flags$;
|
|
9105
9870
|
const effects = storeHandler.$effects$;
|
|
9871
|
+
// We need to retain the nested stores too, they won't be found from the target
|
|
9106
9872
|
const innerStores = [];
|
|
9107
9873
|
for (const prop in storeTarget) {
|
|
9108
9874
|
const propValue = storeTarget[prop];
|
|
9109
|
-
|
|
9110
|
-
|
|
9875
|
+
const innerStore = $storeProxyMap$.get(propValue);
|
|
9876
|
+
if (innerStore) {
|
|
9111
9877
|
innerStores.push(innerStore);
|
|
9112
|
-
serializationContext.$addRoot$(innerStore);
|
|
9113
9878
|
}
|
|
9114
9879
|
}
|
|
9115
9880
|
const out = [storeTarget, flags, effects, ...innerStores];
|
|
9116
9881
|
while (out[out.length - 1] == null) {
|
|
9117
9882
|
out.pop();
|
|
9118
9883
|
}
|
|
9119
|
-
output(
|
|
9884
|
+
output(29 /* TypeIds.Store */, out);
|
|
9120
9885
|
}
|
|
9121
9886
|
}
|
|
9122
9887
|
else if (isSerializerObj(value)) {
|
|
9123
9888
|
const result = value[SerializerSymbol](value);
|
|
9124
9889
|
if (isPromise(result)) {
|
|
9125
9890
|
const forwardRef = $resolvePromise$(result, $addRoot$, (resolved, resolvedValue) => {
|
|
9126
|
-
return new PromiseResult(
|
|
9891
|
+
return new PromiseResult(28 /* TypeIds.SerializerSignal */, resolved, resolvedValue, null, null);
|
|
9127
9892
|
});
|
|
9128
|
-
output(
|
|
9893
|
+
output(2 /* TypeIds.ForwardRef */, forwardRef);
|
|
9129
9894
|
}
|
|
9130
9895
|
else {
|
|
9131
9896
|
depth--;
|
|
@@ -9135,7 +9900,7 @@ async function serialize(serializationContext) {
|
|
|
9135
9900
|
}
|
|
9136
9901
|
else if (isObjectLiteral(value)) {
|
|
9137
9902
|
if (Array.isArray(value)) {
|
|
9138
|
-
output(
|
|
9903
|
+
output(4 /* TypeIds.Array */, value);
|
|
9139
9904
|
}
|
|
9140
9905
|
else {
|
|
9141
9906
|
const out = [];
|
|
@@ -9146,32 +9911,24 @@ async function serialize(serializationContext) {
|
|
|
9146
9911
|
}
|
|
9147
9912
|
}
|
|
9148
9913
|
// TODO if !out.length, output 0 and restore as {}
|
|
9149
|
-
output(
|
|
9914
|
+
output(5 /* TypeIds.Object */, out);
|
|
9150
9915
|
}
|
|
9151
9916
|
}
|
|
9152
9917
|
else if ($isDomRef$(value)) {
|
|
9153
9918
|
value.$ssrNode$.vnodeData[0] |= 16 /* VNodeDataFlag.SERIALIZE */;
|
|
9154
|
-
output(
|
|
9919
|
+
output(10 /* TypeIds.RefVNode */, value.$ssrNode$.id);
|
|
9155
9920
|
}
|
|
9156
9921
|
else if (value instanceof SignalImpl) {
|
|
9157
9922
|
if (value instanceof SerializerSignalImpl) {
|
|
9158
9923
|
addPreloadQrl(value.$computeQrl$);
|
|
9159
9924
|
const forwardRefId = $resolvePromise$($getCustomSerializerPromise$(value, value.$untrackedValue$), $addRoot$, (resolved, resolvedValue) => {
|
|
9160
|
-
return new PromiseResult(
|
|
9925
|
+
return new PromiseResult(28 /* TypeIds.SerializerSignal */, resolved, resolvedValue, value.$effects$, value.$computeQrl$);
|
|
9161
9926
|
});
|
|
9162
|
-
output(
|
|
9927
|
+
output(2 /* TypeIds.ForwardRef */, forwardRefId);
|
|
9163
9928
|
return;
|
|
9164
9929
|
}
|
|
9165
|
-
/**
|
|
9166
|
-
* Special case: when a Signal value is an SSRNode, it always needs to be a DOM ref instead.
|
|
9167
|
-
* It can never be meant to become a vNode, because vNodes are internal only.
|
|
9168
|
-
*/
|
|
9169
|
-
const v = value instanceof ComputedSignalImpl &&
|
|
9170
|
-
(value.$flags$ & 1 /* SignalFlags.INVALID */ || fastSkipSerialize(value.$untrackedValue$))
|
|
9171
|
-
? NEEDS_COMPUTATION
|
|
9172
|
-
: value.$untrackedValue$;
|
|
9173
9930
|
if (value instanceof WrappedSignalImpl) {
|
|
9174
|
-
output(
|
|
9931
|
+
output(25 /* TypeIds.WrappedSignal */, [
|
|
9175
9932
|
...serializeWrappingFn(serializationContext, value),
|
|
9176
9933
|
filterEffectBackRefs(value[_EFFECT_BACK_REF]),
|
|
9177
9934
|
value.$flags$,
|
|
@@ -9179,45 +9936,44 @@ async function serialize(serializationContext) {
|
|
|
9179
9936
|
...(value.$effects$ || []),
|
|
9180
9937
|
]);
|
|
9181
9938
|
}
|
|
9182
|
-
else if (value instanceof AsyncComputedSignalImpl) {
|
|
9183
|
-
addPreloadQrl(value.$computeQrl$);
|
|
9184
|
-
const out = [
|
|
9185
|
-
value.$computeQrl$,
|
|
9186
|
-
value.$effects$,
|
|
9187
|
-
value.$loadingEffects$,
|
|
9188
|
-
value.$errorEffects$,
|
|
9189
|
-
value.$untrackedLoading$,
|
|
9190
|
-
value.$untrackedError$,
|
|
9191
|
-
];
|
|
9192
|
-
if (v !== NEEDS_COMPUTATION) {
|
|
9193
|
-
out.push(v);
|
|
9194
|
-
}
|
|
9195
|
-
output(28 /* TypeIds.AsyncComputedSignal */, out);
|
|
9196
|
-
}
|
|
9197
9939
|
else if (value instanceof ComputedSignalImpl) {
|
|
9940
|
+
let v = value.$untrackedValue$;
|
|
9941
|
+
const shouldAlwaysSerialize = value.$flags$ & 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
|
|
9942
|
+
const shouldNeverSerialize = value.$flags$ & 16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
|
|
9943
|
+
const isInvalid = value.$flags$ & 1 /* SignalFlags.INVALID */;
|
|
9944
|
+
const isSkippable = fastSkipSerialize(value.$untrackedValue$);
|
|
9945
|
+
if (shouldAlwaysSerialize) {
|
|
9946
|
+
v = value.$untrackedValue$;
|
|
9947
|
+
}
|
|
9948
|
+
else if (shouldNeverSerialize) {
|
|
9949
|
+
v = NEEDS_COMPUTATION;
|
|
9950
|
+
}
|
|
9951
|
+
else if (isInvalid || isSkippable) {
|
|
9952
|
+
v = NEEDS_COMPUTATION;
|
|
9953
|
+
}
|
|
9198
9954
|
addPreloadQrl(value.$computeQrl$);
|
|
9199
|
-
const out = [
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
value.$
|
|
9203
|
-
|
|
9955
|
+
const out = [value.$computeQrl$, value.$effects$];
|
|
9956
|
+
const isAsync = value instanceof AsyncComputedSignalImpl;
|
|
9957
|
+
if (isAsync) {
|
|
9958
|
+
out.push(value.$loadingEffects$, value.$errorEffects$, value.$untrackedLoading$, value.$untrackedError$);
|
|
9959
|
+
}
|
|
9204
9960
|
if (v !== NEEDS_COMPUTATION) {
|
|
9205
9961
|
out.push(v);
|
|
9206
9962
|
}
|
|
9207
|
-
output(27 /* TypeIds.ComputedSignal */, out);
|
|
9963
|
+
output(isAsync ? 27 /* TypeIds.AsyncComputedSignal */ : 26 /* TypeIds.ComputedSignal */, out);
|
|
9208
9964
|
}
|
|
9209
9965
|
else {
|
|
9210
|
-
output(
|
|
9966
|
+
output(24 /* TypeIds.Signal */, [value.$untrackedValue$, ...(value.$effects$ || [])]);
|
|
9211
9967
|
}
|
|
9212
9968
|
}
|
|
9213
9969
|
else if (value instanceof URL) {
|
|
9214
|
-
output(
|
|
9970
|
+
output(6 /* TypeIds.URL */, value.href);
|
|
9215
9971
|
}
|
|
9216
9972
|
else if (value instanceof Date) {
|
|
9217
|
-
output(
|
|
9973
|
+
output(7 /* TypeIds.Date */, Number.isNaN(value.valueOf()) ? '' : value.valueOf());
|
|
9218
9974
|
}
|
|
9219
9975
|
else if (value instanceof RegExp) {
|
|
9220
|
-
output(
|
|
9976
|
+
output(8 /* TypeIds.Regex */, value.toString());
|
|
9221
9977
|
}
|
|
9222
9978
|
else if (value instanceof Error) {
|
|
9223
9979
|
const out = [value.message];
|
|
@@ -9233,7 +9989,7 @@ async function serialize(serializationContext) {
|
|
|
9233
9989
|
const rootIndex = $addRoot$(value);
|
|
9234
9990
|
serializationContext.$setProp$(value, ELEMENT_ID, String(rootIndex));
|
|
9235
9991
|
// we need to output before the vnode overwrites its values
|
|
9236
|
-
output(
|
|
9992
|
+
output(9 /* TypeIds.VNode */, value.id);
|
|
9237
9993
|
const vNodeData = value.vnodeData;
|
|
9238
9994
|
if (vNodeData) {
|
|
9239
9995
|
discoverValuesForVNodeData(vNodeData, (vNodeDataValue) => $addRoot$(vNodeDataValue));
|
|
@@ -9269,23 +10025,23 @@ async function serialize(serializationContext) {
|
|
|
9269
10025
|
array.push(key, value.name);
|
|
9270
10026
|
}
|
|
9271
10027
|
});
|
|
9272
|
-
output(
|
|
10028
|
+
output(30 /* TypeIds.FormData */, array);
|
|
9273
10029
|
}
|
|
9274
10030
|
else if (value instanceof URLSearchParams) {
|
|
9275
|
-
output(
|
|
10031
|
+
output(12 /* TypeIds.URLSearchParams */, value.toString());
|
|
9276
10032
|
}
|
|
9277
10033
|
else if (value instanceof Set) {
|
|
9278
|
-
output(
|
|
10034
|
+
output(16 /* TypeIds.Set */, [...value.values()]);
|
|
9279
10035
|
}
|
|
9280
10036
|
else if (value instanceof Map) {
|
|
9281
10037
|
const combined = [];
|
|
9282
10038
|
for (const [k, v] of value.entries()) {
|
|
9283
10039
|
combined.push(k, v);
|
|
9284
10040
|
}
|
|
9285
|
-
output(
|
|
10041
|
+
output(17 /* TypeIds.Map */, combined);
|
|
9286
10042
|
}
|
|
9287
10043
|
else if (isJSXNode(value)) {
|
|
9288
|
-
output(
|
|
10044
|
+
output(31 /* TypeIds.JSXNode */, [
|
|
9289
10045
|
value.type,
|
|
9290
10046
|
value.varProps,
|
|
9291
10047
|
value.constProps,
|
|
@@ -9306,21 +10062,21 @@ async function serialize(serializationContext) {
|
|
|
9306
10062
|
while (out[out.length - 1] == null) {
|
|
9307
10063
|
out.pop();
|
|
9308
10064
|
}
|
|
9309
|
-
output(
|
|
10065
|
+
output(21 /* TypeIds.Task */, out);
|
|
9310
10066
|
}
|
|
9311
10067
|
else if (isPromise(value)) {
|
|
9312
10068
|
const forwardRefId = $resolvePromise$(value, $addRoot$, (resolved, resolvedValue) => {
|
|
9313
|
-
return new PromiseResult(
|
|
10069
|
+
return new PromiseResult(15 /* TypeIds.Promise */, resolved, resolvedValue);
|
|
9314
10070
|
});
|
|
9315
|
-
output(
|
|
10071
|
+
output(2 /* TypeIds.ForwardRef */, forwardRefId);
|
|
9316
10072
|
}
|
|
9317
10073
|
else if (value instanceof PromiseResult) {
|
|
9318
|
-
if (value.$type$ ===
|
|
9319
|
-
output(
|
|
10074
|
+
if (value.$type$ === 22 /* TypeIds.Resource */) {
|
|
10075
|
+
output(22 /* TypeIds.Resource */, [value.$resolved$, value.$value$, value.$effects$]);
|
|
9320
10076
|
}
|
|
9321
|
-
else if (value.$type$ ===
|
|
10077
|
+
else if (value.$type$ === 28 /* TypeIds.SerializerSignal */) {
|
|
9322
10078
|
if (value.$qrl$) {
|
|
9323
|
-
output(
|
|
10079
|
+
output(28 /* TypeIds.SerializerSignal */, [value.$qrl$, value.$effects$, value.$value$]);
|
|
9324
10080
|
}
|
|
9325
10081
|
else if (value.$resolved$) {
|
|
9326
10082
|
writeValue(value.$value$);
|
|
@@ -9331,7 +10087,7 @@ async function serialize(serializationContext) {
|
|
|
9331
10087
|
}
|
|
9332
10088
|
}
|
|
9333
10089
|
else {
|
|
9334
|
-
output(
|
|
10090
|
+
output(15 /* TypeIds.Promise */, [value.$resolved$, value.$value$]);
|
|
9335
10091
|
}
|
|
9336
10092
|
}
|
|
9337
10093
|
else if (value instanceof Uint8Array) {
|
|
@@ -9340,7 +10096,13 @@ async function serialize(serializationContext) {
|
|
|
9340
10096
|
buf += String.fromCharCode(c);
|
|
9341
10097
|
}
|
|
9342
10098
|
const out = btoa(buf).replace(/=+$/, '');
|
|
9343
|
-
output(
|
|
10099
|
+
output(18 /* TypeIds.Uint8Array */, out);
|
|
10100
|
+
}
|
|
10101
|
+
else if (value instanceof SerializationWeakRef) {
|
|
10102
|
+
const forwardRefId = forwardRefsId++;
|
|
10103
|
+
s11nWeakRefs.set(value.$obj$, forwardRefId);
|
|
10104
|
+
forwardRefs[forwardRefId] = -1;
|
|
10105
|
+
output(2 /* TypeIds.ForwardRef */, forwardRefId);
|
|
9344
10106
|
}
|
|
9345
10107
|
else if (vnode_isVNode(value)) {
|
|
9346
10108
|
output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
|
|
@@ -9365,21 +10127,20 @@ async function serialize(serializationContext) {
|
|
|
9365
10127
|
}
|
|
9366
10128
|
const outputRoots = async () => {
|
|
9367
10129
|
$writer$.write('[');
|
|
9368
|
-
let lastRootsLength = 0;
|
|
9369
10130
|
let rootsLength = serializationContext.$roots$.length;
|
|
9370
|
-
while (
|
|
9371
|
-
if (
|
|
10131
|
+
while (rootIdx < rootsLength || promises.size) {
|
|
10132
|
+
if (rootIdx !== 0) {
|
|
9372
10133
|
$writer$.write(',');
|
|
9373
10134
|
}
|
|
9374
10135
|
let separator = false;
|
|
9375
|
-
for (
|
|
10136
|
+
for (; rootIdx < rootsLength; rootIdx++) {
|
|
9376
10137
|
if (separator) {
|
|
9377
10138
|
$writer$.write(',');
|
|
9378
10139
|
}
|
|
9379
10140
|
else {
|
|
9380
10141
|
separator = true;
|
|
9381
10142
|
}
|
|
9382
|
-
writeValue(serializationContext.$roots$[
|
|
10143
|
+
writeValue(serializationContext.$roots$[rootIdx]);
|
|
9383
10144
|
}
|
|
9384
10145
|
if (promises.size) {
|
|
9385
10146
|
try {
|
|
@@ -9389,12 +10150,11 @@ async function serialize(serializationContext) {
|
|
|
9389
10150
|
// ignore rejections, they will be serialized as rejected promises
|
|
9390
10151
|
}
|
|
9391
10152
|
}
|
|
9392
|
-
lastRootsLength = rootsLength;
|
|
9393
10153
|
rootsLength = serializationContext.$roots$.length;
|
|
9394
10154
|
}
|
|
9395
10155
|
if (forwardRefs.length) {
|
|
9396
10156
|
$writer$.write(',');
|
|
9397
|
-
$writer$.write(
|
|
10157
|
+
$writer$.write(13 /* TypeIds.ForwardRefs */ + ',');
|
|
9398
10158
|
outputArray(forwardRefs, (value) => {
|
|
9399
10159
|
$writer$.write(String(value));
|
|
9400
10160
|
});
|
|
@@ -9543,12 +10303,12 @@ function _deserialize(rawStateData, element) {
|
|
|
9543
10303
|
return output;
|
|
9544
10304
|
}
|
|
9545
10305
|
function deserializeData(container, typeId, value) {
|
|
9546
|
-
if (typeId ===
|
|
10306
|
+
if (typeId === 0 /* TypeIds.Plain */) {
|
|
9547
10307
|
return value;
|
|
9548
10308
|
}
|
|
9549
|
-
|
|
9550
|
-
if (typeId
|
|
9551
|
-
|
|
10309
|
+
const propValue = allocate(container, typeId, value);
|
|
10310
|
+
if (needsInflation(typeId)) {
|
|
10311
|
+
inflate(container, propValue, typeId, value);
|
|
9552
10312
|
}
|
|
9553
10313
|
return propValue;
|
|
9554
10314
|
}
|
|
@@ -9571,7 +10331,7 @@ function _createDeserializeContainer(stateData, element) {
|
|
|
9571
10331
|
$storeProxyMap$: new WeakMap(),
|
|
9572
10332
|
element: null,
|
|
9573
10333
|
$forwardRefs$: null,
|
|
9574
|
-
$
|
|
10334
|
+
$initialQRLs$: null,
|
|
9575
10335
|
$scheduler$: null,
|
|
9576
10336
|
};
|
|
9577
10337
|
preprocessState(stateData, container);
|
|
@@ -9631,18 +10391,18 @@ function _createDeserializeContainer(stateData, element) {
|
|
|
9631
10391
|
*/
|
|
9632
10392
|
function preprocessState(data, container) {
|
|
9633
10393
|
const isRootDeepRef = (type, value) => {
|
|
9634
|
-
return type ===
|
|
10394
|
+
return type === 1 /* TypeIds.RootRef */ && typeof value === 'string';
|
|
9635
10395
|
};
|
|
9636
10396
|
const isForwardRefsMap = (type) => {
|
|
9637
|
-
return type ===
|
|
10397
|
+
return type === 13 /* TypeIds.ForwardRefs */;
|
|
9638
10398
|
};
|
|
9639
10399
|
const isPreloadQrlType = (type) => {
|
|
9640
|
-
return type ===
|
|
10400
|
+
return type === 20 /* TypeIds.PreloadQRL */;
|
|
9641
10401
|
};
|
|
9642
10402
|
const processRootRef = (index) => {
|
|
9643
10403
|
const rootRefPath = data[index + 1].split(' ');
|
|
9644
10404
|
let object = data;
|
|
9645
|
-
let objectType =
|
|
10405
|
+
let objectType = 1 /* TypeIds.RootRef */;
|
|
9646
10406
|
let typeIndex = 0;
|
|
9647
10407
|
let valueIndex = 0;
|
|
9648
10408
|
let parent = null;
|
|
@@ -9652,7 +10412,7 @@ function preprocessState(data, container) {
|
|
|
9652
10412
|
valueIndex = typeIndex + 1;
|
|
9653
10413
|
objectType = object[typeIndex];
|
|
9654
10414
|
object = object[valueIndex];
|
|
9655
|
-
if (objectType ===
|
|
10415
|
+
if (objectType === 1 /* TypeIds.RootRef */) {
|
|
9656
10416
|
const rootRef = object;
|
|
9657
10417
|
const rootRefTypeIndex = rootRef * 2;
|
|
9658
10418
|
objectType = data[rootRefTypeIndex];
|
|
@@ -9660,7 +10420,7 @@ function preprocessState(data, container) {
|
|
|
9660
10420
|
}
|
|
9661
10421
|
}
|
|
9662
10422
|
if (parent) {
|
|
9663
|
-
parent[typeIndex] =
|
|
10423
|
+
parent[typeIndex] = 1 /* TypeIds.RootRef */;
|
|
9664
10424
|
parent[valueIndex] = index / 2;
|
|
9665
10425
|
}
|
|
9666
10426
|
data[index] = objectType;
|
|
@@ -9674,8 +10434,8 @@ function preprocessState(data, container) {
|
|
|
9674
10434
|
container.$forwardRefs$ = data[i + 1];
|
|
9675
10435
|
}
|
|
9676
10436
|
else if (isPreloadQrlType(data[i])) {
|
|
9677
|
-
|
|
9678
|
-
container.$
|
|
10437
|
+
const qrl = data[i + 1];
|
|
10438
|
+
(container.$initialQRLs$ ||= []).push(qrl);
|
|
9679
10439
|
}
|
|
9680
10440
|
}
|
|
9681
10441
|
}
|
|
@@ -9695,7 +10455,7 @@ function shouldTrackObj(obj) {
|
|
|
9695
10455
|
return (
|
|
9696
10456
|
// THINK: Not sure if we need to keep track of functions (QRLs) Let's skip them for now.
|
|
9697
10457
|
// and see if we have a test case which requires them.
|
|
9698
|
-
(
|
|
10458
|
+
isObject(obj) ||
|
|
9699
10459
|
/**
|
|
9700
10460
|
* We track all strings greater than 1 character, because those take at least 6 bytes to encode
|
|
9701
10461
|
* and even with 999 root objects it saves one byte per reference. Tracking more objects makes
|
|
@@ -9723,9 +10483,7 @@ function isResource(value) {
|
|
|
9723
10483
|
return '__brand' in value && value.__brand === 'resource';
|
|
9724
10484
|
}
|
|
9725
10485
|
const frameworkType = (obj) => {
|
|
9726
|
-
return ((
|
|
9727
|
-
obj !== null &&
|
|
9728
|
-
(obj instanceof SignalImpl || obj instanceof Task || isJSXNode(obj))) ||
|
|
10486
|
+
return ((isObject(obj) && (obj instanceof SignalImpl || obj instanceof Task || isJSXNode(obj))) ||
|
|
9729
10487
|
isQrl(obj));
|
|
9730
10488
|
};
|
|
9731
10489
|
const canSerialize = (value, seen = new WeakSet()) => {
|
|
@@ -9811,17 +10569,19 @@ const canSerialize = (value, seen = new WeakSet()) => {
|
|
|
9811
10569
|
return true;
|
|
9812
10570
|
}
|
|
9813
10571
|
}
|
|
10572
|
+
else if (value === _UNINITIALIZED) {
|
|
10573
|
+
return true;
|
|
10574
|
+
}
|
|
9814
10575
|
return false;
|
|
9815
10576
|
};
|
|
9816
10577
|
const QRL_RUNTIME_CHUNK = 'mock-chunk';
|
|
9817
10578
|
const _typeIdNames = [
|
|
10579
|
+
'Plain',
|
|
9818
10580
|
'RootRef',
|
|
9819
10581
|
'ForwardRef',
|
|
9820
|
-
'ForwardRefs',
|
|
9821
10582
|
'Constant',
|
|
9822
|
-
'Number',
|
|
9823
|
-
'String',
|
|
9824
10583
|
'Array',
|
|
10584
|
+
'Object',
|
|
9825
10585
|
'URL',
|
|
9826
10586
|
'Date',
|
|
9827
10587
|
'Regex',
|
|
@@ -9829,8 +10589,8 @@ const _typeIdNames = [
|
|
|
9829
10589
|
'RefVNode',
|
|
9830
10590
|
'BigInt',
|
|
9831
10591
|
'URLSearchParams',
|
|
10592
|
+
'ForwardRefs',
|
|
9832
10593
|
'Error',
|
|
9833
|
-
'Object',
|
|
9834
10594
|
'Promise',
|
|
9835
10595
|
'Set',
|
|
9836
10596
|
'Map',
|
|
@@ -9846,16 +10606,15 @@ const _typeIdNames = [
|
|
|
9846
10606
|
'AsyncComputedSignal',
|
|
9847
10607
|
'SerializerSignal',
|
|
9848
10608
|
'Store',
|
|
9849
|
-
'StoreArray',
|
|
9850
10609
|
'FormData',
|
|
9851
10610
|
'JSXNode',
|
|
9852
10611
|
'PropsProxy',
|
|
9853
|
-
'
|
|
10612
|
+
'SubscriptionData',
|
|
9854
10613
|
];
|
|
9855
10614
|
const circularProofJson = (obj, indent) => {
|
|
9856
10615
|
const seen = new WeakSet();
|
|
9857
|
-
return JSON.stringify(obj, (
|
|
9858
|
-
if (
|
|
10616
|
+
return JSON.stringify(obj, (_, value) => {
|
|
10617
|
+
if (isObject(value)) {
|
|
9859
10618
|
if (seen.has(value)) {
|
|
9860
10619
|
return `[Circular ${value.constructor.name}]`;
|
|
9861
10620
|
}
|
|
@@ -9890,9 +10649,15 @@ const dumpState = (state, color = false, prefix = '', limit = 20) => {
|
|
|
9890
10649
|
}
|
|
9891
10650
|
const key = state[i];
|
|
9892
10651
|
let value = state[++i];
|
|
9893
|
-
if (key ===
|
|
9894
|
-
|
|
9895
|
-
|
|
10652
|
+
if (key === 0 /* TypeIds.Plain */) {
|
|
10653
|
+
const isRaw = typeof value !== 'number' && typeof value !== 'string';
|
|
10654
|
+
if (isRaw) {
|
|
10655
|
+
hasRaw = true;
|
|
10656
|
+
}
|
|
10657
|
+
const type = isRaw
|
|
10658
|
+
? `[raw${isObject(value) ? ` ${value.constructor.name}` : ''}]`
|
|
10659
|
+
: typeIdToName(key);
|
|
10660
|
+
out.push(`${RED}${type}${RESET} ${printRaw(value, `${prefix} `)}`);
|
|
9896
10661
|
}
|
|
9897
10662
|
else {
|
|
9898
10663
|
if (key === 3 /* TypeIds.Constant */) {
|
|
@@ -9904,7 +10669,7 @@ const dumpState = (state, color = false, prefix = '', limit = 20) => {
|
|
|
9904
10669
|
value = value.slice(0, 120) + '"...';
|
|
9905
10670
|
}
|
|
9906
10671
|
}
|
|
9907
|
-
else if (key ===
|
|
10672
|
+
else if (key === 13 /* TypeIds.ForwardRefs */) {
|
|
9908
10673
|
value = '[' + `\n${prefix} ${value.join(`\n${prefix} `)}\n${prefix}]`;
|
|
9909
10674
|
}
|
|
9910
10675
|
else if (Array.isArray(value)) {
|
|
@@ -10006,7 +10771,6 @@ const _verifySerializable = (value, seen, ctx, preMessage) => {
|
|
|
10006
10771
|
return value;
|
|
10007
10772
|
};
|
|
10008
10773
|
const noSerializeSet = /*#__PURE__*/ new WeakSet();
|
|
10009
|
-
const weakSerializeSet = /*#__PURE__*/ new WeakSet();
|
|
10010
10774
|
const shouldSerialize = (obj) => {
|
|
10011
10775
|
if (isObject(obj) || isFunction(obj)) {
|
|
10012
10776
|
return !noSerializeSet.has(obj);
|
|
@@ -10015,7 +10779,7 @@ const shouldSerialize = (obj) => {
|
|
|
10015
10779
|
};
|
|
10016
10780
|
const fastSkipSerialize = (obj) => {
|
|
10017
10781
|
return (obj &&
|
|
10018
|
-
(
|
|
10782
|
+
(isObject(obj) || typeof obj === 'function') &&
|
|
10019
10783
|
(NoSerializeSymbol in obj || noSerializeSet.has(obj)));
|
|
10020
10784
|
};
|
|
10021
10785
|
// <docs markdown="../../readme.md#noSerialize">
|
|
@@ -10040,16 +10804,11 @@ const fastSkipSerialize = (obj) => {
|
|
|
10040
10804
|
// </docs>
|
|
10041
10805
|
const noSerialize = (input) => {
|
|
10042
10806
|
// only add supported values to the noSerializeSet, prevent console errors
|
|
10043
|
-
if ((
|
|
10807
|
+
if ((isObject(input) && input !== null) || typeof input === 'function') {
|
|
10044
10808
|
noSerializeSet.add(input);
|
|
10045
10809
|
}
|
|
10046
10810
|
return input;
|
|
10047
10811
|
};
|
|
10048
|
-
/** @internal */
|
|
10049
|
-
const _weakSerialize = (input) => {
|
|
10050
|
-
weakSerializeSet.add(input);
|
|
10051
|
-
return input;
|
|
10052
|
-
};
|
|
10053
10812
|
/**
|
|
10054
10813
|
* If an object has this property, it will not be serialized. Use this on prototypes to avoid having
|
|
10055
10814
|
* to call `noSerialize()` on every object.
|
|
@@ -10076,6 +10835,7 @@ const NoSerializeSymbol = Symbol('noSerialize');
|
|
|
10076
10835
|
const SerializerSymbol = Symbol('serialize');
|
|
10077
10836
|
|
|
10078
10837
|
// keep these imports above the rest to prevent circular dep issues
|
|
10838
|
+
const resolvedSymbol = Symbol('resolved');
|
|
10079
10839
|
const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef) => {
|
|
10080
10840
|
if (qDev && qSerialize) {
|
|
10081
10841
|
if (captureRef) {
|
|
@@ -10128,9 +10888,6 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef) => {
|
|
|
10128
10888
|
};
|
|
10129
10889
|
return bound;
|
|
10130
10890
|
}
|
|
10131
|
-
const resolveLazy = (containerEl) => {
|
|
10132
|
-
return symbolRef !== null ? symbolRef : resolve(containerEl);
|
|
10133
|
-
};
|
|
10134
10891
|
// Wrap functions to provide their lexical scope
|
|
10135
10892
|
const wrapFn = (fn) => {
|
|
10136
10893
|
if (typeof fn !== 'function' || (!capture?.length && !captureRef?.length)) {
|
|
@@ -10159,45 +10916,58 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef) => {
|
|
|
10159
10916
|
return invoke.call(this, context, fn, ...args);
|
|
10160
10917
|
};
|
|
10161
10918
|
};
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
|
|
10919
|
+
// Retrieve memoized result from symbolFn
|
|
10920
|
+
if (symbolFn && resolvedSymbol in symbolFn) {
|
|
10921
|
+
symbolRef = symbolFn[resolvedSymbol];
|
|
10922
|
+
}
|
|
10923
|
+
const resolve = symbolRef
|
|
10924
|
+
? async () => symbolRef
|
|
10925
|
+
: async (containerEl) => {
|
|
10926
|
+
if (symbolRef !== null) {
|
|
10927
|
+
// Resolving (Promise) or already resolved (value)
|
|
10928
|
+
return symbolRef;
|
|
10929
|
+
}
|
|
10930
|
+
if (containerEl) {
|
|
10931
|
+
setContainer(containerEl);
|
|
10932
|
+
}
|
|
10933
|
+
if (chunk === '') {
|
|
10934
|
+
// Sync QRL
|
|
10935
|
+
assertDefined(_containerEl, 'Sync QRL must have container element');
|
|
10936
|
+
const hash = _containerEl.getAttribute(QInstanceAttr);
|
|
10937
|
+
const doc = _containerEl.ownerDocument;
|
|
10938
|
+
const qFuncs = getQFuncs(doc, hash);
|
|
10939
|
+
// No need to wrap, syncQRLs can't have captured scope
|
|
10940
|
+
return (qrl.resolved = symbolRef = qFuncs[Number(symbol)]);
|
|
10941
|
+
}
|
|
10942
|
+
if (isBrowser && chunk) {
|
|
10943
|
+
/** We run the QRL, so now the probability of the chunk is 100% */
|
|
10944
|
+
p(chunk, 1);
|
|
10945
|
+
}
|
|
10946
|
+
const start = now();
|
|
10947
|
+
const ctx = tryGetInvokeContext();
|
|
10948
|
+
if (symbolFn !== null) {
|
|
10949
|
+
symbolRef = symbolFn().then((module) => {
|
|
10950
|
+
const resolved = wrapFn((symbolRef = module[symbol]));
|
|
10951
|
+
// We memoize the result on the symbolFn
|
|
10952
|
+
symbolFn[resolvedSymbol] = resolved;
|
|
10953
|
+
qrl.resolved = resolved;
|
|
10954
|
+
return resolved;
|
|
10955
|
+
});
|
|
10956
|
+
}
|
|
10957
|
+
else {
|
|
10958
|
+
// TODO cache the imported symbol but watch out for dev mode
|
|
10959
|
+
const imported = getPlatform().importSymbol(_containerEl, chunk, symbol);
|
|
10960
|
+
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = wrapFn((symbolRef = ref))));
|
|
10961
|
+
}
|
|
10962
|
+
if (isPromise(symbolRef)) {
|
|
10963
|
+
symbolRef.then(() => emitUsedSymbol(symbol, ctx?.$element$, start), (err) => {
|
|
10964
|
+
console.error(`qrl ${symbol} failed to load`, err);
|
|
10965
|
+
// We shouldn't cache rejections, we can try again later
|
|
10966
|
+
symbolRef = null;
|
|
10967
|
+
});
|
|
10968
|
+
}
|
|
10165
10969
|
return symbolRef;
|
|
10166
|
-
}
|
|
10167
|
-
if (containerEl) {
|
|
10168
|
-
setContainer(containerEl);
|
|
10169
|
-
}
|
|
10170
|
-
if (chunk === '') {
|
|
10171
|
-
// Sync QRL
|
|
10172
|
-
assertDefined(_containerEl, 'Sync QRL must have container element');
|
|
10173
|
-
const hash = _containerEl.getAttribute(QInstanceAttr);
|
|
10174
|
-
const doc = _containerEl.ownerDocument;
|
|
10175
|
-
const qFuncs = getQFuncs(doc, hash);
|
|
10176
|
-
// No need to wrap, syncQRLs can't have captured scope
|
|
10177
|
-
return (qrl.resolved = symbolRef = qFuncs[Number(symbol)]);
|
|
10178
|
-
}
|
|
10179
|
-
if (isBrowser && chunk) {
|
|
10180
|
-
/** We run the QRL, so now the probability of the chunk is 100% */
|
|
10181
|
-
p(chunk, 1);
|
|
10182
|
-
}
|
|
10183
|
-
const start = now();
|
|
10184
|
-
const ctx = tryGetInvokeContext();
|
|
10185
|
-
if (symbolFn !== null) {
|
|
10186
|
-
symbolRef = symbolFn().then((module) => (qrl.resolved = wrapFn((symbolRef = module[symbol]))));
|
|
10187
|
-
}
|
|
10188
|
-
else {
|
|
10189
|
-
const imported = getPlatform().importSymbol(_containerEl, chunk, symbol);
|
|
10190
|
-
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = wrapFn((symbolRef = ref))));
|
|
10191
|
-
}
|
|
10192
|
-
if (typeof symbolRef === 'object' && isPromise(symbolRef)) {
|
|
10193
|
-
symbolRef.then(() => emitUsedSymbol(symbol, ctx?.$element$, start), (err) => {
|
|
10194
|
-
console.error(`qrl ${symbol} failed to load`, err);
|
|
10195
|
-
// We shouldn't cache rejections, we can try again later
|
|
10196
|
-
symbolRef = null;
|
|
10197
|
-
});
|
|
10198
|
-
}
|
|
10199
|
-
return symbolRef;
|
|
10200
|
-
};
|
|
10970
|
+
};
|
|
10201
10971
|
const createOrReuseInvocationContext = (invoke) => {
|
|
10202
10972
|
if (invoke == null) {
|
|
10203
10973
|
return newInvokeContext();
|
|
@@ -10215,7 +10985,6 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef) => {
|
|
|
10215
10985
|
getHash: () => hash,
|
|
10216
10986
|
getCaptured: () => captureRef,
|
|
10217
10987
|
resolve,
|
|
10218
|
-
$resolveLazy$: resolveLazy,
|
|
10219
10988
|
$setContainer$: setContainer,
|
|
10220
10989
|
$chunk$: chunk,
|
|
10221
10990
|
$symbol$: symbol,
|
|
@@ -10516,7 +11285,7 @@ const render = async (parent, jsxNode, opts = {}) => {
|
|
|
10516
11285
|
container.$serverData$ = opts.serverData || {};
|
|
10517
11286
|
const host = container.rootVNode;
|
|
10518
11287
|
container.$scheduler$(4 /* ChoreType.NODE_DIFF */, host, host, jsxNode);
|
|
10519
|
-
await container.$scheduler$(255 /* ChoreType.
|
|
11288
|
+
await container.$scheduler$(255 /* ChoreType.WAIT_FOR_QUEUE */).$returnValue$;
|
|
10520
11289
|
return {
|
|
10521
11290
|
cleanup: () => {
|
|
10522
11291
|
cleanup(container, container.rootVNode);
|
|
@@ -11056,13 +11825,13 @@ const _useStyles = (styleQrl, transform, scoped) => {
|
|
|
11056
11825
|
const styleId = styleKey(styleQrl, i);
|
|
11057
11826
|
const host = iCtx.$hostElement$;
|
|
11058
11827
|
set(styleId);
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
value.then((val) => iCtx.$container$.$appendStyle$(transform(val, styleId), styleId, host, scoped));
|
|
11062
|
-
throw value;
|
|
11828
|
+
if (styleQrl.resolved) {
|
|
11829
|
+
iCtx.$container$.$appendStyle$(transform(styleQrl.resolved, styleId), styleId, host, scoped);
|
|
11063
11830
|
}
|
|
11064
11831
|
else {
|
|
11065
|
-
|
|
11832
|
+
throw styleQrl
|
|
11833
|
+
.resolve()
|
|
11834
|
+
.then((val) => iCtx.$container$.$appendStyle$(transform(val, styleId), styleId, host, scoped));
|
|
11066
11835
|
}
|
|
11067
11836
|
return styleId;
|
|
11068
11837
|
};
|
|
@@ -11243,13 +12012,13 @@ const useConstant = (value) => {
|
|
|
11243
12012
|
return set(value);
|
|
11244
12013
|
};
|
|
11245
12014
|
|
|
11246
|
-
const useComputedCommon = (qrl,
|
|
12015
|
+
const useComputedCommon = (qrl, createFn, options) => {
|
|
11247
12016
|
const { val, set } = useSequentialScope();
|
|
11248
12017
|
if (val) {
|
|
11249
12018
|
return val;
|
|
11250
12019
|
}
|
|
11251
12020
|
assertQrl(qrl);
|
|
11252
|
-
const signal =
|
|
12021
|
+
const signal = createFn(qrl, options);
|
|
11253
12022
|
set(signal);
|
|
11254
12023
|
// Note that we first save the signal
|
|
11255
12024
|
// and then we throw to load the qrl
|
|
@@ -11258,8 +12027,8 @@ const useComputedCommon = (qrl, Class) => {
|
|
|
11258
12027
|
return signal;
|
|
11259
12028
|
};
|
|
11260
12029
|
/** @internal */
|
|
11261
|
-
const useComputedQrl = (qrl) => {
|
|
11262
|
-
return useComputedCommon(qrl,
|
|
12030
|
+
const useComputedQrl = (qrl, options) => {
|
|
12031
|
+
return useComputedCommon(qrl, createComputedSignal, options);
|
|
11263
12032
|
};
|
|
11264
12033
|
/**
|
|
11265
12034
|
* Creates a computed signal which is calculated from the given function. A computed signal is a
|
|
@@ -11274,7 +12043,7 @@ const useComputedQrl = (qrl) => {
|
|
|
11274
12043
|
const useComputed$ = implicit$FirstArg(useComputedQrl);
|
|
11275
12044
|
|
|
11276
12045
|
/** @internal */
|
|
11277
|
-
const useSerializerQrl = (qrl) => useComputedCommon(qrl,
|
|
12046
|
+
const useSerializerQrl = (qrl) => useComputedCommon(qrl, createSerializerSignal);
|
|
11278
12047
|
/**
|
|
11279
12048
|
* Creates a signal which holds a custom serializable value. It requires that the value implements
|
|
11280
12049
|
* the `CustomSerializable` type, which means having a function under the `[SerializeSymbol]`
|
|
@@ -11353,8 +12122,8 @@ const useVisibleTaskQrl = (qrl, opts) => {
|
|
|
11353
12122
|
set(task);
|
|
11354
12123
|
useRunTask(task, eagerness);
|
|
11355
12124
|
if (!isServerPlatform()) {
|
|
11356
|
-
qrl
|
|
11357
|
-
iCtx.$container$.$scheduler$(
|
|
12125
|
+
qrl.resolve(iCtx.$element$);
|
|
12126
|
+
iCtx.$container$.$scheduler$(16 /* ChoreType.VISIBLE */, task);
|
|
11358
12127
|
}
|
|
11359
12128
|
};
|
|
11360
12129
|
const useRunTask = (task, eagerness) => {
|
|
@@ -11529,8 +12298,8 @@ const useTask$ = /*#__PURE__*/ implicit$FirstArg(useTaskQrl);
|
|
|
11529
12298
|
const useVisibleTask$ = /*#__PURE__*/ implicit$FirstArg(useVisibleTaskQrl);
|
|
11530
12299
|
|
|
11531
12300
|
/** @internal */
|
|
11532
|
-
const useAsyncComputedQrl = (qrl) => {
|
|
11533
|
-
return useComputedCommon(qrl,
|
|
12301
|
+
const useAsyncComputedQrl = (qrl, options) => {
|
|
12302
|
+
return useComputedCommon(qrl, createAsyncComputedSignal, options);
|
|
11534
12303
|
};
|
|
11535
12304
|
/**
|
|
11536
12305
|
* Creates a computed signal which is calculated from the given function. A computed signal is a
|
|
@@ -11583,7 +12352,7 @@ const PrefetchServiceWorker = (opts) => {
|
|
|
11583
12352
|
// the file 'qwik-prefetch-service-worker.js' is not located in /build/
|
|
11584
12353
|
resolvedOpts.path = baseUrl + resolvedOpts.path;
|
|
11585
12354
|
}
|
|
11586
|
-
let code = PREFETCH_CODE.replace("
|
|
12355
|
+
let code = PREFETCH_CODE.replace('"_URL_"', JSON.stringify(resolvedOpts.path.split('/').pop()));
|
|
11587
12356
|
if (!isDev) {
|
|
11588
12357
|
// consecutive spaces are indentation
|
|
11589
12358
|
code = code.replaceAll(/\s\s+/gm, '');
|
|
@@ -11613,6 +12382,17 @@ const PREFETCH_CODE = /*#__PURE__*/ ((c // Service worker container
|
|
|
11613
12382
|
});
|
|
11614
12383
|
});
|
|
11615
12384
|
}
|
|
12385
|
+
if ('caches' in window) {
|
|
12386
|
+
caches
|
|
12387
|
+
.keys()
|
|
12388
|
+
.then((names) => {
|
|
12389
|
+
const cacheName = names.find((name) => name.startsWith('QwikBundles'));
|
|
12390
|
+
if (cacheName) {
|
|
12391
|
+
caches.delete(cacheName).catch(console.error);
|
|
12392
|
+
}
|
|
12393
|
+
})
|
|
12394
|
+
.catch(console.error);
|
|
12395
|
+
}
|
|
11616
12396
|
}).toString();
|
|
11617
12397
|
/**
|
|
11618
12398
|
* @deprecated This is no longer needed as the preloading happens automatically in qrl-class. You
|
|
@@ -11621,5 +12401,15 @@ const PREFETCH_CODE = /*#__PURE__*/ ((c // Service worker container
|
|
|
11621
12401
|
*/
|
|
11622
12402
|
const PrefetchGraph = (_opts = {}) => null;
|
|
11623
12403
|
|
|
11624
|
-
|
|
12404
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
|
12405
|
+
// Protect against duplicate imports
|
|
12406
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
|
12407
|
+
if (globalThis.__qwik) {
|
|
12408
|
+
console.error(`==============================================\n` +
|
|
12409
|
+
`Qwik version ${globalThis.__qwik} already imported while importing ${version}. Verify external vs bundled imports etc. This can lead to issues due to duplicated shared structures.\n` +
|
|
12410
|
+
`==============================================\n`);
|
|
12411
|
+
}
|
|
12412
|
+
globalThis.__qwik = version;
|
|
12413
|
+
|
|
12414
|
+
export { $, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, _UNINITIALIZED, _VAR_PROPS, _deserialize, dumpState as _dumpState, _fnSignal, _getConstProps, _getContextContainer, _getContextElement, _getContextEvent, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, isJSXNode as _isJSXNode, isStore as _isStore, isStringifiable as _isStringifiable, isTask as _isTask, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, mapApp_findIndx as _mapApp_findIndx, mapArray_get as _mapArray_get, mapArray_set as _mapArray_set, _noopQrl, _noopQrlDEV, preprocessState as _preprocessState, _qrlSync, _regSymbol, _resolveContextWithoutSequentialScope, _restProps, _run, _serializationWeakRef, _serialize, scheduleTask as _task, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttr as _vnode_getAttr, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getFirstChild as _vnode_getFirstChild, vnode_getNextSibling as _vnode_getNextSibling, vnode_getPropStartIndex as _vnode_getPropStartIndex, vnode_getProps as _vnode_getProps, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_toString as _vnode_toString, _waitUntilRendered, _walkJSX, _wrapProp, _wrapSignal, component$, componentQrl, createAsyncComputed$, createAsyncComputedSignal as createAsyncComputedQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, forceStoreEffects, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsx as jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsyncComputed$, useAsyncComputedQrl, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
|
|
11625
12415
|
//# sourceMappingURL=core.mjs.map
|