@qwik.dev/core 2.0.0-alpha.6 → 2.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bindings/qwik.darwin-arm64.node +0 -0
- package/bindings/qwik.darwin-x64.node +0 -0
- package/bindings/qwik.linux-x64-gnu.node +0 -0
- package/bindings/qwik.win32-x64-msvc.node +0 -0
- package/bindings/qwik_wasm_bg.wasm +0 -0
- package/dist/build/package.json +1 -1
- package/dist/cli.cjs +65 -42
- package/dist/core-internal.d.ts +92 -78
- package/dist/core.cjs +1603 -1374
- package/dist/core.cjs.map +1 -1
- package/dist/core.min.mjs +1 -1
- package/dist/core.mjs +1600 -1374
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.cjs +963 -834
- package/dist/core.prod.mjs +1093 -927
- package/dist/insights/index.qwik.cjs +3679 -167
- package/dist/insights/index.qwik.mjs +3679 -167
- 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 +228 -5715
- package/dist/optimizer.mjs +208 -6038
- package/dist/prefetch/package.json +1 -1
- package/dist/qwikloader.debug.js +12 -15
- package/dist/qwikloader.js +2 -2
- package/dist/server.cjs +787 -7152
- package/dist/server.mjs +805 -7148
- package/dist/starters/adapters/fastify/src/plugins/fastify-qwik.ts +2 -0
- package/dist/starters/features/cypress/package.json +1 -1
- package/dist/starters/features/drizzle/drizzle/schema.ts +6 -18
- package/dist/starters/features/drizzle/drizzle.config.ts +5 -4
- package/dist/starters/features/drizzle/package.json +14 -11
- package/dist/starters/features/pandacss/package.json +1 -1
- package/dist/starters/features/partytown/package.json +1 -1
- package/dist/starters/features/postcss/package.json +1 -1
- package/dist/starters/features/prisma/package.json +1 -1
- package/dist/starters/features/react/package.json +1 -1
- package/dist/starters/features/storybook/package.json +1 -1
- package/dist/starters/features/styled-vanilla-extract/package.json +2 -1
- package/dist/starters/features/tailwind/package.json +15 -9
- package/dist/starters/features/tailwind/src/global.css +1 -7
- package/dist/starters/features/turso/package.json +1 -1
- package/dist/starters/features/vitest/package.json +1 -1
- package/dist/testing/index.cjs +1341 -1180
- package/dist/testing/index.mjs +1354 -1186
- package/dist/testing/package.json +1 -1
- package/handlers.mjs +9 -0
- package/package.json +6 -4
- package/public.d.ts +2 -0
- package/dist/starters/features/tailwind/.vscode/settings.json +0 -3
- package/dist/starters/features/tailwind/postcss.config.cjs +0 -6
- package/dist/starters/features/tailwind/tailwind.config.js +0 -8
package/dist/core.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* @qwik.dev/core 2.0.0-alpha.
|
|
3
|
+
* @qwik.dev/core 2.0.0-alpha.8-dev+66037b5
|
|
4
4
|
* Copyright QwikDev. All Rights Reserved.
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://github.com/QwikDev/qwik/blob/main/LICENSE
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { isDev, isServer } from '@qwik.dev/core/build';
|
|
9
9
|
export { isBrowser, isDev, isServer } from '@qwik.dev/core/build';
|
|
10
10
|
|
|
11
11
|
// same as isDev but separate so we can test
|
|
@@ -118,8 +118,8 @@ const codeToText = (code, ...parts) => {
|
|
|
118
118
|
// Keep one error, one line to make it easier to search for the error message.
|
|
119
119
|
const MAP = [
|
|
120
120
|
'Error while serializing class or style attributes', // 0
|
|
121
|
-
'', // 1
|
|
122
|
-
'', // 2
|
|
121
|
+
'Scheduler not found', // 1
|
|
122
|
+
'track() received object, without prop to track', // 2
|
|
123
123
|
'Only primitive and object literals can be serialized. {{0}}', // 3
|
|
124
124
|
'', // 4 unused
|
|
125
125
|
'You can render over a existing q:container. Skipping render().', // 5
|
|
@@ -162,12 +162,11 @@ const codeToText = (code, ...parts) => {
|
|
|
162
162
|
"Element must have 'q:container' attribute.", // 42
|
|
163
163
|
'Unknown vnode type {{0}}.', // 43
|
|
164
164
|
'Materialize error: missing element: {{0}} {{1}} {{2}}', // 44
|
|
165
|
-
'Cannot coerce a Signal, use `.value` instead', //
|
|
166
|
-
'useComputedSignal$ QRL {{0}} {{1}} returned a Promise', //
|
|
167
|
-
'ComputedSignal is read-only', //
|
|
168
|
-
'WrappedSignal is read-only', //
|
|
169
|
-
'
|
|
170
|
-
'Attribute value is unsafe for SSR', // 51
|
|
165
|
+
'Cannot coerce a Signal, use `.value` instead', // 45
|
|
166
|
+
'useComputedSignal$ QRL {{0}} {{1}} returned a Promise', // 46
|
|
167
|
+
'ComputedSignal is read-only', // 47
|
|
168
|
+
'WrappedSignal is read-only', // 48
|
|
169
|
+
'Attribute value is unsafe for SSR', // 49
|
|
171
170
|
];
|
|
172
171
|
let text = MAP[code] ?? '';
|
|
173
172
|
if (parts.length) {
|
|
@@ -189,8 +188,8 @@ const codeToText = (code, ...parts) => {
|
|
|
189
188
|
var QError;
|
|
190
189
|
(function (QError) {
|
|
191
190
|
QError[QError["stringifyClassOrStyle"] = 0] = "stringifyClassOrStyle";
|
|
192
|
-
QError[QError["
|
|
193
|
-
QError[QError["
|
|
191
|
+
QError[QError["schedulerNotFound"] = 1] = "schedulerNotFound";
|
|
192
|
+
QError[QError["trackObjectWithoutProp"] = 2] = "trackObjectWithoutProp";
|
|
194
193
|
QError[QError["verifySerializable"] = 3] = "verifySerializable";
|
|
195
194
|
QError[QError["UNUSED_4"] = 4] = "UNUSED_4";
|
|
196
195
|
QError[QError["cannotRenderOverExistingContainer"] = 5] = "cannotRenderOverExistingContainer";
|
|
@@ -237,14 +236,37 @@ var QError;
|
|
|
237
236
|
QError[QError["computedNotSync"] = 46] = "computedNotSync";
|
|
238
237
|
QError[QError["computedReadOnly"] = 47] = "computedReadOnly";
|
|
239
238
|
QError[QError["wrappedReadOnly"] = 48] = "wrappedReadOnly";
|
|
240
|
-
QError[QError["
|
|
241
|
-
QError[QError["unsafeAttr"] = 50] = "unsafeAttr";
|
|
239
|
+
QError[QError["unsafeAttr"] = 49] = "unsafeAttr";
|
|
242
240
|
})(QError || (QError = {}));
|
|
243
241
|
const qError = (code, errorMessageArgs = []) => {
|
|
244
242
|
const text = codeToText(code, ...errorMessageArgs);
|
|
245
243
|
return logErrorAndStop(text, ...errorMessageArgs);
|
|
246
244
|
};
|
|
247
245
|
|
|
246
|
+
/** QRL related utilities that you can import without importing all of Qwik. */
|
|
247
|
+
const SYNC_QRL = '<sync>';
|
|
248
|
+
/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
|
|
249
|
+
const isSyncQrl = (value) => {
|
|
250
|
+
return isQrl$1(value) && value.$symbol$ == SYNC_QRL;
|
|
251
|
+
};
|
|
252
|
+
const isQrl$1 = (value) => {
|
|
253
|
+
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
254
|
+
};
|
|
255
|
+
function assertQrl(qrl) {
|
|
256
|
+
if (isDev) {
|
|
257
|
+
if (!isQrl$1(qrl)) {
|
|
258
|
+
throw new Error('Not a QRL');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const getSymbolHash = (symbolName) => {
|
|
263
|
+
const index = symbolName.lastIndexOf('_');
|
|
264
|
+
if (index > -1) {
|
|
265
|
+
return symbolName.slice(index + 1);
|
|
266
|
+
}
|
|
267
|
+
return symbolName;
|
|
268
|
+
};
|
|
269
|
+
|
|
248
270
|
/**
|
|
249
271
|
* A friendly name tag for a VirtualVNode.
|
|
250
272
|
*
|
|
@@ -288,11 +310,10 @@ var QContainerValue;
|
|
|
288
310
|
/** State factory of the component. */
|
|
289
311
|
const OnRenderProp = 'q:renderFn';
|
|
290
312
|
/** Component style content prefix */
|
|
291
|
-
const ComponentStylesPrefixContent = '
|
|
313
|
+
const ComponentStylesPrefixContent = '⚡️';
|
|
292
314
|
/** `<some-element q:slot="...">` */
|
|
293
315
|
const QSlot = 'q:slot';
|
|
294
|
-
const QSlotParent = ':';
|
|
295
|
-
const QSlotRef = 'q:sref';
|
|
316
|
+
const QSlotParent = 'q:sparent';
|
|
296
317
|
const QSlotS = 'q:s';
|
|
297
318
|
const QStyle = 'q:style';
|
|
298
319
|
const QStyleSelector = 'style[q\\:style]';
|
|
@@ -300,7 +321,7 @@ const QStyleSSelector = 'style[q\\:sstyle]';
|
|
|
300
321
|
const QStylesAllSelector = QStyleSelector + ',' + QStyleSSelector;
|
|
301
322
|
const QScopedStyle = 'q:sstyle';
|
|
302
323
|
const QCtxAttr = 'q:ctx';
|
|
303
|
-
const
|
|
324
|
+
const QBackRefs = 'q:brefs';
|
|
304
325
|
const QFuncsPrefix = 'qFuncs_';
|
|
305
326
|
const getQFuncs = (document, hash) => {
|
|
306
327
|
return document[QFuncsPrefix + hash] || [];
|
|
@@ -329,6 +350,7 @@ const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
|
|
|
329
350
|
const ResourceEvent = 'qResource';
|
|
330
351
|
const RenderEvent = 'qRender';
|
|
331
352
|
const TaskEvent = 'qTask';
|
|
353
|
+
/** `<q:slot name="...">` */
|
|
332
354
|
const QDefaultSlot = '';
|
|
333
355
|
/**
|
|
334
356
|
* Attribute to mark that this VNode has a pointer to itself from the `qwik/json` state.
|
|
@@ -496,11 +518,6 @@ const maybeThen = (valueOrPromise, thenFn) => {
|
|
|
496
518
|
? valueOrPromise.then(thenFn, shouldNotError)
|
|
497
519
|
: thenFn(valueOrPromise);
|
|
498
520
|
};
|
|
499
|
-
const maybeThenPassError = (valueOrPromise, thenFn) => {
|
|
500
|
-
return isPromise(valueOrPromise)
|
|
501
|
-
? valueOrPromise.then(thenFn)
|
|
502
|
-
: thenFn(valueOrPromise);
|
|
503
|
-
};
|
|
504
521
|
const shouldNotError = (reason) => {
|
|
505
522
|
throwErrorAndStop(reason);
|
|
506
523
|
};
|
|
@@ -618,7 +635,7 @@ function setLocale(locale) {
|
|
|
618
635
|
_locale = locale;
|
|
619
636
|
}
|
|
620
637
|
|
|
621
|
-
const isQrl
|
|
638
|
+
const isQrl = (value) => {
|
|
622
639
|
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
623
640
|
};
|
|
624
641
|
|
|
@@ -690,21 +707,21 @@ const qrl = (chunkOrFn, symbol, lexicalScopeCapture = EMPTY_ARRAY, stackOffset =
|
|
|
690
707
|
// Emit event
|
|
691
708
|
announcedQRL.add(symbol);
|
|
692
709
|
emitEvent('qprefetch', {
|
|
693
|
-
symbols: [
|
|
710
|
+
symbols: [symbol],
|
|
694
711
|
bundles: chunk && [chunk],
|
|
695
712
|
});
|
|
696
713
|
}
|
|
697
714
|
// Unwrap subscribers
|
|
698
|
-
return createQRL(chunk, symbol, null, symbolFn, null, lexicalScopeCapture
|
|
715
|
+
return createQRL(chunk, symbol, null, symbolFn, null, lexicalScopeCapture);
|
|
699
716
|
};
|
|
700
717
|
/** @internal */
|
|
701
718
|
const inlinedQrl = (symbol, symbolName, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
702
719
|
// Unwrap subscribers
|
|
703
|
-
return createQRL(null, symbolName, symbol, null, null, lexicalScopeCapture
|
|
720
|
+
return createQRL(null, symbolName, symbol, null, null, lexicalScopeCapture);
|
|
704
721
|
};
|
|
705
722
|
/** @internal */
|
|
706
723
|
const _noopQrl = (symbolName, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
707
|
-
return createQRL(null, symbolName, null, null, null, lexicalScopeCapture
|
|
724
|
+
return createQRL(null, symbolName, null, null, null, lexicalScopeCapture);
|
|
708
725
|
};
|
|
709
726
|
/** @internal */
|
|
710
727
|
const _noopQrlDEV = (symbolName, opts, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
@@ -733,6 +750,80 @@ const _regSymbol = (symbol, hash) => {
|
|
|
733
750
|
return symbol;
|
|
734
751
|
};
|
|
735
752
|
|
|
753
|
+
var ChoreType;
|
|
754
|
+
(function (ChoreType) {
|
|
755
|
+
/// MASKS defining three levels of sorting
|
|
756
|
+
ChoreType[ChoreType["MACRO"] = 240] = "MACRO";
|
|
757
|
+
/* order of elements (not encoded here) */
|
|
758
|
+
ChoreType[ChoreType["MICRO"] = 15] = "MICRO";
|
|
759
|
+
/** Ensure that the QRL promise is resolved before processing next chores in the queue */
|
|
760
|
+
ChoreType[ChoreType["QRL_RESOLVE"] = 1] = "QRL_RESOLVE";
|
|
761
|
+
ChoreType[ChoreType["RUN_QRL"] = 2] = "RUN_QRL";
|
|
762
|
+
ChoreType[ChoreType["TASK"] = 3] = "TASK";
|
|
763
|
+
ChoreType[ChoreType["NODE_DIFF"] = 4] = "NODE_DIFF";
|
|
764
|
+
ChoreType[ChoreType["NODE_PROP"] = 5] = "NODE_PROP";
|
|
765
|
+
ChoreType[ChoreType["COMPONENT"] = 6] = "COMPONENT";
|
|
766
|
+
ChoreType[ChoreType["RECOMPUTE_AND_SCHEDULE_EFFECTS"] = 7] = "RECOMPUTE_AND_SCHEDULE_EFFECTS";
|
|
767
|
+
// Next macro level
|
|
768
|
+
ChoreType[ChoreType["JOURNAL_FLUSH"] = 16] = "JOURNAL_FLUSH";
|
|
769
|
+
// Next macro level
|
|
770
|
+
ChoreType[ChoreType["VISIBLE"] = 32] = "VISIBLE";
|
|
771
|
+
// Next macro level
|
|
772
|
+
ChoreType[ChoreType["CLEANUP_VISIBLE"] = 48] = "CLEANUP_VISIBLE";
|
|
773
|
+
// Next macro level
|
|
774
|
+
ChoreType[ChoreType["WAIT_FOR_ALL"] = 255] = "WAIT_FOR_ALL";
|
|
775
|
+
})(ChoreType || (ChoreType = {}));
|
|
776
|
+
|
|
777
|
+
// <docs markdown="../readme.md#useLexicalScope">
|
|
778
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
779
|
+
// (edit ../readme.md#useLexicalScope instead and run `pnpm docs.sync`)
|
|
780
|
+
/**
|
|
781
|
+
* Used by the Qwik Optimizer to restore the lexically scoped variables.
|
|
782
|
+
*
|
|
783
|
+
* This method should not be present in the application source code.
|
|
784
|
+
*
|
|
785
|
+
* NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
|
|
786
|
+
* (before any `await` statements.)
|
|
787
|
+
*
|
|
788
|
+
* @internal
|
|
789
|
+
*/
|
|
790
|
+
// </docs>
|
|
791
|
+
const useLexicalScope = () => {
|
|
792
|
+
const context = getInvokeContext();
|
|
793
|
+
let qrl = context.$qrl$;
|
|
794
|
+
if (!qrl) {
|
|
795
|
+
const el = context.$element$;
|
|
796
|
+
assertDefined(el, 'invoke: element must be defined inside useLexicalScope()', context);
|
|
797
|
+
const containerElement = _getQContainerElement(el);
|
|
798
|
+
assertDefined(containerElement, `invoke: cant find parent q:container of`, el);
|
|
799
|
+
const container = getDomContainer(containerElement);
|
|
800
|
+
qrl = container.parseQRL(decodeURIComponent(String(context.$url$)));
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
assertQrl(qrl);
|
|
804
|
+
assertDefined(qrl.$captureRef$, 'invoke: qrl $captureRef$ must be defined inside useLexicalScope()', qrl);
|
|
805
|
+
}
|
|
806
|
+
return qrl.$captureRef$;
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* This is called by qwik-loader to schedule a QRL. It has to be synchronous.
|
|
811
|
+
*
|
|
812
|
+
* @internal
|
|
813
|
+
*/
|
|
814
|
+
const queueQRL = (...args) => {
|
|
815
|
+
// This will already check container
|
|
816
|
+
const [runQrl] = useLexicalScope();
|
|
817
|
+
const context = getInvokeContext();
|
|
818
|
+
const hostElement = context.$hostElement$;
|
|
819
|
+
const container = getDomContainer(hostElement);
|
|
820
|
+
const scheduler = container.$scheduler$;
|
|
821
|
+
if (!scheduler) {
|
|
822
|
+
throw qError(QError.schedulerNotFound);
|
|
823
|
+
}
|
|
824
|
+
return scheduler(ChoreType.RUN_QRL, hostElement, runQrl, args);
|
|
825
|
+
};
|
|
826
|
+
|
|
736
827
|
/**
|
|
737
828
|
* Allows to project the children of the current component. <Slot/> can only be used within the
|
|
738
829
|
* context of a component defined with `component$`.
|
|
@@ -857,6 +948,47 @@ function isPreventDefault(key) {
|
|
|
857
948
|
return key.startsWith('preventdefault:');
|
|
858
949
|
}
|
|
859
950
|
|
|
951
|
+
function getFileLocationFromJsx(jsxDev) {
|
|
952
|
+
if (!jsxDev) {
|
|
953
|
+
return null;
|
|
954
|
+
}
|
|
955
|
+
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
956
|
+
if (sanitizedFileName) {
|
|
957
|
+
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
958
|
+
}
|
|
959
|
+
return null;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
const styleContent = (styleId) => {
|
|
963
|
+
return ComponentStylesPrefixContent + styleId;
|
|
964
|
+
};
|
|
965
|
+
function hasClassAttr(props) {
|
|
966
|
+
for (const key in props) {
|
|
967
|
+
if (Object.prototype.hasOwnProperty.call(props, key) && isClassAttr(key)) {
|
|
968
|
+
return true;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
function isClassAttr(key) {
|
|
974
|
+
return key === 'class' || key === 'className';
|
|
975
|
+
}
|
|
976
|
+
function convertScopedStyleIdsToArray(scopedStyleIds) {
|
|
977
|
+
return scopedStyleIds?.split(' ') ?? null;
|
|
978
|
+
}
|
|
979
|
+
function convertStyleIdsToString(scopedStyleIds) {
|
|
980
|
+
return Array.from(scopedStyleIds).join(' ');
|
|
981
|
+
}
|
|
982
|
+
const addComponentStylePrefix = (styleId) => {
|
|
983
|
+
if (styleId) {
|
|
984
|
+
let idx = 0;
|
|
985
|
+
do {
|
|
986
|
+
styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
|
|
987
|
+
} while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
|
|
988
|
+
}
|
|
989
|
+
return styleId || null;
|
|
990
|
+
};
|
|
991
|
+
|
|
860
992
|
/** CSS properties which accept numbers but are not in units of "px". */
|
|
861
993
|
const unitlessNumbers = new Set([
|
|
862
994
|
'animationIterationCount',
|
|
@@ -1015,40 +1147,10 @@ const styleKey = (qStyles, index) => {
|
|
|
1015
1147
|
assertQrl(qStyles);
|
|
1016
1148
|
return `${hashCode(qStyles.$hash$)}-${index}`;
|
|
1017
1149
|
};
|
|
1018
|
-
const styleContent = (styleId) => {
|
|
1019
|
-
return ComponentStylesPrefixContent + styleId;
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
|
-
function hasClassAttr(props) {
|
|
1023
|
-
for (const key in props) {
|
|
1024
|
-
if (Object.prototype.hasOwnProperty.call(props, key) && isClassAttr(key)) {
|
|
1025
|
-
return true;
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
return false;
|
|
1029
|
-
}
|
|
1030
|
-
function isClassAttr(key) {
|
|
1031
|
-
return key === 'class' || key === 'className';
|
|
1032
|
-
}
|
|
1033
|
-
function convertScopedStyleIdsToArray(scopedStyleIds) {
|
|
1034
|
-
return scopedStyleIds?.split(' ') ?? null;
|
|
1035
|
-
}
|
|
1036
|
-
function convertStyleIdsToString(scopedStyleIds) {
|
|
1037
|
-
return Array.from(scopedStyleIds).join(' ');
|
|
1038
|
-
}
|
|
1039
|
-
const addComponentStylePrefix = (styleId) => {
|
|
1040
|
-
if (styleId) {
|
|
1041
|
-
let idx = 0;
|
|
1042
|
-
do {
|
|
1043
|
-
styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
|
|
1044
|
-
} while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
|
|
1045
|
-
}
|
|
1046
|
-
return styleId || null;
|
|
1047
|
-
};
|
|
1048
1150
|
|
|
1049
1151
|
const STORE_TARGET = Symbol('store.target');
|
|
1050
1152
|
const STORE_HANDLER = Symbol('store.handler');
|
|
1051
|
-
const
|
|
1153
|
+
const STORE_ALL_PROPS = Symbol('store.all');
|
|
1052
1154
|
var StoreFlags;
|
|
1053
1155
|
(function (StoreFlags) {
|
|
1054
1156
|
StoreFlags[StoreFlags["NONE"] = 0] = "NONE";
|
|
@@ -1123,7 +1225,7 @@ class StoreHandler {
|
|
|
1123
1225
|
}
|
|
1124
1226
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
1125
1227
|
if (effectSubscriber) {
|
|
1126
|
-
|
|
1228
|
+
addStoreEffect(target, Array.isArray(target) ? STORE_ALL_PROPS : prop, this, effectSubscriber);
|
|
1127
1229
|
}
|
|
1128
1230
|
}
|
|
1129
1231
|
if (prop === 'toString' && value === Object.prototype.toString) {
|
|
@@ -1174,7 +1276,7 @@ class StoreHandler {
|
|
|
1174
1276
|
if (ctx) {
|
|
1175
1277
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
1176
1278
|
if (effectSubscriber) {
|
|
1177
|
-
|
|
1279
|
+
addStoreEffect(target, Array.isArray(target) ? STORE_ALL_PROPS : prop, this, effectSubscriber);
|
|
1178
1280
|
}
|
|
1179
1281
|
}
|
|
1180
1282
|
}
|
|
@@ -1184,13 +1286,17 @@ class StoreHandler {
|
|
|
1184
1286
|
const ctx = tryGetInvokeContext();
|
|
1185
1287
|
const effectSubscriber = ctx?.$effectSubscriber$;
|
|
1186
1288
|
if (effectSubscriber) {
|
|
1187
|
-
|
|
1289
|
+
addStoreEffect(target, STORE_ALL_PROPS, this, effectSubscriber);
|
|
1188
1290
|
}
|
|
1189
1291
|
return Reflect.ownKeys(target);
|
|
1190
1292
|
}
|
|
1191
1293
|
getOwnPropertyDescriptor(target, prop) {
|
|
1294
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
1192
1295
|
if (Array.isArray(target) || typeof prop === 'symbol') {
|
|
1193
|
-
return
|
|
1296
|
+
return descriptor;
|
|
1297
|
+
}
|
|
1298
|
+
if (descriptor && !descriptor.configurable) {
|
|
1299
|
+
return descriptor;
|
|
1194
1300
|
}
|
|
1195
1301
|
return {
|
|
1196
1302
|
enumerable: true,
|
|
@@ -1198,355 +1304,280 @@ class StoreHandler {
|
|
|
1198
1304
|
};
|
|
1199
1305
|
}
|
|
1200
1306
|
}
|
|
1201
|
-
function
|
|
1202
|
-
const effectsMap = (store.$effects$ ||=
|
|
1203
|
-
|
|
1204
|
-
|
|
1307
|
+
function addStoreEffect(target, prop, store, effectSubscription) {
|
|
1308
|
+
const effectsMap = (store.$effects$ ||= new Map());
|
|
1309
|
+
let effects = effectsMap.get(prop);
|
|
1310
|
+
if (!effects) {
|
|
1311
|
+
effects = new Set();
|
|
1312
|
+
effectsMap.set(prop, effects);
|
|
1313
|
+
}
|
|
1205
1314
|
// Let's make sure that we have a reference to this effect.
|
|
1206
1315
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
1207
1316
|
// changes we know who to notify.
|
|
1208
|
-
|
|
1317
|
+
ensureContainsSubscription(effects, effectSubscription);
|
|
1209
1318
|
// But when effect is scheduled in needs to be able to know which signals
|
|
1210
1319
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
1211
1320
|
// to this signal.
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
ensureEffectContainsSubscriber(effectSubscriber[EffectSubscriptionsProp.EFFECT], target, store.$container$);
|
|
1321
|
+
ensureContainsBackRef(effectSubscription, target);
|
|
1322
|
+
addQrlToSerializationCtx(effectSubscription, store.$container$);
|
|
1215
1323
|
}
|
|
1216
1324
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
1217
1325
|
target[prop] = value;
|
|
1218
1326
|
triggerEffects(currentStore.$container$, currentStore, getEffects(target, prop, currentStore.$effects$));
|
|
1219
1327
|
}
|
|
1220
1328
|
function getEffects(target, prop, storeEffects) {
|
|
1221
|
-
let effectsToTrigger
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1329
|
+
let effectsToTrigger;
|
|
1330
|
+
if (storeEffects) {
|
|
1331
|
+
if (Array.isArray(target)) {
|
|
1332
|
+
for (const effects of storeEffects.values()) {
|
|
1333
|
+
effectsToTrigger ||= new Set();
|
|
1334
|
+
for (const effect of effects) {
|
|
1335
|
+
effectsToTrigger.add(effect);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
else {
|
|
1340
|
+
effectsToTrigger = storeEffects.get(prop);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
const storeArrayValue = storeEffects?.get(STORE_ALL_PROPS);
|
|
1227
1344
|
if (storeArrayValue) {
|
|
1228
|
-
effectsToTrigger ||=
|
|
1229
|
-
|
|
1345
|
+
effectsToTrigger ||= new Set();
|
|
1346
|
+
for (const effect of storeArrayValue) {
|
|
1347
|
+
effectsToTrigger.add(effect);
|
|
1348
|
+
}
|
|
1230
1349
|
}
|
|
1231
|
-
return effectsToTrigger;
|
|
1350
|
+
return effectsToTrigger || null;
|
|
1232
1351
|
}
|
|
1233
1352
|
|
|
1234
1353
|
/**
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
1354
|
+
* Special value used to mark that a given signal needs to be computed. This is essentially a
|
|
1355
|
+
* "marked as dirty" flag.
|
|
1237
1356
|
*/
|
|
1238
|
-
const
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
const host = hostElement;
|
|
1242
|
-
let seq = iCtx.$container$.getHostProp(host, ELEMENT_SEQ);
|
|
1243
|
-
if (seq === null) {
|
|
1244
|
-
seq = [];
|
|
1245
|
-
iCtx.$container$.setHostProp(host, ELEMENT_SEQ, seq);
|
|
1246
|
-
}
|
|
1247
|
-
let seqIdx = iCtx.$container$.getHostProp(host, ELEMENT_SEQ_IDX);
|
|
1248
|
-
if (seqIdx === null) {
|
|
1249
|
-
seqIdx = 0;
|
|
1250
|
-
}
|
|
1251
|
-
iCtx.$container$.setHostProp(host, ELEMENT_SEQ_IDX, seqIdx + 1);
|
|
1252
|
-
while (seq.length <= seqIdx) {
|
|
1253
|
-
seq.push(undefined);
|
|
1254
|
-
}
|
|
1255
|
-
const set = (value) => {
|
|
1256
|
-
if (qDev && qSerialize) {
|
|
1257
|
-
verifySerializable(value);
|
|
1258
|
-
}
|
|
1259
|
-
return (seq[seqIdx] = value);
|
|
1260
|
-
};
|
|
1261
|
-
return {
|
|
1262
|
-
val: seq[seqIdx],
|
|
1263
|
-
set,
|
|
1264
|
-
i: seqIdx,
|
|
1265
|
-
iCtx,
|
|
1266
|
-
};
|
|
1267
|
-
};
|
|
1357
|
+
const NEEDS_COMPUTATION = Symbol('invalid');
|
|
1358
|
+
/** @internal */
|
|
1359
|
+
const _EFFECT_BACK_REF = Symbol('backRef');
|
|
1268
1360
|
|
|
1269
|
-
|
|
1270
|
-
|
|
1361
|
+
/** Class for back reference to the EffectSubscription */
|
|
1362
|
+
class BackRef {
|
|
1363
|
+
[_EFFECT_BACK_REF] = null;
|
|
1271
1364
|
}
|
|
1272
|
-
function
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
function clearVNodeEffectDependencies(container, value) {
|
|
1276
|
-
if (vnode_isElementVNode(value)) {
|
|
1277
|
-
ensureMaterialized(value);
|
|
1365
|
+
function clearAllEffects(container, consumer) {
|
|
1366
|
+
if (vnode_isVNode(consumer) && vnode_isElementVNode(consumer)) {
|
|
1367
|
+
ensureMaterialized(consumer);
|
|
1278
1368
|
}
|
|
1279
|
-
const effects =
|
|
1369
|
+
const effects = consumer[_EFFECT_BACK_REF];
|
|
1280
1370
|
if (!effects) {
|
|
1281
1371
|
return;
|
|
1282
1372
|
}
|
|
1283
|
-
for (
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
if (effects.length === 0) {
|
|
1288
|
-
vnode_setProp(value, QSubscribers, null);
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
function clearSubscriberEffectDependencies(container, value) {
|
|
1292
|
-
if (value.$effectDependencies$) {
|
|
1293
|
-
for (let i = value.$effectDependencies$.length - 1; i >= 0; i--) {
|
|
1294
|
-
const subscriber = value.$effectDependencies$[i];
|
|
1295
|
-
clearEffects(subscriber, value, value.$effectDependencies$, i, container);
|
|
1296
|
-
}
|
|
1297
|
-
if (value.$effectDependencies$.length === 0) {
|
|
1298
|
-
value.$effectDependencies$ = null;
|
|
1373
|
+
for (const [, effect] of effects) {
|
|
1374
|
+
const backRefs = effect[EffectSubscriptionProp.BACK_REF];
|
|
1375
|
+
if (!backRefs) {
|
|
1376
|
+
return;
|
|
1299
1377
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
let subscriptionRemoved = false;
|
|
1304
|
-
const seenSet = new Set();
|
|
1305
|
-
if (subscriber instanceof WrappedSignal) {
|
|
1306
|
-
subscriptionRemoved = clearSignalEffects(subscriber, value, seenSet);
|
|
1307
|
-
}
|
|
1308
|
-
else if (container.$storeProxyMap$.has(subscriber)) {
|
|
1309
|
-
const store = container.$storeProxyMap$.get(subscriber);
|
|
1310
|
-
const handler = getStoreHandler(store);
|
|
1311
|
-
subscriptionRemoved = clearStoreEffects(handler, value);
|
|
1312
|
-
}
|
|
1313
|
-
if (subscriptionRemoved) {
|
|
1314
|
-
effectArray.splice(indexToRemove, 1);
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
function clearSignalEffects(subscriber, value, seenSet) {
|
|
1318
|
-
const effectSubscriptions = subscriber.$effects$;
|
|
1319
|
-
let subscriptionRemoved = false;
|
|
1320
|
-
if (effectSubscriptions) {
|
|
1321
|
-
for (let i = effectSubscriptions.length - 1; i >= 0; i--) {
|
|
1322
|
-
const effect = effectSubscriptions[i];
|
|
1323
|
-
if (effect[EffectSubscriptionsProp.EFFECT] === value) {
|
|
1324
|
-
effectSubscriptions.splice(i, 1);
|
|
1325
|
-
subscriptionRemoved = true;
|
|
1378
|
+
for (const producer of backRefs) {
|
|
1379
|
+
if (producer instanceof Signal) {
|
|
1380
|
+
clearSignal(container, producer, effect);
|
|
1326
1381
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
if (hostElement && hostElement === value) {
|
|
1332
|
-
subscriber.$hostElement$ = null;
|
|
1333
|
-
}
|
|
1334
|
-
// clear the effects of the arguments
|
|
1335
|
-
const args = subscriber.$args$;
|
|
1336
|
-
if (args) {
|
|
1337
|
-
clearArgsEffects(args, subscriber, seenSet);
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
return subscriptionRemoved;
|
|
1341
|
-
}
|
|
1342
|
-
function clearStoreEffects(storeHandler, value) {
|
|
1343
|
-
const effectSubscriptions = storeHandler.$effects$;
|
|
1344
|
-
if (!effectSubscriptions) {
|
|
1345
|
-
return false;
|
|
1346
|
-
}
|
|
1347
|
-
let subscriptionRemoved = false;
|
|
1348
|
-
for (const key in effectSubscriptions) {
|
|
1349
|
-
const effects = effectSubscriptions[key];
|
|
1350
|
-
for (let i = effects.length - 1; i >= 0; i--) {
|
|
1351
|
-
const effect = effects[i];
|
|
1352
|
-
if (effect[EffectSubscriptionsProp.EFFECT] === value) {
|
|
1353
|
-
effects.splice(i, 1);
|
|
1354
|
-
subscriptionRemoved = true;
|
|
1382
|
+
else if (container.$storeProxyMap$.has(producer)) {
|
|
1383
|
+
const target = container.$storeProxyMap$.get(producer);
|
|
1384
|
+
const storeHandler = getStoreHandler(target);
|
|
1385
|
+
clearStore(storeHandler, effect);
|
|
1355
1386
|
}
|
|
1356
1387
|
}
|
|
1357
|
-
if (effects.length === 0) {
|
|
1358
|
-
delete effectSubscriptions[key];
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
return subscriptionRemoved;
|
|
1362
|
-
}
|
|
1363
|
-
function clearArgsEffects(args, subscriber, seenSet) {
|
|
1364
|
-
for (let i = args.length - 1; i >= 0; i--) {
|
|
1365
|
-
const arg = args[i];
|
|
1366
|
-
clearArgEffect(arg, subscriber, seenSet);
|
|
1367
1388
|
}
|
|
1368
1389
|
}
|
|
1369
|
-
function
|
|
1370
|
-
|
|
1371
|
-
|
|
1390
|
+
function clearSignal(container, producer, effect) {
|
|
1391
|
+
const effects = producer.$effects$;
|
|
1392
|
+
if (effects) {
|
|
1393
|
+
effects.delete(effect);
|
|
1372
1394
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1395
|
+
if (producer instanceof WrappedSignal) {
|
|
1396
|
+
producer.$hostElement$ = null;
|
|
1397
|
+
clearAllEffects(container, producer);
|
|
1376
1398
|
}
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
// To avoid that we need to get the constProps and varProps directly
|
|
1384
|
-
// from the props proxy object and loop over them.
|
|
1385
|
-
const constProps = arg[_CONST_PROPS];
|
|
1386
|
-
const varProps = arg[_VAR_PROPS];
|
|
1387
|
-
if (constProps) {
|
|
1388
|
-
for (const key in constProps) {
|
|
1389
|
-
clearArgEffect(constProps[key], subscriber, seenSet);
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
for (const key in varProps) {
|
|
1393
|
-
clearArgEffect(varProps[key], subscriber, seenSet);
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
else {
|
|
1397
|
-
for (const key in arg) {
|
|
1398
|
-
clearArgEffect(arg[key], subscriber, seenSet);
|
|
1399
|
-
}
|
|
1399
|
+
}
|
|
1400
|
+
function clearStore(producer, effect) {
|
|
1401
|
+
const effects = producer?.$effects$;
|
|
1402
|
+
if (effects) {
|
|
1403
|
+
for (const propEffects of effects.values()) {
|
|
1404
|
+
propEffects.delete(effect);
|
|
1400
1405
|
}
|
|
1401
1406
|
}
|
|
1402
|
-
else if (Array.isArray(arg)) {
|
|
1403
|
-
clearArgsEffects(arg, subscriber, seenSet);
|
|
1404
|
-
}
|
|
1405
|
-
else ;
|
|
1406
1407
|
}
|
|
1407
1408
|
|
|
1408
|
-
|
|
1409
|
-
const useResourceQrl = (qrl, opts) => {
|
|
1410
|
-
const { val, set, i, iCtx } = useSequentialScope();
|
|
1411
|
-
if (val != null) {
|
|
1412
|
-
return val;
|
|
1413
|
-
}
|
|
1414
|
-
assertQrl(qrl);
|
|
1415
|
-
const container = iCtx.$container$;
|
|
1416
|
-
const resource = createResourceReturn(container, opts);
|
|
1417
|
-
const el = iCtx.$hostElement$;
|
|
1418
|
-
const task = new Task(TaskFlags.DIRTY | TaskFlags.RESOURCE, i, el, qrl, resource, null);
|
|
1419
|
-
runResource(task, container, iCtx.$hostElement$);
|
|
1420
|
-
set(resource);
|
|
1421
|
-
return resource;
|
|
1422
|
-
};
|
|
1423
|
-
// <docs markdown="../readme.md#useResource">
|
|
1409
|
+
// <docs markdown="../../readme.md#implicit$FirstArg">
|
|
1424
1410
|
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
1425
|
-
// (edit
|
|
1411
|
+
// (edit ../../readme.md#implicit$FirstArg instead and run `pnpm docs.sync`)
|
|
1426
1412
|
/**
|
|
1427
|
-
*
|
|
1428
|
-
* and returns some data.
|
|
1413
|
+
* Create a `____$(...)` convenience method from `___(...)`.
|
|
1429
1414
|
*
|
|
1430
|
-
*
|
|
1431
|
-
*
|
|
1415
|
+
* It is very common for functions to take a lazy-loadable resource as a first argument. For this
|
|
1416
|
+
* reason, the Qwik Optimizer automatically extracts the first argument from any function which ends
|
|
1417
|
+
* in `$`.
|
|
1432
1418
|
*
|
|
1433
|
-
*
|
|
1419
|
+
* This means that `foo$(arg0)` and `foo($(arg0))` are equivalent with respect to Qwik Optimizer.
|
|
1420
|
+
* The former is just a shorthand for the latter.
|
|
1434
1421
|
*
|
|
1435
|
-
*
|
|
1436
|
-
* - `resolved` - the data is available.
|
|
1437
|
-
* - `rejected` - the data is not available due to an error or timeout.
|
|
1422
|
+
* For example, these function calls are equivalent:
|
|
1438
1423
|
*
|
|
1439
|
-
*
|
|
1440
|
-
* re-throw it (or a new Error), the resource status will never be `rejected`.
|
|
1424
|
+
* - `component$(() => {...})` is same as `component($(() => {...}))`
|
|
1441
1425
|
*
|
|
1442
|
-
*
|
|
1426
|
+
* ```tsx
|
|
1427
|
+
* export function myApi(callback: QRL<() => void>): void {
|
|
1428
|
+
* // ...
|
|
1429
|
+
* }
|
|
1443
1430
|
*
|
|
1444
|
-
*
|
|
1445
|
-
*
|
|
1431
|
+
* export const myApi$ = implicit$FirstArg(myApi);
|
|
1432
|
+
* // type of myApi$: (callback: () => void): void
|
|
1446
1433
|
*
|
|
1447
|
-
*
|
|
1448
|
-
*
|
|
1449
|
-
* const cityS = useSignal('');
|
|
1434
|
+
* // can be used as:
|
|
1435
|
+
* myApi$(() => console.log('callback'));
|
|
1450
1436
|
*
|
|
1451
|
-
*
|
|
1452
|
-
*
|
|
1453
|
-
*
|
|
1454
|
-
* cleanup(() => abortController.abort('cleanup'));
|
|
1455
|
-
* const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
|
|
1456
|
-
* signal: abortController.signal,
|
|
1457
|
-
* });
|
|
1458
|
-
* const data = await res.json();
|
|
1459
|
-
* return data as { temp: number };
|
|
1460
|
-
* });
|
|
1437
|
+
* // will be transpiled to:
|
|
1438
|
+
* // FILE: <current file>
|
|
1439
|
+
* myApi(qrl('./chunk-abc.js', 'callback'));
|
|
1461
1440
|
*
|
|
1462
|
-
*
|
|
1463
|
-
*
|
|
1464
|
-
* <input name="city" bind:value={cityS} />
|
|
1465
|
-
* <Resource
|
|
1466
|
-
* value={weatherResource}
|
|
1467
|
-
* onResolved={(weather) => {
|
|
1468
|
-
* return <div>Temperature: {weather.temp}</div>;
|
|
1469
|
-
* }}
|
|
1470
|
-
* />
|
|
1471
|
-
* </div>
|
|
1472
|
-
* );
|
|
1473
|
-
* });
|
|
1441
|
+
* // FILE: chunk-abc.js
|
|
1442
|
+
* export const callback = () => console.log('callback');
|
|
1474
1443
|
* ```
|
|
1475
1444
|
*
|
|
1445
|
+
* @param fn - A function that should have its first argument automatically `$`.
|
|
1476
1446
|
* @public
|
|
1477
|
-
* @see Resource
|
|
1478
|
-
* @see ResourceReturn
|
|
1479
1447
|
*/
|
|
1480
1448
|
// </docs>
|
|
1481
|
-
const
|
|
1482
|
-
|
|
1483
|
-
|
|
1449
|
+
const implicit$FirstArg = (fn) => {
|
|
1450
|
+
return function (first, ...rest) {
|
|
1451
|
+
return fn.call(null, dollar(first), ...rest);
|
|
1452
|
+
};
|
|
1484
1453
|
};
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1454
|
+
|
|
1455
|
+
const createSignal$1 = (value) => {
|
|
1456
|
+
return new Signal(null, value);
|
|
1457
|
+
};
|
|
1458
|
+
const createComputedSignal = (qrl) => {
|
|
1459
|
+
throwIfQRLNotResolved(qrl);
|
|
1460
|
+
return new ComputedSignal(null, qrl);
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1463
|
+
/**
|
|
1464
|
+
* Creates a Signal with the given value. If no value is given, the signal is created with
|
|
1465
|
+
* `undefined`.
|
|
1466
|
+
*
|
|
1467
|
+
* @public
|
|
1468
|
+
*/
|
|
1469
|
+
const createSignal = createSignal$1;
|
|
1470
|
+
/** @internal */
|
|
1471
|
+
const createComputedQrl = createComputedSignal;
|
|
1472
|
+
/**
|
|
1473
|
+
* Create a computed signal which is calculated from the given QRL. A computed signal is a signal
|
|
1474
|
+
* which is calculated from other signals. When the signals change, the computed signal is
|
|
1475
|
+
* recalculated.
|
|
1476
|
+
*
|
|
1477
|
+
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
1478
|
+
* effects, and it mus be synchronous.
|
|
1479
|
+
*
|
|
1480
|
+
* If you need the function to be async, use `useSignal` and `useTask$` instead.
|
|
1481
|
+
*
|
|
1482
|
+
* @public
|
|
1483
|
+
*/
|
|
1484
|
+
const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedQrl);
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* @internal
|
|
1488
|
+
* The storage provider for hooks. Each invocation increases index i. Data is stored in an array.
|
|
1489
|
+
*/
|
|
1490
|
+
const useSequentialScope = () => {
|
|
1491
|
+
const iCtx = useInvokeContext();
|
|
1492
|
+
const hostElement = iCtx.$hostElement$;
|
|
1493
|
+
const host = hostElement;
|
|
1494
|
+
let seq = iCtx.$container$.getHostProp(host, ELEMENT_SEQ);
|
|
1495
|
+
if (seq === null) {
|
|
1496
|
+
seq = [];
|
|
1497
|
+
iCtx.$container$.setHostProp(host, ELEMENT_SEQ, seq);
|
|
1510
1498
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1499
|
+
let seqIdx = iCtx.$container$.getHostProp(host, ELEMENT_SEQ_IDX);
|
|
1500
|
+
if (seqIdx === null) {
|
|
1501
|
+
seqIdx = 0;
|
|
1513
1502
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1503
|
+
iCtx.$container$.setHostProp(host, ELEMENT_SEQ_IDX, seqIdx + 1);
|
|
1504
|
+
while (seq.length <= seqIdx) {
|
|
1505
|
+
seq.push(undefined);
|
|
1516
1506
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
value
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1507
|
+
const set = (value) => {
|
|
1508
|
+
if (qDev && qSerialize) {
|
|
1509
|
+
verifySerializable(value);
|
|
1510
|
+
}
|
|
1511
|
+
return (seq[seqIdx] = value);
|
|
1512
|
+
};
|
|
1513
|
+
return {
|
|
1514
|
+
val: seq[seqIdx],
|
|
1515
|
+
set,
|
|
1516
|
+
i: seqIdx,
|
|
1517
|
+
iCtx,
|
|
1528
1518
|
};
|
|
1529
|
-
return resource;
|
|
1530
|
-
};
|
|
1531
|
-
const createResourceReturn = (container, opts, initialPromise) => {
|
|
1532
|
-
const result = _createResourceReturn(opts);
|
|
1533
|
-
result.value = initialPromise;
|
|
1534
|
-
return createStore(container, result, StoreFlags.RECURSIVE);
|
|
1535
1519
|
};
|
|
1536
|
-
|
|
1537
|
-
|
|
1520
|
+
|
|
1521
|
+
function getSubscriber(effect, prop, data) {
|
|
1522
|
+
if (!effect[_EFFECT_BACK_REF]) {
|
|
1523
|
+
if (isServer && isSsrNode(effect)) {
|
|
1524
|
+
effect.setProp(QBackRefs, new Map());
|
|
1525
|
+
}
|
|
1526
|
+
else {
|
|
1527
|
+
effect[_EFFECT_BACK_REF] = new Map();
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
const subMap = effect[_EFFECT_BACK_REF];
|
|
1531
|
+
let sub = subMap.get(prop);
|
|
1532
|
+
if (!sub) {
|
|
1533
|
+
sub = [effect, prop];
|
|
1534
|
+
subMap.set(prop, sub);
|
|
1535
|
+
}
|
|
1536
|
+
if (data) {
|
|
1537
|
+
sub[EffectSubscriptionProp.DATA] = data;
|
|
1538
|
+
}
|
|
1539
|
+
return sub;
|
|
1540
|
+
}
|
|
1541
|
+
function isSsrNode(value) {
|
|
1542
|
+
return '__brand__' in value && 'currentComponentNode' in value;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
var TaskFlags;
|
|
1546
|
+
(function (TaskFlags) {
|
|
1547
|
+
TaskFlags[TaskFlags["VISIBLE_TASK"] = 1] = "VISIBLE_TASK";
|
|
1548
|
+
TaskFlags[TaskFlags["TASK"] = 2] = "TASK";
|
|
1549
|
+
TaskFlags[TaskFlags["RESOURCE"] = 4] = "RESOURCE";
|
|
1550
|
+
TaskFlags[TaskFlags["DIRTY"] = 8] = "DIRTY";
|
|
1551
|
+
})(TaskFlags || (TaskFlags = {}));
|
|
1552
|
+
/** @internal */
|
|
1553
|
+
const useTaskQrl = (qrl) => {
|
|
1554
|
+
const { val, set, iCtx, i } = useSequentialScope();
|
|
1555
|
+
if (val) {
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
assertQrl(qrl);
|
|
1559
|
+
set(1);
|
|
1560
|
+
const task = new Task(TaskFlags.DIRTY | TaskFlags.TASK, i, iCtx.$hostElement$, qrl, undefined, null);
|
|
1561
|
+
// In V2 we add the task to the sequential scope. We need to do this
|
|
1562
|
+
// in order to be able to retrieve it later when the parent element is
|
|
1563
|
+
// deleted and we need to be able to release the task subscriptions.
|
|
1564
|
+
set(task);
|
|
1565
|
+
const container = iCtx.$container$;
|
|
1566
|
+
const promise = container.$scheduler$(ChoreType.TASK, task);
|
|
1567
|
+
if (isPromise(promise)) {
|
|
1568
|
+
// TODO: should we handle this differently?
|
|
1569
|
+
promise.catch(() => { });
|
|
1570
|
+
}
|
|
1538
1571
|
};
|
|
1539
|
-
const
|
|
1572
|
+
const runTask = (task, container, host) => {
|
|
1540
1573
|
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
1541
1574
|
cleanupTask(task);
|
|
1542
|
-
const iCtx = newInvokeContext(container.$locale$, host, undefined,
|
|
1575
|
+
const iCtx = newInvokeContext(container.$locale$, host, undefined, TaskEvent);
|
|
1543
1576
|
iCtx.$container$ = container;
|
|
1544
|
-
const taskFn = task.$qrl$.getFn(iCtx, () =>
|
|
1545
|
-
const resource = task.$state$;
|
|
1546
|
-
assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
|
|
1577
|
+
const taskFn = task.$qrl$.getFn(iCtx, () => clearAllEffects(container, task));
|
|
1547
1578
|
const track = (obj, prop) => {
|
|
1548
1579
|
const ctx = newInvokeContext();
|
|
1549
|
-
ctx.$effectSubscriber$ =
|
|
1580
|
+
ctx.$effectSubscriber$ = getSubscriber(task, EffectProperty.COMPONENT);
|
|
1550
1581
|
ctx.$container$ = container;
|
|
1551
1582
|
return invoke(ctx, () => {
|
|
1552
1583
|
if (isFunction(obj)) {
|
|
@@ -1558,116 +1589,91 @@ const runResource = (task, container, host) => {
|
|
|
1558
1589
|
else if (isSignal(obj)) {
|
|
1559
1590
|
return obj.value;
|
|
1560
1591
|
}
|
|
1561
|
-
else {
|
|
1592
|
+
else if (isStore(obj)) {
|
|
1593
|
+
// track whole store
|
|
1594
|
+
addStoreEffect(getStoreTarget(obj), STORE_ALL_PROPS, getStoreHandler(obj), ctx.$effectSubscriber$);
|
|
1562
1595
|
return obj;
|
|
1563
1596
|
}
|
|
1597
|
+
else {
|
|
1598
|
+
throw qError(QError.trackObjectWithoutProp);
|
|
1599
|
+
}
|
|
1564
1600
|
});
|
|
1565
1601
|
};
|
|
1566
1602
|
const handleError = (reason) => container.handleError(reason, host);
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1603
|
+
let cleanupFns = null;
|
|
1604
|
+
const cleanup = (fn) => {
|
|
1605
|
+
if (typeof fn == 'function') {
|
|
1606
|
+
if (!cleanupFns) {
|
|
1607
|
+
cleanupFns = [];
|
|
1608
|
+
task.$destroy$ = noSerialize(() => {
|
|
1609
|
+
task.$destroy$ = null;
|
|
1610
|
+
cleanupFns.forEach((fn) => {
|
|
1611
|
+
try {
|
|
1612
|
+
fn();
|
|
1613
|
+
}
|
|
1614
|
+
catch (err) {
|
|
1615
|
+
handleError(err);
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
});
|
|
1575
1619
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1620
|
+
cleanupFns.push(fn);
|
|
1621
|
+
}
|
|
1622
|
+
};
|
|
1623
|
+
const taskApi = { track, cleanup };
|
|
1624
|
+
const result = safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
1625
|
+
// If a Promise is thrown, that means we need to re-run the task.
|
|
1626
|
+
if (isPromise(err)) {
|
|
1627
|
+
return err.then(() => runTask(task, container, host));
|
|
1628
|
+
}
|
|
1629
|
+
else {
|
|
1630
|
+
throw err;
|
|
1631
|
+
}
|
|
1578
1632
|
});
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
cache(policy) {
|
|
1588
|
-
let milliseconds = 0;
|
|
1589
|
-
if (policy === 'immutable') {
|
|
1590
|
-
milliseconds = Infinity;
|
|
1591
|
-
}
|
|
1592
|
-
else {
|
|
1593
|
-
milliseconds = policy;
|
|
1594
|
-
}
|
|
1595
|
-
resource._cache = milliseconds;
|
|
1596
|
-
},
|
|
1597
|
-
previous: resourceTarget._resolved,
|
|
1598
|
-
};
|
|
1599
|
-
let resolve;
|
|
1600
|
-
let reject;
|
|
1601
|
-
let done = false;
|
|
1602
|
-
const setState = (resolved, value) => {
|
|
1603
|
-
if (!done) {
|
|
1604
|
-
done = true;
|
|
1605
|
-
if (resolved) {
|
|
1606
|
-
done = true;
|
|
1607
|
-
resource.loading = false;
|
|
1608
|
-
resource._state = 'resolved';
|
|
1609
|
-
resource._resolved = value;
|
|
1610
|
-
resource._error = undefined;
|
|
1611
|
-
resolve(value);
|
|
1612
|
-
}
|
|
1613
|
-
else {
|
|
1614
|
-
done = true;
|
|
1615
|
-
resource.loading = false;
|
|
1616
|
-
resource._state = 'rejected';
|
|
1617
|
-
resource._error = value;
|
|
1618
|
-
reject(value);
|
|
1619
|
-
}
|
|
1620
|
-
return true;
|
|
1621
|
-
}
|
|
1622
|
-
return false;
|
|
1623
|
-
};
|
|
1624
|
-
/**
|
|
1625
|
-
* Add cleanup to resolve the resource if we are trying to run the same resource again while the
|
|
1626
|
-
* previous one is not resolved yet. The next `runResource` run will call this cleanup
|
|
1627
|
-
*/
|
|
1628
|
-
cleanups.push(() => {
|
|
1629
|
-
if (untrack(() => resource.loading) === true) {
|
|
1630
|
-
const value = untrack(() => resource._resolved);
|
|
1631
|
-
setState(true, value);
|
|
1632
|
-
}
|
|
1633
|
-
});
|
|
1634
|
-
// Execute mutation inside empty invocation
|
|
1635
|
-
invoke(iCtx, () => {
|
|
1636
|
-
// console.log('RESOURCE.pending: ');
|
|
1637
|
-
resource._state = 'pending';
|
|
1638
|
-
resource.loading = !isServerPlatform();
|
|
1639
|
-
const promise = (resource.value = new Promise((r, re) => {
|
|
1640
|
-
resolve = r;
|
|
1641
|
-
reject = re;
|
|
1642
|
-
}));
|
|
1643
|
-
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
1644
|
-
});
|
|
1645
|
-
const promise = safeCall(() => Promise.resolve(taskFn(opts)), (value) => {
|
|
1646
|
-
setState(true, value);
|
|
1647
|
-
}, (err) => {
|
|
1648
|
-
if (isPromise(err)) {
|
|
1649
|
-
return err.then(() => runResource(task, container, host));
|
|
1633
|
+
return result;
|
|
1634
|
+
};
|
|
1635
|
+
const cleanupTask = (task) => {
|
|
1636
|
+
const destroy = task.$destroy$;
|
|
1637
|
+
if (destroy) {
|
|
1638
|
+
task.$destroy$ = null;
|
|
1639
|
+
try {
|
|
1640
|
+
destroy();
|
|
1650
1641
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1642
|
+
catch (err) {
|
|
1643
|
+
logError(err);
|
|
1653
1644
|
}
|
|
1654
|
-
});
|
|
1655
|
-
const timeout = resourceTarget._timeout;
|
|
1656
|
-
if (timeout > 0) {
|
|
1657
|
-
return Promise.race([
|
|
1658
|
-
promise,
|
|
1659
|
-
delay(timeout).then(() => {
|
|
1660
|
-
if (setState(false, new Error('timeout'))) {
|
|
1661
|
-
cleanupTask(task);
|
|
1662
|
-
}
|
|
1663
|
-
}),
|
|
1664
|
-
]);
|
|
1665
1645
|
}
|
|
1666
|
-
return promise;
|
|
1667
1646
|
};
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1647
|
+
class Task extends BackRef {
|
|
1648
|
+
$flags$;
|
|
1649
|
+
$index$;
|
|
1650
|
+
$el$;
|
|
1651
|
+
$qrl$;
|
|
1652
|
+
$state$;
|
|
1653
|
+
$destroy$;
|
|
1654
|
+
constructor($flags$, $index$, $el$, $qrl$, $state$, $destroy$) {
|
|
1655
|
+
super();
|
|
1656
|
+
this.$flags$ = $flags$;
|
|
1657
|
+
this.$index$ = $index$;
|
|
1658
|
+
this.$el$ = $el$;
|
|
1659
|
+
this.$qrl$ = $qrl$;
|
|
1660
|
+
this.$state$ = $state$;
|
|
1661
|
+
this.$destroy$ = $destroy$;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
const isTask = (value) => {
|
|
1665
|
+
return value instanceof Task;
|
|
1666
|
+
};
|
|
1667
|
+
/**
|
|
1668
|
+
* Used internally as a qrl event handler to schedule a task.
|
|
1669
|
+
*
|
|
1670
|
+
* @internal
|
|
1671
|
+
*/
|
|
1672
|
+
const scheduleTask = (_event, element) => {
|
|
1673
|
+
const [task] = useLexicalScope();
|
|
1674
|
+
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
|
|
1675
|
+
const container = getDomContainer(element);
|
|
1676
|
+
container.$scheduler$(type, task);
|
|
1671
1677
|
};
|
|
1672
1678
|
|
|
1673
1679
|
/** @file Public types for the client deserialization */
|
|
@@ -1745,22 +1751,67 @@ var VirtualVNodeProps;
|
|
|
1745
1751
|
VirtualVNodeProps[VirtualVNodeProps["PROPS_OFFSET"] = 6] = "PROPS_OFFSET";
|
|
1746
1752
|
})(VirtualVNodeProps || (VirtualVNodeProps = {}));
|
|
1747
1753
|
|
|
1748
|
-
const
|
|
1754
|
+
const mapApp_findIndx = (array, key, start) => {
|
|
1755
|
+
assertTrue(start % 2 === 0, 'Expecting even number.');
|
|
1756
|
+
let bottom = start >> 1;
|
|
1757
|
+
let top = (array.length - 2) >> 1;
|
|
1758
|
+
while (bottom <= top) {
|
|
1759
|
+
const mid = bottom + ((top - bottom) >> 1);
|
|
1760
|
+
const midKey = array[mid << 1];
|
|
1761
|
+
if (midKey === key) {
|
|
1762
|
+
return mid << 1;
|
|
1763
|
+
}
|
|
1764
|
+
if (midKey < key) {
|
|
1765
|
+
bottom = mid + 1;
|
|
1766
|
+
}
|
|
1767
|
+
else {
|
|
1768
|
+
top = mid - 1;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
return (bottom << 1) ^ -1;
|
|
1772
|
+
};
|
|
1773
|
+
const mapArray_set = (array, key, value, start) => {
|
|
1774
|
+
const indx = mapApp_findIndx(array, key, start);
|
|
1775
|
+
if (indx >= 0) {
|
|
1776
|
+
if (value == null) {
|
|
1777
|
+
array.splice(indx, 2);
|
|
1778
|
+
}
|
|
1779
|
+
else {
|
|
1780
|
+
array[indx + 1] = value;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
else if (value != null) {
|
|
1784
|
+
array.splice(indx ^ -1, 0, key, value);
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
const mapArray_get = (array, key, start) => {
|
|
1788
|
+
const indx = mapApp_findIndx(array, key, start);
|
|
1789
|
+
if (indx >= 0) {
|
|
1790
|
+
return array[indx + 1];
|
|
1791
|
+
}
|
|
1792
|
+
else {
|
|
1793
|
+
return null;
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
|
|
1797
|
+
const isForeignObjectElement = (elementName) => {
|
|
1798
|
+
return isDev ? elementName.toLowerCase() === 'foreignobject' : elementName === 'foreignObject';
|
|
1799
|
+
};
|
|
1749
1800
|
const isSvgElement = (elementName) => elementName === 'svg' || isForeignObjectElement(elementName);
|
|
1750
1801
|
const isMathElement = (elementName) => elementName === 'math';
|
|
1751
1802
|
const vnode_isDefaultNamespace = (vnode) => {
|
|
1752
1803
|
const flags = vnode[VNodeProps.flags];
|
|
1753
1804
|
return (flags & VNodeFlags.NAMESPACE_MASK) === 0;
|
|
1754
1805
|
};
|
|
1755
|
-
const vnode_getElementNamespaceFlags = (
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1806
|
+
const vnode_getElementNamespaceFlags = (element) => {
|
|
1807
|
+
const namespace = fastNamespaceURI(element);
|
|
1808
|
+
switch (namespace) {
|
|
1809
|
+
case SVG_NS:
|
|
1810
|
+
return VNodeFlags.NS_svg;
|
|
1811
|
+
case MATH_NS:
|
|
1812
|
+
return VNodeFlags.NS_math;
|
|
1813
|
+
default:
|
|
1814
|
+
return VNodeFlags.NS_html;
|
|
1764
1815
|
}
|
|
1765
1816
|
};
|
|
1766
1817
|
function vnode_getDomChildrenWithCorrectNamespacesToInsert(journal, domParentVNode, newChild) {
|
|
@@ -2114,19 +2165,21 @@ const useOnEventsSequentialScope = () => {
|
|
|
2114
2165
|
* @returns
|
|
2115
2166
|
*/
|
|
2116
2167
|
const executeComponent = (container, renderHost, subscriptionHost, componentQRL, props) => {
|
|
2117
|
-
const iCtx = newInvokeContext(container.$locale$, subscriptionHost, undefined, RenderEvent);
|
|
2118
|
-
|
|
2119
|
-
|
|
2168
|
+
const iCtx = newInvokeContext(container.$locale$, subscriptionHost || undefined, undefined, RenderEvent);
|
|
2169
|
+
if (subscriptionHost) {
|
|
2170
|
+
iCtx.$effectSubscriber$ = getSubscriber(subscriptionHost, EffectProperty.COMPONENT);
|
|
2171
|
+
iCtx.$container$ = container;
|
|
2172
|
+
}
|
|
2120
2173
|
let componentFn;
|
|
2121
2174
|
container.ensureProjectionResolved(renderHost);
|
|
2122
2175
|
let isInlineComponent = false;
|
|
2123
2176
|
if (componentQRL === null) {
|
|
2124
|
-
componentQRL =
|
|
2177
|
+
componentQRL = container.getHostProp(renderHost, OnRenderProp);
|
|
2125
2178
|
assertDefined(componentQRL, 'No Component found at this location');
|
|
2126
2179
|
}
|
|
2127
|
-
if (isQrl(componentQRL)) {
|
|
2180
|
+
if (isQrl$1(componentQRL)) {
|
|
2128
2181
|
props = props || container.getHostProp(renderHost, ELEMENT_PROPS) || EMPTY_OBJ;
|
|
2129
|
-
if (props
|
|
2182
|
+
if (props.children) {
|
|
2130
2183
|
delete props.children;
|
|
2131
2184
|
}
|
|
2132
2185
|
componentFn = componentQRL.getFn(iCtx);
|
|
@@ -2144,18 +2197,16 @@ const executeComponent = (container, renderHost, subscriptionHost, componentQRL,
|
|
|
2144
2197
|
if (!isInlineComponent) {
|
|
2145
2198
|
container.setHostProp(renderHost, ELEMENT_SEQ_IDX, null);
|
|
2146
2199
|
container.setHostProp(renderHost, USE_ON_LOCAL_SEQ_IDX, null);
|
|
2147
|
-
|
|
2148
|
-
container.setHostProp(renderHost, ELEMENT_PROPS, props);
|
|
2149
|
-
}
|
|
2200
|
+
container.setHostProp(renderHost, ELEMENT_PROPS, props);
|
|
2150
2201
|
}
|
|
2151
2202
|
if (vnode_isVNode(renderHost)) {
|
|
2152
|
-
|
|
2203
|
+
clearAllEffects(container, renderHost);
|
|
2153
2204
|
}
|
|
2154
2205
|
return componentFn(props);
|
|
2155
2206
|
}, (jsx) => {
|
|
2156
2207
|
const useOnEvents = container.getHostProp(renderHost, USE_ON_LOCAL);
|
|
2157
2208
|
if (useOnEvents) {
|
|
2158
|
-
return
|
|
2209
|
+
return addUseOnEvents(jsx, useOnEvents);
|
|
2159
2210
|
}
|
|
2160
2211
|
return jsx;
|
|
2161
2212
|
}, (err) => {
|
|
@@ -2181,6 +2232,7 @@ const executeComponent = (container, renderHost, subscriptionHost, componentQRL,
|
|
|
2181
2232
|
*/
|
|
2182
2233
|
function addUseOnEvents(jsx, useOnEvents) {
|
|
2183
2234
|
const jsxElement = findFirstStringJSX(jsx);
|
|
2235
|
+
let jsxResult = jsx;
|
|
2184
2236
|
return maybeThen(jsxElement, (jsxElement) => {
|
|
2185
2237
|
let isInvisibleComponent = false;
|
|
2186
2238
|
if (!jsxElement) {
|
|
@@ -2199,13 +2251,15 @@ function addUseOnEvents(jsx, useOnEvents) {
|
|
|
2199
2251
|
if (Object.prototype.hasOwnProperty.call(useOnEvents, key)) {
|
|
2200
2252
|
if (isInvisibleComponent) {
|
|
2201
2253
|
if (key === 'onQvisible$') {
|
|
2202
|
-
jsxElement = addScriptNodeForInvisibleComponents(
|
|
2254
|
+
const [jsxElement, jsx] = addScriptNodeForInvisibleComponents(jsxResult);
|
|
2255
|
+
jsxResult = jsx;
|
|
2203
2256
|
if (jsxElement) {
|
|
2204
2257
|
addUseOnEvent(jsxElement, 'document:onQinit$', useOnEvents[key]);
|
|
2205
2258
|
}
|
|
2206
2259
|
}
|
|
2207
2260
|
else if (key.startsWith('document:') || key.startsWith('window:')) {
|
|
2208
|
-
jsxElement = addScriptNodeForInvisibleComponents(
|
|
2261
|
+
const [jsxElement, jsx] = addScriptNodeForInvisibleComponents(jsxResult);
|
|
2262
|
+
jsxResult = jsx;
|
|
2209
2263
|
if (jsxElement) {
|
|
2210
2264
|
addUseOnEvent(jsxElement, key, useOnEvents[key]);
|
|
2211
2265
|
}
|
|
@@ -2223,7 +2277,7 @@ function addUseOnEvents(jsx, useOnEvents) {
|
|
|
2223
2277
|
}
|
|
2224
2278
|
}
|
|
2225
2279
|
}
|
|
2226
|
-
return
|
|
2280
|
+
return jsxResult;
|
|
2227
2281
|
});
|
|
2228
2282
|
}
|
|
2229
2283
|
function addUseOnEvent(jsxElement, key, value) {
|
|
@@ -2269,6 +2323,9 @@ function addScriptNodeForInvisibleComponents(jsx) {
|
|
|
2269
2323
|
type: 'placeholder',
|
|
2270
2324
|
hidden: '',
|
|
2271
2325
|
}, null, 3);
|
|
2326
|
+
if (jsx.type === Slot) {
|
|
2327
|
+
return [jsxElement, _jsxSorted(Fragment, null, null, [jsx, jsxElement], 0, null)];
|
|
2328
|
+
}
|
|
2272
2329
|
if (jsx.children == null) {
|
|
2273
2330
|
jsx.children = jsxElement;
|
|
2274
2331
|
}
|
|
@@ -2278,29 +2335,46 @@ function addScriptNodeForInvisibleComponents(jsx) {
|
|
|
2278
2335
|
else {
|
|
2279
2336
|
jsx.children = [jsx.children, jsxElement];
|
|
2280
2337
|
}
|
|
2281
|
-
return jsxElement;
|
|
2338
|
+
return [jsxElement, jsx];
|
|
2282
2339
|
}
|
|
2283
2340
|
else if (Array.isArray(jsx) && jsx.length) {
|
|
2284
2341
|
// get first element
|
|
2285
|
-
|
|
2342
|
+
const [jsxElement, _] = addScriptNodeForInvisibleComponents(jsx[0]);
|
|
2343
|
+
return [jsxElement, jsx];
|
|
2286
2344
|
}
|
|
2287
|
-
return null;
|
|
2345
|
+
return [null, null];
|
|
2288
2346
|
}
|
|
2289
2347
|
|
|
2348
|
+
/** @internal */
|
|
2349
|
+
const _CONST_PROPS = Symbol('CONST');
|
|
2350
|
+
/** @internal */
|
|
2351
|
+
const _VAR_PROPS = Symbol('VAR');
|
|
2352
|
+
/** @internal @deprecated v1 compat */
|
|
2353
|
+
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
2354
|
+
|
|
2290
2355
|
function isSlotProp(prop) {
|
|
2291
2356
|
return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
|
|
2292
2357
|
}
|
|
2293
|
-
function isParentSlotProp(prop) {
|
|
2294
|
-
return prop.startsWith(QSlotParent);
|
|
2295
|
-
}
|
|
2296
2358
|
/** @internal */
|
|
2297
2359
|
const _restProps = (props, omit, target = {}) => {
|
|
2298
|
-
|
|
2360
|
+
let constPropsTarget = null;
|
|
2361
|
+
const constProps = props[_CONST_PROPS];
|
|
2362
|
+
if (constProps) {
|
|
2363
|
+
for (const key in constProps) {
|
|
2364
|
+
if (!omit.includes(key)) {
|
|
2365
|
+
constPropsTarget ||= {};
|
|
2366
|
+
constPropsTarget[key] = constProps[key];
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
const varPropsTarget = target;
|
|
2371
|
+
const varProps = props[_VAR_PROPS];
|
|
2372
|
+
for (const key in varProps) {
|
|
2299
2373
|
if (!omit.includes(key)) {
|
|
2300
|
-
|
|
2374
|
+
varPropsTarget[key] = varProps[key];
|
|
2301
2375
|
}
|
|
2302
2376
|
}
|
|
2303
|
-
return
|
|
2377
|
+
return createPropsProxy(varPropsTarget, constPropsTarget);
|
|
2304
2378
|
};
|
|
2305
2379
|
|
|
2306
2380
|
function escapeHTML(html) {
|
|
@@ -2342,17 +2416,6 @@ function escapeHTML(html) {
|
|
|
2342
2416
|
}
|
|
2343
2417
|
}
|
|
2344
2418
|
|
|
2345
|
-
function getFileLocationFromJsx(jsxDev) {
|
|
2346
|
-
if (!jsxDev) {
|
|
2347
|
-
return null;
|
|
2348
|
-
}
|
|
2349
|
-
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
2350
|
-
if (sanitizedFileName) {
|
|
2351
|
-
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
2352
|
-
}
|
|
2353
|
-
return null;
|
|
2354
|
-
}
|
|
2355
|
-
|
|
2356
2419
|
const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
2357
2420
|
let journal = container.$journal$;
|
|
2358
2421
|
/**
|
|
@@ -2371,9 +2434,9 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2371
2434
|
/// (Node can be null, if we are at the end of the list.)
|
|
2372
2435
|
let vCurrent = null;
|
|
2373
2436
|
/// When we insert new node we start it here so that we can descend into it.
|
|
2374
|
-
/// NOTE: it can't be stored in `vCurrent` because `
|
|
2437
|
+
/// NOTE: it can't be stored in `vCurrent` because `vNewNode` is in journal
|
|
2375
2438
|
/// and is not connected to the tree.
|
|
2376
|
-
let vNewNode = null;
|
|
2439
|
+
let vNewNode = null;
|
|
2377
2440
|
/// When elements have keys they can be consumed out of order and therefore we can't use nextSibling.
|
|
2378
2441
|
/// In such a case this array will contain the elements after the current location.
|
|
2379
2442
|
/// The array even indices will contains keys and odd indices the vNode.
|
|
@@ -2426,7 +2489,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2426
2489
|
}
|
|
2427
2490
|
else if (isSignal(jsxValue)) {
|
|
2428
2491
|
if (vCurrent) {
|
|
2429
|
-
|
|
2492
|
+
clearAllEffects(container, vCurrent);
|
|
2430
2493
|
}
|
|
2431
2494
|
expectVirtual(VirtualType.WrappedSignal, null);
|
|
2432
2495
|
descend(trackSignalAndAssignHost(jsxValue, (vNewNode || vCurrent), EffectProperty.VNODE, container), true);
|
|
@@ -2641,9 +2704,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2641
2704
|
};
|
|
2642
2705
|
const projections = [];
|
|
2643
2706
|
if (host) {
|
|
2707
|
+
const props = vnode_getProps(host);
|
|
2644
2708
|
// we need to create empty projections for all the slots to remove unused slots content
|
|
2645
|
-
for (let i =
|
|
2646
|
-
const prop =
|
|
2709
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
2710
|
+
const prop = props[i];
|
|
2647
2711
|
if (isSlotProp(prop)) {
|
|
2648
2712
|
const slotName = prop;
|
|
2649
2713
|
projections.push(slotName);
|
|
@@ -2684,6 +2748,8 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2684
2748
|
// console.log('expectProjection', JSON.stringify(slotName));
|
|
2685
2749
|
vCurrent = vnode_getProp(vParent, // The parent is the component and it should have our portal.
|
|
2686
2750
|
slotName, (id) => vnode_locate(container.rootVNode, id));
|
|
2751
|
+
// if projection is marked as deleted then we need to create a new one
|
|
2752
|
+
vCurrent = vCurrent && vCurrent[VNodeProps.flags] & VNodeFlags.Deleted ? null : vCurrent;
|
|
2687
2753
|
if (vCurrent == null) {
|
|
2688
2754
|
vNewNode = vnode_newVirtual();
|
|
2689
2755
|
// you may be tempted to add the projection into the current parent, but
|
|
@@ -2720,6 +2786,19 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2720
2786
|
}
|
|
2721
2787
|
else if (vProjectedNode === vCurrent) ;
|
|
2722
2788
|
else {
|
|
2789
|
+
const parent = vnode_getParent(vProjectedNode);
|
|
2790
|
+
const isAlreadyProjected = !!parent && !(vnode_isElementVNode(parent) && vnode_getElementName(parent) === QTemplate);
|
|
2791
|
+
if (isAlreadyProjected && vParent !== parent) {
|
|
2792
|
+
/**
|
|
2793
|
+
* The node is already projected, but structure has been changed. In next steps we will
|
|
2794
|
+
* insert the vProjectedNode at the end. However we will find existing projection elements
|
|
2795
|
+
* (from already projected THE SAME projection as vProjectedNode!) during
|
|
2796
|
+
* vnode_insertBefore. We need to remove vnode from the vnode tree to avoid referencing it
|
|
2797
|
+
* to self and cause infinite loop. Don't remove it from DOM to avoid additional operations
|
|
2798
|
+
* and flickering.
|
|
2799
|
+
*/
|
|
2800
|
+
vnode_remove(journal, parent, vProjectedNode, false);
|
|
2801
|
+
}
|
|
2723
2802
|
// move from q:template to the target node
|
|
2724
2803
|
vnode_insertBefore(journal, vParent, (vNewNode = vProjectedNode), vCurrent && getInsertBefore());
|
|
2725
2804
|
vnode_setProp(vNewNode, QSlot, slotNameKey);
|
|
@@ -2773,8 +2852,8 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2773
2852
|
while (vCurrent) {
|
|
2774
2853
|
const toRemove = vCurrent;
|
|
2775
2854
|
advanceToNextSibling();
|
|
2776
|
-
cleanup(container, toRemove);
|
|
2777
2855
|
if (vParent === vnode_getParent(toRemove)) {
|
|
2856
|
+
cleanup(container, toRemove);
|
|
2778
2857
|
// If we are diffing projection than the parent is not the parent of the node.
|
|
2779
2858
|
// If that is the case we don't want to remove the node from the parent.
|
|
2780
2859
|
vnode_remove(journal, vParent, toRemove, true);
|
|
@@ -2811,10 +2890,19 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2811
2890
|
// But we need to mark them so that they don't get pulled into the diff.
|
|
2812
2891
|
const eventName = getEventNameFromJsxProp(key);
|
|
2813
2892
|
const scope = getEventNameScopeFromJsxProp(key);
|
|
2814
|
-
vnode_setProp(vNewNode, HANDLER_PREFIX + ':' + scope + ':' + eventName, value);
|
|
2815
2893
|
if (eventName) {
|
|
2894
|
+
vnode_setProp(vNewNode, HANDLER_PREFIX + ':' + scope + ':' + eventName, value);
|
|
2816
2895
|
registerQwikLoaderEvent(eventName);
|
|
2817
2896
|
}
|
|
2897
|
+
if (scope) {
|
|
2898
|
+
// add an event attr with empty value for qwikloader element selector.
|
|
2899
|
+
// We don't need value here. For ssr this value is a QRL,
|
|
2900
|
+
// but for CSR value should be just empty
|
|
2901
|
+
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
2902
|
+
if (htmlEvent) {
|
|
2903
|
+
vnode_setAttr(journal, vNewNode, htmlEvent, '');
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2818
2906
|
needsQDispatchEventPatch = true;
|
|
2819
2907
|
continue;
|
|
2820
2908
|
}
|
|
@@ -2827,12 +2915,15 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2827
2915
|
value(element);
|
|
2828
2916
|
continue;
|
|
2829
2917
|
}
|
|
2918
|
+
else if (value == null) {
|
|
2919
|
+
continue;
|
|
2920
|
+
}
|
|
2830
2921
|
else {
|
|
2831
2922
|
throw qError(QError.invalidRefValue, [currentFile]);
|
|
2832
2923
|
}
|
|
2833
2924
|
}
|
|
2834
2925
|
if (isSignal(value)) {
|
|
2835
|
-
const signalData = new
|
|
2926
|
+
const signalData = new SubscriptionData({
|
|
2836
2927
|
$scopedStyleIdPrefix$: scopedStyleIdPrefix,
|
|
2837
2928
|
$isConst$: true,
|
|
2838
2929
|
});
|
|
@@ -2936,7 +3027,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2936
3027
|
let returnValue = false;
|
|
2937
3028
|
qrls.flat(2).forEach((qrl) => {
|
|
2938
3029
|
if (qrl) {
|
|
2939
|
-
const value = qrl
|
|
3030
|
+
const value = container.$scheduler$(ChoreType.RUN_QRL, vNode, qrl, [event, element]);
|
|
2940
3031
|
returnValue = returnValue || value === true;
|
|
2941
3032
|
}
|
|
2942
3033
|
});
|
|
@@ -2948,10 +3039,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2948
3039
|
/** @param tag Returns true if `qDispatchEvent` needs patching */
|
|
2949
3040
|
function setBulkProps(vnode, srcAttrs, currentFile) {
|
|
2950
3041
|
vnode_ensureElementInflated(vnode);
|
|
2951
|
-
const dstAttrs = vnode;
|
|
3042
|
+
const dstAttrs = vnode_getProps(vnode);
|
|
2952
3043
|
let srcIdx = 0;
|
|
2953
3044
|
const srcLength = srcAttrs.length;
|
|
2954
|
-
let dstIdx =
|
|
3045
|
+
let dstIdx = 0;
|
|
2955
3046
|
let dstLength = dstAttrs.length;
|
|
2956
3047
|
let srcKey = srcIdx < srcLength ? srcAttrs[srcIdx++] : null;
|
|
2957
3048
|
let dstKey = dstIdx < dstLength ? dstAttrs[dstIdx++] : null;
|
|
@@ -2971,12 +3062,15 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2971
3062
|
value(element);
|
|
2972
3063
|
return;
|
|
2973
3064
|
}
|
|
3065
|
+
else if (value == null) {
|
|
3066
|
+
return;
|
|
3067
|
+
}
|
|
2974
3068
|
else {
|
|
2975
3069
|
throw qError(QError.invalidRefValue, [currentFile]);
|
|
2976
3070
|
}
|
|
2977
3071
|
}
|
|
2978
3072
|
if (isSignal(value)) {
|
|
2979
|
-
const signalData = new
|
|
3073
|
+
const signalData = new SubscriptionData({
|
|
2980
3074
|
$scopedStyleIdPrefix$: scopedStyleIdPrefix,
|
|
2981
3075
|
$isConst$: false,
|
|
2982
3076
|
});
|
|
@@ -2990,21 +3084,21 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
2990
3084
|
};
|
|
2991
3085
|
const recordJsxEvent = (key, value) => {
|
|
2992
3086
|
const eventName = getEventNameFromJsxProp(key);
|
|
3087
|
+
const scope = getEventNameScopeFromJsxProp(key);
|
|
2993
3088
|
if (eventName) {
|
|
2994
|
-
const scope = getEventNameScopeFromJsxProp(key);
|
|
2995
3089
|
record(':' + scope + ':' + eventName, value);
|
|
2996
|
-
|
|
2997
|
-
// add an event attr with empty value for qwikloader element selector.
|
|
2998
|
-
// We don't need value here. For ssr this value is a QRL,
|
|
2999
|
-
// but for CSR value should be just empty
|
|
3000
|
-
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
3001
|
-
if (htmlEvent) {
|
|
3002
|
-
record(htmlEvent, '');
|
|
3003
|
-
}
|
|
3004
|
-
// register an event for qwik loader
|
|
3005
|
-
if (eventName) {
|
|
3090
|
+
// register an event for qwik loader
|
|
3006
3091
|
registerQwikLoaderEvent(eventName);
|
|
3007
3092
|
}
|
|
3093
|
+
if (scope) {
|
|
3094
|
+
// add an event attr with empty value for qwikloader element selector.
|
|
3095
|
+
// We don't need value here. For ssr this value is a QRL,
|
|
3096
|
+
// but for CSR value should be just empty
|
|
3097
|
+
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
3098
|
+
if (htmlEvent) {
|
|
3099
|
+
record(htmlEvent, '');
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3008
3102
|
};
|
|
3009
3103
|
while (srcKey !== null || dstKey !== null) {
|
|
3010
3104
|
if (dstKey?.startsWith(HANDLER_PREFIX) || dstKey?.startsWith(Q_PREFIX)) {
|
|
@@ -3199,14 +3293,8 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
3199
3293
|
}
|
|
3200
3294
|
else if (!hashesAreEqual) {
|
|
3201
3295
|
insertNewComponent(host, componentQRL, jsxProps);
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
// TODO(varixo): not sure why we need to copy flags here.
|
|
3205
|
-
vNewNode[VNodeProps.flags] = host[VNodeProps.flags];
|
|
3206
|
-
}
|
|
3207
|
-
host = vNewNode;
|
|
3208
|
-
shouldRender = true;
|
|
3209
|
-
}
|
|
3296
|
+
host = vNewNode;
|
|
3297
|
+
shouldRender = true;
|
|
3210
3298
|
}
|
|
3211
3299
|
if (host) {
|
|
3212
3300
|
const vNodeProps = vnode_getProp(host, ELEMENT_PROPS, container.$getObjectById$);
|
|
@@ -3227,6 +3315,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
3227
3315
|
const lookupKey = jsxNode.key;
|
|
3228
3316
|
const vNodeLookupKey = getKey(host);
|
|
3229
3317
|
const lookupKeysAreEqual = lookupKey === vNodeLookupKey;
|
|
3318
|
+
const vNodeComponentHash = getComponentHash(host, container.$getObjectById$);
|
|
3230
3319
|
if (!lookupKeysAreEqual) {
|
|
3231
3320
|
// See if we already have this inline component later on.
|
|
3232
3321
|
vNewNode = retrieveChildWithKey(null, lookupKey);
|
|
@@ -3240,6 +3329,11 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
3240
3329
|
}
|
|
3241
3330
|
host = vNewNode;
|
|
3242
3331
|
}
|
|
3332
|
+
// inline components don't have component hash - q:renderFn prop, so it should be null
|
|
3333
|
+
else if (vNodeComponentHash != null) {
|
|
3334
|
+
insertNewInlineComponent();
|
|
3335
|
+
host = vNewNode;
|
|
3336
|
+
}
|
|
3243
3337
|
if (host) {
|
|
3244
3338
|
let componentHost = host;
|
|
3245
3339
|
// Find the closest component host which has `OnRender` prop. This is need for subscriptions context.
|
|
@@ -3256,7 +3350,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
3256
3350
|
}
|
|
3257
3351
|
function insertNewComponent(host, componentQRL, jsxProps) {
|
|
3258
3352
|
if (host) {
|
|
3259
|
-
|
|
3353
|
+
clearAllEffects(container, host);
|
|
3260
3354
|
}
|
|
3261
3355
|
vnode_insertBefore(journal, vParent, (vNewNode = vnode_newVirtual()), vCurrent && getInsertBefore());
|
|
3262
3356
|
const jsxNode = jsxValue;
|
|
@@ -3344,8 +3438,8 @@ function propsDiffer(src, dst) {
|
|
|
3344
3438
|
if (!src || !dst) {
|
|
3345
3439
|
return true;
|
|
3346
3440
|
}
|
|
3347
|
-
let srcKeys = removePropsKeys(Object.keys(src), ['children',
|
|
3348
|
-
let dstKeys = removePropsKeys(Object.keys(dst), ['children',
|
|
3441
|
+
let srcKeys = removePropsKeys(Object.keys(src), ['children', QBackRefs]);
|
|
3442
|
+
let dstKeys = removePropsKeys(Object.keys(dst), ['children', QBackRefs]);
|
|
3349
3443
|
if (srcKeys.length !== dstKeys.length) {
|
|
3350
3444
|
return true;
|
|
3351
3445
|
}
|
|
@@ -3384,6 +3478,7 @@ function cleanup(container, vNode) {
|
|
|
3384
3478
|
let vCursor = vNode;
|
|
3385
3479
|
// Depth first traversal
|
|
3386
3480
|
if (vnode_isTextVNode(vNode)) {
|
|
3481
|
+
markVNodeAsDeleted(vCursor);
|
|
3387
3482
|
// Text nodes don't have subscriptions or children;
|
|
3388
3483
|
return;
|
|
3389
3484
|
}
|
|
@@ -3391,7 +3486,7 @@ function cleanup(container, vNode) {
|
|
|
3391
3486
|
do {
|
|
3392
3487
|
const type = vCursor[VNodeProps.flags];
|
|
3393
3488
|
if (type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) {
|
|
3394
|
-
|
|
3489
|
+
clearAllEffects(container, vCursor);
|
|
3395
3490
|
markVNodeAsDeleted(vCursor);
|
|
3396
3491
|
// Only elements and virtual nodes need to be traversed for children
|
|
3397
3492
|
if (type & VNodeFlags.Virtual) {
|
|
@@ -3401,7 +3496,7 @@ function cleanup(container, vNode) {
|
|
|
3401
3496
|
const obj = seq[i];
|
|
3402
3497
|
if (isTask(obj)) {
|
|
3403
3498
|
const task = obj;
|
|
3404
|
-
|
|
3499
|
+
clearAllEffects(container, task);
|
|
3405
3500
|
if (task.$flags$ & TaskFlags.VISIBLE_TASK) {
|
|
3406
3501
|
container.$scheduler$(ChoreType.CLEANUP_VISIBLE, task);
|
|
3407
3502
|
}
|
|
@@ -3416,10 +3511,10 @@ function cleanup(container, vNode) {
|
|
|
3416
3511
|
vnode_getProp(vCursor, OnRenderProp, null) !== null;
|
|
3417
3512
|
if (isComponent) {
|
|
3418
3513
|
// SPECIAL CASE: If we are a component, we need to descend into the projected content and release the content.
|
|
3419
|
-
const attrs = vCursor;
|
|
3420
|
-
for (let i =
|
|
3514
|
+
const attrs = vnode_getProps(vCursor);
|
|
3515
|
+
for (let i = 0; i < attrs.length; i = i + 2) {
|
|
3421
3516
|
const key = attrs[i];
|
|
3422
|
-
if (
|
|
3517
|
+
if (isSlotProp(key)) {
|
|
3423
3518
|
const value = attrs[i + 1];
|
|
3424
3519
|
if (value) {
|
|
3425
3520
|
attrs[i + 1] = null; // prevent infinite loop
|
|
@@ -3436,7 +3531,7 @@ function cleanup(container, vNode) {
|
|
|
3436
3531
|
}
|
|
3437
3532
|
}
|
|
3438
3533
|
}
|
|
3439
|
-
const isProjection =
|
|
3534
|
+
const isProjection = vnode_isProjection(vCursor);
|
|
3440
3535
|
// Descend into children
|
|
3441
3536
|
if (!isProjection) {
|
|
3442
3537
|
// Only if it is not a projection
|
|
@@ -3459,6 +3554,9 @@ function cleanup(container, vNode) {
|
|
|
3459
3554
|
}
|
|
3460
3555
|
}
|
|
3461
3556
|
}
|
|
3557
|
+
else if (type & VNodeFlags.Text) {
|
|
3558
|
+
markVNodeAsDeleted(vCursor);
|
|
3559
|
+
}
|
|
3462
3560
|
// Out of children
|
|
3463
3561
|
if (vCursor === vNode) {
|
|
3464
3562
|
// we are where we started, this means that vNode has no children, so we are done.
|
|
@@ -3525,82 +3623,270 @@ var SiblingsArray;
|
|
|
3525
3623
|
SiblingsArray[SiblingsArray["NextVNode"] = 5] = "NextVNode";
|
|
3526
3624
|
})(SiblingsArray || (SiblingsArray = {}));
|
|
3527
3625
|
|
|
3528
|
-
|
|
3626
|
+
/** @internal */
|
|
3627
|
+
const useResourceQrl = (qrl, opts) => {
|
|
3628
|
+
const { val, set, i, iCtx } = useSequentialScope();
|
|
3629
|
+
if (val != null) {
|
|
3630
|
+
return val;
|
|
3631
|
+
}
|
|
3632
|
+
assertQrl(qrl);
|
|
3633
|
+
const container = iCtx.$container$;
|
|
3634
|
+
const resource = createResourceReturn(container, opts);
|
|
3635
|
+
const el = iCtx.$hostElement$;
|
|
3636
|
+
const task = new Task(TaskFlags.DIRTY | TaskFlags.RESOURCE, i, el, qrl, resource, null);
|
|
3637
|
+
container.$scheduler$(ChoreType.TASK, task);
|
|
3638
|
+
set(resource);
|
|
3639
|
+
return resource;
|
|
3640
|
+
};
|
|
3641
|
+
// <docs markdown="../readme.md#useResource">
|
|
3529
3642
|
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
3530
|
-
// (edit
|
|
3643
|
+
// (edit ../readme.md#useResource instead and run `pnpm docs.sync`)
|
|
3531
3644
|
/**
|
|
3532
|
-
*
|
|
3645
|
+
* This method works like an async memoized function that runs whenever some tracked value changes
|
|
3646
|
+
* and returns some data.
|
|
3533
3647
|
*
|
|
3534
|
-
*
|
|
3535
|
-
*
|
|
3536
|
-
* in `$`.
|
|
3648
|
+
* `useResource` however returns immediate a `ResourceReturn` object that contains the data and a
|
|
3649
|
+
* state that indicates if the data is available or not.
|
|
3537
3650
|
*
|
|
3538
|
-
*
|
|
3539
|
-
* The former is just a shorthand for the latter.
|
|
3651
|
+
* The status can be one of the following:
|
|
3540
3652
|
*
|
|
3541
|
-
*
|
|
3653
|
+
* - `pending` - the data is not yet available.
|
|
3654
|
+
* - `resolved` - the data is available.
|
|
3655
|
+
* - `rejected` - the data is not available due to an error or timeout.
|
|
3542
3656
|
*
|
|
3543
|
-
*
|
|
3657
|
+
* Be careful when using a `try/catch` statement in `useResource$`. If you catch the error and don't
|
|
3658
|
+
* re-throw it (or a new Error), the resource status will never be `rejected`.
|
|
3544
3659
|
*
|
|
3545
|
-
*
|
|
3546
|
-
* export function myApi(callback: QRL<() => void>): void {
|
|
3547
|
-
* // ...
|
|
3548
|
-
* }
|
|
3660
|
+
* ### Example
|
|
3549
3661
|
*
|
|
3550
|
-
*
|
|
3551
|
-
*
|
|
3662
|
+
* Example showing how `useResource` to perform a fetch to request the weather, whenever the input
|
|
3663
|
+
* city name changes.
|
|
3552
3664
|
*
|
|
3553
|
-
*
|
|
3554
|
-
*
|
|
3665
|
+
* ```tsx
|
|
3666
|
+
* const Cmp = component$(() => {
|
|
3667
|
+
* const cityS = useSignal('');
|
|
3555
3668
|
*
|
|
3556
|
-
*
|
|
3557
|
-
*
|
|
3558
|
-
*
|
|
3669
|
+
* const weatherResource = useResource$(async ({ track, cleanup }) => {
|
|
3670
|
+
* const cityName = track(cityS);
|
|
3671
|
+
* const abortController = new AbortController();
|
|
3672
|
+
* cleanup(() => abortController.abort('cleanup'));
|
|
3673
|
+
* const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
|
|
3674
|
+
* signal: abortController.signal,
|
|
3675
|
+
* });
|
|
3676
|
+
* const data = await res.json();
|
|
3677
|
+
* return data as { temp: number };
|
|
3678
|
+
* });
|
|
3559
3679
|
*
|
|
3560
|
-
*
|
|
3561
|
-
*
|
|
3680
|
+
* return (
|
|
3681
|
+
* <div>
|
|
3682
|
+
* <input name="city" bind:value={cityS} />
|
|
3683
|
+
* <Resource
|
|
3684
|
+
* value={weatherResource}
|
|
3685
|
+
* onResolved={(weather) => {
|
|
3686
|
+
* return <div>Temperature: {weather.temp}</div>;
|
|
3687
|
+
* }}
|
|
3688
|
+
* />
|
|
3689
|
+
* </div>
|
|
3690
|
+
* );
|
|
3691
|
+
* });
|
|
3562
3692
|
* ```
|
|
3563
3693
|
*
|
|
3564
|
-
* @param fn - A function that should have its first argument automatically `$`.
|
|
3565
3694
|
* @public
|
|
3695
|
+
* @see Resource
|
|
3696
|
+
* @see ResourceReturn
|
|
3566
3697
|
*/
|
|
3567
3698
|
// </docs>
|
|
3568
|
-
const
|
|
3569
|
-
|
|
3570
|
-
|
|
3699
|
+
const Resource = (props) => {
|
|
3700
|
+
// Resource path
|
|
3701
|
+
return _jsxSorted(Fragment, null, null, getResourceValueAsPromise(props), 0, null);
|
|
3702
|
+
};
|
|
3703
|
+
function getResourceValueAsPromise(props) {
|
|
3704
|
+
const resource = props.value;
|
|
3705
|
+
if (isResourceReturn(resource) && resource.value) {
|
|
3706
|
+
const isBrowser = !isServerPlatform();
|
|
3707
|
+
if (isBrowser) {
|
|
3708
|
+
// create a subscription for the resource._state changes
|
|
3709
|
+
const state = resource._state;
|
|
3710
|
+
if (state === 'pending' && props.onPending) {
|
|
3711
|
+
return Promise.resolve().then(useBindInvokeContext(props.onPending));
|
|
3712
|
+
}
|
|
3713
|
+
else if (state === 'rejected' && props.onRejected) {
|
|
3714
|
+
return Promise.resolve(resource._error).then(useBindInvokeContext(props.onRejected));
|
|
3715
|
+
}
|
|
3716
|
+
else {
|
|
3717
|
+
const resolvedValue = untrack(() => resource._resolved);
|
|
3718
|
+
if (resolvedValue !== undefined) {
|
|
3719
|
+
// resolved, pending without onPending prop or rejected without onRejected prop
|
|
3720
|
+
return Promise.resolve(resolvedValue).then(useBindInvokeContext(props.onResolved));
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3724
|
+
return resource.value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3725
|
+
}
|
|
3726
|
+
else if (isPromise(resource)) {
|
|
3727
|
+
return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3728
|
+
}
|
|
3729
|
+
else if (isSignal(resource)) {
|
|
3730
|
+
return Promise.resolve(resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3731
|
+
}
|
|
3732
|
+
else {
|
|
3733
|
+
return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
const _createResourceReturn = (opts) => {
|
|
3737
|
+
const resource = {
|
|
3738
|
+
__brand: 'resource',
|
|
3739
|
+
value: undefined,
|
|
3740
|
+
loading: isServerPlatform() ? false : true,
|
|
3741
|
+
_resolved: undefined,
|
|
3742
|
+
_error: undefined,
|
|
3743
|
+
_state: 'pending',
|
|
3744
|
+
_timeout: opts?.timeout ?? -1,
|
|
3745
|
+
_cache: 0,
|
|
3571
3746
|
};
|
|
3747
|
+
return resource;
|
|
3572
3748
|
};
|
|
3573
|
-
|
|
3574
|
-
const
|
|
3575
|
-
|
|
3749
|
+
const createResourceReturn = (container, opts, initialPromise) => {
|
|
3750
|
+
const result = _createResourceReturn(opts);
|
|
3751
|
+
result.value = initialPromise;
|
|
3752
|
+
return createStore(container, result, StoreFlags.RECURSIVE);
|
|
3576
3753
|
};
|
|
3577
|
-
const
|
|
3578
|
-
|
|
3579
|
-
|
|
3754
|
+
const isResourceReturn = (obj) => {
|
|
3755
|
+
return isObject(obj) && (getStoreTarget(obj) || obj).__brand === 'resource';
|
|
3756
|
+
};
|
|
3757
|
+
const runResource = (task, container, host) => {
|
|
3758
|
+
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
3759
|
+
cleanupTask(task);
|
|
3760
|
+
const iCtx = newInvokeContext(container.$locale$, host, undefined, ResourceEvent);
|
|
3761
|
+
iCtx.$container$ = container;
|
|
3762
|
+
const taskFn = task.$qrl$.getFn(iCtx, () => clearAllEffects(container, task));
|
|
3763
|
+
const resource = task.$state$;
|
|
3764
|
+
assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
|
|
3765
|
+
const track = (obj, prop) => {
|
|
3766
|
+
const ctx = newInvokeContext();
|
|
3767
|
+
ctx.$effectSubscriber$ = getSubscriber(task, EffectProperty.COMPONENT);
|
|
3768
|
+
ctx.$container$ = container;
|
|
3769
|
+
return invoke(ctx, () => {
|
|
3770
|
+
if (isFunction(obj)) {
|
|
3771
|
+
return obj();
|
|
3772
|
+
}
|
|
3773
|
+
if (prop) {
|
|
3774
|
+
return obj[prop];
|
|
3775
|
+
}
|
|
3776
|
+
else if (isSignal(obj)) {
|
|
3777
|
+
return obj.value;
|
|
3778
|
+
}
|
|
3779
|
+
else {
|
|
3780
|
+
return obj;
|
|
3781
|
+
}
|
|
3782
|
+
});
|
|
3783
|
+
};
|
|
3784
|
+
const handleError = (reason) => container.handleError(reason, host);
|
|
3785
|
+
const cleanups = [];
|
|
3786
|
+
task.$destroy$ = noSerialize(() => {
|
|
3787
|
+
cleanups.forEach((fn) => {
|
|
3788
|
+
try {
|
|
3789
|
+
fn();
|
|
3790
|
+
}
|
|
3791
|
+
catch (err) {
|
|
3792
|
+
handleError(err);
|
|
3793
|
+
}
|
|
3794
|
+
});
|
|
3795
|
+
done = true;
|
|
3796
|
+
});
|
|
3797
|
+
const resourceTarget = unwrapStore(resource);
|
|
3798
|
+
const opts = {
|
|
3799
|
+
track,
|
|
3800
|
+
cleanup(fn) {
|
|
3801
|
+
if (typeof fn === 'function') {
|
|
3802
|
+
cleanups.push(fn);
|
|
3803
|
+
}
|
|
3804
|
+
},
|
|
3805
|
+
cache(policy) {
|
|
3806
|
+
let milliseconds = 0;
|
|
3807
|
+
if (policy === 'immutable') {
|
|
3808
|
+
milliseconds = Infinity;
|
|
3809
|
+
}
|
|
3810
|
+
else {
|
|
3811
|
+
milliseconds = policy;
|
|
3812
|
+
}
|
|
3813
|
+
resource._cache = milliseconds;
|
|
3814
|
+
},
|
|
3815
|
+
previous: resourceTarget._resolved,
|
|
3816
|
+
};
|
|
3817
|
+
let resolve;
|
|
3818
|
+
let reject;
|
|
3819
|
+
let done = false;
|
|
3820
|
+
const setState = (resolved, value) => {
|
|
3821
|
+
if (!done) {
|
|
3822
|
+
done = true;
|
|
3823
|
+
if (resolved) {
|
|
3824
|
+
done = true;
|
|
3825
|
+
resource.loading = false;
|
|
3826
|
+
resource._state = 'resolved';
|
|
3827
|
+
resource._resolved = value;
|
|
3828
|
+
resource._error = undefined;
|
|
3829
|
+
resolve(value);
|
|
3830
|
+
}
|
|
3831
|
+
else {
|
|
3832
|
+
done = true;
|
|
3833
|
+
resource.loading = false;
|
|
3834
|
+
resource._state = 'rejected';
|
|
3835
|
+
resource._error = value;
|
|
3836
|
+
reject(value);
|
|
3837
|
+
}
|
|
3838
|
+
return true;
|
|
3839
|
+
}
|
|
3840
|
+
return false;
|
|
3841
|
+
};
|
|
3842
|
+
/**
|
|
3843
|
+
* Add cleanup to resolve the resource if we are trying to run the same resource again while the
|
|
3844
|
+
* previous one is not resolved yet. The next `runResource` run will call this cleanup
|
|
3845
|
+
*/
|
|
3846
|
+
cleanups.push(() => {
|
|
3847
|
+
if (untrack(() => resource.loading) === true) {
|
|
3848
|
+
const value = untrack(() => resource._resolved);
|
|
3849
|
+
setState(true, value);
|
|
3850
|
+
}
|
|
3851
|
+
});
|
|
3852
|
+
// Execute mutation inside empty invocation
|
|
3853
|
+
invoke(iCtx, () => {
|
|
3854
|
+
// console.log('RESOURCE.pending: ');
|
|
3855
|
+
resource._state = 'pending';
|
|
3856
|
+
resource.loading = !isServerPlatform();
|
|
3857
|
+
const promise = (resource.value = new Promise((r, re) => {
|
|
3858
|
+
resolve = r;
|
|
3859
|
+
reject = re;
|
|
3860
|
+
}));
|
|
3861
|
+
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
3862
|
+
});
|
|
3863
|
+
const promise = safeCall(() => Promise.resolve(taskFn(opts)), (value) => {
|
|
3864
|
+
setState(true, value);
|
|
3865
|
+
}, (err) => {
|
|
3866
|
+
if (isPromise(err)) {
|
|
3867
|
+
return err.then(() => runResource(task, container, host));
|
|
3868
|
+
}
|
|
3869
|
+
else {
|
|
3870
|
+
setState(false, err);
|
|
3871
|
+
}
|
|
3872
|
+
});
|
|
3873
|
+
const timeout = resourceTarget._timeout;
|
|
3874
|
+
if (timeout > 0) {
|
|
3875
|
+
return Promise.race([
|
|
3876
|
+
promise,
|
|
3877
|
+
delay(timeout).then(() => {
|
|
3878
|
+
if (setState(false, new Error('timeout'))) {
|
|
3879
|
+
cleanupTask(task);
|
|
3880
|
+
}
|
|
3881
|
+
}),
|
|
3882
|
+
]);
|
|
3883
|
+
}
|
|
3884
|
+
return promise;
|
|
3885
|
+
};
|
|
3886
|
+
const ignoreErrorToPreventNodeFromCrashing = (err) => {
|
|
3887
|
+
// ignore error to prevent node from crashing
|
|
3888
|
+
// node will crash in promise is rejected and no one is listening to the rejection.
|
|
3580
3889
|
};
|
|
3581
|
-
|
|
3582
|
-
/**
|
|
3583
|
-
* Creates a Signal with the given value. If no value is given, the signal is created with
|
|
3584
|
-
* `undefined`.
|
|
3585
|
-
*
|
|
3586
|
-
* @public
|
|
3587
|
-
*/
|
|
3588
|
-
const createSignal = createSignal$1;
|
|
3589
|
-
/** @internal */
|
|
3590
|
-
const createComputedQrl = createComputedSignal;
|
|
3591
|
-
/**
|
|
3592
|
-
* Create a computed signal which is calculated from the given QRL. A computed signal is a signal
|
|
3593
|
-
* which is calculated from other signals. When the signals change, the computed signal is
|
|
3594
|
-
* recalculated.
|
|
3595
|
-
*
|
|
3596
|
-
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
3597
|
-
* effects, and it mus be synchronous.
|
|
3598
|
-
*
|
|
3599
|
-
* If you need the function to be async, use `useSignal` and `useTask$` instead.
|
|
3600
|
-
*
|
|
3601
|
-
* @public
|
|
3602
|
-
*/
|
|
3603
|
-
const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedQrl);
|
|
3604
3890
|
|
|
3605
3891
|
/// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
|
|
3606
3892
|
const aVNodePath = [];
|
|
@@ -3785,38 +4071,29 @@ const ssrNodeDocumentPosition = (a, b) => {
|
|
|
3785
4071
|
* - Visible Tasks are sorted afterJournalFlush, than depth first on component and finally in
|
|
3786
4072
|
* declaration order within component.
|
|
3787
4073
|
*/
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
ChoreType[ChoreType["MICRO"] = 15] = "MICRO";
|
|
3794
|
-
/** Ensure tha the QRL promise is resolved before processing next chores in the queue */
|
|
3795
|
-
ChoreType[ChoreType["QRL_RESOLVE"] = 1] = "QRL_RESOLVE";
|
|
3796
|
-
ChoreType[ChoreType["RESOURCE"] = 2] = "RESOURCE";
|
|
3797
|
-
ChoreType[ChoreType["TASK"] = 3] = "TASK";
|
|
3798
|
-
ChoreType[ChoreType["NODE_DIFF"] = 4] = "NODE_DIFF";
|
|
3799
|
-
ChoreType[ChoreType["NODE_PROP"] = 5] = "NODE_PROP";
|
|
3800
|
-
ChoreType[ChoreType["COMPONENT_SSR"] = 6] = "COMPONENT_SSR";
|
|
3801
|
-
ChoreType[ChoreType["COMPONENT"] = 7] = "COMPONENT";
|
|
3802
|
-
ChoreType[ChoreType["RECOMPUTE_AND_SCHEDULE_EFFECTS"] = 8] = "RECOMPUTE_AND_SCHEDULE_EFFECTS";
|
|
3803
|
-
ChoreType[ChoreType["JOURNAL_FLUSH"] = 16] = "JOURNAL_FLUSH";
|
|
3804
|
-
ChoreType[ChoreType["VISIBLE"] = 32] = "VISIBLE";
|
|
3805
|
-
ChoreType[ChoreType["CLEANUP_VISIBLE"] = 48] = "CLEANUP_VISIBLE";
|
|
3806
|
-
ChoreType[ChoreType["WAIT_FOR_ALL"] = 255] = "WAIT_FOR_ALL";
|
|
3807
|
-
})(ChoreType || (ChoreType = {}));
|
|
4074
|
+
// Turn this on to get debug output of what the scheduler is doing.
|
|
4075
|
+
const DEBUG$1 = false;
|
|
4076
|
+
const getPromise = (chore) => (chore.$promise$ ||= new Promise((resolve) => {
|
|
4077
|
+
chore.$resolve$ = resolve;
|
|
4078
|
+
}));
|
|
3808
4079
|
const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
3809
4080
|
const choreQueue = [];
|
|
4081
|
+
const qrlRuns = [];
|
|
3810
4082
|
let currentChore = null;
|
|
3811
|
-
let
|
|
4083
|
+
let drainScheduled = false;
|
|
3812
4084
|
return schedule;
|
|
3813
4085
|
///// IMPLEMENTATION /////
|
|
3814
4086
|
function schedule(type, hostOrTask = null, targetOrQrl = null, payload = null) {
|
|
3815
|
-
const
|
|
3816
|
-
const
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
4087
|
+
const isServer = !isDomContainer(container);
|
|
4088
|
+
const isComponentSsr = isServer && type === ChoreType.COMPONENT;
|
|
4089
|
+
const runLater = type !== ChoreType.WAIT_FOR_ALL && !isComponentSsr && type !== ChoreType.RUN_QRL;
|
|
4090
|
+
const isTask = type === ChoreType.TASK || type === ChoreType.VISIBLE || type === ChoreType.CLEANUP_VISIBLE;
|
|
4091
|
+
const isClientOnly = type === ChoreType.JOURNAL_FLUSH ||
|
|
4092
|
+
type === ChoreType.NODE_DIFF ||
|
|
4093
|
+
type === ChoreType.NODE_PROP;
|
|
4094
|
+
if (isServer && isClientOnly) {
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
3820
4097
|
if (isTask) {
|
|
3821
4098
|
hostOrTask.$flags$ |= TaskFlags.DIRTY;
|
|
3822
4099
|
}
|
|
@@ -3835,192 +4112,234 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
|
3835
4112
|
$returnValue$: null,
|
|
3836
4113
|
$executed$: false,
|
|
3837
4114
|
};
|
|
3838
|
-
chore.$promise$ = new Promise((resolve) => (chore.$resolve$ = resolve));
|
|
3839
4115
|
chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
|
|
3840
|
-
if (!
|
|
4116
|
+
if (!drainScheduled && runLater) {
|
|
3841
4117
|
// If we are not currently draining, we need to schedule a drain.
|
|
3842
|
-
|
|
4118
|
+
drainScheduled = true;
|
|
3843
4119
|
schedule(ChoreType.JOURNAL_FLUSH);
|
|
3844
|
-
|
|
4120
|
+
// Catch here to avoid unhandled promise rejection
|
|
4121
|
+
scheduleDrain()?.catch?.(() => { });
|
|
3845
4122
|
}
|
|
4123
|
+
// TODO figure out what to do with chore errors
|
|
3846
4124
|
if (runLater) {
|
|
3847
|
-
return chore
|
|
4125
|
+
return getPromise(chore);
|
|
3848
4126
|
}
|
|
3849
4127
|
else {
|
|
3850
|
-
return drainUpTo(chore,
|
|
4128
|
+
return drainUpTo(chore, isServer);
|
|
3851
4129
|
}
|
|
3852
4130
|
}
|
|
3853
|
-
/**
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
* @param runUptoChore
|
|
3857
|
-
*/
|
|
3858
|
-
function drainUpTo(runUptoChore, rootVNode) {
|
|
3859
|
-
// If it already ran, it's not in the queue
|
|
3860
|
-
if (runUptoChore.$executed$) {
|
|
3861
|
-
return runUptoChore.$returnValue$;
|
|
3862
|
-
}
|
|
3863
|
-
if (currentChore) {
|
|
3864
|
-
// Already running chore, which means we're waiting for async completion
|
|
3865
|
-
return runUptoChore.$promise$;
|
|
3866
|
-
}
|
|
4131
|
+
/** Execute all of the chores up to and including the given chore. */
|
|
4132
|
+
function drainUpTo(runUptoChore, isServer) {
|
|
4133
|
+
let maxRetries = 5000;
|
|
3867
4134
|
while (choreQueue.length) {
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
if (order === null) {
|
|
3871
|
-
continue;
|
|
4135
|
+
if (maxRetries-- < 0) {
|
|
4136
|
+
throw new Error('drainUpTo: max retries reached');
|
|
3872
4137
|
}
|
|
3873
|
-
if (
|
|
3874
|
-
//
|
|
3875
|
-
|
|
4138
|
+
if (currentChore) {
|
|
4139
|
+
// Already running chore, which means we're waiting for async completion
|
|
4140
|
+
return getPromise(currentChore)
|
|
4141
|
+
.then(() => drainUpTo(runUptoChore, isServer))
|
|
4142
|
+
.catch((e) => {
|
|
4143
|
+
container.handleError(e, currentChore?.$host$);
|
|
4144
|
+
});
|
|
4145
|
+
}
|
|
4146
|
+
const nextChore = choreQueue[0];
|
|
4147
|
+
if (nextChore.$executed$) {
|
|
4148
|
+
choreQueue.shift();
|
|
4149
|
+
if (nextChore === runUptoChore) {
|
|
4150
|
+
break;
|
|
4151
|
+
}
|
|
4152
|
+
continue;
|
|
3876
4153
|
}
|
|
3877
|
-
|
|
3878
|
-
if (isDeletedVNode &&
|
|
4154
|
+
if (vNodeAlreadyDeleted(nextChore) &&
|
|
3879
4155
|
// we need to process cleanup tasks for deleted nodes
|
|
3880
4156
|
nextChore.$type$ !== ChoreType.CLEANUP_VISIBLE) {
|
|
4157
|
+
choreQueue.shift();
|
|
3881
4158
|
continue;
|
|
3882
4159
|
}
|
|
3883
|
-
|
|
3884
|
-
if (isPromise(returnValue)) {
|
|
3885
|
-
const promise = returnValue.then(() => drainUpTo(runUptoChore, rootVNode));
|
|
3886
|
-
return promise;
|
|
3887
|
-
}
|
|
4160
|
+
executeChore(nextChore, isServer);
|
|
3888
4161
|
}
|
|
3889
4162
|
return runUptoChore.$returnValue$;
|
|
3890
4163
|
}
|
|
3891
|
-
function executeChore(chore) {
|
|
4164
|
+
function executeChore(chore, isServer) {
|
|
3892
4165
|
const host = chore.$host$;
|
|
3893
4166
|
assertEqual(currentChore, null, 'Chore already running.');
|
|
3894
4167
|
currentChore = chore;
|
|
3895
4168
|
let returnValue = null;
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
3904
|
-
if (chore.$type$ === ChoreType.COMPONENT) {
|
|
3905
|
-
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
3906
|
-
return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
|
|
4169
|
+
try {
|
|
4170
|
+
switch (chore.$type$) {
|
|
4171
|
+
case ChoreType.WAIT_FOR_ALL:
|
|
4172
|
+
{
|
|
4173
|
+
if (isServer) {
|
|
4174
|
+
drainScheduled = false;
|
|
4175
|
+
}
|
|
3907
4176
|
}
|
|
3908
|
-
|
|
3909
|
-
|
|
4177
|
+
break;
|
|
4178
|
+
case ChoreType.JOURNAL_FLUSH:
|
|
4179
|
+
{
|
|
4180
|
+
returnValue = journalFlush();
|
|
4181
|
+
drainScheduled = false;
|
|
4182
|
+
}
|
|
4183
|
+
break;
|
|
4184
|
+
case ChoreType.COMPONENT:
|
|
4185
|
+
{
|
|
4186
|
+
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
4187
|
+
if (isServer) {
|
|
4188
|
+
return jsx;
|
|
4189
|
+
}
|
|
4190
|
+
else {
|
|
4191
|
+
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
4192
|
+
return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
|
|
4193
|
+
}
|
|
4194
|
+
}, (err) => container.handleError(err, host));
|
|
4195
|
+
}
|
|
4196
|
+
break;
|
|
4197
|
+
case ChoreType.RUN_QRL:
|
|
4198
|
+
{
|
|
4199
|
+
const fn = chore.$target$.getFn();
|
|
4200
|
+
const result = retryOnPromise(() => fn(...chore.$payload$));
|
|
4201
|
+
if (isPromise(result)) {
|
|
4202
|
+
const handled = result
|
|
4203
|
+
.finally(() => {
|
|
4204
|
+
qrlRuns.splice(qrlRuns.indexOf(handled), 1);
|
|
4205
|
+
})
|
|
4206
|
+
.catch((error) => {
|
|
4207
|
+
container.handleError(error, chore.$host$);
|
|
4208
|
+
});
|
|
4209
|
+
// Don't wait for the promise to resolve
|
|
4210
|
+
// TODO come up with a better solution, we also want concurrent signal handling with tasks but serial tasks
|
|
4211
|
+
qrlRuns.push(handled);
|
|
4212
|
+
DEBUG$1 &&
|
|
4213
|
+
debugTrace('execute.DONE (but still running)', chore, currentChore, choreQueue);
|
|
4214
|
+
chore.$returnValue$ = handled;
|
|
4215
|
+
chore.$resolve$?.(handled);
|
|
4216
|
+
currentChore = null;
|
|
4217
|
+
chore.$executed$ = true;
|
|
4218
|
+
// early out so we don't call after()
|
|
4219
|
+
return;
|
|
4220
|
+
}
|
|
4221
|
+
returnValue = null;
|
|
4222
|
+
}
|
|
4223
|
+
break;
|
|
4224
|
+
case ChoreType.TASK:
|
|
4225
|
+
case ChoreType.VISIBLE:
|
|
4226
|
+
{
|
|
4227
|
+
const payload = chore.$payload$;
|
|
4228
|
+
if (payload.$flags$ & TaskFlags.RESOURCE) {
|
|
4229
|
+
const result = runResource(payload, container, host);
|
|
4230
|
+
// Don't await the return value of the resource, because async resources should not be awaited.
|
|
4231
|
+
// The reason for this is that we should be able to update for example a node with loading
|
|
4232
|
+
// text. If we await the resource, the loading text will not be displayed until the resource
|
|
4233
|
+
// is loaded.
|
|
4234
|
+
// Awaiting on the client also causes a deadlock.
|
|
4235
|
+
// In any case, the resource will never throw.
|
|
4236
|
+
returnValue = isServer ? result : null;
|
|
4237
|
+
}
|
|
4238
|
+
else {
|
|
4239
|
+
returnValue = runTask(payload, container, host);
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
break;
|
|
4243
|
+
case ChoreType.CLEANUP_VISIBLE:
|
|
4244
|
+
{
|
|
4245
|
+
const task = chore.$payload$;
|
|
4246
|
+
cleanupTask(task);
|
|
4247
|
+
}
|
|
4248
|
+
break;
|
|
4249
|
+
case ChoreType.NODE_DIFF:
|
|
4250
|
+
{
|
|
4251
|
+
const parentVirtualNode = chore.$target$;
|
|
4252
|
+
let jsx = chore.$payload$;
|
|
4253
|
+
if (isSignal(jsx)) {
|
|
4254
|
+
jsx = jsx.value;
|
|
4255
|
+
}
|
|
4256
|
+
returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
|
|
4257
|
+
}
|
|
4258
|
+
break;
|
|
4259
|
+
case ChoreType.NODE_PROP:
|
|
4260
|
+
{
|
|
4261
|
+
const virtualNode = chore.$host$;
|
|
4262
|
+
const payload = chore.$payload$;
|
|
4263
|
+
let value = payload.$value$;
|
|
4264
|
+
if (isSignal(value)) {
|
|
4265
|
+
value = value.value;
|
|
4266
|
+
}
|
|
4267
|
+
const isConst = payload.$isConst$;
|
|
4268
|
+
const journal = container.$journal$;
|
|
4269
|
+
const property = chore.$idx$;
|
|
4270
|
+
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
4271
|
+
if (isConst) {
|
|
4272
|
+
const element = virtualNode[ElementVNodeProps.element];
|
|
4273
|
+
journal.push(VNodeJournalOpCode.SetAttribute, element, property, serializedValue);
|
|
4274
|
+
}
|
|
4275
|
+
else {
|
|
4276
|
+
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
break;
|
|
4280
|
+
case ChoreType.QRL_RESOLVE: {
|
|
4281
|
+
{
|
|
4282
|
+
const target = chore.$target$;
|
|
4283
|
+
returnValue = !target.resolved ? target.resolve() : null;
|
|
3910
4284
|
}
|
|
3911
|
-
}, (err) => container.handleError(err, host));
|
|
3912
|
-
break;
|
|
3913
|
-
case ChoreType.RESOURCE:
|
|
3914
|
-
// Don't await the return value of the resource, because async resources should not be awaited.
|
|
3915
|
-
// The reason for this is that we should be able to update for example a node with loading
|
|
3916
|
-
// text. If we await the resource, the loading text will not be displayed until the resource
|
|
3917
|
-
// is loaded.
|
|
3918
|
-
const result = runResource(chore.$payload$, container, host);
|
|
3919
|
-
returnValue = isDomContainer(container) ? null : result;
|
|
3920
|
-
break;
|
|
3921
|
-
case ChoreType.TASK:
|
|
3922
|
-
returnValue = runTask(chore.$payload$, container, host);
|
|
3923
|
-
break;
|
|
3924
|
-
case ChoreType.VISIBLE:
|
|
3925
|
-
returnValue = runTask(chore.$payload$, container, host);
|
|
3926
|
-
break;
|
|
3927
|
-
case ChoreType.CLEANUP_VISIBLE:
|
|
3928
|
-
const task = chore.$payload$;
|
|
3929
|
-
cleanupTask(task);
|
|
3930
|
-
break;
|
|
3931
|
-
case ChoreType.NODE_DIFF:
|
|
3932
|
-
const parentVirtualNode = chore.$target$;
|
|
3933
|
-
let jsx = chore.$payload$;
|
|
3934
|
-
if (isSignal(jsx)) {
|
|
3935
|
-
jsx = jsx.value;
|
|
3936
|
-
}
|
|
3937
|
-
returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
|
|
3938
|
-
break;
|
|
3939
|
-
case ChoreType.NODE_PROP:
|
|
3940
|
-
const virtualNode = chore.$host$;
|
|
3941
|
-
const payload = chore.$payload$;
|
|
3942
|
-
let value = payload.$value$;
|
|
3943
|
-
if (isSignal(value)) {
|
|
3944
|
-
value = value.value;
|
|
3945
|
-
}
|
|
3946
|
-
const isConst = payload.$isConst$;
|
|
3947
|
-
const journal = container.$journal$;
|
|
3948
|
-
const property = chore.$idx$;
|
|
3949
|
-
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
3950
|
-
if (isConst) {
|
|
3951
|
-
const element = virtualNode[ElementVNodeProps.element];
|
|
3952
|
-
journal.push(VNodeJournalOpCode.SetAttribute, element, property, serializedValue);
|
|
3953
|
-
}
|
|
3954
|
-
else {
|
|
3955
|
-
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
3956
|
-
}
|
|
3957
|
-
break;
|
|
3958
|
-
case ChoreType.QRL_RESOLVE: {
|
|
3959
|
-
const target = chore.$target$;
|
|
3960
|
-
returnValue = !target.resolved ? target.resolve() : null;
|
|
3961
|
-
break;
|
|
3962
|
-
}
|
|
3963
|
-
case ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS: {
|
|
3964
|
-
const target = chore.$target$;
|
|
3965
|
-
const forceRunEffects = target.$forceRunEffects$;
|
|
3966
|
-
target.$forceRunEffects$ = false;
|
|
3967
|
-
if (!target.$effects$?.length) {
|
|
3968
4285
|
break;
|
|
3969
4286
|
}
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
4287
|
+
case ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS: {
|
|
4288
|
+
{
|
|
4289
|
+
const target = chore.$target$;
|
|
4290
|
+
const forceRunEffects = target.$forceRunEffects$;
|
|
4291
|
+
target.$forceRunEffects$ = false;
|
|
4292
|
+
if (!target.$effects$?.size) {
|
|
4293
|
+
break;
|
|
4294
|
+
}
|
|
4295
|
+
returnValue = retryOnPromise(() => {
|
|
4296
|
+
if (target.$computeIfNeeded$() || forceRunEffects) {
|
|
4297
|
+
triggerEffects(container, target, target.$effects$);
|
|
4298
|
+
}
|
|
4299
|
+
});
|
|
3973
4300
|
}
|
|
3974
|
-
|
|
3975
|
-
|
|
4301
|
+
break;
|
|
4302
|
+
}
|
|
3976
4303
|
}
|
|
3977
4304
|
}
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
}
|
|
4305
|
+
catch (e) {
|
|
4306
|
+
returnValue = Promise.reject(e);
|
|
4307
|
+
}
|
|
4308
|
+
const after = (value, error) => {
|
|
3983
4309
|
currentChore = null;
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
}
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
}
|
|
4001
|
-
function vNodeAlreadyDeleted(chore) {
|
|
4002
|
-
return !!(chore.$host$ &&
|
|
4003
|
-
vnode_isVNode(chore.$host$) &&
|
|
4004
|
-
chore.$host$[VNodeProps.flags] & VNodeFlags.Deleted);
|
|
4005
|
-
}
|
|
4006
|
-
/**
|
|
4007
|
-
* Compares two chores to determine their execution order in the scheduler's queue.
|
|
4008
|
-
*
|
|
4009
|
-
* @param a - The first chore to compare
|
|
4010
|
-
* @param b - The second chore to compare
|
|
4011
|
-
* @returns A number indicating the relative order of the chores. A negative number means `a` runs
|
|
4012
|
-
* before `b`.
|
|
4013
|
-
*/
|
|
4014
|
-
function choreComparator(a, b, rootVNode) {
|
|
4015
|
-
const macroTypeDiff = (a.$type$ & ChoreType.MACRO) - (b.$type$ & ChoreType.MACRO);
|
|
4016
|
-
if (macroTypeDiff !== 0) {
|
|
4017
|
-
return macroTypeDiff;
|
|
4310
|
+
chore.$executed$ = true;
|
|
4311
|
+
if (error) {
|
|
4312
|
+
container.handleError(error, host);
|
|
4313
|
+
}
|
|
4314
|
+
else {
|
|
4315
|
+
chore.$returnValue$ = value;
|
|
4316
|
+
chore.$resolve$?.(value);
|
|
4317
|
+
}
|
|
4318
|
+
};
|
|
4319
|
+
if (isPromise(returnValue)) {
|
|
4320
|
+
chore.$promise$ = returnValue.then(after, (error) => after(undefined, error));
|
|
4321
|
+
chore.$resolve$?.(chore.$promise$);
|
|
4322
|
+
chore.$resolve$ = undefined;
|
|
4323
|
+
}
|
|
4324
|
+
else {
|
|
4325
|
+
after(returnValue);
|
|
4326
|
+
}
|
|
4018
4327
|
}
|
|
4019
|
-
|
|
4020
|
-
|
|
4328
|
+
/**
|
|
4329
|
+
* Compares two chores to determine their execution order in the scheduler's queue.
|
|
4330
|
+
*
|
|
4331
|
+
* @param a - The first chore to compare
|
|
4332
|
+
* @param b - The second chore to compare
|
|
4333
|
+
* @returns A number indicating the relative order of the chores. A negative number means `a` runs
|
|
4334
|
+
* before `b`.
|
|
4335
|
+
*/
|
|
4336
|
+
function choreComparator(a, b, rootVNode) {
|
|
4337
|
+
const macroTypeDiff = (a.$type$ & ChoreType.MACRO) - (b.$type$ & ChoreType.MACRO);
|
|
4338
|
+
if (macroTypeDiff !== 0) {
|
|
4339
|
+
return macroTypeDiff;
|
|
4340
|
+
}
|
|
4021
4341
|
const aHost = a.$host$;
|
|
4022
4342
|
const bHost = b.$host$;
|
|
4023
|
-
// QRL_RESOLVE does not have a host.
|
|
4024
4343
|
if (aHost !== bHost && aHost !== null && bHost !== null) {
|
|
4025
4344
|
if (vnode_isVNode(aHost) && vnode_isVNode(bHost)) {
|
|
4026
4345
|
// we are running on the client.
|
|
@@ -4030,6 +4349,8 @@ function choreComparator(a, b, rootVNode) {
|
|
|
4030
4349
|
}
|
|
4031
4350
|
}
|
|
4032
4351
|
else {
|
|
4352
|
+
assertFalse(vnode_isVNode(aHost), 'expected aHost to be SSRNode but it is a VNode');
|
|
4353
|
+
assertFalse(vnode_isVNode(bHost), 'expected bHost to be SSRNode but it is a VNode');
|
|
4033
4354
|
// we are running on the server.
|
|
4034
4355
|
// On server we can't schedule task for a different host!
|
|
4035
4356
|
// Server is SSR, and therefore scheduling for anything but the current host
|
|
@@ -4046,250 +4367,117 @@ function choreComparator(a, b, rootVNode) {
|
|
|
4046
4367
|
}
|
|
4047
4368
|
}
|
|
4048
4369
|
const microTypeDiff = (a.$type$ & ChoreType.MICRO) - (b.$type$ & ChoreType.MICRO);
|
|
4049
|
-
if (microTypeDiff !== 0) {
|
|
4050
|
-
return microTypeDiff;
|
|
4051
|
-
}
|
|
4052
|
-
const idxDiff = toNumber(a.$idx$) - toNumber(b.$idx$);
|
|
4053
|
-
if (idxDiff !== 0) {
|
|
4054
|
-
return idxDiff;
|
|
4055
|
-
}
|
|
4056
|
-
// If the host is the same, we need to compare the target.
|
|
4057
|
-
if (a.$target$ !== b.$target$ &&
|
|
4058
|
-
((a.$type$ === ChoreType.QRL_RESOLVE && b.$type$ === ChoreType.QRL_RESOLVE) ||
|
|
4059
|
-
(a.$type$ === ChoreType.NODE_PROP && b.$type$ === ChoreType.NODE_PROP) ||
|
|
4060
|
-
(a.$type$ === ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS &&
|
|
4061
|
-
b.$type$ === ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS))) {
|
|
4062
|
-
// 1 means that we are going to process chores as FIFO
|
|
4063
|
-
return 1;
|
|
4064
|
-
}
|
|
4065
|
-
}
|
|
4066
|
-
return 0;
|
|
4067
|
-
}
|
|
4068
|
-
function sortedFindIndex(sortedArray, value, rootVNode) {
|
|
4069
|
-
/// We need to ensure that the `queue` is sorted by priority.
|
|
4070
|
-
/// 1. Find a place where to insert into.
|
|
4071
|
-
let bottom = 0;
|
|
4072
|
-
let top = sortedArray.length;
|
|
4073
|
-
while (bottom < top) {
|
|
4074
|
-
const middle = bottom + ((top - bottom) >> 1);
|
|
4075
|
-
const midChore = sortedArray[middle];
|
|
4076
|
-
const comp = choreComparator(value, midChore, rootVNode);
|
|
4077
|
-
if (comp < 0) {
|
|
4078
|
-
top = middle;
|
|
4079
|
-
}
|
|
4080
|
-
else if (comp > 0) {
|
|
4081
|
-
bottom = middle + 1;
|
|
4082
|
-
}
|
|
4083
|
-
else {
|
|
4084
|
-
// We already have the host in the queue.
|
|
4085
|
-
return middle;
|
|
4086
|
-
}
|
|
4087
|
-
}
|
|
4088
|
-
return ~bottom;
|
|
4089
|
-
}
|
|
4090
|
-
function sortedInsert(sortedArray, value, rootVNode) {
|
|
4091
|
-
/// We need to ensure that the `queue` is sorted by priority.
|
|
4092
|
-
/// 1. Find a place where to insert into.
|
|
4093
|
-
const idx = sortedFindIndex(sortedArray, value, rootVNode);
|
|
4094
|
-
if (idx < 0) {
|
|
4095
|
-
/// 2. Insert the chore into the queue.
|
|
4096
|
-
sortedArray.splice(~idx, 0, value);
|
|
4097
|
-
return value;
|
|
4098
|
-
}
|
|
4099
|
-
const existing = sortedArray[idx];
|
|
4100
|
-
choreUpdate(existing, value);
|
|
4101
|
-
return existing;
|
|
4102
|
-
}
|
|
4103
|
-
|
|
4104
|
-
// <docs markdown="../readme.md#useLexicalScope">
|
|
4105
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
4106
|
-
// (edit ../readme.md#useLexicalScope instead and run `pnpm docs.sync`)
|
|
4107
|
-
/**
|
|
4108
|
-
* Used by the Qwik Optimizer to restore the lexically scoped variables.
|
|
4109
|
-
*
|
|
4110
|
-
* This method should not be present in the application source code.
|
|
4111
|
-
*
|
|
4112
|
-
* NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
|
|
4113
|
-
* (before any `await` statements.)
|
|
4114
|
-
*
|
|
4115
|
-
* @internal
|
|
4116
|
-
*/
|
|
4117
|
-
// </docs>
|
|
4118
|
-
const useLexicalScope = () => {
|
|
4119
|
-
const context = getInvokeContext();
|
|
4120
|
-
let qrl = context.$qrl$;
|
|
4121
|
-
if (!qrl) {
|
|
4122
|
-
const el = context.$element$;
|
|
4123
|
-
assertDefined(el, 'invoke: element must be defined inside useLexicalScope()', context);
|
|
4124
|
-
const containerElement = _getQContainerElement(el);
|
|
4125
|
-
assertDefined(containerElement, `invoke: cant find parent q:container of`, el);
|
|
4126
|
-
const container = getDomContainer(containerElement);
|
|
4127
|
-
qrl = container.parseQRL(decodeURIComponent(String(context.$url$)));
|
|
4128
|
-
}
|
|
4129
|
-
else {
|
|
4130
|
-
assertQrl(qrl);
|
|
4131
|
-
assertDefined(qrl.$captureRef$, 'invoke: qrl $captureRef$ must be defined inside useLexicalScope()', qrl);
|
|
4132
|
-
}
|
|
4133
|
-
return qrl.$captureRef$;
|
|
4134
|
-
};
|
|
4135
|
-
|
|
4136
|
-
var TaskFlags;
|
|
4137
|
-
(function (TaskFlags) {
|
|
4138
|
-
TaskFlags[TaskFlags["VISIBLE_TASK"] = 1] = "VISIBLE_TASK";
|
|
4139
|
-
TaskFlags[TaskFlags["TASK"] = 2] = "TASK";
|
|
4140
|
-
TaskFlags[TaskFlags["RESOURCE"] = 4] = "RESOURCE";
|
|
4141
|
-
TaskFlags[TaskFlags["DIRTY"] = 8] = "DIRTY";
|
|
4142
|
-
})(TaskFlags || (TaskFlags = {}));
|
|
4143
|
-
/** @internal */
|
|
4144
|
-
const useTaskQrl = (qrl, opts) => {
|
|
4145
|
-
const { val, set, iCtx, i } = useSequentialScope();
|
|
4146
|
-
if (val) {
|
|
4147
|
-
return;
|
|
4148
|
-
}
|
|
4149
|
-
assertQrl(qrl);
|
|
4150
|
-
set(1);
|
|
4151
|
-
const host = iCtx.$hostElement$;
|
|
4152
|
-
const task = new Task(TaskFlags.DIRTY | TaskFlags.TASK, i, iCtx.$hostElement$, qrl, undefined, null);
|
|
4153
|
-
// In V2 we add the task to the sequential scope. We need to do this
|
|
4154
|
-
// in order to be able to retrieve it later when the parent element is
|
|
4155
|
-
// deleted and we need to be able to release the task subscriptions.
|
|
4156
|
-
set(task);
|
|
4157
|
-
const result = runTask(task, iCtx.$container$, host);
|
|
4158
|
-
if (isPromise(result)) {
|
|
4159
|
-
throw result;
|
|
4160
|
-
}
|
|
4161
|
-
qrl.$resolveLazy$(iCtx.$element$);
|
|
4162
|
-
if (isServerPlatform()) {
|
|
4163
|
-
useRunTask(task, opts?.eagerness);
|
|
4164
|
-
}
|
|
4165
|
-
};
|
|
4166
|
-
const runTask = (task, container, host) => {
|
|
4167
|
-
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
4168
|
-
cleanupTask(task);
|
|
4169
|
-
const iCtx = newInvokeContext(container.$locale$, host, undefined, TaskEvent);
|
|
4170
|
-
iCtx.$container$ = container;
|
|
4171
|
-
const taskFn = task.$qrl$.getFn(iCtx, () => clearSubscriberEffectDependencies(container, task));
|
|
4172
|
-
const track = (obj, prop) => {
|
|
4173
|
-
const ctx = newInvokeContext();
|
|
4174
|
-
ctx.$effectSubscriber$ = [task, EffectProperty.COMPONENT];
|
|
4175
|
-
ctx.$container$ = container;
|
|
4176
|
-
return invoke(ctx, () => {
|
|
4177
|
-
if (isFunction(obj)) {
|
|
4178
|
-
return obj();
|
|
4179
|
-
}
|
|
4180
|
-
if (prop) {
|
|
4181
|
-
return obj[prop];
|
|
4182
|
-
}
|
|
4183
|
-
else if (isSignal(obj)) {
|
|
4184
|
-
return obj.value;
|
|
4185
|
-
}
|
|
4186
|
-
else {
|
|
4187
|
-
return obj;
|
|
4188
|
-
}
|
|
4189
|
-
});
|
|
4190
|
-
};
|
|
4191
|
-
const handleError = (reason) => container.handleError(reason, host);
|
|
4192
|
-
let cleanupFns = null;
|
|
4193
|
-
const cleanup = (fn) => {
|
|
4194
|
-
if (typeof fn == 'function') {
|
|
4195
|
-
if (!cleanupFns) {
|
|
4196
|
-
cleanupFns = [];
|
|
4197
|
-
task.$destroy$ = noSerialize(() => {
|
|
4198
|
-
task.$destroy$ = null;
|
|
4199
|
-
cleanupFns.forEach((fn) => {
|
|
4200
|
-
try {
|
|
4201
|
-
fn();
|
|
4202
|
-
}
|
|
4203
|
-
catch (err) {
|
|
4204
|
-
handleError(err);
|
|
4205
|
-
}
|
|
4206
|
-
});
|
|
4207
|
-
});
|
|
4208
|
-
}
|
|
4209
|
-
cleanupFns.push(fn);
|
|
4210
|
-
}
|
|
4211
|
-
};
|
|
4212
|
-
const taskApi = { track, cleanup };
|
|
4213
|
-
const result = safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
4214
|
-
if (isPromise(err)) {
|
|
4215
|
-
return err.then(() => runTask(task, container, host));
|
|
4216
|
-
}
|
|
4217
|
-
else {
|
|
4218
|
-
return handleError(err);
|
|
4219
|
-
}
|
|
4220
|
-
});
|
|
4221
|
-
return result;
|
|
4222
|
-
};
|
|
4223
|
-
const cleanupTask = (task) => {
|
|
4224
|
-
const destroy = task.$destroy$;
|
|
4225
|
-
if (destroy) {
|
|
4226
|
-
task.$destroy$ = null;
|
|
4227
|
-
try {
|
|
4228
|
-
destroy();
|
|
4370
|
+
if (microTypeDiff !== 0) {
|
|
4371
|
+
return microTypeDiff;
|
|
4229
4372
|
}
|
|
4230
|
-
|
|
4231
|
-
|
|
4373
|
+
// types are the same
|
|
4374
|
+
const idxDiff = toNumber(a.$idx$) - toNumber(b.$idx$);
|
|
4375
|
+
if (idxDiff !== 0) {
|
|
4376
|
+
return idxDiff;
|
|
4232
4377
|
}
|
|
4378
|
+
// If the host is the same (or missing), and the type is the same, we need to compare the target.
|
|
4379
|
+
if (a.$target$ !== b.$target$ || a.$payload$ !== b.$payload$) {
|
|
4380
|
+
// 1 means that we are going to process chores as FIFO
|
|
4381
|
+
return 1;
|
|
4382
|
+
}
|
|
4383
|
+
// If the chore is the same as the current chore, we will run it again
|
|
4384
|
+
if (b === currentChore) {
|
|
4385
|
+
return 1;
|
|
4386
|
+
}
|
|
4387
|
+
// The chores are the same and will run only once
|
|
4388
|
+
return 0;
|
|
4233
4389
|
}
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4390
|
+
function sortedFindIndex(sortedArray, value, rootVNode) {
|
|
4391
|
+
/// We need to ensure that the `queue` is sorted by priority.
|
|
4392
|
+
/// 1. Find a place where to insert into.
|
|
4393
|
+
let bottom = 0;
|
|
4394
|
+
let top = sortedArray.length;
|
|
4395
|
+
while (bottom < top) {
|
|
4396
|
+
const middle = bottom + ((top - bottom) >> 1);
|
|
4397
|
+
const midChore = sortedArray[middle];
|
|
4398
|
+
const comp = choreComparator(value, midChore, rootVNode);
|
|
4399
|
+
if (comp < 0) {
|
|
4400
|
+
top = middle;
|
|
4401
|
+
}
|
|
4402
|
+
else if (comp > 0) {
|
|
4403
|
+
bottom = middle + 1;
|
|
4404
|
+
}
|
|
4405
|
+
else {
|
|
4406
|
+
// We already have the host in the queue.
|
|
4407
|
+
return middle;
|
|
4408
|
+
}
|
|
4409
|
+
}
|
|
4410
|
+
return ~bottom;
|
|
4241
4411
|
}
|
|
4242
|
-
|
|
4243
|
-
|
|
4412
|
+
function sortedInsert(sortedArray, value, rootVNode) {
|
|
4413
|
+
/// We need to ensure that the `queue` is sorted by priority.
|
|
4414
|
+
/// 1. Find a place where to insert into.
|
|
4415
|
+
const idx = sortedFindIndex(sortedArray, value, rootVNode);
|
|
4416
|
+
if (idx < 0) {
|
|
4417
|
+
/// 2. Insert the chore into the queue.
|
|
4418
|
+
sortedArray.splice(~idx, 0, value);
|
|
4419
|
+
return value;
|
|
4420
|
+
}
|
|
4421
|
+
const existing = sortedArray[idx];
|
|
4422
|
+
/**
|
|
4423
|
+
* When a derived signal is updated we need to run vnode_diff. However the signal can update
|
|
4424
|
+
* multiple times during component execution. For this reason it is necessary for us to update
|
|
4425
|
+
* the chore with the latest result of the signal.
|
|
4426
|
+
*/
|
|
4427
|
+
if (existing.$type$ === ChoreType.NODE_DIFF) {
|
|
4428
|
+
existing.$payload$ = value.$payload$;
|
|
4429
|
+
}
|
|
4430
|
+
if (existing.$executed$) {
|
|
4431
|
+
existing.$executed$ = false;
|
|
4432
|
+
}
|
|
4433
|
+
return existing;
|
|
4244
4434
|
}
|
|
4245
4435
|
};
|
|
4246
|
-
const
|
|
4247
|
-
|
|
4248
|
-
const taskHandler = createQRL(taskQrl.$chunk$, '_hW', _hW, null, null, [task], taskQrl.$symbol$);
|
|
4249
|
-
// Needed for chunk lookup in dev mode
|
|
4250
|
-
if (taskQrl.dev) {
|
|
4251
|
-
taskHandler.dev = taskQrl.dev;
|
|
4252
|
-
}
|
|
4253
|
-
return taskHandler;
|
|
4436
|
+
const toNumber = (value) => {
|
|
4437
|
+
return typeof value === 'number' ? value : -1;
|
|
4254
4438
|
};
|
|
4255
|
-
|
|
4256
|
-
$
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4439
|
+
function vNodeAlreadyDeleted(chore) {
|
|
4440
|
+
return !!(chore.$host$ &&
|
|
4441
|
+
vnode_isVNode(chore.$host$) &&
|
|
4442
|
+
chore.$host$[VNodeProps.flags] & VNodeFlags.Deleted);
|
|
4443
|
+
}
|
|
4444
|
+
function debugChoreTypeToString(type) {
|
|
4445
|
+
return ({
|
|
4446
|
+
[ChoreType.QRL_RESOLVE]: 'QRL_RESOLVE',
|
|
4447
|
+
[ChoreType.RUN_QRL]: 'RUN_QRL',
|
|
4448
|
+
[ChoreType.TASK]: 'TASK',
|
|
4449
|
+
[ChoreType.NODE_DIFF]: 'NODE_DIFF',
|
|
4450
|
+
[ChoreType.NODE_PROP]: 'NODE_PROP',
|
|
4451
|
+
[ChoreType.COMPONENT]: 'COMPONENT',
|
|
4452
|
+
[ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS]: 'RECOMPUTE_SIGNAL',
|
|
4453
|
+
[ChoreType.JOURNAL_FLUSH]: 'JOURNAL_FLUSH',
|
|
4454
|
+
[ChoreType.VISIBLE]: 'VISIBLE',
|
|
4455
|
+
[ChoreType.CLEANUP_VISIBLE]: 'CLEANUP_VISIBLE',
|
|
4456
|
+
[ChoreType.WAIT_FOR_ALL]: 'WAIT_FOR_ALL',
|
|
4457
|
+
}[type] || 'UNKNOWN: ' + type);
|
|
4458
|
+
}
|
|
4459
|
+
function debugChoreToString(chore) {
|
|
4460
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
4461
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
4462
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
4463
|
+
return `Chore(${type} ${chore.$type$ === ChoreType.QRL_RESOLVE || chore.$type$ === ChoreType.RUN_QRL ? qrlTarget : host} ${chore.$idx$})`;
|
|
4464
|
+
}
|
|
4465
|
+
function debugTrace(action, arg, currentChore, queue) {
|
|
4466
|
+
const lines = ['===========================\nScheduler: ' + action];
|
|
4467
|
+
if (arg && !('$type$' in arg)) {
|
|
4468
|
+
lines.push(' arg: ' + String(arg).replaceAll(/\n.*/gim, ''));
|
|
4469
|
+
}
|
|
4470
|
+
if (queue) {
|
|
4471
|
+
queue.forEach((chore) => {
|
|
4472
|
+
const active = chore === arg ? '>>>' : ' ';
|
|
4473
|
+
lines.push(` ${active} > ` +
|
|
4474
|
+
(chore === currentChore ? '[running] ' : '') +
|
|
4475
|
+
debugChoreToString(chore));
|
|
4476
|
+
});
|
|
4270
4477
|
}
|
|
4478
|
+
// eslint-disable-next-line no-console
|
|
4479
|
+
console.log(lines.join('\n') + '\n');
|
|
4271
4480
|
}
|
|
4272
|
-
const isTask = (value) => {
|
|
4273
|
-
return value instanceof Task;
|
|
4274
|
-
};
|
|
4275
|
-
/**
|
|
4276
|
-
* Low-level API used by the Optimizer to process `useTask$()` API. This method is not intended to
|
|
4277
|
-
* be used by developers.
|
|
4278
|
-
*
|
|
4279
|
-
* @internal
|
|
4280
|
-
*/
|
|
4281
|
-
const _hW = () => {
|
|
4282
|
-
const [task] = useLexicalScope();
|
|
4283
|
-
const container = getDomContainer(task.$el$);
|
|
4284
|
-
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
|
|
4285
|
-
container.$scheduler$(type, task);
|
|
4286
|
-
};
|
|
4287
|
-
|
|
4288
|
-
/**
|
|
4289
|
-
* Special value used to mark that a given signal needs to be computed. This is essentially a
|
|
4290
|
-
* "marked as dirty" flag.
|
|
4291
|
-
*/
|
|
4292
|
-
const NEEDS_COMPUTATION = Symbol('invalid');
|
|
4293
4481
|
|
|
4294
4482
|
/**
|
|
4295
4483
|
* @file
|
|
@@ -4307,6 +4495,15 @@ const NEEDS_COMPUTATION = Symbol('invalid');
|
|
|
4307
4495
|
const DEBUG = false;
|
|
4308
4496
|
// eslint-disable-next-line no-console
|
|
4309
4497
|
const log = (...args) => console.log('SIGNAL', ...args.map(qwikDebugToString));
|
|
4498
|
+
var SignalFlags;
|
|
4499
|
+
(function (SignalFlags) {
|
|
4500
|
+
SignalFlags[SignalFlags["INVALID"] = 1] = "INVALID";
|
|
4501
|
+
})(SignalFlags || (SignalFlags = {}));
|
|
4502
|
+
var WrappedSignalFlags;
|
|
4503
|
+
(function (WrappedSignalFlags) {
|
|
4504
|
+
// should subscribe to value and be unwrapped for PropsProxy
|
|
4505
|
+
WrappedSignalFlags[WrappedSignalFlags["UNWRAP"] = 2] = "UNWRAP";
|
|
4506
|
+
})(WrappedSignalFlags || (WrappedSignalFlags = {}));
|
|
4310
4507
|
const throwIfQRLNotResolved = (qrl) => {
|
|
4311
4508
|
const resolved = qrl.resolved;
|
|
4312
4509
|
if (!resolved) {
|
|
@@ -4323,18 +4520,19 @@ const isSignal = (value) => {
|
|
|
4323
4520
|
return value instanceof Signal;
|
|
4324
4521
|
};
|
|
4325
4522
|
/** @internal */
|
|
4326
|
-
class
|
|
4523
|
+
class SubscriptionData {
|
|
4327
4524
|
data;
|
|
4328
4525
|
constructor(data) {
|
|
4329
4526
|
this.data = data;
|
|
4330
4527
|
}
|
|
4331
4528
|
}
|
|
4332
|
-
var
|
|
4333
|
-
(function (
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4529
|
+
var EffectSubscriptionProp;
|
|
4530
|
+
(function (EffectSubscriptionProp) {
|
|
4531
|
+
EffectSubscriptionProp[EffectSubscriptionProp["CONSUMER"] = 0] = "CONSUMER";
|
|
4532
|
+
EffectSubscriptionProp[EffectSubscriptionProp["PROPERTY"] = 1] = "PROPERTY";
|
|
4533
|
+
EffectSubscriptionProp[EffectSubscriptionProp["BACK_REF"] = 2] = "BACK_REF";
|
|
4534
|
+
EffectSubscriptionProp[EffectSubscriptionProp["DATA"] = 3] = "DATA";
|
|
4535
|
+
})(EffectSubscriptionProp || (EffectSubscriptionProp = {}));
|
|
4338
4536
|
var EffectProperty;
|
|
4339
4537
|
(function (EffectProperty) {
|
|
4340
4538
|
EffectProperty["COMPONENT"] = ":";
|
|
@@ -4371,19 +4569,16 @@ class Signal {
|
|
|
4371
4569
|
}
|
|
4372
4570
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
4373
4571
|
if (effectSubscriber) {
|
|
4374
|
-
const effects = (this.$effects$ ||=
|
|
4572
|
+
const effects = (this.$effects$ ||= new Set());
|
|
4375
4573
|
// Let's make sure that we have a reference to this effect.
|
|
4376
4574
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
4377
4575
|
// changes we know who to notify.
|
|
4378
|
-
|
|
4576
|
+
ensureContainsSubscription(effects, effectSubscriber);
|
|
4379
4577
|
// But when effect is scheduled in needs to be able to know which signals
|
|
4380
4578
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
4381
4579
|
// to this signal.
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
// We need to add the subscriber to the effect so that we can clean it up later
|
|
4385
|
-
ensureEffectContainsSubscriber(effectSubscriber[EffectSubscriptionsProp.EFFECT], this, this.$container$);
|
|
4386
|
-
}
|
|
4580
|
+
ensureContainsBackRef(effectSubscriber, this);
|
|
4581
|
+
addQrlToSerializationCtx(effectSubscriber, this.$container$);
|
|
4387
4582
|
}
|
|
4388
4583
|
}
|
|
4389
4584
|
return this.untrackedValue;
|
|
@@ -4401,123 +4596,98 @@ class Signal {
|
|
|
4401
4596
|
}
|
|
4402
4597
|
}
|
|
4403
4598
|
toString() {
|
|
4404
|
-
return (`[${this.constructor.name}${this.$
|
|
4405
|
-
(this.$effects
|
|
4599
|
+
return (`[${this.constructor.name}${this.$flags$ & SignalFlags.INVALID ? ' INVALID' : ''} ${String(this.$untrackedValue$)}]` +
|
|
4600
|
+
(Array.from(this.$effects$ || [])
|
|
4601
|
+
.map((e) => '\n -> ' + pad(qwikDebugToString(e[0]), ' '))
|
|
4602
|
+
.join('\n') || ''));
|
|
4406
4603
|
}
|
|
4407
4604
|
toJSON() {
|
|
4408
4605
|
return { value: this.$untrackedValue$ };
|
|
4409
4606
|
}
|
|
4410
4607
|
}
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
const isMissing = array.indexOf(value) === -1;
|
|
4414
|
-
if (isMissing) {
|
|
4415
|
-
array.push(value);
|
|
4416
|
-
}
|
|
4417
|
-
};
|
|
4418
|
-
const ensureContainsEffect = (array, effectSubscriptions) => {
|
|
4419
|
-
for (let i = 0; i < array.length; i++) {
|
|
4420
|
-
const existingEffect = array[i];
|
|
4421
|
-
if (existingEffect[0] === effectSubscriptions[0] &&
|
|
4422
|
-
existingEffect[1] === effectSubscriptions[1]) {
|
|
4423
|
-
return;
|
|
4424
|
-
}
|
|
4425
|
-
}
|
|
4426
|
-
array.push(effectSubscriptions);
|
|
4608
|
+
const ensureContainsSubscription = (array, effectSubscription) => {
|
|
4609
|
+
array.add(effectSubscription);
|
|
4427
4610
|
};
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4611
|
+
/** Ensure the item is in back refs set */
|
|
4612
|
+
const ensureContainsBackRef = (array, value) => {
|
|
4613
|
+
array[EffectSubscriptionProp.BACK_REF] ||= new Set();
|
|
4614
|
+
array[EffectSubscriptionProp.BACK_REF].add(value);
|
|
4615
|
+
};
|
|
4616
|
+
const addQrlToSerializationCtx = (effectSubscriber, container) => {
|
|
4617
|
+
if (!!container && !isDomContainer(container)) {
|
|
4618
|
+
const effect = effectSubscriber[EffectSubscriptionProp.CONSUMER];
|
|
4619
|
+
const property = effectSubscriber[EffectSubscriptionProp.PROPERTY];
|
|
4620
|
+
let qrl = null;
|
|
4621
|
+
if (isTask(effect)) {
|
|
4622
|
+
qrl = effect.$qrl$;
|
|
4433
4623
|
}
|
|
4434
|
-
effect
|
|
4435
|
-
|
|
4436
|
-
else if (vnode_isVNode(effect) && !vnode_isTextVNode(effect)) {
|
|
4437
|
-
let subscribers = vnode_getProp(effect, QSubscribers, container ? container.$getObjectById$ : null);
|
|
4438
|
-
subscribers ||= [];
|
|
4439
|
-
if (subscriberExistInSubscribers(subscribers, subscriber)) {
|
|
4440
|
-
return;
|
|
4624
|
+
else if (effect instanceof ComputedSignal) {
|
|
4625
|
+
qrl = effect.$computeQrl$;
|
|
4441
4626
|
}
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
}
|
|
4445
|
-
else if (isSSRNode(effect)) {
|
|
4446
|
-
let subscribers = effect.getProp(QSubscribers);
|
|
4447
|
-
subscribers ||= [];
|
|
4448
|
-
if (subscriberExistInSubscribers(subscribers, subscriber)) {
|
|
4449
|
-
return;
|
|
4627
|
+
else if (property === EffectProperty.COMPONENT) {
|
|
4628
|
+
qrl = container.getHostProp(effect, OnRenderProp);
|
|
4450
4629
|
}
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
}
|
|
4454
|
-
};
|
|
4455
|
-
const isSSRNode = (effect) => {
|
|
4456
|
-
return 'setProp' in effect && 'getProp' in effect && 'removeProp' in effect && 'id' in effect;
|
|
4457
|
-
};
|
|
4458
|
-
const subscriberExistInSubscribers = (subscribers, subscriber) => {
|
|
4459
|
-
for (let i = 0; i < subscribers.length; i++) {
|
|
4460
|
-
if (subscribers[i] === subscriber) {
|
|
4461
|
-
return true;
|
|
4630
|
+
if (qrl) {
|
|
4631
|
+
container.serializationCtx.$eventQrls$.add(qrl);
|
|
4462
4632
|
}
|
|
4463
4633
|
}
|
|
4464
|
-
return false;
|
|
4465
4634
|
};
|
|
4466
4635
|
const triggerEffects = (container, signal, effects) => {
|
|
4636
|
+
const isBrowser = isDomContainer(container);
|
|
4467
4637
|
if (effects) {
|
|
4468
|
-
const scheduleEffect = (
|
|
4469
|
-
const
|
|
4470
|
-
const property =
|
|
4638
|
+
const scheduleEffect = (effectSubscription) => {
|
|
4639
|
+
const consumer = effectSubscription[EffectSubscriptionProp.CONSUMER];
|
|
4640
|
+
const property = effectSubscription[EffectSubscriptionProp.PROPERTY];
|
|
4471
4641
|
assertDefined(container, 'Container must be defined.');
|
|
4472
|
-
if (isTask(
|
|
4473
|
-
|
|
4642
|
+
if (isTask(consumer)) {
|
|
4643
|
+
consumer.$flags$ |= TaskFlags.DIRTY;
|
|
4474
4644
|
let choreType = ChoreType.TASK;
|
|
4475
|
-
if (
|
|
4645
|
+
if (consumer.$flags$ & TaskFlags.VISIBLE_TASK) {
|
|
4476
4646
|
choreType = ChoreType.VISIBLE;
|
|
4477
4647
|
}
|
|
4478
|
-
|
|
4479
|
-
choreType = ChoreType.RESOURCE;
|
|
4480
|
-
}
|
|
4481
|
-
container.$scheduler$(choreType, effect);
|
|
4648
|
+
container.$scheduler$(choreType, consumer);
|
|
4482
4649
|
}
|
|
4483
|
-
else if (
|
|
4650
|
+
else if (consumer instanceof Signal) {
|
|
4484
4651
|
// we don't schedule ComputedSignal/DerivedSignal directly, instead we invalidate it and
|
|
4485
4652
|
// and schedule the signals effects (recursively)
|
|
4486
|
-
if (
|
|
4653
|
+
if (consumer instanceof ComputedSignal) {
|
|
4487
4654
|
// Ensure that the computed signal's QRL is resolved.
|
|
4488
4655
|
// If not resolved schedule it to be resolved.
|
|
4489
|
-
if (!
|
|
4490
|
-
container.$scheduler$(ChoreType.QRL_RESOLVE, null,
|
|
4656
|
+
if (!consumer.$computeQrl$.resolved) {
|
|
4657
|
+
container.$scheduler$(ChoreType.QRL_RESOLVE, null, consumer.$computeQrl$);
|
|
4491
4658
|
}
|
|
4492
4659
|
}
|
|
4493
|
-
|
|
4660
|
+
consumer.$invalidate$();
|
|
4494
4661
|
}
|
|
4495
4662
|
else if (property === EffectProperty.COMPONENT) {
|
|
4496
|
-
const host =
|
|
4663
|
+
const host = consumer;
|
|
4497
4664
|
const qrl = container.getHostProp(host, OnRenderProp);
|
|
4498
4665
|
assertDefined(qrl, 'Component must have QRL');
|
|
4499
4666
|
const props = container.getHostProp(host, ELEMENT_PROPS);
|
|
4500
4667
|
container.$scheduler$(ChoreType.COMPONENT, host, qrl, props);
|
|
4501
4668
|
}
|
|
4502
|
-
else if (
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4669
|
+
else if (isBrowser) {
|
|
4670
|
+
if (property === EffectProperty.VNODE) {
|
|
4671
|
+
const host = consumer;
|
|
4672
|
+
container.$scheduler$(ChoreType.NODE_DIFF, host, host, signal);
|
|
4673
|
+
}
|
|
4674
|
+
else {
|
|
4675
|
+
const host = consumer;
|
|
4676
|
+
const effectData = effectSubscription[EffectSubscriptionProp.DATA];
|
|
4677
|
+
if (effectData instanceof SubscriptionData) {
|
|
4678
|
+
const data = effectData.data;
|
|
4679
|
+
const payload = {
|
|
4680
|
+
...data,
|
|
4681
|
+
$value$: signal,
|
|
4682
|
+
};
|
|
4683
|
+
container.$scheduler$(ChoreType.NODE_PROP, host, property, payload);
|
|
4684
|
+
}
|
|
4517
4685
|
}
|
|
4518
4686
|
}
|
|
4519
4687
|
};
|
|
4520
|
-
effects
|
|
4688
|
+
for (const effect of effects) {
|
|
4689
|
+
scheduleEffect(effect);
|
|
4690
|
+
}
|
|
4521
4691
|
}
|
|
4522
4692
|
};
|
|
4523
4693
|
/**
|
|
@@ -4533,18 +4703,21 @@ class ComputedSignal extends Signal {
|
|
|
4533
4703
|
* resolve the QRL during the mark dirty phase so that any call to it will be synchronous). )
|
|
4534
4704
|
*/
|
|
4535
4705
|
$computeQrl$;
|
|
4706
|
+
$flags$;
|
|
4707
|
+
$forceRunEffects$ = false;
|
|
4708
|
+
[_EFFECT_BACK_REF] = null;
|
|
4709
|
+
constructor(container, fn,
|
|
4536
4710
|
// We need a separate flag to know when the computation needs running because
|
|
4537
4711
|
// we need the old value to know if effects need running after computation
|
|
4538
|
-
|
|
4539
|
-
$forceRunEffects$ = false;
|
|
4540
|
-
constructor(container, fn) {
|
|
4712
|
+
flags = SignalFlags.INVALID) {
|
|
4541
4713
|
// The value is used for comparison when signals trigger, which can only happen
|
|
4542
4714
|
// when it was calculated before. Therefore we can pass whatever we like.
|
|
4543
4715
|
super(container, NEEDS_COMPUTATION);
|
|
4544
4716
|
this.$computeQrl$ = fn;
|
|
4717
|
+
this.$flags$ = flags;
|
|
4545
4718
|
}
|
|
4546
4719
|
$invalidate$() {
|
|
4547
|
-
this.$
|
|
4720
|
+
this.$flags$ |= SignalFlags.INVALID;
|
|
4548
4721
|
this.$forceRunEffects$ = false;
|
|
4549
4722
|
// We should only call subscribers if the calculation actually changed.
|
|
4550
4723
|
// Therefore, we need to calculate the value now.
|
|
@@ -4555,7 +4728,7 @@ class ComputedSignal extends Signal {
|
|
|
4555
4728
|
* remained the same object
|
|
4556
4729
|
*/
|
|
4557
4730
|
force() {
|
|
4558
|
-
this.$
|
|
4731
|
+
this.$flags$ |= SignalFlags.INVALID;
|
|
4559
4732
|
this.$forceRunEffects$ = false;
|
|
4560
4733
|
triggerEffects(this.$container$, this, this.$effects$);
|
|
4561
4734
|
}
|
|
@@ -4568,14 +4741,14 @@ class ComputedSignal extends Signal {
|
|
|
4568
4741
|
return this.$untrackedValue$;
|
|
4569
4742
|
}
|
|
4570
4743
|
$computeIfNeeded$() {
|
|
4571
|
-
if (!this.$
|
|
4744
|
+
if (!(this.$flags$ & SignalFlags.INVALID)) {
|
|
4572
4745
|
return false;
|
|
4573
4746
|
}
|
|
4574
4747
|
const computeQrl = this.$computeQrl$;
|
|
4575
4748
|
throwIfQRLNotResolved(computeQrl);
|
|
4576
4749
|
const ctx = tryGetInvokeContext();
|
|
4577
4750
|
const previousEffectSubscription = ctx?.$effectSubscriber$;
|
|
4578
|
-
ctx && (ctx.$effectSubscriber$ =
|
|
4751
|
+
ctx && (ctx.$effectSubscriber$ = getSubscriber(this, EffectProperty.VNODE));
|
|
4579
4752
|
try {
|
|
4580
4753
|
const untrackedValue = computeQrl.getFn(ctx)();
|
|
4581
4754
|
if (isPromise(untrackedValue)) {
|
|
@@ -4585,7 +4758,7 @@ class ComputedSignal extends Signal {
|
|
|
4585
4758
|
]);
|
|
4586
4759
|
}
|
|
4587
4760
|
DEBUG && log('Signal.$compute$', untrackedValue);
|
|
4588
|
-
this.$
|
|
4761
|
+
this.$flags$ &= ~SignalFlags.INVALID;
|
|
4589
4762
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
4590
4763
|
if (didChange) {
|
|
4591
4764
|
this.$untrackedValue$ = untrackedValue;
|
|
@@ -4610,20 +4783,22 @@ class WrappedSignal extends Signal {
|
|
|
4610
4783
|
$args$;
|
|
4611
4784
|
$func$;
|
|
4612
4785
|
$funcStr$;
|
|
4613
|
-
|
|
4614
|
-
// we need the old value to know if effects need running after computation
|
|
4615
|
-
$invalid$ = true;
|
|
4616
|
-
$effectDependencies$ = null;
|
|
4786
|
+
$flags$;
|
|
4617
4787
|
$hostElement$ = null;
|
|
4618
4788
|
$forceRunEffects$ = false;
|
|
4619
|
-
|
|
4789
|
+
[_EFFECT_BACK_REF] = null;
|
|
4790
|
+
constructor(container, fn, args, fnStr,
|
|
4791
|
+
// We need a separate flag to know when the computation needs running because
|
|
4792
|
+
// we need the old value to know if effects need running after computation
|
|
4793
|
+
flags = SignalFlags.INVALID | WrappedSignalFlags.UNWRAP) {
|
|
4620
4794
|
super(container, NEEDS_COMPUTATION);
|
|
4621
4795
|
this.$args$ = args;
|
|
4622
4796
|
this.$func$ = fn;
|
|
4623
4797
|
this.$funcStr$ = fnStr;
|
|
4798
|
+
this.$flags$ = flags;
|
|
4624
4799
|
}
|
|
4625
4800
|
$invalidate$() {
|
|
4626
|
-
this.$
|
|
4801
|
+
this.$flags$ |= SignalFlags.INVALID;
|
|
4627
4802
|
this.$forceRunEffects$ = false;
|
|
4628
4803
|
// We should only call subscribers if the calculation actually changed.
|
|
4629
4804
|
// Therefore, we need to calculate the value now.
|
|
@@ -4634,7 +4809,7 @@ class WrappedSignal extends Signal {
|
|
|
4634
4809
|
* remained the same object
|
|
4635
4810
|
*/
|
|
4636
4811
|
force() {
|
|
4637
|
-
this.$
|
|
4812
|
+
this.$flags$ |= SignalFlags.INVALID;
|
|
4638
4813
|
this.$forceRunEffects$ = false;
|
|
4639
4814
|
triggerEffects(this.$container$, this, this.$effects$);
|
|
4640
4815
|
}
|
|
@@ -4647,10 +4822,12 @@ class WrappedSignal extends Signal {
|
|
|
4647
4822
|
return this.$untrackedValue$;
|
|
4648
4823
|
}
|
|
4649
4824
|
$computeIfNeeded$() {
|
|
4650
|
-
if (!this.$
|
|
4825
|
+
if (!(this.$flags$ & SignalFlags.INVALID)) {
|
|
4651
4826
|
return false;
|
|
4652
4827
|
}
|
|
4653
4828
|
const untrackedValue = trackSignal(() => this.$func$(...this.$args$), this, EffectProperty.VNODE, this.$container$);
|
|
4829
|
+
// TODO: we should remove invalid flag here
|
|
4830
|
+
// this.$flags$ &= ~SignalFlags.INVALID;
|
|
4654
4831
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
4655
4832
|
if (didChange) {
|
|
4656
4833
|
this.$untrackedValue$ = untrackedValue;
|
|
@@ -4683,7 +4860,7 @@ const applyQwikComponentBody = (ssr, jsx, component) => {
|
|
|
4683
4860
|
if (jsx.key !== null) {
|
|
4684
4861
|
host.setProp(ELEMENT_KEY, jsx.key);
|
|
4685
4862
|
}
|
|
4686
|
-
return scheduler(ChoreType.
|
|
4863
|
+
return scheduler(ChoreType.COMPONENT, host, componentQrl, srcProps);
|
|
4687
4864
|
};
|
|
4688
4865
|
|
|
4689
4866
|
class ParentComponentData {
|
|
@@ -4695,21 +4872,10 @@ class ParentComponentData {
|
|
|
4695
4872
|
}
|
|
4696
4873
|
}
|
|
4697
4874
|
/** @internal */
|
|
4698
|
-
function _walkJSX(ssr, value, options) {
|
|
4875
|
+
async function _walkJSX(ssr, value, options) {
|
|
4699
4876
|
const stack = [value];
|
|
4700
|
-
let resolveDrain;
|
|
4701
|
-
let rejectDrain;
|
|
4702
|
-
const drained = options.allowPromises &&
|
|
4703
|
-
new Promise((res, rej) => {
|
|
4704
|
-
resolveDrain = res;
|
|
4705
|
-
rejectDrain = rej;
|
|
4706
|
-
});
|
|
4707
4877
|
const enqueue = (value) => stack.push(value);
|
|
4708
|
-
const
|
|
4709
|
-
stack.push(value);
|
|
4710
|
-
drain();
|
|
4711
|
-
};
|
|
4712
|
-
const drain = () => {
|
|
4878
|
+
const drain = async () => {
|
|
4713
4879
|
while (stack.length) {
|
|
4714
4880
|
const value = stack.pop();
|
|
4715
4881
|
if (value instanceof ParentComponentData) {
|
|
@@ -4719,20 +4885,10 @@ function _walkJSX(ssr, value, options) {
|
|
|
4719
4885
|
}
|
|
4720
4886
|
else if (typeof value === 'function') {
|
|
4721
4887
|
if (value === Promise) {
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
}
|
|
4725
|
-
stack.pop().then(resolveValue, rejectDrain);
|
|
4726
|
-
return;
|
|
4727
|
-
}
|
|
4728
|
-
const waitOn = value.apply(ssr);
|
|
4729
|
-
if (waitOn) {
|
|
4730
|
-
if (!options.allowPromises) {
|
|
4731
|
-
throw qError(QError.promisesNotExpected);
|
|
4732
|
-
}
|
|
4733
|
-
waitOn.then(drain, rejectDrain);
|
|
4734
|
-
return;
|
|
4888
|
+
stack.push(await stack.pop());
|
|
4889
|
+
continue;
|
|
4735
4890
|
}
|
|
4891
|
+
await value.apply(ssr);
|
|
4736
4892
|
continue;
|
|
4737
4893
|
}
|
|
4738
4894
|
processJSXNode(ssr, enqueue, value, {
|
|
@@ -4740,12 +4896,8 @@ function _walkJSX(ssr, value, options) {
|
|
|
4740
4896
|
parentComponentFrame: options.parentComponentFrame,
|
|
4741
4897
|
});
|
|
4742
4898
|
}
|
|
4743
|
-
if (stack.length === 0 && options.allowPromises) {
|
|
4744
|
-
resolveDrain();
|
|
4745
|
-
}
|
|
4746
4899
|
};
|
|
4747
|
-
drain();
|
|
4748
|
-
return drained;
|
|
4900
|
+
await drain();
|
|
4749
4901
|
}
|
|
4750
4902
|
function processJSXNode(ssr, enqueue, value, options) {
|
|
4751
4903
|
// console.log('processJSXNode', value);
|
|
@@ -4784,7 +4936,6 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
4784
4936
|
enqueue(async () => {
|
|
4785
4937
|
for await (const chunk of value) {
|
|
4786
4938
|
await _walkJSX(ssr, chunk, {
|
|
4787
|
-
allowPromises: true,
|
|
4788
4939
|
currentStyleScoped: options.styleScoped,
|
|
4789
4940
|
parentComponentFrame: options.parentComponentFrame,
|
|
4790
4941
|
});
|
|
@@ -4838,7 +4989,7 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
4838
4989
|
if (componentFrame) {
|
|
4839
4990
|
const compId = componentFrame.componentNode.id || '';
|
|
4840
4991
|
const projectionAttrs = isDev ? [DEBUG_TYPE, VirtualType.Projection] : [];
|
|
4841
|
-
projectionAttrs.push(
|
|
4992
|
+
projectionAttrs.push(QSlotParent, compId);
|
|
4842
4993
|
ssr.openProjection(projectionAttrs);
|
|
4843
4994
|
const host = componentFrame.componentNode;
|
|
4844
4995
|
const node = ssr.getLastNode();
|
|
@@ -4871,7 +5022,6 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
4871
5022
|
value = generator({
|
|
4872
5023
|
async write(chunk) {
|
|
4873
5024
|
await _walkJSX(ssr, chunk, {
|
|
4874
|
-
allowPromises: true,
|
|
4875
5025
|
currentStyleScoped: options.styleScoped,
|
|
4876
5026
|
parentComponentFrame: options.parentComponentFrame,
|
|
4877
5027
|
});
|
|
@@ -5028,11 +5178,23 @@ function setEvent(serializationCtx, key, rawValue) {
|
|
|
5028
5178
|
const appendToValue = (valueToAppend) => {
|
|
5029
5179
|
value = (value == null ? '' : value + '\n') + valueToAppend;
|
|
5030
5180
|
};
|
|
5181
|
+
const getQrlString = (qrl) => {
|
|
5182
|
+
/**
|
|
5183
|
+
* If there are captures we need to schedule so everything is executed in the right order + qrls
|
|
5184
|
+
* are resolved.
|
|
5185
|
+
*
|
|
5186
|
+
* For internal qrls (starting with `_`) we assume that they do the right thing.
|
|
5187
|
+
*/
|
|
5188
|
+
if (!qrl.$symbol$.startsWith('_') && (qrl.$captureRef$ || qrl.$capture$)) {
|
|
5189
|
+
qrl = createQRL(null, '_run', queueQRL, null, null, [qrl]);
|
|
5190
|
+
}
|
|
5191
|
+
return qrlToString(serializationCtx, qrl);
|
|
5192
|
+
};
|
|
5031
5193
|
if (Array.isArray(qrls)) {
|
|
5032
5194
|
for (let i = 0; i <= qrls.length; i++) {
|
|
5033
5195
|
const qrl = qrls[i];
|
|
5034
|
-
if (isQrl(qrl)) {
|
|
5035
|
-
appendToValue(
|
|
5196
|
+
if (isQrl$1(qrl)) {
|
|
5197
|
+
appendToValue(getQrlString(qrl));
|
|
5036
5198
|
addQwikEventToSerializationContext(serializationCtx, key, qrl);
|
|
5037
5199
|
}
|
|
5038
5200
|
else if (qrl != null) {
|
|
@@ -5044,8 +5206,8 @@ function setEvent(serializationCtx, key, rawValue) {
|
|
|
5044
5206
|
}
|
|
5045
5207
|
}
|
|
5046
5208
|
}
|
|
5047
|
-
else if (isQrl(qrls)) {
|
|
5048
|
-
value =
|
|
5209
|
+
else if (isQrl$1(qrls)) {
|
|
5210
|
+
value = getQrlString(qrls);
|
|
5049
5211
|
addQwikEventToSerializationContext(serializationCtx, key, qrls);
|
|
5050
5212
|
}
|
|
5051
5213
|
return value;
|
|
@@ -5095,7 +5257,7 @@ function appendClassIfScopedStyleExists(jsx, styleScoped) {
|
|
|
5095
5257
|
*
|
|
5096
5258
|
* @public
|
|
5097
5259
|
*/
|
|
5098
|
-
const version = "2.0.0-alpha.
|
|
5260
|
+
const version = "2.0.0-alpha.8-dev+66037b5";
|
|
5099
5261
|
|
|
5100
5262
|
/** @internal */
|
|
5101
5263
|
class _SharedContainer {
|
|
@@ -5127,13 +5289,6 @@ class _SharedContainer {
|
|
|
5127
5289
|
}
|
|
5128
5290
|
}
|
|
5129
5291
|
|
|
5130
|
-
/** @internal */
|
|
5131
|
-
const _CONST_PROPS = Symbol('CONST');
|
|
5132
|
-
/** @internal */
|
|
5133
|
-
const _VAR_PROPS = Symbol('VAR');
|
|
5134
|
-
/** @internal @deprecated v1 compat */
|
|
5135
|
-
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
5136
|
-
|
|
5137
5292
|
// Keep these properties named like this so they're the same as from wrapSignal
|
|
5138
5293
|
const getValueProp = (p0) => p0.value;
|
|
5139
5294
|
const getProp = (p0, p1) => p0[p1];
|
|
@@ -5157,7 +5312,7 @@ const _wrapProp = (...args) => {
|
|
|
5157
5312
|
}
|
|
5158
5313
|
if (isSignal(obj)) {
|
|
5159
5314
|
assertEqual(prop, 'value', 'Left side is a signal, prop must be value');
|
|
5160
|
-
if (obj instanceof WrappedSignal) {
|
|
5315
|
+
if (obj instanceof WrappedSignal && obj.flags & WrappedSignalFlags.UNWRAP) {
|
|
5161
5316
|
return obj;
|
|
5162
5317
|
}
|
|
5163
5318
|
return getWrapped(args);
|
|
@@ -5183,6 +5338,17 @@ const _wrapProp = (...args) => {
|
|
|
5183
5338
|
// We need to forward the access to the original object
|
|
5184
5339
|
return getWrapped(args);
|
|
5185
5340
|
};
|
|
5341
|
+
/** @internal */
|
|
5342
|
+
const _wrapStore = (obj, prop) => {
|
|
5343
|
+
const target = getStoreTarget(obj);
|
|
5344
|
+
const value = target[prop];
|
|
5345
|
+
if (isSignal(value)) {
|
|
5346
|
+
return value;
|
|
5347
|
+
}
|
|
5348
|
+
else {
|
|
5349
|
+
return new WrappedSignal(null, getProp, [obj, prop], null, SignalFlags.INVALID);
|
|
5350
|
+
}
|
|
5351
|
+
};
|
|
5186
5352
|
/** @internal @deprecated v1 compat */
|
|
5187
5353
|
const _wrapSignal = (obj, prop) => {
|
|
5188
5354
|
const r = _wrapProp(obj, prop);
|
|
@@ -5453,7 +5619,9 @@ class PropsProxyHandler {
|
|
|
5453
5619
|
? this.$constProps$[prop]
|
|
5454
5620
|
: this.$varProps$[prop];
|
|
5455
5621
|
// a proxied value that the optimizer made
|
|
5456
|
-
return value instanceof WrappedSignal
|
|
5622
|
+
return value instanceof WrappedSignal && value.$flags$ & WrappedSignalFlags.UNWRAP
|
|
5623
|
+
? value.value
|
|
5624
|
+
: value;
|
|
5457
5625
|
}
|
|
5458
5626
|
set(_, prop, value) {
|
|
5459
5627
|
if (prop === _CONST_PROPS) {
|
|
@@ -5545,7 +5713,7 @@ function qwikDebugToString(value) {
|
|
|
5545
5713
|
else if (isTask(value)) {
|
|
5546
5714
|
return `Task(${qwikDebugToString(value.$qrl$)})`;
|
|
5547
5715
|
}
|
|
5548
|
-
else if (isQrl
|
|
5716
|
+
else if (isQrl(value)) {
|
|
5549
5717
|
return `Qrl(${value.$symbol$})`;
|
|
5550
5718
|
}
|
|
5551
5719
|
else if (typeof value === 'object' || typeof value === 'function') {
|
|
@@ -5687,8 +5855,8 @@ const VNodeDataChar = {
|
|
|
5687
5855
|
ID_CHAR: /* ********* */ '=',
|
|
5688
5856
|
PROPS: /* ************** */ 62, // `>` - `q:props' - Component Props
|
|
5689
5857
|
PROPS_CHAR: /* ****** */ '>',
|
|
5690
|
-
|
|
5691
|
-
|
|
5858
|
+
SLOT_PARENT: /* ******** */ 63, // `?` - `q:sparent` - Slot parent.
|
|
5859
|
+
SLOT_PARENT_CHAR: /* */ '?',
|
|
5692
5860
|
KEY: /* **************** */ 64, // `@` - `q:key` - Element key.
|
|
5693
5861
|
KEY_CHAR: /* ******** */ '@',
|
|
5694
5862
|
SEQ: /* **************** */ 91, // `[` - `q:seq' - Seq value from `useSequentialScope()`
|
|
@@ -5699,14 +5867,21 @@ const VNodeDataChar = {
|
|
|
5699
5867
|
CONTEXT_CHAR: /* **** */ ']',
|
|
5700
5868
|
SEQ_IDX: /* ************ */ 94, // `^` - `q:seqIdx' - Sequential scope id
|
|
5701
5869
|
SEQ_IDX_CHAR: /* **** */ '^',
|
|
5702
|
-
|
|
5703
|
-
|
|
5870
|
+
BACK_REFS: /* ********** */ 96, // '`' - `q:brefs' - Effect dependencies/subscriptions
|
|
5871
|
+
BACK_REFS_CHAR: /* ** */ '`',
|
|
5704
5872
|
SEPARATOR: /* ********* */ 124, // `|` - Separator char to encode any key/value pairs.
|
|
5705
5873
|
SEPARATOR_CHAR: /* ** */ '|',
|
|
5706
5874
|
SLOT: /* ************** */ 126, // `~` - `q:slot' - Slot name
|
|
5707
5875
|
SLOT_CHAR: /* ******* */ '~',
|
|
5708
5876
|
};
|
|
5709
5877
|
|
|
5878
|
+
const mergeMaps = (map1, map2) => {
|
|
5879
|
+
for (const [k, v] of map2) {
|
|
5880
|
+
map1.set(k, v);
|
|
5881
|
+
}
|
|
5882
|
+
return map1;
|
|
5883
|
+
};
|
|
5884
|
+
|
|
5710
5885
|
/**
|
|
5711
5886
|
* @file
|
|
5712
5887
|
*
|
|
@@ -5929,6 +6104,12 @@ const vnode_isVirtualVNode = (vNode) => {
|
|
|
5929
6104
|
const flag = vNode[VNodeProps.flags];
|
|
5930
6105
|
return (flag & VNodeFlags.Virtual) === VNodeFlags.Virtual;
|
|
5931
6106
|
};
|
|
6107
|
+
const vnode_isProjection = (vNode) => {
|
|
6108
|
+
assertDefined(vNode, 'Missing vNode');
|
|
6109
|
+
const flag = vNode[VNodeProps.flags];
|
|
6110
|
+
return ((flag & VNodeFlags.Virtual) === VNodeFlags.Virtual &&
|
|
6111
|
+
vnode_getProp(vNode, QSlot, null) !== null);
|
|
6112
|
+
};
|
|
5932
6113
|
const ensureTextVNode = (vNode) => {
|
|
5933
6114
|
assertTrue(vnode_isTextVNode(vNode), 'Expecting TextVNode was: ' + vnode_getNodeTypeName(vNode));
|
|
5934
6115
|
return vNode;
|
|
@@ -5962,6 +6143,7 @@ const vnode_ensureElementInflated = (vnode) => {
|
|
|
5962
6143
|
elementVNode[VNodeProps.flags] ^= VNodeFlags.Inflated;
|
|
5963
6144
|
const element = elementVNode[ElementVNodeProps.element];
|
|
5964
6145
|
const attributes = element.attributes;
|
|
6146
|
+
const props = vnode_getProps(elementVNode);
|
|
5965
6147
|
for (let idx = 0; idx < attributes.length; idx++) {
|
|
5966
6148
|
const attr = attributes[idx];
|
|
5967
6149
|
const key = attr.name;
|
|
@@ -5972,15 +6154,15 @@ const vnode_ensureElementInflated = (vnode) => {
|
|
|
5972
6154
|
}
|
|
5973
6155
|
else if (key.startsWith(QContainerAttr)) {
|
|
5974
6156
|
if (attr.value === QContainerValue.HTML) {
|
|
5975
|
-
mapArray_set(
|
|
6157
|
+
mapArray_set(props, dangerouslySetInnerHTML, element.innerHTML, 0);
|
|
5976
6158
|
}
|
|
5977
6159
|
else if (attr.value === QContainerValue.TEXT && 'value' in element) {
|
|
5978
|
-
mapArray_set(
|
|
6160
|
+
mapArray_set(props, 'value', element.value, 0);
|
|
5979
6161
|
}
|
|
5980
6162
|
}
|
|
5981
6163
|
else if (!key.startsWith('on:')) {
|
|
5982
6164
|
const value = attr.value;
|
|
5983
|
-
mapArray_set(
|
|
6165
|
+
mapArray_set(props, key, value, 0);
|
|
5984
6166
|
}
|
|
5985
6167
|
}
|
|
5986
6168
|
}
|
|
@@ -6372,7 +6554,7 @@ const vnode_applyJournal = (journal) => {
|
|
|
6372
6554
|
element[key] = parseBoolean(value);
|
|
6373
6555
|
}
|
|
6374
6556
|
else if (key === 'value' && key in element) {
|
|
6375
|
-
element.value =
|
|
6557
|
+
element.value = String(value);
|
|
6376
6558
|
}
|
|
6377
6559
|
else if (key === dangerouslySetInnerHTML) {
|
|
6378
6560
|
element.innerHTML = value;
|
|
@@ -6416,54 +6598,16 @@ const vnode_applyJournal = (journal) => {
|
|
|
6416
6598
|
journal.length = 0;
|
|
6417
6599
|
};
|
|
6418
6600
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
6419
|
-
const mapApp_findIndx = (elementVNode, key, start) => {
|
|
6420
|
-
assertTrue(start % 2 === 0, 'Expecting even number.');
|
|
6421
|
-
let bottom = start >> 1;
|
|
6422
|
-
let top = (elementVNode.length - 2) >> 1;
|
|
6423
|
-
while (bottom <= top) {
|
|
6424
|
-
const mid = bottom + ((top - bottom) >> 1);
|
|
6425
|
-
const midKey = elementVNode[mid << 1];
|
|
6426
|
-
if (midKey === key) {
|
|
6427
|
-
return mid << 1;
|
|
6428
|
-
}
|
|
6429
|
-
if (midKey < key) {
|
|
6430
|
-
bottom = mid + 1;
|
|
6431
|
-
}
|
|
6432
|
-
else {
|
|
6433
|
-
top = mid - 1;
|
|
6434
|
-
}
|
|
6435
|
-
}
|
|
6436
|
-
return (bottom << 1) ^ -1;
|
|
6437
|
-
};
|
|
6438
|
-
const mapArray_set = (elementVNode, key, value, start) => {
|
|
6439
|
-
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
6440
|
-
if (indx >= 0) {
|
|
6441
|
-
if (value == null) {
|
|
6442
|
-
elementVNode.splice(indx, 2);
|
|
6443
|
-
}
|
|
6444
|
-
else {
|
|
6445
|
-
elementVNode[indx + 1] = value;
|
|
6446
|
-
}
|
|
6447
|
-
}
|
|
6448
|
-
else if (value != null) {
|
|
6449
|
-
elementVNode.splice(indx ^ -1, 0, key, value);
|
|
6450
|
-
}
|
|
6451
|
-
};
|
|
6452
|
-
const mapArray_get = (elementVNode, key, start) => {
|
|
6453
|
-
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
6454
|
-
if (indx >= 0) {
|
|
6455
|
-
return elementVNode[indx + 1];
|
|
6456
|
-
}
|
|
6457
|
-
else {
|
|
6458
|
-
return null;
|
|
6459
|
-
}
|
|
6460
|
-
};
|
|
6461
|
-
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
6462
6601
|
const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
|
|
6463
6602
|
ensureElementOrVirtualVNode(parent);
|
|
6464
6603
|
if (vnode_isElementVNode(parent)) {
|
|
6465
6604
|
ensureMaterialized(parent);
|
|
6466
6605
|
}
|
|
6606
|
+
if (newChild === insertBefore) {
|
|
6607
|
+
// invalid insertBefore. We can't insert before self reference
|
|
6608
|
+
// prevent infinity loop and putting self reference to next sibling
|
|
6609
|
+
insertBefore = null;
|
|
6610
|
+
}
|
|
6467
6611
|
let adjustedInsertBefore = null;
|
|
6468
6612
|
if (insertBefore == null) {
|
|
6469
6613
|
if (vnode_isVirtualVNode(parent)) {
|
|
@@ -6587,9 +6731,10 @@ const vnode_getElementName = (vnode) => {
|
|
|
6587
6731
|
const elementVNode = ensureElementVNode(vnode);
|
|
6588
6732
|
let elementName = elementVNode[ElementVNodeProps.elementName];
|
|
6589
6733
|
if (elementName === undefined) {
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
elementVNode[
|
|
6734
|
+
const element = elementVNode[ElementVNodeProps.element];
|
|
6735
|
+
const nodeName = isDev ? fastNodeName(element).toLowerCase() : fastNodeName(element);
|
|
6736
|
+
elementName = elementVNode[ElementVNodeProps.elementName] = nodeName;
|
|
6737
|
+
elementVNode[VNodeProps.flags] |= vnode_getElementNamespaceFlags(element);
|
|
6593
6738
|
}
|
|
6594
6739
|
return elementName;
|
|
6595
6740
|
};
|
|
@@ -6771,6 +6916,20 @@ const fastFirstChild = (node) => {
|
|
|
6771
6916
|
}
|
|
6772
6917
|
return node;
|
|
6773
6918
|
};
|
|
6919
|
+
let _fastNamespaceURI = null;
|
|
6920
|
+
const fastNamespaceURI = (element) => {
|
|
6921
|
+
if (!_fastNamespaceURI) {
|
|
6922
|
+
_fastNamespaceURI = fastGetter(element, 'namespaceURI');
|
|
6923
|
+
}
|
|
6924
|
+
return _fastNamespaceURI.call(element);
|
|
6925
|
+
};
|
|
6926
|
+
let _fastNodeName = null;
|
|
6927
|
+
const fastNodeName = (element) => {
|
|
6928
|
+
if (!_fastNodeName) {
|
|
6929
|
+
_fastNodeName = fastGetter(element, 'nodeName');
|
|
6930
|
+
}
|
|
6931
|
+
return _fastNodeName.call(element);
|
|
6932
|
+
};
|
|
6774
6933
|
const fastGetter = (prototype, name) => {
|
|
6775
6934
|
let getter;
|
|
6776
6935
|
while (prototype && !(getter = Object.getOwnPropertyDescriptor(prototype, name)?.get)) {
|
|
@@ -6837,8 +6996,11 @@ const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
|
6837
6996
|
container.$setRawState$(parseInt(id), vParent);
|
|
6838
6997
|
isDev && vnode_setAttr(null, vParent, ELEMENT_ID, id);
|
|
6839
6998
|
}
|
|
6840
|
-
else if (peek() === VNodeDataChar.
|
|
6841
|
-
|
|
6999
|
+
else if (peek() === VNodeDataChar.BACK_REFS) {
|
|
7000
|
+
if (!container) {
|
|
7001
|
+
container = getDomContainer(vParent[ElementVNodeProps.element]);
|
|
7002
|
+
}
|
|
7003
|
+
setEffectBackRefFromVNodeData(vParent, consumeValue(), container);
|
|
6842
7004
|
}
|
|
6843
7005
|
else {
|
|
6844
7006
|
// prevent infinity loop if there are some characters outside the range
|
|
@@ -6848,6 +7010,18 @@ const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
|
6848
7010
|
}
|
|
6849
7011
|
return vFirstChild;
|
|
6850
7012
|
};
|
|
7013
|
+
function setEffectBackRefFromVNodeData(vParent, value, container) {
|
|
7014
|
+
const deserializedSubMap = container.$getObjectById$(value);
|
|
7015
|
+
if (!vParent[_EFFECT_BACK_REF]) {
|
|
7016
|
+
Object.defineProperty(vParent, _EFFECT_BACK_REF, {
|
|
7017
|
+
value: deserializedSubMap,
|
|
7018
|
+
});
|
|
7019
|
+
}
|
|
7020
|
+
else {
|
|
7021
|
+
const subMap = vParent[_EFFECT_BACK_REF];
|
|
7022
|
+
mergeMaps(subMap, deserializedSubMap);
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
6851
7025
|
const processVNodeData$1 = (vData, callback) => {
|
|
6852
7026
|
let nextToConsumeIdx = 0;
|
|
6853
7027
|
let ch = 0;
|
|
@@ -6892,8 +7066,9 @@ const vnode_getAttrKeys = (vnode) => {
|
|
|
6892
7066
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6893
7067
|
vnode_ensureElementInflated(vnode);
|
|
6894
7068
|
const keys = [];
|
|
6895
|
-
|
|
6896
|
-
|
|
7069
|
+
const props = vnode_getProps(vnode);
|
|
7070
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
7071
|
+
const key = props[i];
|
|
6897
7072
|
if (!key.startsWith(Q_PROPS_SEPARATOR)) {
|
|
6898
7073
|
keys.push(key);
|
|
6899
7074
|
}
|
|
@@ -6906,22 +7081,23 @@ const vnode_setAttr = (journal, vnode, key, value) => {
|
|
|
6906
7081
|
const type = vnode[VNodeProps.flags];
|
|
6907
7082
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6908
7083
|
vnode_ensureElementInflated(vnode);
|
|
6909
|
-
const
|
|
7084
|
+
const props = vnode_getProps(vnode);
|
|
7085
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6910
7086
|
if (idx >= 0) {
|
|
6911
|
-
if (
|
|
7087
|
+
if (props[idx + 1] != value && (type & VNodeFlags.Element) !== 0) {
|
|
6912
7088
|
// Values are different, update DOM
|
|
6913
7089
|
const element = vnode[ElementVNodeProps.element];
|
|
6914
7090
|
journal && journal.push(VNodeJournalOpCode.SetAttribute, element, key, value);
|
|
6915
7091
|
}
|
|
6916
7092
|
if (value == null) {
|
|
6917
|
-
|
|
7093
|
+
props.splice(idx, 2);
|
|
6918
7094
|
}
|
|
6919
7095
|
else {
|
|
6920
|
-
|
|
7096
|
+
props[idx + 1] = value;
|
|
6921
7097
|
}
|
|
6922
7098
|
}
|
|
6923
7099
|
else if (value != null) {
|
|
6924
|
-
|
|
7100
|
+
props.splice(idx ^ -1, 0, key, value);
|
|
6925
7101
|
if ((type & VNodeFlags.Element) !== 0) {
|
|
6926
7102
|
// New value, update DOM
|
|
6927
7103
|
const element = vnode[ElementVNodeProps.element];
|
|
@@ -6934,7 +7110,8 @@ const vnode_getAttr = (vnode, key) => {
|
|
|
6934
7110
|
const type = vnode[VNodeProps.flags];
|
|
6935
7111
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6936
7112
|
vnode_ensureElementInflated(vnode);
|
|
6937
|
-
|
|
7113
|
+
const props = vnode_getProps(vnode);
|
|
7114
|
+
return mapArray_get(props, key, 0);
|
|
6938
7115
|
}
|
|
6939
7116
|
return null;
|
|
6940
7117
|
};
|
|
@@ -6942,11 +7119,12 @@ const vnode_getProp = (vnode, key, getObject) => {
|
|
|
6942
7119
|
const type = vnode[VNodeProps.flags];
|
|
6943
7120
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6944
7121
|
type & VNodeFlags.Element && vnode_ensureElementInflated(vnode);
|
|
6945
|
-
const
|
|
7122
|
+
const props = vnode_getProps(vnode);
|
|
7123
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6946
7124
|
if (idx >= 0) {
|
|
6947
|
-
let value =
|
|
7125
|
+
let value = props[idx + 1];
|
|
6948
7126
|
if (typeof value === 'string' && getObject) {
|
|
6949
|
-
|
|
7127
|
+
props[idx + 1] = value = getObject(value);
|
|
6950
7128
|
}
|
|
6951
7129
|
return value;
|
|
6952
7130
|
}
|
|
@@ -6955,12 +7133,13 @@ const vnode_getProp = (vnode, key, getObject) => {
|
|
|
6955
7133
|
};
|
|
6956
7134
|
const vnode_setProp = (vnode, key, value) => {
|
|
6957
7135
|
ensureElementOrVirtualVNode(vnode);
|
|
6958
|
-
const
|
|
7136
|
+
const props = vnode_getProps(vnode);
|
|
7137
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6959
7138
|
if (idx >= 0) {
|
|
6960
|
-
|
|
7139
|
+
props[idx + 1] = value;
|
|
6961
7140
|
}
|
|
6962
7141
|
else if (value != null) {
|
|
6963
|
-
|
|
7142
|
+
props.splice(idx ^ -1, 0, key, value);
|
|
6964
7143
|
}
|
|
6965
7144
|
};
|
|
6966
7145
|
const vnode_getPropStartIndex = (vnode) => {
|
|
@@ -6973,6 +7152,9 @@ const vnode_getPropStartIndex = (vnode) => {
|
|
|
6973
7152
|
}
|
|
6974
7153
|
throw qError(QError.invalidVNodeType, [type]);
|
|
6975
7154
|
};
|
|
7155
|
+
const vnode_getProps = (vnode) => {
|
|
7156
|
+
return vnode[vnode_getPropStartIndex(vnode)];
|
|
7157
|
+
};
|
|
6976
7158
|
const vnode_getParent = (vnode) => {
|
|
6977
7159
|
return vnode[VNodeProps.parent] || null;
|
|
6978
7160
|
};
|
|
@@ -7124,9 +7306,6 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
7124
7306
|
else if (peek() === VNodeDataChar.PROPS) {
|
|
7125
7307
|
vnode_setAttr(null, vParent, ELEMENT_PROPS, consumeValue());
|
|
7126
7308
|
}
|
|
7127
|
-
else if (peek() === VNodeDataChar.SLOT_REF) {
|
|
7128
|
-
vnode_setAttr(null, vParent, QSlotRef, consumeValue());
|
|
7129
|
-
}
|
|
7130
7309
|
else if (peek() === VNodeDataChar.KEY) {
|
|
7131
7310
|
vnode_setAttr(null, vParent, ELEMENT_KEY, consumeValue());
|
|
7132
7311
|
}
|
|
@@ -7136,8 +7315,14 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
7136
7315
|
else if (peek() === VNodeDataChar.SEQ_IDX) {
|
|
7137
7316
|
vnode_setAttr(null, vParent, ELEMENT_SEQ_IDX, consumeValue());
|
|
7138
7317
|
}
|
|
7139
|
-
else if (peek() === VNodeDataChar.
|
|
7140
|
-
|
|
7318
|
+
else if (peek() === VNodeDataChar.BACK_REFS) {
|
|
7319
|
+
if (!container) {
|
|
7320
|
+
container = getDomContainer(element);
|
|
7321
|
+
}
|
|
7322
|
+
setEffectBackRefFromVNodeData(vParent, consumeValue(), container);
|
|
7323
|
+
}
|
|
7324
|
+
else if (peek() === VNodeDataChar.SLOT_PARENT) {
|
|
7325
|
+
vnode_setProp(vParent, QSlotParent, consumeValue());
|
|
7141
7326
|
}
|
|
7142
7327
|
else if (peek() === VNodeDataChar.CONTEXT) {
|
|
7143
7328
|
vnode_setAttr(null, vParent, QCtxAttr, consumeValue());
|
|
@@ -7245,23 +7430,20 @@ const vnode_getProjectionParentComponent = (vHost, rootVNode) => {
|
|
|
7245
7430
|
};
|
|
7246
7431
|
const VNodeArray = class VNode extends Array {
|
|
7247
7432
|
static createElement(flags, parent, previousSibling, nextSibling, firstChild, lastChild, element, elementName) {
|
|
7248
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7249
|
-
vnode.push(firstChild, lastChild, element, elementName);
|
|
7433
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, firstChild, lastChild, element, elementName, []);
|
|
7250
7434
|
return vnode;
|
|
7251
7435
|
}
|
|
7252
7436
|
static createText(flags, parent, previousSibling, nextSibling, textNode, text) {
|
|
7253
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7254
|
-
vnode.push(textNode, text);
|
|
7437
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, textNode, text);
|
|
7255
7438
|
return vnode;
|
|
7256
7439
|
}
|
|
7257
7440
|
static createVirtual(flags, parent, previousSibling, nextSibling, firstChild, lastChild) {
|
|
7258
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7259
|
-
vnode.push(firstChild, lastChild);
|
|
7441
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, firstChild, lastChild, []);
|
|
7260
7442
|
return vnode;
|
|
7261
7443
|
}
|
|
7262
|
-
constructor(flags, parent, previousSibling, nextSibling) {
|
|
7263
|
-
|
|
7264
|
-
|
|
7444
|
+
constructor(flags, parent, previousSibling, nextSibling, ...rest) {
|
|
7445
|
+
// @ts-expect-error
|
|
7446
|
+
super(flags, parent, previousSibling, nextSibling, ...rest);
|
|
7265
7447
|
if (isDev) {
|
|
7266
7448
|
this.toString = vnode_toString;
|
|
7267
7449
|
}
|
|
@@ -7326,10 +7508,12 @@ function invokeApply(context, fn, args) {
|
|
|
7326
7508
|
return returnValue;
|
|
7327
7509
|
}
|
|
7328
7510
|
const newInvokeContextFromTuple = ([element, event, url]) => {
|
|
7329
|
-
const
|
|
7511
|
+
const domContainer = getDomContainer(element);
|
|
7512
|
+
const container = domContainer.element;
|
|
7513
|
+
const vNode = container ? vnode_locate(domContainer.rootVNode, element) : undefined;
|
|
7330
7514
|
const locale = container?.getAttribute(QLocaleAttr) || undefined;
|
|
7331
7515
|
locale && setLocale(locale);
|
|
7332
|
-
return newInvokeContext(locale,
|
|
7516
|
+
return newInvokeContext(locale, vNode, element, event, url);
|
|
7333
7517
|
};
|
|
7334
7518
|
// TODO how about putting url and locale (and event/custom?) in to a "static" object
|
|
7335
7519
|
const newInvokeContext = (locale, hostElement, element, event, url) => {
|
|
@@ -7364,16 +7548,14 @@ const trackInvocation = /*#__PURE__*/ newInvokeContext(undefined, undefined, und
|
|
|
7364
7548
|
* @param property `true` - subscriber is component `false` - subscriber is VNode `string` -
|
|
7365
7549
|
* subscriber is property
|
|
7366
7550
|
* @param container
|
|
7551
|
+
* @param data - Additional subscription data
|
|
7367
7552
|
* @returns
|
|
7368
7553
|
*/
|
|
7369
7554
|
const trackSignal = (fn, subscriber, property, container, data) => {
|
|
7370
7555
|
const previousSubscriber = trackInvocation.$effectSubscriber$;
|
|
7371
7556
|
const previousContainer = trackInvocation.$container$;
|
|
7372
7557
|
try {
|
|
7373
|
-
trackInvocation.$effectSubscriber$ =
|
|
7374
|
-
if (data) {
|
|
7375
|
-
trackInvocation.$effectSubscriber$.push(data);
|
|
7376
|
-
}
|
|
7558
|
+
trackInvocation.$effectSubscriber$ = getSubscriber(subscriber, property, data);
|
|
7377
7559
|
trackInvocation.$container$ = container;
|
|
7378
7560
|
return invoke(trackInvocation, fn);
|
|
7379
7561
|
}
|
|
@@ -7394,8 +7576,16 @@ const _getContextElement = () => {
|
|
|
7394
7576
|
if (iCtx) {
|
|
7395
7577
|
const hostElement = iCtx.$hostElement$;
|
|
7396
7578
|
let element = null;
|
|
7397
|
-
if (
|
|
7398
|
-
|
|
7579
|
+
if (hostElement != null) {
|
|
7580
|
+
if (vnode_isVNode(hostElement)) {
|
|
7581
|
+
if (vnode_isElementVNode(hostElement)) {
|
|
7582
|
+
element = vnode_getNode(hostElement);
|
|
7583
|
+
}
|
|
7584
|
+
}
|
|
7585
|
+
else {
|
|
7586
|
+
// isSSRnode
|
|
7587
|
+
element = hostElement;
|
|
7588
|
+
}
|
|
7399
7589
|
}
|
|
7400
7590
|
return element ?? iCtx.$qrl$?.$setContainer$(undefined);
|
|
7401
7591
|
}
|
|
@@ -8031,12 +8221,12 @@ class DomContainer extends _SharedContainer {
|
|
|
8031
8221
|
$storeProxyMap$ = new WeakMap();
|
|
8032
8222
|
$qFuncs$;
|
|
8033
8223
|
$instanceHash$;
|
|
8034
|
-
|
|
8224
|
+
vNodeLocate = (id) => vnode_locate(this.rootVNode, id);
|
|
8225
|
+
$stateData$;
|
|
8035
8226
|
$styleIds$ = null;
|
|
8036
|
-
$vnodeLocate$ = (id) => vnode_locate(this.rootVNode, id);
|
|
8037
8227
|
$renderCount$ = 0;
|
|
8038
8228
|
constructor(element) {
|
|
8039
|
-
super(() => this.scheduleRender(), () => vnode_applyJournal(this.$journal$), {}, element.getAttribute(
|
|
8229
|
+
super(() => this.scheduleRender(), () => vnode_applyJournal(this.$journal$), {}, element.getAttribute(QLocaleAttr));
|
|
8040
8230
|
this.qContainer = element.getAttribute(QContainerAttr);
|
|
8041
8231
|
if (!this.qContainer) {
|
|
8042
8232
|
throw qError(QError.elementWithoutContainer);
|
|
@@ -8059,29 +8249,29 @@ class DomContainer extends _SharedContainer {
|
|
|
8059
8249
|
this.rootVNode = vnode_newUnMaterializedElement(this.element);
|
|
8060
8250
|
// These are here to initialize all properties at once for single class transition
|
|
8061
8251
|
this.$rawStateData$ = null;
|
|
8062
|
-
this
|
|
8252
|
+
this.$stateData$ = null;
|
|
8063
8253
|
const document = this.element.ownerDocument;
|
|
8064
8254
|
if (!document.qVNodeData) {
|
|
8065
8255
|
processVNodeData(document);
|
|
8066
8256
|
}
|
|
8067
8257
|
this.$rawStateData$ = [];
|
|
8068
|
-
this
|
|
8258
|
+
this.$stateData$ = [];
|
|
8069
8259
|
const qwikStates = element.querySelectorAll('script[type="qwik/state"]');
|
|
8070
8260
|
if (qwikStates.length !== 0) {
|
|
8071
8261
|
const lastState = qwikStates[qwikStates.length - 1];
|
|
8072
8262
|
this.$rawStateData$ = JSON.parse(lastState.textContent);
|
|
8073
|
-
this
|
|
8263
|
+
this.$stateData$ = wrapDeserializerProxy(this, this.$rawStateData$);
|
|
8074
8264
|
}
|
|
8075
8265
|
this.$qFuncs$ = getQFuncs(document, this.$instanceHash$) || EMPTY_ARRAY;
|
|
8076
8266
|
}
|
|
8077
8267
|
$setRawState$(id, vParent) {
|
|
8078
|
-
this
|
|
8268
|
+
this.$stateData$[id] = vParent;
|
|
8079
8269
|
}
|
|
8080
8270
|
parseQRL(qrl) {
|
|
8081
8271
|
return inflateQRL(this, parseQRL(qrl));
|
|
8082
8272
|
}
|
|
8083
8273
|
handleError(err, host) {
|
|
8084
|
-
if (qDev) {
|
|
8274
|
+
if (qDev && host) {
|
|
8085
8275
|
// Clean vdom
|
|
8086
8276
|
if (typeof document !== 'undefined') {
|
|
8087
8277
|
const vHost = host;
|
|
@@ -8105,7 +8295,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8105
8295
|
throw err;
|
|
8106
8296
|
}
|
|
8107
8297
|
}
|
|
8108
|
-
const errorStore = this.resolveContext(host, ERROR_CONTEXT);
|
|
8298
|
+
const errorStore = host && this.resolveContext(host, ERROR_CONTEXT);
|
|
8109
8299
|
if (!errorStore) {
|
|
8110
8300
|
throw err;
|
|
8111
8301
|
}
|
|
@@ -8141,7 +8331,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8141
8331
|
vNode =
|
|
8142
8332
|
vnode_getParent(vNode) ||
|
|
8143
8333
|
// If virtual node, than it could be a slot so we need to read its parent.
|
|
8144
|
-
vnode_getProp(vNode, QSlotParent, this
|
|
8334
|
+
vnode_getProp(vNode, QSlotParent, this.vNodeLocate);
|
|
8145
8335
|
}
|
|
8146
8336
|
else {
|
|
8147
8337
|
vNode = vnode_getParent(vNode);
|
|
@@ -8161,7 +8351,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8161
8351
|
case ELEMENT_PROPS:
|
|
8162
8352
|
case OnRenderProp:
|
|
8163
8353
|
case QCtxAttr:
|
|
8164
|
-
case
|
|
8354
|
+
case QBackRefs:
|
|
8165
8355
|
getObjectById = this.$getObjectById$;
|
|
8166
8356
|
break;
|
|
8167
8357
|
case ELEMENT_SEQ_IDX:
|
|
@@ -8174,7 +8364,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8174
8364
|
scheduleRender() {
|
|
8175
8365
|
this.$renderCount$++;
|
|
8176
8366
|
this.renderDone ||= getPlatform().nextTick(() => this.processChores());
|
|
8177
|
-
return this.renderDone;
|
|
8367
|
+
return this.renderDone.finally(() => emitEvent('qrender', { instanceHash: this.$instanceHash$, renderCount: this.$renderCount$ }));
|
|
8178
8368
|
}
|
|
8179
8369
|
processChores() {
|
|
8180
8370
|
let renderCount = this.$renderCount$;
|
|
@@ -8197,12 +8387,13 @@ class DomContainer extends _SharedContainer {
|
|
|
8197
8387
|
ensureProjectionResolved(vNode) {
|
|
8198
8388
|
if ((vNode[VNodeProps.flags] & VNodeFlags.Resolved) === 0) {
|
|
8199
8389
|
vNode[VNodeProps.flags] |= VNodeFlags.Resolved;
|
|
8200
|
-
|
|
8201
|
-
|
|
8390
|
+
const props = vnode_getProps(vNode);
|
|
8391
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
8392
|
+
const prop = props[i];
|
|
8202
8393
|
if (isSlotProp(prop)) {
|
|
8203
|
-
const value =
|
|
8394
|
+
const value = props[i + 1];
|
|
8204
8395
|
if (typeof value == 'string') {
|
|
8205
|
-
|
|
8396
|
+
props[i + 1] = this.vNodeLocate(value);
|
|
8206
8397
|
}
|
|
8207
8398
|
}
|
|
8208
8399
|
}
|
|
@@ -8213,7 +8404,7 @@ class DomContainer extends _SharedContainer {
|
|
|
8213
8404
|
id = parseFloat(id);
|
|
8214
8405
|
}
|
|
8215
8406
|
assertTrue(id < this.$rawStateData$.length / 2, `Invalid reference: ${id} >= ${this.$rawStateData$.length / 2}`);
|
|
8216
|
-
return this
|
|
8407
|
+
return this.$stateData$[id];
|
|
8217
8408
|
};
|
|
8218
8409
|
getSyncFn(id) {
|
|
8219
8410
|
const fn = this.$qFuncs$[id];
|
|
@@ -8285,8 +8476,7 @@ class DeserializationHandler {
|
|
|
8285
8476
|
? parseInt(property, 10)
|
|
8286
8477
|
: NaN;
|
|
8287
8478
|
if (Number.isNaN(i) || i < 0 || i >= this.$length$) {
|
|
8288
|
-
|
|
8289
|
-
return out;
|
|
8479
|
+
return Reflect.get(target, property, receiver);
|
|
8290
8480
|
}
|
|
8291
8481
|
// The serialized data is an array with 2 values for each item
|
|
8292
8482
|
const idx = i * 2;
|
|
@@ -8352,6 +8542,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8352
8542
|
switch (typeId) {
|
|
8353
8543
|
case TypeIds.Object:
|
|
8354
8544
|
// We use getters for making complex values lazy
|
|
8545
|
+
// TODO scan the data for computeQRLs and schedule resolve chores
|
|
8355
8546
|
for (let i = 0; i < data.length; i += 4) {
|
|
8356
8547
|
const key = deserializeData(container, data[i], data[i + 1]);
|
|
8357
8548
|
const valType = data[i + 2];
|
|
@@ -8391,7 +8582,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8391
8582
|
task.$flags$ = v[1];
|
|
8392
8583
|
task.$index$ = v[2];
|
|
8393
8584
|
task.$el$ = v[3];
|
|
8394
|
-
task
|
|
8585
|
+
task[_EFFECT_BACK_REF] = v[4];
|
|
8395
8586
|
task.$state$ = v[5];
|
|
8396
8587
|
break;
|
|
8397
8588
|
case TypeIds.Resource:
|
|
@@ -8414,12 +8605,9 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8414
8605
|
break;
|
|
8415
8606
|
case TypeIds.Store:
|
|
8416
8607
|
case TypeIds.StoreArray: {
|
|
8417
|
-
const [value, flags, effects
|
|
8608
|
+
const [value, flags, effects] = data;
|
|
8418
8609
|
const store = getOrCreateStore(value, flags, container);
|
|
8419
8610
|
const storeHandler = getStoreHandler(store);
|
|
8420
|
-
if (storeEffect) {
|
|
8421
|
-
effects[STORE_ARRAY_PROP] = storeEffect;
|
|
8422
|
-
}
|
|
8423
8611
|
storeHandler.$effects$ = effects;
|
|
8424
8612
|
target = store;
|
|
8425
8613
|
break;
|
|
@@ -8428,7 +8616,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8428
8616
|
const signal = target;
|
|
8429
8617
|
const d = data;
|
|
8430
8618
|
signal.$untrackedValue$ = d[0];
|
|
8431
|
-
signal.$effects$ = d.slice(1);
|
|
8619
|
+
signal.$effects$ = new Set(d.slice(1));
|
|
8432
8620
|
break;
|
|
8433
8621
|
}
|
|
8434
8622
|
case TypeIds.WrappedSignal: {
|
|
@@ -8436,10 +8624,11 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8436
8624
|
const d = data;
|
|
8437
8625
|
signal.$func$ = container.getSyncFn(d[0]);
|
|
8438
8626
|
signal.$args$ = d[1];
|
|
8439
|
-
signal
|
|
8627
|
+
signal[_EFFECT_BACK_REF] = d[2];
|
|
8440
8628
|
signal.$untrackedValue$ = d[3];
|
|
8441
|
-
signal.$
|
|
8442
|
-
signal.$
|
|
8629
|
+
signal.$flags$ = d[4];
|
|
8630
|
+
signal.$hostElement$ = d[5];
|
|
8631
|
+
signal.$effects$ = new Set(d.slice(6));
|
|
8443
8632
|
break;
|
|
8444
8633
|
}
|
|
8445
8634
|
case TypeIds.ComputedSignal: {
|
|
@@ -8451,7 +8640,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
8451
8640
|
computed.$untrackedValue$ = d[2];
|
|
8452
8641
|
}
|
|
8453
8642
|
else {
|
|
8454
|
-
computed.$
|
|
8643
|
+
computed.$flags$ |= SignalFlags.INVALID;
|
|
8455
8644
|
/**
|
|
8456
8645
|
* If we try to compute value and the qrl is not resolved, then system throws an error with
|
|
8457
8646
|
* qrl promise. To prevent that we should early resolve computed qrl while computed
|
|
@@ -8559,6 +8748,7 @@ const _constants = [
|
|
|
8559
8748
|
EMPTY_ARRAY,
|
|
8560
8749
|
EMPTY_OBJ,
|
|
8561
8750
|
NEEDS_COMPUTATION,
|
|
8751
|
+
STORE_ALL_PROPS,
|
|
8562
8752
|
Slot,
|
|
8563
8753
|
Fragment,
|
|
8564
8754
|
NaN,
|
|
@@ -8639,6 +8829,8 @@ const allocate = (container, typeId, value) => {
|
|
|
8639
8829
|
reject = rej;
|
|
8640
8830
|
});
|
|
8641
8831
|
resolvers.set(promise, [resolve, reject]);
|
|
8832
|
+
// Don't leave unhandled promise rejections
|
|
8833
|
+
promise.catch(() => { });
|
|
8642
8834
|
return promise;
|
|
8643
8835
|
case TypeIds.Uint8Array:
|
|
8644
8836
|
const encodedLength = value.length;
|
|
@@ -8648,12 +8840,9 @@ const allocate = (container, typeId, value) => {
|
|
|
8648
8840
|
return new Uint8Array(decodedLength);
|
|
8649
8841
|
case TypeIds.PropsProxy:
|
|
8650
8842
|
return createPropsProxy(null, null);
|
|
8651
|
-
case TypeIds.RefVNode:
|
|
8652
8843
|
case TypeIds.VNode:
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
return vnodeOrDocument;
|
|
8656
|
-
}
|
|
8844
|
+
return retrieveVNodeOrDocument(container, value);
|
|
8845
|
+
case TypeIds.RefVNode:
|
|
8657
8846
|
const vNode = retrieveVNodeOrDocument(container, value);
|
|
8658
8847
|
if (vnode_isVNode(vNode)) {
|
|
8659
8848
|
return vnode_getNode(vNode);
|
|
@@ -8662,7 +8851,7 @@ const allocate = (container, typeId, value) => {
|
|
|
8662
8851
|
throw qError(QError.serializeErrorExpectedVNode, [typeof vNode]);
|
|
8663
8852
|
}
|
|
8664
8853
|
case TypeIds.EffectData:
|
|
8665
|
-
return new
|
|
8854
|
+
return new SubscriptionData({});
|
|
8666
8855
|
default:
|
|
8667
8856
|
throw qError(QError.serializeErrorCannotAllocate, [typeId]);
|
|
8668
8857
|
}
|
|
@@ -8694,7 +8883,7 @@ function parseQRL(qrl) {
|
|
|
8694
8883
|
assertDefined(backChannel, 'Missing QRL_RUNTIME_CHUNK');
|
|
8695
8884
|
qrlRef = backChannel.get(symbol);
|
|
8696
8885
|
}
|
|
8697
|
-
return createQRL(chunk, symbol, qrlRef, null, captureIds, null
|
|
8886
|
+
return createQRL(chunk, symbol, qrlRef, null, captureIds, null);
|
|
8698
8887
|
}
|
|
8699
8888
|
function inflateQRL(container, qrl) {
|
|
8700
8889
|
const captureIds = qrl.$capture$;
|
|
@@ -8812,7 +9001,7 @@ prepVNodeData) => {
|
|
|
8812
9001
|
/** Visit an object, adding anything that will be serialized as to scan */
|
|
8813
9002
|
const visit = (obj) => {
|
|
8814
9003
|
if (typeof obj === 'function') {
|
|
8815
|
-
if (isQrl(obj)) {
|
|
9004
|
+
if (isQrl$1(obj)) {
|
|
8816
9005
|
if (obj.$captureRef$) {
|
|
8817
9006
|
discoveredValues.push(...obj.$captureRef$);
|
|
8818
9007
|
}
|
|
@@ -8831,6 +9020,7 @@ prepVNodeData) => {
|
|
|
8831
9020
|
obj instanceof RegExp ||
|
|
8832
9021
|
obj instanceof Uint8Array ||
|
|
8833
9022
|
obj instanceof URLSearchParams ||
|
|
9023
|
+
vnode_isVNode(obj) ||
|
|
8834
9024
|
(typeof FormData !== 'undefined' && obj instanceof FormData) ||
|
|
8835
9025
|
// Ignore the no serialize objects
|
|
8836
9026
|
fastSkipSerialize(obj)) ;
|
|
@@ -8840,8 +9030,7 @@ prepVNodeData) => {
|
|
|
8840
9030
|
else if (isStore(obj)) {
|
|
8841
9031
|
const target = getStoreTarget(obj);
|
|
8842
9032
|
const effects = getStoreHandler(obj).$effects$;
|
|
8843
|
-
|
|
8844
|
-
discoveredValues.push(target, effects, storeEffect);
|
|
9033
|
+
discoveredValues.push(target, effects);
|
|
8845
9034
|
for (const prop in target) {
|
|
8846
9035
|
const propValue = target[prop];
|
|
8847
9036
|
if (storeProxyMap.has(propValue)) {
|
|
@@ -8864,20 +9053,19 @@ prepVNodeData) => {
|
|
|
8864
9053
|
*/
|
|
8865
9054
|
const v = obj instanceof WrappedSignal
|
|
8866
9055
|
? obj.untrackedValue
|
|
8867
|
-
: obj instanceof ComputedSignal &&
|
|
9056
|
+
: obj instanceof ComputedSignal &&
|
|
9057
|
+
(obj.$flags$ & SignalFlags.INVALID || fastSkipSerialize(obj))
|
|
8868
9058
|
? NEEDS_COMPUTATION
|
|
8869
9059
|
: obj.$untrackedValue$;
|
|
8870
9060
|
if (v !== NEEDS_COMPUTATION) {
|
|
8871
9061
|
discoveredValues.push(v);
|
|
8872
9062
|
}
|
|
8873
9063
|
if (obj.$effects$) {
|
|
8874
|
-
discoveredValues.push(
|
|
9064
|
+
discoveredValues.push(obj.$effects$);
|
|
8875
9065
|
}
|
|
8876
9066
|
// WrappedSignal uses syncQrl which has no captured refs
|
|
8877
9067
|
if (obj instanceof WrappedSignal) {
|
|
8878
|
-
|
|
8879
|
-
discoveredValues.push(...obj.$effectDependencies$);
|
|
8880
|
-
}
|
|
9068
|
+
discoverEffectBackRefs(obj[_EFFECT_BACK_REF], discoveredValues);
|
|
8881
9069
|
if (obj.$args$) {
|
|
8882
9070
|
discoveredValues.push(...obj.$args$);
|
|
8883
9071
|
}
|
|
@@ -8886,11 +9074,13 @@ prepVNodeData) => {
|
|
|
8886
9074
|
}
|
|
8887
9075
|
}
|
|
8888
9076
|
else if (obj instanceof ComputedSignal) {
|
|
9077
|
+
discoverEffectBackRefs(obj[_EFFECT_BACK_REF], discoveredValues);
|
|
8889
9078
|
discoveredValues.push(obj.$computeQrl$);
|
|
8890
9079
|
}
|
|
8891
9080
|
}
|
|
8892
9081
|
else if (obj instanceof Task) {
|
|
8893
|
-
discoveredValues.push(obj.$el$, obj.$qrl$, obj.$state
|
|
9082
|
+
discoveredValues.push(obj.$el$, obj.$qrl$, obj.$state$);
|
|
9083
|
+
discoverEffectBackRefs(obj[_EFFECT_BACK_REF], discoveredValues);
|
|
8894
9084
|
}
|
|
8895
9085
|
else if (isSsrNode(obj)) {
|
|
8896
9086
|
discoverValuesForVNodeData(obj.vnodeData, discoveredValues);
|
|
@@ -8909,7 +9099,7 @@ prepVNodeData) => {
|
|
|
8909
9099
|
else if (Array.isArray(obj)) {
|
|
8910
9100
|
discoveredValues.push(...obj);
|
|
8911
9101
|
}
|
|
8912
|
-
else if (isQrl(obj)) {
|
|
9102
|
+
else if (isQrl$1(obj)) {
|
|
8913
9103
|
obj.$captureRef$ && obj.$captureRef$.length && discoveredValues.push(...obj.$captureRef$);
|
|
8914
9104
|
}
|
|
8915
9105
|
else if (isPropsProxy(obj)) {
|
|
@@ -8925,7 +9115,7 @@ prepVNodeData) => {
|
|
|
8925
9115
|
});
|
|
8926
9116
|
promises.push(obj);
|
|
8927
9117
|
}
|
|
8928
|
-
else if (obj instanceof
|
|
9118
|
+
else if (obj instanceof SubscriptionData) {
|
|
8929
9119
|
discoveredValues.push(obj.data);
|
|
8930
9120
|
}
|
|
8931
9121
|
else if (isObjectLiteral(obj)) {
|
|
@@ -8970,15 +9160,20 @@ const discoverValuesForVNodeData = (vnodeData, discoveredValues) => {
|
|
|
8970
9160
|
for (const value of vnodeData) {
|
|
8971
9161
|
if (isSsrAttrs(value)) {
|
|
8972
9162
|
for (let i = 1; i < value.length; i += 2) {
|
|
8973
|
-
|
|
9163
|
+
const attrValue = value[i];
|
|
9164
|
+
if (typeof attrValue === 'string') {
|
|
8974
9165
|
continue;
|
|
8975
9166
|
}
|
|
8976
|
-
const attrValue = value[i];
|
|
8977
9167
|
discoveredValues.push(attrValue);
|
|
8978
9168
|
}
|
|
8979
9169
|
}
|
|
8980
9170
|
}
|
|
8981
9171
|
};
|
|
9172
|
+
const discoverEffectBackRefs = (effectsBackRefs, discoveredValues) => {
|
|
9173
|
+
if (effectsBackRefs) {
|
|
9174
|
+
discoveredValues.push(effectsBackRefs);
|
|
9175
|
+
}
|
|
9176
|
+
};
|
|
8982
9177
|
const promiseResults = new WeakMap();
|
|
8983
9178
|
/**
|
|
8984
9179
|
* Format:
|
|
@@ -9050,7 +9245,7 @@ function serialize(serializationContext) {
|
|
|
9050
9245
|
else if (value === Fragment) {
|
|
9051
9246
|
output(TypeIds.Constant, Constants.Fragment);
|
|
9052
9247
|
}
|
|
9053
|
-
else if (isQrl(value)) {
|
|
9248
|
+
else if (isQrl$1(value)) {
|
|
9054
9249
|
const qrl = qrlToString(serializationContext, value);
|
|
9055
9250
|
const id = serializationContext.$addRoot$(qrl);
|
|
9056
9251
|
output(TypeIds.QRL, id);
|
|
@@ -9125,6 +9320,9 @@ function serialize(serializationContext) {
|
|
|
9125
9320
|
else if (value === NEEDS_COMPUTATION) {
|
|
9126
9321
|
output(TypeIds.Constant, Constants.NEEDS_COMPUTATION);
|
|
9127
9322
|
}
|
|
9323
|
+
else if (value === STORE_ALL_PROPS) {
|
|
9324
|
+
output(TypeIds.Constant, Constants.STORE_ALL_PROPS);
|
|
9325
|
+
}
|
|
9128
9326
|
else {
|
|
9129
9327
|
throw qError(QError.serializeErrorUnknownType, [typeof value]);
|
|
9130
9328
|
}
|
|
@@ -9161,7 +9359,7 @@ function serialize(serializationContext) {
|
|
|
9161
9359
|
: 0;
|
|
9162
9360
|
output(TypeIds.PropsProxy, out);
|
|
9163
9361
|
}
|
|
9164
|
-
else if (value instanceof
|
|
9362
|
+
else if (value instanceof SubscriptionData) {
|
|
9165
9363
|
output(TypeIds.EffectData, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
|
|
9166
9364
|
}
|
|
9167
9365
|
else if (isStore(value)) {
|
|
@@ -9172,6 +9370,7 @@ function serialize(serializationContext) {
|
|
|
9172
9370
|
if (!res) {
|
|
9173
9371
|
throw qError(QError.serializeErrorUnvisited, ['resource']);
|
|
9174
9372
|
}
|
|
9373
|
+
// TODO the effects include the resourcereturn which has duplicate data
|
|
9175
9374
|
output(TypeIds.Resource, [...res, getStoreHandler(value).$effects$]);
|
|
9176
9375
|
}
|
|
9177
9376
|
else {
|
|
@@ -9179,7 +9378,6 @@ function serialize(serializationContext) {
|
|
|
9179
9378
|
const storeTarget = getStoreTarget(value);
|
|
9180
9379
|
const flags = storeHandler.$flags$;
|
|
9181
9380
|
const effects = storeHandler.$effects$;
|
|
9182
|
-
const storeEffect = effects?.[STORE_ARRAY_PROP] ?? null;
|
|
9183
9381
|
const innerStores = [];
|
|
9184
9382
|
for (const prop in storeTarget) {
|
|
9185
9383
|
const propValue = storeTarget[prop];
|
|
@@ -9189,7 +9387,7 @@ function serialize(serializationContext) {
|
|
|
9189
9387
|
serializationContext.$addRoot$(innerStore);
|
|
9190
9388
|
}
|
|
9191
9389
|
}
|
|
9192
|
-
const out = [storeTarget, flags, effects,
|
|
9390
|
+
const out = [storeTarget, flags, effects, ...innerStores];
|
|
9193
9391
|
while (out[out.length - 1] == null) {
|
|
9194
9392
|
out.pop();
|
|
9195
9393
|
}
|
|
@@ -9222,14 +9420,15 @@ function serialize(serializationContext) {
|
|
|
9222
9420
|
* It can never be meant to become a vNode, because vNodes are internal only.
|
|
9223
9421
|
*/
|
|
9224
9422
|
const v = value instanceof ComputedSignal &&
|
|
9225
|
-
(value.$
|
|
9423
|
+
(value.$flags$ & SignalFlags.INVALID || fastSkipSerialize(value.$untrackedValue$))
|
|
9226
9424
|
? NEEDS_COMPUTATION
|
|
9227
9425
|
: value.$untrackedValue$;
|
|
9228
9426
|
if (value instanceof WrappedSignal) {
|
|
9229
9427
|
output(TypeIds.WrappedSignal, [
|
|
9230
9428
|
...serializeWrappingFn(serializationContext, value),
|
|
9231
|
-
value
|
|
9429
|
+
filterEffectBackRefs(value[_EFFECT_BACK_REF]),
|
|
9232
9430
|
v,
|
|
9431
|
+
value.$flags$,
|
|
9233
9432
|
value.$hostElement$,
|
|
9234
9433
|
...(value.$effects$ || []),
|
|
9235
9434
|
]);
|
|
@@ -9335,7 +9534,7 @@ function serialize(serializationContext) {
|
|
|
9335
9534
|
value.$flags$,
|
|
9336
9535
|
value.$index$,
|
|
9337
9536
|
value.$el$,
|
|
9338
|
-
value
|
|
9537
|
+
value[_EFFECT_BACK_REF],
|
|
9339
9538
|
value.$state$,
|
|
9340
9539
|
];
|
|
9341
9540
|
while (out[out.length - 1] == null) {
|
|
@@ -9358,12 +9557,27 @@ function serialize(serializationContext) {
|
|
|
9358
9557
|
const out = btoa(buf).replace(/=+$/, '');
|
|
9359
9558
|
output(TypeIds.Uint8Array, out);
|
|
9360
9559
|
}
|
|
9560
|
+
else if (vnode_isVNode(value)) {
|
|
9561
|
+
output(TypeIds.Constant, Constants.Undefined);
|
|
9562
|
+
}
|
|
9361
9563
|
else {
|
|
9362
9564
|
throw qError(QError.serializeErrorUnknownType, [typeof value]);
|
|
9363
9565
|
}
|
|
9364
9566
|
};
|
|
9365
9567
|
writeValue(serializationContext.$roots$, -1);
|
|
9366
9568
|
}
|
|
9569
|
+
function filterEffectBackRefs(effectBackRef) {
|
|
9570
|
+
let effectBackRefToSerialize = null;
|
|
9571
|
+
if (effectBackRef) {
|
|
9572
|
+
for (const [effectProp, effect] of effectBackRef) {
|
|
9573
|
+
if (effect[EffectSubscriptionProp.BACK_REF]) {
|
|
9574
|
+
effectBackRefToSerialize ||= new Map();
|
|
9575
|
+
effectBackRefToSerialize.set(effectProp, effect);
|
|
9576
|
+
}
|
|
9577
|
+
}
|
|
9578
|
+
}
|
|
9579
|
+
return effectBackRefToSerialize;
|
|
9580
|
+
}
|
|
9367
9581
|
function serializeWrappingFn(serializationContext, value) {
|
|
9368
9582
|
// if value is an object then we need to wrap this in ()
|
|
9369
9583
|
if (value.$funcStr$ && value.$funcStr$[0] === '{') {
|
|
@@ -9376,15 +9590,12 @@ function serializeWrappingFn(serializationContext, value) {
|
|
|
9376
9590
|
function qrlToString(serializationContext, value) {
|
|
9377
9591
|
let symbol = value.$symbol$;
|
|
9378
9592
|
let chunk = value.$chunk$;
|
|
9379
|
-
const refSymbol = value.$refSymbol$ ?? symbol;
|
|
9380
9593
|
const platform = getPlatform();
|
|
9381
9594
|
if (platform) {
|
|
9382
|
-
const result = platform.chunkForSymbol(
|
|
9595
|
+
const result = platform.chunkForSymbol(symbol, chunk, value.dev?.file);
|
|
9383
9596
|
if (result) {
|
|
9384
9597
|
chunk = result[1];
|
|
9385
|
-
|
|
9386
|
-
symbol = result[0];
|
|
9387
|
-
}
|
|
9598
|
+
symbol = result[0];
|
|
9388
9599
|
}
|
|
9389
9600
|
}
|
|
9390
9601
|
const isSync = isSyncQrl(value);
|
|
@@ -9561,9 +9772,9 @@ const frameworkType = (obj) => {
|
|
|
9561
9772
|
return ((typeof obj === 'object' &&
|
|
9562
9773
|
obj !== null &&
|
|
9563
9774
|
(obj instanceof Signal || obj instanceof Task || isJSXNode(obj))) ||
|
|
9564
|
-
isQrl(obj));
|
|
9775
|
+
isQrl$1(obj));
|
|
9565
9776
|
};
|
|
9566
|
-
const canSerialize = (value) => {
|
|
9777
|
+
const canSerialize = (value, seen = new WeakSet()) => {
|
|
9567
9778
|
if (value == null ||
|
|
9568
9779
|
typeof value === 'string' ||
|
|
9569
9780
|
typeof value === 'number' ||
|
|
@@ -9572,6 +9783,10 @@ const canSerialize = (value) => {
|
|
|
9572
9783
|
return true;
|
|
9573
9784
|
}
|
|
9574
9785
|
else if (typeof value === 'object') {
|
|
9786
|
+
if (seen.has(value)) {
|
|
9787
|
+
return true;
|
|
9788
|
+
}
|
|
9789
|
+
seen.add(value);
|
|
9575
9790
|
const proto = Object.getPrototypeOf(value);
|
|
9576
9791
|
if (isStore(value)) {
|
|
9577
9792
|
value = getStoreTarget(value);
|
|
@@ -9580,7 +9795,7 @@ const canSerialize = (value) => {
|
|
|
9580
9795
|
for (const key in value) {
|
|
9581
9796
|
// if the value is a props proxy, then sometimes we could create a component-level subscription,
|
|
9582
9797
|
// so we should call untrack here to avoid tracking the value
|
|
9583
|
-
if (!canSerialize(untrack(() => value[key]))) {
|
|
9798
|
+
if (!canSerialize(untrack(() => value[key]), seen)) {
|
|
9584
9799
|
return false;
|
|
9585
9800
|
}
|
|
9586
9801
|
}
|
|
@@ -9588,7 +9803,7 @@ const canSerialize = (value) => {
|
|
|
9588
9803
|
}
|
|
9589
9804
|
else if (proto == Array.prototype) {
|
|
9590
9805
|
for (let i = 0; i < value.length; i++) {
|
|
9591
|
-
if (!canSerialize(value[i])) {
|
|
9806
|
+
if (!canSerialize(value[i], seen)) {
|
|
9592
9807
|
return false;
|
|
9593
9808
|
}
|
|
9594
9809
|
}
|
|
@@ -9638,7 +9853,7 @@ const canSerialize = (value) => {
|
|
|
9638
9853
|
}
|
|
9639
9854
|
}
|
|
9640
9855
|
else if (typeof value === 'function') {
|
|
9641
|
-
if (isQrl(value) || isQwikComponent(value)) {
|
|
9856
|
+
if (isQrl$1(value) || isQwikComponent(value)) {
|
|
9642
9857
|
return true;
|
|
9643
9858
|
}
|
|
9644
9859
|
}
|
|
@@ -9691,20 +9906,21 @@ var Constants;
|
|
|
9691
9906
|
Constants[Constants["EMPTY_ARRAY"] = 5] = "EMPTY_ARRAY";
|
|
9692
9907
|
Constants[Constants["EMPTY_OBJ"] = 6] = "EMPTY_OBJ";
|
|
9693
9908
|
Constants[Constants["NEEDS_COMPUTATION"] = 7] = "NEEDS_COMPUTATION";
|
|
9694
|
-
Constants[Constants["
|
|
9695
|
-
Constants[Constants["
|
|
9696
|
-
Constants[Constants["
|
|
9697
|
-
Constants[Constants["
|
|
9698
|
-
Constants[Constants["
|
|
9699
|
-
Constants[Constants["
|
|
9909
|
+
Constants[Constants["STORE_ALL_PROPS"] = 8] = "STORE_ALL_PROPS";
|
|
9910
|
+
Constants[Constants["Slot"] = 9] = "Slot";
|
|
9911
|
+
Constants[Constants["Fragment"] = 10] = "Fragment";
|
|
9912
|
+
Constants[Constants["NaN"] = 11] = "NaN";
|
|
9913
|
+
Constants[Constants["PositiveInfinity"] = 12] = "PositiveInfinity";
|
|
9914
|
+
Constants[Constants["NegativeInfinity"] = 13] = "NegativeInfinity";
|
|
9915
|
+
Constants[Constants["MaxSafeInt"] = 14] = "MaxSafeInt";
|
|
9700
9916
|
// used for close fragment
|
|
9701
|
-
Constants[Constants["AlmostMaxSafeInt"] =
|
|
9702
|
-
Constants[Constants["MinSafeInt"] =
|
|
9917
|
+
Constants[Constants["AlmostMaxSafeInt"] = 15] = "AlmostMaxSafeInt";
|
|
9918
|
+
Constants[Constants["MinSafeInt"] = 16] = "MinSafeInt";
|
|
9703
9919
|
})(Constants || (Constants = {}));
|
|
9704
9920
|
|
|
9705
9921
|
/** @internal */
|
|
9706
9922
|
const verifySerializable = (value, preMessage) => {
|
|
9707
|
-
const seen = new
|
|
9923
|
+
const seen = new WeakSet();
|
|
9708
9924
|
return _verifySerializable(value, seen, '_', preMessage);
|
|
9709
9925
|
};
|
|
9710
9926
|
const _verifySerializable = (value, seen, ctx, preMessage) => {
|
|
@@ -9713,10 +9929,12 @@ const _verifySerializable = (value, seen, ctx, preMessage) => {
|
|
|
9713
9929
|
return value;
|
|
9714
9930
|
}
|
|
9715
9931
|
if (shouldSerialize(unwrapped)) {
|
|
9716
|
-
if (
|
|
9717
|
-
|
|
9932
|
+
if (typeof unwrapped === 'object') {
|
|
9933
|
+
if (seen.has(unwrapped)) {
|
|
9934
|
+
return value;
|
|
9935
|
+
}
|
|
9936
|
+
seen.add(unwrapped);
|
|
9718
9937
|
}
|
|
9719
|
-
seen.add(unwrapped);
|
|
9720
9938
|
if (isSignal(unwrapped)) {
|
|
9721
9939
|
return value;
|
|
9722
9940
|
}
|
|
@@ -9820,16 +10038,7 @@ const _weakSerialize = (input) => {
|
|
|
9820
10038
|
return input;
|
|
9821
10039
|
};
|
|
9822
10040
|
|
|
9823
|
-
const
|
|
9824
|
-
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
9825
|
-
};
|
|
9826
|
-
// Make sure this value is same as value in `platform.ts`
|
|
9827
|
-
const SYNC_QRL = '<sync>';
|
|
9828
|
-
/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
|
|
9829
|
-
const isSyncQrl = (value) => {
|
|
9830
|
-
return isQrl(value) && value.$symbol$ == SYNC_QRL;
|
|
9831
|
-
};
|
|
9832
|
-
const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refSymbol) => {
|
|
10041
|
+
const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef) => {
|
|
9833
10042
|
if (qDev && qSerialize) {
|
|
9834
10043
|
if (captureRef) {
|
|
9835
10044
|
for (const item of captureRef) {
|
|
@@ -9851,9 +10060,14 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9851
10060
|
};
|
|
9852
10061
|
function bindFnToContext(currentCtx, beforeFn) {
|
|
9853
10062
|
// Note that we bind the current `this`
|
|
9854
|
-
|
|
9855
|
-
if (!
|
|
9856
|
-
|
|
10063
|
+
const bound = (...args) => {
|
|
10064
|
+
if (!qrl.resolved) {
|
|
10065
|
+
return qrl.resolve().then((fn) => {
|
|
10066
|
+
if (!isFunction(fn)) {
|
|
10067
|
+
throw qError(QError.qrlIsNotFunction);
|
|
10068
|
+
}
|
|
10069
|
+
return bound(...args);
|
|
10070
|
+
});
|
|
9857
10071
|
}
|
|
9858
10072
|
if (beforeFn && beforeFn() === false) {
|
|
9859
10073
|
return;
|
|
@@ -9866,13 +10080,14 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9866
10080
|
context.$qrl$ = qrl;
|
|
9867
10081
|
context.$event$ ||= this;
|
|
9868
10082
|
try {
|
|
9869
|
-
return invoke.call(this, context,
|
|
10083
|
+
return invoke.call(this, context, symbolRef, ...args);
|
|
9870
10084
|
}
|
|
9871
10085
|
finally {
|
|
9872
10086
|
context.$qrl$ = prevQrl;
|
|
9873
10087
|
context.$event$ = prevEvent;
|
|
9874
10088
|
}
|
|
9875
|
-
}
|
|
10089
|
+
};
|
|
10090
|
+
return bound;
|
|
9876
10091
|
}
|
|
9877
10092
|
const resolveLazy = (containerEl) => {
|
|
9878
10093
|
return symbolRef !== null ? symbolRef : resolve(containerEl);
|
|
@@ -9884,8 +10099,20 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9884
10099
|
}
|
|
9885
10100
|
return function (...args) {
|
|
9886
10101
|
let context = tryGetInvokeContext();
|
|
10102
|
+
// use the given qrl if it is the right one
|
|
9887
10103
|
if (context) {
|
|
9888
|
-
|
|
10104
|
+
// TODO check if this is necessary in production
|
|
10105
|
+
if (context.$qrl$?.$symbol$ === qrl.$symbol$) {
|
|
10106
|
+
return fn.apply(this, args);
|
|
10107
|
+
}
|
|
10108
|
+
const prevQrl = context.$qrl$;
|
|
10109
|
+
context.$qrl$ = qrl;
|
|
10110
|
+
try {
|
|
10111
|
+
return fn.apply(this, args);
|
|
10112
|
+
}
|
|
10113
|
+
finally {
|
|
10114
|
+
context.$qrl$ = prevQrl;
|
|
10115
|
+
}
|
|
9889
10116
|
}
|
|
9890
10117
|
context = newInvokeContext();
|
|
9891
10118
|
context.$qrl$ = qrl;
|
|
@@ -9913,11 +10140,11 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9913
10140
|
const start = now();
|
|
9914
10141
|
const ctx = tryGetInvokeContext();
|
|
9915
10142
|
if (symbolFn !== null) {
|
|
9916
|
-
symbolRef = symbolFn().then((module) => (qrl.resolved = symbolRef =
|
|
10143
|
+
symbolRef = symbolFn().then((module) => (qrl.resolved = wrapFn((symbolRef = module[symbol]))));
|
|
9917
10144
|
}
|
|
9918
10145
|
else {
|
|
9919
10146
|
const imported = getPlatform().importSymbol(_containerEl, chunk, symbol);
|
|
9920
|
-
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = symbolRef =
|
|
10147
|
+
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = wrapFn((symbolRef = ref))));
|
|
9921
10148
|
}
|
|
9922
10149
|
if (typeof symbolRef === 'object' && isPromise(symbolRef)) {
|
|
9923
10150
|
symbolRef.then(() => emitUsedSymbol(symbol, ctx?.$element$, start), (err) => {
|
|
@@ -9940,10 +10167,9 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9940
10167
|
return invoke;
|
|
9941
10168
|
}
|
|
9942
10169
|
};
|
|
9943
|
-
const
|
|
9944
|
-
const hash = getSymbolHash(resolvedSymbol);
|
|
10170
|
+
const hash = getSymbolHash(symbol);
|
|
9945
10171
|
Object.assign(qrl, {
|
|
9946
|
-
getSymbol: () =>
|
|
10172
|
+
getSymbol: () => symbol,
|
|
9947
10173
|
getHash: () => hash,
|
|
9948
10174
|
getCaptured: () => captureRef,
|
|
9949
10175
|
resolve,
|
|
@@ -9951,7 +10177,6 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9951
10177
|
$setContainer$: setContainer,
|
|
9952
10178
|
$chunk$: chunk,
|
|
9953
10179
|
$symbol$: symbol,
|
|
9954
|
-
$refSymbol$: refSymbol,
|
|
9955
10180
|
$hash$: hash,
|
|
9956
10181
|
getFn: bindFnToContext,
|
|
9957
10182
|
$capture$: capture,
|
|
@@ -9960,8 +10185,8 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9960
10185
|
resolved: undefined,
|
|
9961
10186
|
});
|
|
9962
10187
|
if (symbolRef) {
|
|
9963
|
-
//
|
|
9964
|
-
symbolRef = maybeThen(symbolRef, (resolved) => (qrl.resolved = symbolRef =
|
|
10188
|
+
// Unwrap any promises
|
|
10189
|
+
symbolRef = maybeThen(symbolRef, (resolved) => (qrl.resolved = wrapFn((symbolRef = resolved))));
|
|
9965
10190
|
}
|
|
9966
10191
|
if (isDev) {
|
|
9967
10192
|
Object.defineProperty(qrl, '_devOnlySymbolRef', {
|
|
@@ -9975,20 +10200,6 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refS
|
|
|
9975
10200
|
}
|
|
9976
10201
|
return qrl;
|
|
9977
10202
|
};
|
|
9978
|
-
const getSymbolHash = (symbolName) => {
|
|
9979
|
-
const index = symbolName.lastIndexOf('_');
|
|
9980
|
-
if (index > -1) {
|
|
9981
|
-
return symbolName.slice(index + 1);
|
|
9982
|
-
}
|
|
9983
|
-
return symbolName;
|
|
9984
|
-
};
|
|
9985
|
-
function assertQrl(qrl) {
|
|
9986
|
-
if (qDev) {
|
|
9987
|
-
if (!isQrl(qrl)) {
|
|
9988
|
-
throw new Error('Not a QRL');
|
|
9989
|
-
}
|
|
9990
|
-
}
|
|
9991
|
-
}
|
|
9992
10203
|
const EMITTED = /*#__PURE__*/ new Set();
|
|
9993
10204
|
const emitUsedSymbol = (symbol, element, reqTime) => {
|
|
9994
10205
|
if (!EMITTED.has(symbol)) {
|
|
@@ -10101,7 +10312,7 @@ const $ = (expression) => {
|
|
|
10101
10312
|
if (!qRuntimeQrl && qDev) {
|
|
10102
10313
|
throw new Error('Optimizer should replace all usages of $() with some special syntax. If you need to create a QRL manually, use inlinedQrl() instead.');
|
|
10103
10314
|
}
|
|
10104
|
-
return createQRL(null, 's' + runtimeSymbolId++, expression, null, null, null
|
|
10315
|
+
return createQRL(null, 's' + runtimeSymbolId++, expression, null, null, null);
|
|
10105
10316
|
};
|
|
10106
10317
|
/** @private Use To avoid optimizer replacement */
|
|
10107
10318
|
const dollar = $;
|
|
@@ -10127,7 +10338,7 @@ const sync$ = (fn) => {
|
|
|
10127
10338
|
// eslint-disable-next-line no-new-func
|
|
10128
10339
|
fn = new Function('return ' + fn.toString())();
|
|
10129
10340
|
}
|
|
10130
|
-
return createQRL('', SYNC_QRL, fn, null, null, null
|
|
10341
|
+
return createQRL('', SYNC_QRL, fn, null, null, null);
|
|
10131
10342
|
};
|
|
10132
10343
|
/**
|
|
10133
10344
|
* Extract function into a synchronously loadable QRL.
|
|
@@ -10144,7 +10355,7 @@ const _qrlSync = function (fn, serializedFn) {
|
|
|
10144
10355
|
serializedFn = fn.toString();
|
|
10145
10356
|
}
|
|
10146
10357
|
fn.serialized = serializedFn;
|
|
10147
|
-
return createQRL('', SYNC_QRL, fn, null, null, null
|
|
10358
|
+
return createQRL('', SYNC_QRL, fn, null, null, null);
|
|
10148
10359
|
};
|
|
10149
10360
|
|
|
10150
10361
|
/** @internal */
|
|
@@ -10863,6 +11074,21 @@ const useVisibleTaskQrl = (qrl, opts) => {
|
|
|
10863
11074
|
iCtx.$container$.$scheduler$(ChoreType.VISIBLE, task);
|
|
10864
11075
|
}
|
|
10865
11076
|
};
|
|
11077
|
+
const useRunTask = (task, eagerness) => {
|
|
11078
|
+
if (eagerness === 'intersection-observer') {
|
|
11079
|
+
useOn('qvisible', getTaskHandlerQrl(task));
|
|
11080
|
+
}
|
|
11081
|
+
else if (eagerness === 'document-ready') {
|
|
11082
|
+
useOnDocument('qinit', getTaskHandlerQrl(task));
|
|
11083
|
+
}
|
|
11084
|
+
else if (eagerness === 'document-idle') {
|
|
11085
|
+
useOnDocument('qidle', getTaskHandlerQrl(task));
|
|
11086
|
+
}
|
|
11087
|
+
};
|
|
11088
|
+
const getTaskHandlerQrl = (task) => {
|
|
11089
|
+
const taskHandler = createQRL(null, '_task', scheduleTask, null, null, [task]);
|
|
11090
|
+
return taskHandler;
|
|
11091
|
+
};
|
|
10866
11092
|
|
|
10867
11093
|
// <docs markdown="../readme.md#useResource">
|
|
10868
11094
|
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
@@ -11173,5 +11399,5 @@ const PrefetchGraph = (opts = {}) => {
|
|
|
11173
11399
|
return _jsxSorted('script', null, props, null, 0, 'prefetch-graph');
|
|
11174
11400
|
};
|
|
11175
11401
|
|
|
11176
|
-
export { $, Fragment, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, EMPTY_ARRAY as _EMPTY_ARRAY,
|
|
11402
|
+
export { $, Fragment, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, SubscriptionData as _EffectData, _IMMUTABLE, _SharedContainer, _VAR_PROPS, _deserialize, _fnSignal, _getContextElement, _getContextEvent, getDomContainer as _getDomContainer, _getQContainerElement, isJSXNode as _isJSXNode, isStringifiable as _isStringifiable, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, _noopQrl, _noopQrlDEV, _qrlSync, _regSymbol, _restProps, queueQRL as _run, _serialize, scheduleTask as _task, verifySerializable as _verifySerializable, _waitUntilRendered, _walkJSX, _weakSerialize, _wrapProp, _wrapSignal, _wrapStore, component$, componentQrl, createComputed$, createComputedQrl, createContextId, h as createElement, createSignal, event$, eventQrl, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsx as jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
|
|
11177
11403
|
//# sourceMappingURL=core.mjs.map
|