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