@qwik.dev/core 2.0.0-beta.34 → 2.0.0-beta.35
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/dist/backpatch/package.json +1 -1
- package/dist/build/package.json +1 -1
- package/dist/cli.mjs +26 -22
- package/dist/core-internal.d.ts +67 -1
- package/dist/core.min.mjs +9 -2
- package/dist/core.mjs +578 -230
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.mjs +3054 -2906
- package/dist/loader/package.json +1 -1
- package/dist/optimizer.d.ts +2 -2
- package/dist/optimizer.mjs +2411 -1589
- package/dist/preloader.mjs +1 -268
- package/dist/server-modules.d.ts +1 -0
- package/dist/server.mjs +88 -139
- package/dist/server.prod.mjs +262 -310
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.mjs +427 -266
- package/dist/testing/package.json +1 -1
- package/dist/worker/index.d.mts +21 -0
- package/dist/worker/index.mjs +318 -0
- package/dist/worker/package.json +9 -0
- package/dist/worker/worker.js +13 -0
- package/dist/worker/worker.node.js +15 -0
- package/dist/worker/worker.shared.js +63 -0
- package/handlers.mjs +18 -1
- package/package.json +10 -4
- package/public.d.ts +5 -0
- package/worker.d.ts +2 -0
package/dist/core.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* @qwik.dev/core 2.0.0-beta.
|
|
3
|
+
* @qwik.dev/core 2.0.0-beta.35-dev+4603135
|
|
4
4
|
* Copyright QwikDev. All Rights Reserved.
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://github.com/QwikDev/qwik/blob/main/LICENSE
|
|
@@ -9,13 +9,14 @@ import { isDev, isServer, isBrowser as isBrowser$1 } from '@qwik.dev/core/build'
|
|
|
9
9
|
export { isBrowser, isDev, isServer } from '@qwik.dev/core/build';
|
|
10
10
|
import { p } from '@qwik.dev/core/preloader';
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
12
|
+
// Direct `globalThis.X` accesses (no alias) so Terser's `global_defs` engages
|
|
13
|
+
// and folds these to literal booleans in production builds, allowing
|
|
14
|
+
// `qTest ? testBranch : prodBranch` shims to tree-shake.
|
|
15
|
+
const qDev = globalThis.qDev !== false;
|
|
16
|
+
const qInspector = globalThis.qInspector === true;
|
|
17
|
+
const qDynamicPlatform = globalThis.qDynamicPlatform !== false;
|
|
18
|
+
const qTest = globalThis.qTest === true;
|
|
19
|
+
const qRuntimeQrl = globalThis.qRuntimeQrl === true;
|
|
19
20
|
const seal = (obj) => {
|
|
20
21
|
if (qDev) {
|
|
21
22
|
Object.seal(obj);
|
|
@@ -191,7 +192,7 @@ const isPrimitiveOrNullUndefined = (v) => {
|
|
|
191
192
|
|
|
192
193
|
const baseUrl = 'https://qwikdev-build-v2.qwik-8nx.pages.dev/docs/errors/#q';
|
|
193
194
|
const codeToText = (code, ...parts) => {
|
|
194
|
-
if (
|
|
195
|
+
if (isDev) {
|
|
195
196
|
// Keep one error, one line to make it easier to search for the error message.
|
|
196
197
|
// Keep in sync with packages/docs/src/routes/docs/errors/index.mdx
|
|
197
198
|
const MAP = [
|
|
@@ -443,6 +444,7 @@ const ELEMENT_KEY = 'q:key';
|
|
|
443
444
|
const ELEMENT_PROPS = 'q:props';
|
|
444
445
|
const ELEMENT_SEQ = 'q:seq';
|
|
445
446
|
const ELEMENT_SEQ_IDX = 'q:seqIdx';
|
|
447
|
+
const Q_PREFIX = 'q:';
|
|
446
448
|
const ITERATION_ITEM_SINGLE = 'q:p'; // Single iteration parameter (not an array)
|
|
447
449
|
const ITERATION_ITEM_MULTI = 'q:ps'; // Multiple iteration parameters (array)
|
|
448
450
|
/** Non serializable markers - always begins with `:` character */
|
|
@@ -450,6 +452,8 @@ const NON_SERIALIZABLE_MARKER_PREFIX = ':';
|
|
|
450
452
|
const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
|
|
451
453
|
const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
|
|
452
454
|
const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
|
|
455
|
+
const QCursorBoundary = Q_PREFIX + 'cursorBoundary';
|
|
456
|
+
const QNearestCursorBoundary = NON_SERIALIZABLE_MARKER_PREFIX + 'nearestCursorBoundary';
|
|
453
457
|
const Q_PROPS_SEPARATOR = ':';
|
|
454
458
|
const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
|
|
455
459
|
const qwikInspectorAttr = 'data-qwik-inspector';
|
|
@@ -793,6 +797,30 @@ const styleKey = (qStyles, index) => {
|
|
|
793
797
|
return `${hashCode(qStyles.$hash$)}-${index}`;
|
|
794
798
|
};
|
|
795
799
|
|
|
800
|
+
/**
|
|
801
|
+
* Creates a function that schedules `fn` to run as a microtask. Microtasks run before browser
|
|
802
|
+
* paint, preventing flickering.
|
|
803
|
+
*/
|
|
804
|
+
const createMicroTask = (fn) => {
|
|
805
|
+
return () => queueMicrotask(fn);
|
|
806
|
+
};
|
|
807
|
+
/**
|
|
808
|
+
* Creates a function that schedules `fn` to run as a macrotask. Macrotasks yield to the browser,
|
|
809
|
+
* allowing paint and user input. Used for time-slicing to avoid blocking the main thread.
|
|
810
|
+
*/
|
|
811
|
+
const createMacroTask = (fn) => {
|
|
812
|
+
let macroTask;
|
|
813
|
+
if (typeof MessageChannel !== 'undefined') {
|
|
814
|
+
const channel = new MessageChannel();
|
|
815
|
+
channel.port1.onmessage = () => fn();
|
|
816
|
+
macroTask = () => channel.port2.postMessage(null);
|
|
817
|
+
}
|
|
818
|
+
else {
|
|
819
|
+
macroTask = () => setTimeout(fn);
|
|
820
|
+
}
|
|
821
|
+
return macroTask;
|
|
822
|
+
};
|
|
823
|
+
|
|
796
824
|
// keep this import from core/build so the cjs build works
|
|
797
825
|
const createPlatform = () => {
|
|
798
826
|
return {
|
|
@@ -893,31 +921,8 @@ const isServerPlatform = () => {
|
|
|
893
921
|
return false;
|
|
894
922
|
};
|
|
895
923
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
* paint, preventing flickering.
|
|
899
|
-
*/
|
|
900
|
-
const createMicroTask = (fn) => {
|
|
901
|
-
return () => queueMicrotask(fn);
|
|
902
|
-
};
|
|
903
|
-
/**
|
|
904
|
-
* Creates a function that schedules `fn` to run as a macrotask. Macrotasks yield to the browser,
|
|
905
|
-
* allowing paint and user input. Used for time-slicing to avoid blocking the main thread.
|
|
906
|
-
*/
|
|
907
|
-
const createMacroTask = (fn) => {
|
|
908
|
-
let macroTask;
|
|
909
|
-
if (typeof MessageChannel !== 'undefined') {
|
|
910
|
-
const channel = new MessageChannel();
|
|
911
|
-
channel.port1.onmessage = () => fn();
|
|
912
|
-
macroTask = () => channel.port2.postMessage(null);
|
|
913
|
-
}
|
|
914
|
-
else {
|
|
915
|
-
macroTask = () => setTimeout(fn);
|
|
916
|
-
}
|
|
917
|
-
return macroTask;
|
|
918
|
-
};
|
|
919
|
-
|
|
920
|
-
const isBrowser = import.meta.env.TEST ? !isServerPlatform() : !isServer;
|
|
924
|
+
const hasDocument = typeof document !== 'undefined';
|
|
925
|
+
const isBrowser = (qTest ? !isServerPlatform() : !isServer) && hasDocument;
|
|
921
926
|
// Browser-specific setup
|
|
922
927
|
const doc = isBrowser ? document : undefined;
|
|
923
928
|
const config = {
|
|
@@ -938,7 +943,6 @@ const BundleImportState_Alias = 3;
|
|
|
938
943
|
const BundleImportState_Loaded = 4;
|
|
939
944
|
|
|
940
945
|
let base;
|
|
941
|
-
import.meta.env.TEST ? !isServerPlatform() : !isServer;
|
|
942
946
|
const makeBundle = (name, deps) => {
|
|
943
947
|
return {
|
|
944
948
|
$name$: name,
|
|
@@ -968,7 +972,6 @@ const nextAdjustmentMacroTask = createMacroTask(processPendingAdjustments);
|
|
|
968
972
|
let isTriggerScheduled = false;
|
|
969
973
|
let isAdjustmentScheduled = false;
|
|
970
974
|
let isProcessingAdjustments = false;
|
|
971
|
-
const shouldYieldInBrowser = import.meta.env.TEST ? !isServerPlatform() : isBrowser$1;
|
|
972
975
|
const adjustmentStack = [];
|
|
973
976
|
/**
|
|
974
977
|
* This is called when a bundle is queued, or finished loading.
|
|
@@ -1081,12 +1084,12 @@ function processPendingAdjustments() {
|
|
|
1081
1084
|
}
|
|
1082
1085
|
isAdjustmentScheduled = false;
|
|
1083
1086
|
isProcessingAdjustments = true;
|
|
1084
|
-
const deadline =
|
|
1087
|
+
const deadline = isBrowser ? performance.now() + yieldInterval : 0;
|
|
1085
1088
|
let processed = false;
|
|
1086
1089
|
while (adjustmentStack.length) {
|
|
1087
1090
|
processed = true;
|
|
1088
1091
|
const checkDeadline = processAdjustmentFrame();
|
|
1089
|
-
if (
|
|
1092
|
+
if (isBrowser && checkDeadline && performance.now() >= deadline) {
|
|
1090
1093
|
if (!isAdjustmentScheduled) {
|
|
1091
1094
|
isAdjustmentScheduled = true;
|
|
1092
1095
|
nextAdjustmentMacroTask();
|
|
@@ -1095,7 +1098,7 @@ function processPendingAdjustments() {
|
|
|
1095
1098
|
}
|
|
1096
1099
|
}
|
|
1097
1100
|
isProcessingAdjustments = false;
|
|
1098
|
-
if (processed &&
|
|
1101
|
+
if (processed && isBrowser) {
|
|
1099
1102
|
nextTriggerMacroTask();
|
|
1100
1103
|
}
|
|
1101
1104
|
}
|
|
@@ -1147,14 +1150,14 @@ const preload = (item, probability) => {
|
|
|
1147
1150
|
else {
|
|
1148
1151
|
handleBundle(item, inverseProbability);
|
|
1149
1152
|
}
|
|
1150
|
-
if (
|
|
1153
|
+
if (isBrowser) {
|
|
1151
1154
|
nextAdjustmentMacroTask();
|
|
1152
1155
|
}
|
|
1153
1156
|
else {
|
|
1154
1157
|
processPendingAdjustments();
|
|
1155
1158
|
}
|
|
1156
1159
|
};
|
|
1157
|
-
if (
|
|
1160
|
+
if (isBrowser) {
|
|
1158
1161
|
// Get early hints from qwikloader
|
|
1159
1162
|
document.addEventListener('qsymbol', (ev) => {
|
|
1160
1163
|
const { symbol, href } = ev.detail;
|
|
@@ -1188,7 +1191,7 @@ const COMMA = ',';
|
|
|
1188
1191
|
*
|
|
1189
1192
|
* @public
|
|
1190
1193
|
*/
|
|
1191
|
-
const version = "2.0.0-beta.
|
|
1194
|
+
const version = "2.0.0-beta.35-dev+4603135";
|
|
1192
1195
|
|
|
1193
1196
|
const isNode = (value) => {
|
|
1194
1197
|
return value && typeof value.nodeType === 'number';
|
|
@@ -1644,6 +1647,17 @@ function mergeCursors(container, newCursorData, oldCursor) {
|
|
|
1644
1647
|
newCursorData.journal = oldJournal;
|
|
1645
1648
|
}
|
|
1646
1649
|
}
|
|
1650
|
+
// merge cursor boundaries
|
|
1651
|
+
const oldBoundaries = oldCursorData.boundaries;
|
|
1652
|
+
if (__EXPERIMENTAL__.suspense && oldBoundaries && oldBoundaries.length > 0) {
|
|
1653
|
+
const newBoundaries = (newCursorData.boundaries ||= []);
|
|
1654
|
+
for (let i = 0; i < oldBoundaries.length; i++) {
|
|
1655
|
+
const boundary = oldBoundaries[i];
|
|
1656
|
+
if (!newBoundaries.includes(boundary)) {
|
|
1657
|
+
newBoundaries.push(boundary);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1647
1661
|
}
|
|
1648
1662
|
/**
|
|
1649
1663
|
* Gets the cursor data from a vNode.
|
|
@@ -1874,7 +1888,7 @@ class SignalImpl {
|
|
|
1874
1888
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
1875
1889
|
// to this signal.
|
|
1876
1890
|
ensureContainsBackRef(effectSubscriber, this);
|
|
1877
|
-
(
|
|
1891
|
+
(qTest ? !isDomContainer(this.$container$) : isServer) &&
|
|
1878
1892
|
addQrlToSerializationCtx(effectSubscriber, this.$container$);
|
|
1879
1893
|
}
|
|
1880
1894
|
return val;
|
|
@@ -2100,8 +2114,7 @@ class AsyncSignalImpl extends ComputedSignalImpl {
|
|
|
2100
2114
|
get untrackedValue() {
|
|
2101
2115
|
this.$computeIfNeeded$();
|
|
2102
2116
|
if (this.$current$?.$promise$) {
|
|
2103
|
-
if (this.$untrackedValue$ === NEEDS_COMPUTATION ||
|
|
2104
|
-
(import.meta.env.TEST ? isServerPlatform() : isServer)) {
|
|
2117
|
+
if (this.$untrackedValue$ === NEEDS_COMPUTATION || (qTest ? isServerPlatform() : isServer)) {
|
|
2105
2118
|
throw this.$current$?.$promise$;
|
|
2106
2119
|
}
|
|
2107
2120
|
return this.$untrackedValue$;
|
|
@@ -2111,7 +2124,7 @@ class AsyncSignalImpl extends ComputedSignalImpl {
|
|
|
2111
2124
|
}
|
|
2112
2125
|
// For clientOnly signals without initial value during SSR, throw if trying to read value
|
|
2113
2126
|
// During SSR, clientOnly signals are skipped, so there's no computed value available
|
|
2114
|
-
if ((
|
|
2127
|
+
if ((qTest ? isServerPlatform() : isServer) &&
|
|
2115
2128
|
this.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */ &&
|
|
2116
2129
|
this.$untrackedValue$ === NEEDS_COMPUTATION) {
|
|
2117
2130
|
throw qError(35 /* QError.asyncClientOnlyValueDuringSSR */);
|
|
@@ -2185,7 +2198,7 @@ class AsyncSignalImpl extends ComputedSignalImpl {
|
|
|
2185
2198
|
// reading `.loading` means someone is interested in the result, so we should trigger the computation. The alternative is eager computation or imperative calls to invalidate; this seems nicer.
|
|
2186
2199
|
this.$computeIfNeeded$();
|
|
2187
2200
|
// During SSR there's no such thing as loading state, we must render complete results
|
|
2188
|
-
if ((
|
|
2201
|
+
if ((qTest ? isServerPlatform() : isServer) && this.$current$?.$promise$) {
|
|
2189
2202
|
throw this.$current$?.$promise$;
|
|
2190
2203
|
}
|
|
2191
2204
|
return this.$untrackedLoading$;
|
|
@@ -2286,7 +2299,7 @@ class AsyncSignalImpl extends ComputedSignalImpl {
|
|
|
2286
2299
|
if (!(this.$flags$ & 32 /* AsyncSignalFlags.EAGER_CLEANUP */) || this.$hasSubscribers$()) {
|
|
2287
2300
|
return;
|
|
2288
2301
|
}
|
|
2289
|
-
if (!(
|
|
2302
|
+
if (!(qTest ? !isServerPlatform() : isBrowser$1)) {
|
|
2290
2303
|
return;
|
|
2291
2304
|
}
|
|
2292
2305
|
setTimeout(() => {
|
|
@@ -2309,8 +2322,7 @@ class AsyncSignalImpl extends ComputedSignalImpl {
|
|
|
2309
2322
|
return;
|
|
2310
2323
|
}
|
|
2311
2324
|
// Skip computation on SSR for clientOnly signals
|
|
2312
|
-
if ((
|
|
2313
|
-
this.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
|
|
2325
|
+
if ((qTest ? isServerPlatform() : isServer) && this.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
|
|
2314
2326
|
// We must pretend to load, and register as a listener for the captures
|
|
2315
2327
|
this.$untrackedLoading$ = true;
|
|
2316
2328
|
this.$container$?.serializationCtx.$eagerResume$.add(this);
|
|
@@ -2458,7 +2470,7 @@ class AsyncSignalImpl extends ComputedSignalImpl {
|
|
|
2458
2470
|
}
|
|
2459
2471
|
}
|
|
2460
2472
|
$scheduleNextPoll$() {
|
|
2461
|
-
if ((
|
|
2473
|
+
if ((qTest ? isServerPlatform() : isServer) || !this.$expires$) {
|
|
2462
2474
|
return;
|
|
2463
2475
|
}
|
|
2464
2476
|
this.$clearNextPoll$();
|
|
@@ -3601,7 +3613,7 @@ const executeComponent = (container, renderHost, subscriptionHost, componentQRL,
|
|
|
3601
3613
|
const inlineComponent = componentQRL;
|
|
3602
3614
|
componentFn = () => invokeApply(iCtx, inlineComponent, [props || EMPTY_OBJ]);
|
|
3603
3615
|
}
|
|
3604
|
-
const isSsr =
|
|
3616
|
+
const isSsr = qTest ? isServerPlatform() : isServer;
|
|
3605
3617
|
const executeComponentWithPromiseExceptionRetry = (retryCount = 0) => safeCall(() => {
|
|
3606
3618
|
if (!isInlineComponent) {
|
|
3607
3619
|
container.setHostProp(renderHost, ELEMENT_SEQ_IDX, null);
|
|
@@ -3986,6 +3998,214 @@ const createSetTextOperation = (target, text) => new SetTextOperation(target, te
|
|
|
3986
3998
|
const createInsertOrMoveOperation = (target, parent, beforeTarget) => new InsertOrMoveOperation(target, parent, beforeTarget);
|
|
3987
3999
|
const createSetAttributeOperation = (target, attrName, attrValue, scopedStyleIdPrefix = null, isSvg = false) => new SetAttributeOperation(target, attrName, attrValue, scopedStyleIdPrefix, isSvg);
|
|
3988
4000
|
|
|
4001
|
+
/**
|
|
4002
|
+
* @internal
|
|
4003
|
+
* The storage provider for hooks. Each invocation increases index i. Data is stored in an array.
|
|
4004
|
+
*/
|
|
4005
|
+
const useSequentialScope = () => {
|
|
4006
|
+
const iCtx = useInvokeContext();
|
|
4007
|
+
const hostElement = iCtx.$hostElement$;
|
|
4008
|
+
const host = hostElement;
|
|
4009
|
+
let seq = iCtx.$container$.getHostProp(host, ELEMENT_SEQ);
|
|
4010
|
+
if (seq === null) {
|
|
4011
|
+
seq = [];
|
|
4012
|
+
iCtx.$container$.setHostProp(host, ELEMENT_SEQ, seq);
|
|
4013
|
+
}
|
|
4014
|
+
let seqIdx = iCtx.$container$.getHostProp(host, ELEMENT_SEQ_IDX);
|
|
4015
|
+
if (seqIdx === null) {
|
|
4016
|
+
seqIdx = 0;
|
|
4017
|
+
}
|
|
4018
|
+
iCtx.$container$.setHostProp(host, ELEMENT_SEQ_IDX, seqIdx + 1);
|
|
4019
|
+
while (seq.length <= seqIdx) {
|
|
4020
|
+
seq.push(undefined);
|
|
4021
|
+
}
|
|
4022
|
+
const set = (value) => {
|
|
4023
|
+
if (qDev) {
|
|
4024
|
+
verifySerializable(value);
|
|
4025
|
+
}
|
|
4026
|
+
return (seq[seqIdx] = value);
|
|
4027
|
+
};
|
|
4028
|
+
return {
|
|
4029
|
+
val: seq[seqIdx],
|
|
4030
|
+
set,
|
|
4031
|
+
i: seqIdx,
|
|
4032
|
+
iCtx,
|
|
4033
|
+
};
|
|
4034
|
+
};
|
|
4035
|
+
|
|
4036
|
+
const getSignal = (initialState) => {
|
|
4037
|
+
const value = isFunction(initialState) && !isQwikComponent(initialState)
|
|
4038
|
+
? invoke(undefined, initialState)
|
|
4039
|
+
: initialState;
|
|
4040
|
+
return createSignal(value);
|
|
4041
|
+
};
|
|
4042
|
+
// <docs markdown="../readme.md#useSignal">
|
|
4043
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
4044
|
+
// (edit ../readme.md#useSignal instead and run `pnpm docs.sync`)
|
|
4045
|
+
/**
|
|
4046
|
+
* Creates an object with a single reactive `.value` property, that Qwik can track across
|
|
4047
|
+
* serializations.
|
|
4048
|
+
*
|
|
4049
|
+
* Use it to create state for your application. The object has a getter and setter to track reads
|
|
4050
|
+
* and writes of the `.value` property. When the value changes, any functions that read from it will
|
|
4051
|
+
* re-run.
|
|
4052
|
+
*
|
|
4053
|
+
* Prefer `useSignal` over `useStore` when possible, as it is more efficient.
|
|
4054
|
+
*
|
|
4055
|
+
* ### Example
|
|
4056
|
+
*
|
|
4057
|
+
* ```tsx
|
|
4058
|
+
* const Signals = component$(() => {
|
|
4059
|
+
* const counter = useSignal(1);
|
|
4060
|
+
* const text = useSignal('changeme');
|
|
4061
|
+
* const toggle = useSignal(false);
|
|
4062
|
+
*
|
|
4063
|
+
* // useSignal() can also accept a function to calculate the initial value
|
|
4064
|
+
* const state = useSignal(() => {
|
|
4065
|
+
* return expensiveInitialValue();
|
|
4066
|
+
* });
|
|
4067
|
+
*
|
|
4068
|
+
* return (
|
|
4069
|
+
* <div>
|
|
4070
|
+
* <button onClick$={() => counter.value++}>Counter: {counter.value}</button>
|
|
4071
|
+
* {
|
|
4072
|
+
* // pass signal values as the value, the optimizer will make it pass the signal
|
|
4073
|
+
* }
|
|
4074
|
+
* <Child state={state.value} />
|
|
4075
|
+
* {
|
|
4076
|
+
* // signals can be bound to inputs. A property named `bind:x` implies that the property
|
|
4077
|
+
* is a signal
|
|
4078
|
+
* }
|
|
4079
|
+
* <input type="text" bind:value={text} />
|
|
4080
|
+
* <input type="checkbox" bind:checked={toggle} />
|
|
4081
|
+
* </div>
|
|
4082
|
+
* );
|
|
4083
|
+
* });
|
|
4084
|
+
* ```
|
|
4085
|
+
*
|
|
4086
|
+
* @public
|
|
4087
|
+
*/
|
|
4088
|
+
// </docs>
|
|
4089
|
+
const useSignal = (initialState) => {
|
|
4090
|
+
return useConstant((getSignal), initialState);
|
|
4091
|
+
};
|
|
4092
|
+
/**
|
|
4093
|
+
* Stores a value which is retained for the lifetime of the component. Subsequent calls to
|
|
4094
|
+
* `useConstant` will always return the first value given.
|
|
4095
|
+
*
|
|
4096
|
+
* If the value is a function, the function is invoked once to calculate the actual value. You can
|
|
4097
|
+
* then also pass arguments to call the function with, so that you don't need to create a new
|
|
4098
|
+
* function on every render.
|
|
4099
|
+
*
|
|
4100
|
+
* @example
|
|
4101
|
+
*
|
|
4102
|
+
* ```tsx
|
|
4103
|
+
* const fixedRandomValue = useConstant(() => Math.random);
|
|
4104
|
+
* const otherFixedRandomValue = useConstant(Math.random);
|
|
4105
|
+
*
|
|
4106
|
+
* const getConfig = (env: string) => { ... }
|
|
4107
|
+
* const config = useConstant(getConfig, environment);
|
|
4108
|
+
* ```
|
|
4109
|
+
*
|
|
4110
|
+
* @public
|
|
4111
|
+
*/
|
|
4112
|
+
const useConstant = (value, ...args) => {
|
|
4113
|
+
const { val, set } = useSequentialScope();
|
|
4114
|
+
if (val != null) {
|
|
4115
|
+
return val;
|
|
4116
|
+
}
|
|
4117
|
+
// We don't want to create a subscription since we only run this once
|
|
4118
|
+
// Note: We are not using `invoke` here because we don't want to clear the context
|
|
4119
|
+
value = isFunction(value) && !isQwikComponent(value) ? untrack(value, ...args) : value;
|
|
4120
|
+
return set(value);
|
|
4121
|
+
};
|
|
4122
|
+
|
|
4123
|
+
const createCursorBoundary = () => {
|
|
4124
|
+
return {
|
|
4125
|
+
pending: createSignal(0),
|
|
4126
|
+
version: createSignal(0),
|
|
4127
|
+
};
|
|
4128
|
+
};
|
|
4129
|
+
/** @internal */
|
|
4130
|
+
const useCursorBoundary = () => {
|
|
4131
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4132
|
+
throw new Error('useCursorBoundary is experimental and must be enabled with `experimental: ["suspense"]` in the `qwikVite` plugin.');
|
|
4133
|
+
}
|
|
4134
|
+
return useConstant(createCursorBoundary);
|
|
4135
|
+
};
|
|
4136
|
+
function addCursorBoundary(cursorData, vNode) {
|
|
4137
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4138
|
+
return;
|
|
4139
|
+
}
|
|
4140
|
+
const boundary = getNearestCursorBoundary(cursorData.container, vNode);
|
|
4141
|
+
if (!boundary) {
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
const boundaries = (cursorData.boundaries ||= []);
|
|
4145
|
+
if (!boundaries.includes(boundary)) {
|
|
4146
|
+
boundaries.push(boundary);
|
|
4147
|
+
boundary.pending.value++;
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
function resolveCursorBoundaries(cursorData) {
|
|
4151
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4152
|
+
return;
|
|
4153
|
+
}
|
|
4154
|
+
const boundaries = cursorData.boundaries;
|
|
4155
|
+
if (!boundaries) {
|
|
4156
|
+
return;
|
|
4157
|
+
}
|
|
4158
|
+
cursorData.boundaries = null;
|
|
4159
|
+
for (let i = 0; i < boundaries.length; i++) {
|
|
4160
|
+
const boundary = boundaries[i];
|
|
4161
|
+
boundary.pending.value = Math.max(0, boundary.pending.value - 1);
|
|
4162
|
+
boundary.version.value++;
|
|
4163
|
+
}
|
|
4164
|
+
}
|
|
4165
|
+
function getOwnCursorBoundary(container, vNode) {
|
|
4166
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4167
|
+
return null;
|
|
4168
|
+
}
|
|
4169
|
+
return container.getHostProp(vNode, QCursorBoundary);
|
|
4170
|
+
}
|
|
4171
|
+
function getNearestCursorBoundaryProp(vNode) {
|
|
4172
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4173
|
+
return null;
|
|
4174
|
+
}
|
|
4175
|
+
return (vnode_getProp(vNode, QNearestCursorBoundary, null) ||
|
|
4176
|
+
null);
|
|
4177
|
+
}
|
|
4178
|
+
function clearNearestCursorBoundary(vNode) {
|
|
4179
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4180
|
+
return;
|
|
4181
|
+
}
|
|
4182
|
+
vnode_setProp(vNode, QNearestCursorBoundary, null);
|
|
4183
|
+
}
|
|
4184
|
+
function getNearestCursorBoundary(container, vNode) {
|
|
4185
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4186
|
+
return null;
|
|
4187
|
+
}
|
|
4188
|
+
return getNearestCursorBoundaryProp(vNode) || getOwnCursorBoundary(container, vNode);
|
|
4189
|
+
}
|
|
4190
|
+
function setNearestCursorBoundary(vNode, boundary) {
|
|
4191
|
+
__EXPERIMENTAL__.suspense && vnode_setProp(vNode, QNearestCursorBoundary, boundary);
|
|
4192
|
+
}
|
|
4193
|
+
/** Updates the nearest cursor boundary cache on a vnode and any already-dirty descendants. */
|
|
4194
|
+
function updateDirtySubtreeCursorBoundary(container, vNode, boundary) {
|
|
4195
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
4196
|
+
return;
|
|
4197
|
+
}
|
|
4198
|
+
setNearestCursorBoundary(vNode, boundary);
|
|
4199
|
+
const dirtyChildren = vNode.dirtyChildren;
|
|
4200
|
+
if (!dirtyChildren || dirtyChildren.length === 0) {
|
|
4201
|
+
return;
|
|
4202
|
+
}
|
|
4203
|
+
for (let i = 0; i < dirtyChildren.length; i++) {
|
|
4204
|
+
const child = dirtyChildren[i];
|
|
4205
|
+
updateDirtySubtreeCursorBoundary(container, child, getOwnCursorBoundary(container, child) || boundary);
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
4208
|
+
|
|
3989
4209
|
const cleanupDestroyable = (destroyable) => {
|
|
3990
4210
|
if (destroyable.$destroy$) {
|
|
3991
4211
|
try {
|
|
@@ -4106,7 +4326,7 @@ function peekNextSiblingWithinBoundary(diffContext, vCurrent) {
|
|
|
4106
4326
|
const _hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
4107
4327
|
/** Helper to set an attribute on a vnode. Extracted to module scope to avoid closure allocation. */
|
|
4108
4328
|
function setAttribute(journal, vnode, key, value, scopedStyleIdPrefix, originalValue) {
|
|
4109
|
-
|
|
4329
|
+
qTest &&
|
|
4110
4330
|
scopedStyleIdPrefix &&
|
|
4111
4331
|
vnode_setProp(vnode, debugStyleScopeIdPrefixAttr, scopedStyleIdPrefix);
|
|
4112
4332
|
vnode_setProp(vnode, key, originalValue);
|
|
@@ -4510,8 +4730,10 @@ function expectProjection(diffContext) {
|
|
|
4510
4730
|
}
|
|
4511
4731
|
}
|
|
4512
4732
|
function expectSlot(diffContext) {
|
|
4733
|
+
const jsxNode = diffContext.$jsxValue$;
|
|
4513
4734
|
const vHost = vnode_getProjectionParentComponent(diffContext.$vParent$);
|
|
4514
4735
|
const slotNameKey = getSlotNameKey(diffContext, vHost);
|
|
4736
|
+
const cursorBoundary = directGetPropsProxyProp(jsxNode, QCursorBoundary) || null;
|
|
4515
4737
|
const vProjectedNode = vHost
|
|
4516
4738
|
? vnode_getProp(vHost, slotNameKey,
|
|
4517
4739
|
// for slots this id is vnode ref id
|
|
@@ -4522,6 +4744,8 @@ function expectSlot(diffContext) {
|
|
|
4522
4744
|
if (vProjectedNode == null) {
|
|
4523
4745
|
diffContext.$vNewNode$ = vnode_newVirtual();
|
|
4524
4746
|
vnode_setProp(diffContext.$vNewNode$, QSlot, slotNameKey);
|
|
4747
|
+
vnode_setProp(diffContext.$vNewNode$, QCursorBoundary, cursorBoundary);
|
|
4748
|
+
updateDirtySubtreeCursorBoundary(diffContext.$container$, diffContext.$vNewNode$, cursorBoundary);
|
|
4525
4749
|
vHost && vnode_setProp(vHost, slotNameKey, diffContext.$vNewNode$);
|
|
4526
4750
|
isDev &&
|
|
4527
4751
|
vnode_setProp(diffContext.$vNewNode$, DEBUG_TYPE, "P" /* VirtualType.Projection */); // Nothing to project, so render content of the slot.
|
|
@@ -4534,6 +4758,8 @@ function expectSlot(diffContext) {
|
|
|
4534
4758
|
const oldParent = vProjectedNode.parent;
|
|
4535
4759
|
diffContext.$vNewNode$ = vProjectedNode;
|
|
4536
4760
|
vnode_setProp(diffContext.$vNewNode$, QSlot, slotNameKey);
|
|
4761
|
+
vnode_setProp(diffContext.$vNewNode$, QCursorBoundary, cursorBoundary);
|
|
4762
|
+
updateDirtySubtreeCursorBoundary(diffContext.$container$, diffContext.$vNewNode$, cursorBoundary);
|
|
4537
4763
|
vHost && vnode_setProp(vHost, slotNameKey, diffContext.$vNewNode$);
|
|
4538
4764
|
isDev &&
|
|
4539
4765
|
vnode_setProp(diffContext.$vNewNode$, DEBUG_TYPE, "P" /* VirtualType.Projection */);
|
|
@@ -4769,7 +4995,7 @@ function registerEventHandlers(key, value, element, vnode, diffContext) {
|
|
|
4769
4995
|
function createElementWithNamespace(diffContext, elementName) {
|
|
4770
4996
|
const domParentVNode = vnode_getDomParentVNode(diffContext.$vParent$, true);
|
|
4771
4997
|
const namespaceData = getNewElementNamespaceData(domParentVNode, elementName);
|
|
4772
|
-
const currentDocument =
|
|
4998
|
+
const currentDocument = qTest ? diffContext.$container$.document : document;
|
|
4773
4999
|
const element = namespaceData.elementNamespaceFlag === 0 /* VNodeFlags.NS_html */
|
|
4774
5000
|
? currentDocument.createElement(elementName)
|
|
4775
5001
|
: currentDocument.createElementNS(namespaceData.elementNamespace, elementName);
|
|
@@ -4894,7 +5120,7 @@ const patchProperty = (diffContext, vnode, key, value, currentFile) => {
|
|
|
4894
5120
|
setAttribute(diffContext.$journal$, vnode, key, value, diffContext.$scopedStyleIdPrefix$, originalValue);
|
|
4895
5121
|
};
|
|
4896
5122
|
function registerQwikLoaderEvent(diffContext, eventName) {
|
|
4897
|
-
const qWindow =
|
|
5123
|
+
const qWindow = qTest
|
|
4898
5124
|
? diffContext.$container$.document.defaultView
|
|
4899
5125
|
: window;
|
|
4900
5126
|
if (qWindow) {
|
|
@@ -5208,7 +5434,7 @@ function expectText(diffContext, text) {
|
|
|
5208
5434
|
return;
|
|
5209
5435
|
}
|
|
5210
5436
|
}
|
|
5211
|
-
vnode_insertElementBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newText((
|
|
5437
|
+
vnode_insertElementBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newText((qTest ? diffContext.$container$.document : document).createTextNode(text), text)), getCurrentInsertBefore(diffContext));
|
|
5212
5438
|
}
|
|
5213
5439
|
/**
|
|
5214
5440
|
* Retrieve the key from the VNode.
|
|
@@ -6311,7 +6537,7 @@ function processCursorQueue() {
|
|
|
6311
6537
|
* tick)
|
|
6312
6538
|
*/
|
|
6313
6539
|
function walkCursor(cursor, until) {
|
|
6314
|
-
const isRunningOnServer =
|
|
6540
|
+
const isRunningOnServer = qTest ? isServerPlatform() : isServer;
|
|
6315
6541
|
const cursorData = getCursorData(cursor);
|
|
6316
6542
|
// Check if cursor is blocked by a promise
|
|
6317
6543
|
const blockingPromise = cursorData.promise;
|
|
@@ -6335,7 +6561,8 @@ function walkCursor(cursor, until) {
|
|
|
6335
6561
|
// Skip if the vNode is not dirty
|
|
6336
6562
|
if (!(currentVNode.dirty & 511 /* ChoreBits.DIRTY_MASK */)) {
|
|
6337
6563
|
// Move to next node
|
|
6338
|
-
|
|
6564
|
+
__EXPERIMENTAL__.suspense && clearNearestCursorBoundary(currentVNode);
|
|
6565
|
+
setCursorPosition(container, cursorData, getNextVNode(currentVNode, cursor, container));
|
|
6339
6566
|
continue;
|
|
6340
6567
|
}
|
|
6341
6568
|
// Skip if the vNode is deleted
|
|
@@ -6353,7 +6580,7 @@ function walkCursor(cursor, until) {
|
|
|
6353
6580
|
}
|
|
6354
6581
|
// Clear dirty bits and move to next node
|
|
6355
6582
|
currentVNode.dirty &= -512 /* ChoreBits.DIRTY_MASK */;
|
|
6356
|
-
setCursorPosition(container, cursorData, getNextVNode(currentVNode, cursor));
|
|
6583
|
+
setCursorPosition(container, cursorData, getNextVNode(currentVNode, cursor, container));
|
|
6357
6584
|
continue;
|
|
6358
6585
|
}
|
|
6359
6586
|
let result;
|
|
@@ -6396,6 +6623,7 @@ function walkCursor(cursor, until) {
|
|
|
6396
6623
|
}
|
|
6397
6624
|
// Handle blocking promise
|
|
6398
6625
|
if (result && isPromise(result)) {
|
|
6626
|
+
addCursorBoundary(cursorData, currentVNode);
|
|
6399
6627
|
// Store promise on cursor and pause
|
|
6400
6628
|
cursorData.promise = result;
|
|
6401
6629
|
pauseCursor(cursor, container);
|
|
@@ -6426,6 +6654,7 @@ function finishWalk(container, cursor, cursorData, isServer) {
|
|
|
6426
6654
|
if (!isServer) {
|
|
6427
6655
|
executeFlushPhase(cursor, container);
|
|
6428
6656
|
}
|
|
6657
|
+
resolveCursorBoundaries(cursorData);
|
|
6429
6658
|
if (cursorData.extraPromises) {
|
|
6430
6659
|
Promise.all(cursorData.extraPromises).then(() => {
|
|
6431
6660
|
resolveCursor(container);
|
|
@@ -6446,30 +6675,14 @@ function tryDescendDirtyChildren(container, cursorData, currentVNode, cursor) {
|
|
|
6446
6675
|
const dirtyChildren = currentVNode.dirtyChildren;
|
|
6447
6676
|
if (!dirtyChildren || dirtyChildren.length === 0) {
|
|
6448
6677
|
currentVNode.dirty &= -33 /* ChoreBits.CHILDREN */;
|
|
6678
|
+
clearNearestCursorBoundary(currentVNode);
|
|
6449
6679
|
return null;
|
|
6450
6680
|
}
|
|
6451
6681
|
partitionDirtyChildren(dirtyChildren, currentVNode);
|
|
6452
|
-
// Scan dirtyChildren directly instead of going through getNextVNode.
|
|
6453
|
-
// getNextVNode follows the child's parent/slotParent pointer, which for Projection nodes
|
|
6454
|
-
// points to the DOM insertion location rather than currentVNode — that would scan the
|
|
6455
|
-
// wrong dirtyChildren array and potentially cause infinite loops.
|
|
6456
|
-
// const len = dirtyChildren.length;
|
|
6457
|
-
// for (let i = 0; i < len; i++) {
|
|
6458
|
-
// const child = dirtyChildren[i];
|
|
6459
|
-
// if (child.dirty & ChoreBits.DIRTY_MASK) {
|
|
6460
|
-
// currentVNode.nextDirtyChildIndex = (i + 1) % len;
|
|
6461
|
-
// setCursorPosition(container, cursorData, child);
|
|
6462
|
-
// return child;
|
|
6463
|
-
// }
|
|
6464
|
-
// }
|
|
6465
|
-
// // No dirty child found — clean up
|
|
6466
|
-
// currentVNode.dirty &= ~ChoreBits.CHILDREN;
|
|
6467
|
-
// currentVNode.dirtyChildren = null;
|
|
6468
6682
|
currentVNode.nextDirtyChildIndex = 0;
|
|
6469
|
-
const next = getNextVNode(dirtyChildren[0], cursor);
|
|
6683
|
+
const next = getNextVNode(dirtyChildren[0], cursor, container);
|
|
6470
6684
|
setCursorPosition(container, cursorData, next);
|
|
6471
6685
|
return next;
|
|
6472
|
-
// return null;
|
|
6473
6686
|
}
|
|
6474
6687
|
/**
|
|
6475
6688
|
* Partitions dirtyChildren array so non-projections come first, projections last. Uses in-place
|
|
@@ -6491,7 +6704,7 @@ function partitionDirtyChildren(dirtyChildren, parent) {
|
|
|
6491
6704
|
}
|
|
6492
6705
|
}
|
|
6493
6706
|
/** @returns Next vNode to process, or null if traversal is complete */
|
|
6494
|
-
function getNextVNode(vNode, cursor) {
|
|
6707
|
+
function getNextVNode(vNode, cursor, container) {
|
|
6495
6708
|
if (vNode === cursor) {
|
|
6496
6709
|
if (cursor.dirty & 511 /* ChoreBits.DIRTY_MASK */) {
|
|
6497
6710
|
return cursor;
|
|
@@ -6519,6 +6732,13 @@ function getNextVNode(vNode, cursor) {
|
|
|
6519
6732
|
while (count-- > 0) {
|
|
6520
6733
|
const nextVNode = dirtyChildren[index];
|
|
6521
6734
|
if (nextVNode.dirty & 511 /* ChoreBits.DIRTY_MASK */) {
|
|
6735
|
+
if (container && splitCursorBoundary(container, nextVNode)) {
|
|
6736
|
+
index++;
|
|
6737
|
+
if (index === len) {
|
|
6738
|
+
index = 0;
|
|
6739
|
+
}
|
|
6740
|
+
continue;
|
|
6741
|
+
}
|
|
6522
6742
|
parent.nextDirtyChildIndex = (index + 1) % len;
|
|
6523
6743
|
return nextVNode;
|
|
6524
6744
|
}
|
|
@@ -6531,7 +6751,22 @@ function getNextVNode(vNode, cursor) {
|
|
|
6531
6751
|
parent.dirty &= -33 /* ChoreBits.CHILDREN */;
|
|
6532
6752
|
parent.dirtyChildren = null;
|
|
6533
6753
|
parent.nextDirtyChildIndex = 0;
|
|
6534
|
-
|
|
6754
|
+
__EXPERIMENTAL__.suspense && clearNearestCursorBoundary(parent);
|
|
6755
|
+
return getNextVNode(parent, cursor, container);
|
|
6756
|
+
}
|
|
6757
|
+
function splitCursorBoundary(container, vNode) {
|
|
6758
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
6759
|
+
return false;
|
|
6760
|
+
}
|
|
6761
|
+
if (!vNode.props ||
|
|
6762
|
+
!(QCursorBoundary in vNode.props) ||
|
|
6763
|
+
!container.getHostProp(vNode, QCursorBoundary)) {
|
|
6764
|
+
return false;
|
|
6765
|
+
}
|
|
6766
|
+
if (!isCursor(vNode)) {
|
|
6767
|
+
addCursor(container, vNode, 0);
|
|
6768
|
+
}
|
|
6769
|
+
return true;
|
|
6535
6770
|
}
|
|
6536
6771
|
|
|
6537
6772
|
/**
|
|
@@ -6551,6 +6786,7 @@ function addCursor(container, root, priority) {
|
|
|
6551
6786
|
position: root,
|
|
6552
6787
|
priority: priority,
|
|
6553
6788
|
promise: null,
|
|
6789
|
+
boundaries: null,
|
|
6554
6790
|
};
|
|
6555
6791
|
setCursorData(root, cursorData);
|
|
6556
6792
|
const cursor = root;
|
|
@@ -6594,7 +6830,7 @@ function _executeSsrChores(container, ssrNode) {
|
|
|
6594
6830
|
if (ssrNode.dirty & 16 /* ChoreBits.COMPUTE */) {
|
|
6595
6831
|
executeCompute(ssrNode, container);
|
|
6596
6832
|
}
|
|
6597
|
-
if (ssrNode.dirty & 511 /* ChoreBits.DIRTY_MASK */) {
|
|
6833
|
+
if (isDev && ssrNode.dirty & 511 /* ChoreBits.DIRTY_MASK */) {
|
|
6598
6834
|
// We are running on the server.
|
|
6599
6835
|
// On server we can't schedule task for a different host!
|
|
6600
6836
|
// Server is SSR, and therefore scheduling for anything but the current host
|
|
@@ -6717,14 +6953,23 @@ function propagatePath(target) {
|
|
|
6717
6953
|
* Propagates dirty bits from vNode up to the specified cursorRoot. Used during diff when we know
|
|
6718
6954
|
* the cursor root to merge with. Also updates cursor position if we pass through any cursors.
|
|
6719
6955
|
*/
|
|
6720
|
-
function propagateToCursorRoot(vNode, cursorRoot) {
|
|
6956
|
+
function propagateToCursorRoot(container, vNode, cursorRoot) {
|
|
6721
6957
|
reusablePath.push(vNode);
|
|
6958
|
+
let cursorBoundary = getOwnCursorBoundary(container, vNode);
|
|
6722
6959
|
let current = vNode.slotParent || vNode.parent;
|
|
6723
6960
|
while (current) {
|
|
6724
6961
|
const isDirty = current.dirty & 511 /* ChoreBits.DIRTY_MASK */;
|
|
6725
6962
|
const currentIsCursor = isCursor(current);
|
|
6963
|
+
if (__EXPERIMENTAL__.suspense) {
|
|
6964
|
+
cursorBoundary ||=
|
|
6965
|
+
getOwnCursorBoundary(container, current) ||
|
|
6966
|
+
(isDirty ? getNearestCursorBoundary(container, current) : null);
|
|
6967
|
+
}
|
|
6726
6968
|
// Stop when we reach the cursor root or a dirty ancestor
|
|
6727
6969
|
if (current === cursorRoot || isDirty) {
|
|
6970
|
+
// Known cursor root / dirty ancestor case: cache the boundary discovered while walking
|
|
6971
|
+
// before attaching this dirty vnode to the existing scheduled subtree.
|
|
6972
|
+
setNearestCursorBoundary(vNode, cursorBoundary);
|
|
6728
6973
|
propagatePath(current);
|
|
6729
6974
|
// Update cursor position if current is a cursor
|
|
6730
6975
|
if (currentIsCursor) {
|
|
@@ -6753,12 +6998,23 @@ function propagateToCursorRoot(vNode, cursorRoot) {
|
|
|
6753
6998
|
* Finds a blocking cursor or dirty ancestor and propagates dirty bits to it. Returns true if found
|
|
6754
6999
|
* and attached, false if a new cursor should be created.
|
|
6755
7000
|
*/
|
|
6756
|
-
function findAndPropagateToBlockingCursor(vNode) {
|
|
7001
|
+
function findAndPropagateToBlockingCursor(container, vNode) {
|
|
6757
7002
|
reusablePath.push(vNode);
|
|
7003
|
+
let cursorBoundary = __EXPERIMENTAL__.suspense
|
|
7004
|
+
? getOwnCursorBoundary(container, vNode)
|
|
7005
|
+
: null;
|
|
6758
7006
|
let current = vNode.slotParent || vNode.parent;
|
|
6759
7007
|
while (current) {
|
|
6760
7008
|
const currentIsCursor = isCursor(current);
|
|
7009
|
+
if (__EXPERIMENTAL__.suspense) {
|
|
7010
|
+
cursorBoundary ||=
|
|
7011
|
+
getOwnCursorBoundary(container, current) ||
|
|
7012
|
+
(currentIsCursor ? getNearestCursorBoundary(container, current) : null);
|
|
7013
|
+
}
|
|
6761
7014
|
if (currentIsCursor) {
|
|
7015
|
+
// Existing cursor case: attach this dirty vnode to the blocking cursor found above it and
|
|
7016
|
+
// remember that cursor's nearest boundary for async/suspense bookkeeping.
|
|
7017
|
+
setNearestCursorBoundary(vNode, cursorBoundary);
|
|
6762
7018
|
propagatePath(current);
|
|
6763
7019
|
reusablePath.length = 0;
|
|
6764
7020
|
return true;
|
|
@@ -6766,11 +7022,14 @@ function findAndPropagateToBlockingCursor(vNode) {
|
|
|
6766
7022
|
reusablePath.push(current);
|
|
6767
7023
|
current = current.slotParent || current.parent;
|
|
6768
7024
|
}
|
|
7025
|
+
// New cursor case: no blocking cursor was found above this vnode, so cache the nearest boundary
|
|
7026
|
+
// before the caller creates a cursor rooted at this vnode.
|
|
7027
|
+
setNearestCursorBoundary(vNode, cursorBoundary);
|
|
6769
7028
|
reusablePath.length = 0;
|
|
6770
7029
|
return false;
|
|
6771
7030
|
}
|
|
6772
7031
|
function isSsrNodeGuard(_vNode) {
|
|
6773
|
-
return
|
|
7032
|
+
return qTest ? isServerPlatform() : isServer;
|
|
6774
7033
|
}
|
|
6775
7034
|
/**
|
|
6776
7035
|
* Marks a vNode as dirty and propagates dirty bits up the tree.
|
|
@@ -6801,11 +7060,14 @@ function markVNodeDirty(container, vNode, bits, cursorRoot = null) {
|
|
|
6801
7060
|
const parent = vNode.slotParent || vNode.parent;
|
|
6802
7061
|
// If cursorRoot is provided, propagate up to it
|
|
6803
7062
|
if (cursorRoot && isRealDirty && parent && !parent.dirty) {
|
|
6804
|
-
propagateToCursorRoot(vNode, cursorRoot);
|
|
7063
|
+
propagateToCursorRoot(container, vNode, cursorRoot);
|
|
6805
7064
|
return;
|
|
6806
7065
|
}
|
|
6807
7066
|
// We must attach to a cursor subtree if it exists
|
|
6808
7067
|
if (parent && parent.dirty & 511 /* ChoreBits.DIRTY_MASK */) {
|
|
7068
|
+
// Dirty parent case: this vnode joins an already scheduled subtree, so inherit the parent's
|
|
7069
|
+
// nearest boundary unless this vnode owns a boundary itself.
|
|
7070
|
+
setNearestCursorBoundary(vNode, getOwnCursorBoundary(container, vNode) || getNearestCursorBoundary(container, parent));
|
|
6809
7071
|
if (isRealDirty) {
|
|
6810
7072
|
parent.dirty |= 32 /* ChoreBits.CHILDREN */;
|
|
6811
7073
|
}
|
|
@@ -6837,11 +7099,16 @@ function markVNodeDirty(container, vNode, bits, cursorRoot = null) {
|
|
|
6837
7099
|
else if (!isCursor(vNode)) {
|
|
6838
7100
|
// Check if there's an existing cursor that is blocking (executing a render-blocking task)
|
|
6839
7101
|
// If so, merge with it instead of creating a new cursor (single-pass find + propagate)
|
|
6840
|
-
if (!findAndPropagateToBlockingCursor(vNode)) {
|
|
7102
|
+
if (!findAndPropagateToBlockingCursor(container, vNode)) {
|
|
6841
7103
|
// No blocking cursor found, create a new one
|
|
6842
7104
|
addCursor(container, vNode, 0);
|
|
6843
7105
|
}
|
|
6844
7106
|
}
|
|
7107
|
+
else {
|
|
7108
|
+
// Existing cursor-root case: the vnode is already the scheduled cursor, so only its own
|
|
7109
|
+
// boundary can be authoritative here.
|
|
7110
|
+
setNearestCursorBoundary(vNode, getOwnCursorBoundary(container, vNode));
|
|
7111
|
+
}
|
|
6845
7112
|
}
|
|
6846
7113
|
function addVNodeOperation(journal, operation) {
|
|
6847
7114
|
journal.push(operation);
|
|
@@ -7127,7 +7394,7 @@ const vnode_setProp = (vNode, key, value) => {
|
|
|
7127
7394
|
};
|
|
7128
7395
|
const vnode_setAttr = (journal, vNode, key, value, scopedStyleIdPrefix = null) => {
|
|
7129
7396
|
if (vnode_isElementVNode(vNode)) {
|
|
7130
|
-
|
|
7397
|
+
qTest &&
|
|
7131
7398
|
scopedStyleIdPrefix &&
|
|
7132
7399
|
vnode_setProp(vNode, debugStyleScopeIdPrefixAttr, scopedStyleIdPrefix);
|
|
7133
7400
|
vnode_setProp(vNode, key, value);
|
|
@@ -8716,41 +8983,6 @@ function clearStoreOrProps(producer, effect) {
|
|
|
8716
8983
|
}
|
|
8717
8984
|
}
|
|
8718
8985
|
|
|
8719
|
-
/**
|
|
8720
|
-
* @internal
|
|
8721
|
-
* The storage provider for hooks. Each invocation increases index i. Data is stored in an array.
|
|
8722
|
-
*/
|
|
8723
|
-
const useSequentialScope = () => {
|
|
8724
|
-
const iCtx = useInvokeContext();
|
|
8725
|
-
const hostElement = iCtx.$hostElement$;
|
|
8726
|
-
const host = hostElement;
|
|
8727
|
-
let seq = iCtx.$container$.getHostProp(host, ELEMENT_SEQ);
|
|
8728
|
-
if (seq === null) {
|
|
8729
|
-
seq = [];
|
|
8730
|
-
iCtx.$container$.setHostProp(host, ELEMENT_SEQ, seq);
|
|
8731
|
-
}
|
|
8732
|
-
let seqIdx = iCtx.$container$.getHostProp(host, ELEMENT_SEQ_IDX);
|
|
8733
|
-
if (seqIdx === null) {
|
|
8734
|
-
seqIdx = 0;
|
|
8735
|
-
}
|
|
8736
|
-
iCtx.$container$.setHostProp(host, ELEMENT_SEQ_IDX, seqIdx + 1);
|
|
8737
|
-
while (seq.length <= seqIdx) {
|
|
8738
|
-
seq.push(undefined);
|
|
8739
|
-
}
|
|
8740
|
-
const set = (value) => {
|
|
8741
|
-
if (qDev) {
|
|
8742
|
-
verifySerializable(value);
|
|
8743
|
-
}
|
|
8744
|
-
return (seq[seqIdx] = value);
|
|
8745
|
-
};
|
|
8746
|
-
return {
|
|
8747
|
-
val: seq[seqIdx],
|
|
8748
|
-
set,
|
|
8749
|
-
i: seqIdx,
|
|
8750
|
-
iCtx,
|
|
8751
|
-
};
|
|
8752
|
-
};
|
|
8753
|
-
|
|
8754
8986
|
/** @internal */
|
|
8755
8987
|
const useTaskQrl = (qrl, opts) => {
|
|
8756
8988
|
const { val, set, iCtx, i } = useSequentialScope();
|
|
@@ -8896,7 +9128,7 @@ const addQrlToSerializationCtx = (effectSubscriber, container) => {
|
|
|
8896
9128
|
}
|
|
8897
9129
|
};
|
|
8898
9130
|
const scheduleEffects = (container, signal, effects) => {
|
|
8899
|
-
const
|
|
9131
|
+
const isRunningOnBrowser = qTest ? !isServerPlatform() : isBrowser$1;
|
|
8900
9132
|
if (effects) {
|
|
8901
9133
|
const scheduleEffect = (effectSubscription) => {
|
|
8902
9134
|
const consumer = effectSubscription.consumer;
|
|
@@ -8913,7 +9145,7 @@ const scheduleEffects = (container, signal, effects) => {
|
|
|
8913
9145
|
markVNodeDirty(container, consumer, 4 /* ChoreBits.COMPONENT */);
|
|
8914
9146
|
}
|
|
8915
9147
|
else if (property === "." /* EffectProperty.VNODE */) {
|
|
8916
|
-
if (
|
|
9148
|
+
if (isRunningOnBrowser) {
|
|
8917
9149
|
setNodeDiffPayload(consumer, signal);
|
|
8918
9150
|
markVNodeDirty(container, consumer, 2 /* ChoreBits.NODE_DIFF */);
|
|
8919
9151
|
}
|
|
@@ -8927,7 +9159,7 @@ const scheduleEffects = (container, signal, effects) => {
|
|
|
8927
9159
|
scopedStyleIdPrefix: data.$scopedStyleIdPrefix$,
|
|
8928
9160
|
value: signal,
|
|
8929
9161
|
};
|
|
8930
|
-
if (
|
|
9162
|
+
if (isRunningOnBrowser) {
|
|
8931
9163
|
setNodePropData(consumer, property, payload);
|
|
8932
9164
|
}
|
|
8933
9165
|
else {
|
|
@@ -9283,7 +9515,7 @@ function addStoreEffect(target, prop, store, effectSubscription) {
|
|
|
9283
9515
|
// to this signal.
|
|
9284
9516
|
ensureContainsBackRef(effectSubscription, target);
|
|
9285
9517
|
// TODO is this needed with the preloader?
|
|
9286
|
-
(
|
|
9518
|
+
(qTest ? !isDomContainer(store.$container$) : isServer) &&
|
|
9287
9519
|
addQrlToSerializationCtx(effectSubscription, store.$container$);
|
|
9288
9520
|
}
|
|
9289
9521
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
@@ -10924,19 +11156,29 @@ const _noopQrl = (symbolName, lexicalScopeCapture) => {
|
|
|
10924
11156
|
/** @internal */
|
|
10925
11157
|
const _noopQrlDEV = (symbolName, opts, lexicalScopeCapture) => {
|
|
10926
11158
|
const newQrl = _noopQrl(symbolName, lexicalScopeCapture);
|
|
11159
|
+
qDev && newQrl.$setDev$(opts);
|
|
11160
|
+
return newQrl;
|
|
11161
|
+
};
|
|
11162
|
+
/** @internal */
|
|
11163
|
+
const _qrlWithChunk = (chunk, importer, symbol, lexicalScopeCapture) => {
|
|
11164
|
+
return createQRL(chunk, symbol, null, importer, lexicalScopeCapture);
|
|
11165
|
+
};
|
|
11166
|
+
/** @internal */
|
|
11167
|
+
const _qrlWithChunkDEV = (chunk, importer, symbol, opts, lexicalScopeCapture) => {
|
|
11168
|
+
const newQrl = _qrlWithChunk(chunk, importer, symbol, lexicalScopeCapture);
|
|
10927
11169
|
newQrl.$setDev$(opts);
|
|
10928
11170
|
return newQrl;
|
|
10929
11171
|
};
|
|
10930
11172
|
/** @internal */
|
|
10931
11173
|
const qrlDEV = (chunkOrFn, symbol, opts, lexicalScopeCapture) => {
|
|
10932
11174
|
const newQrl = qrl(chunkOrFn, symbol, lexicalScopeCapture, 1);
|
|
10933
|
-
newQrl.$setDev$(opts);
|
|
11175
|
+
qDev && newQrl.$setDev$(opts);
|
|
10934
11176
|
return newQrl;
|
|
10935
11177
|
};
|
|
10936
11178
|
/** @internal */
|
|
10937
11179
|
const inlinedQrlDEV = (symbol, symbolName, opts, lexicalScopeCapture) => {
|
|
10938
11180
|
const qrl = inlinedQrl(symbol, symbolName, lexicalScopeCapture);
|
|
10939
|
-
qrl.$setDev$(opts);
|
|
11181
|
+
qDev && qrl.$setDev$(opts);
|
|
10940
11182
|
return qrl;
|
|
10941
11183
|
};
|
|
10942
11184
|
/**
|
|
@@ -10953,6 +11195,12 @@ const _regSymbol = (symbol, hash) => {
|
|
|
10953
11195
|
return symbol;
|
|
10954
11196
|
};
|
|
10955
11197
|
|
|
11198
|
+
/** @internal */
|
|
11199
|
+
const getAsyncLocalStorage = () => {
|
|
11200
|
+
const process = globalThis.process;
|
|
11201
|
+
return process?.getBuiltinModule?.('node:async_hooks')?.AsyncLocalStorage;
|
|
11202
|
+
};
|
|
11203
|
+
|
|
10956
11204
|
/** @file Shared types */
|
|
10957
11205
|
/** @internal */
|
|
10958
11206
|
function isStringifiable(value) {
|
|
@@ -11168,9 +11416,11 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
11168
11416
|
const componentFrame = options.parentComponentFrame;
|
|
11169
11417
|
if (componentFrame) {
|
|
11170
11418
|
const compId = componentFrame.componentNode.id || '';
|
|
11171
|
-
const projectionAttrs = isDev
|
|
11172
|
-
|
|
11173
|
-
|
|
11419
|
+
const projectionAttrs = isDev ? { [DEBUG_TYPE]: "P" /* VirtualType.Projection */ } : {};
|
|
11420
|
+
const cursorBoundary = directGetPropsProxyProp(jsx, QCursorBoundary);
|
|
11421
|
+
if (cursorBoundary) {
|
|
11422
|
+
projectionAttrs[QCursorBoundary] = cursorBoundary;
|
|
11423
|
+
}
|
|
11174
11424
|
projectionAttrs[QSlotParent] = compId;
|
|
11175
11425
|
ssr.openProjection(projectionAttrs);
|
|
11176
11426
|
const host = componentFrame.componentNode;
|
|
@@ -12090,7 +12340,7 @@ function inflateWrappedSignalValue(signal) {
|
|
|
12090
12340
|
}
|
|
12091
12341
|
}
|
|
12092
12342
|
function restoreEffectBackRefForConsumer(effect) {
|
|
12093
|
-
const isServerSide =
|
|
12343
|
+
const isServerSide = qTest ? isServerPlatform() : isServer;
|
|
12094
12344
|
const consumerBackRef = effect.consumer;
|
|
12095
12345
|
if (isServerSide && !consumerBackRef) {
|
|
12096
12346
|
// on browser, we don't serialize for example VNodes, so then on server side we don't have consumer
|
|
@@ -12238,6 +12488,7 @@ function getObjectById(id, stateData) {
|
|
|
12238
12488
|
isDev && assertTrue(id < stateData.length, `Invalid reference ${id} >= ${stateData.length}`);
|
|
12239
12489
|
return stateData[id];
|
|
12240
12490
|
}
|
|
12491
|
+
/** @internal */
|
|
12241
12492
|
function _createDeserializeContainer(stateData) {
|
|
12242
12493
|
// eslint-disable-next-line prefer-const
|
|
12243
12494
|
let state;
|
|
@@ -13140,6 +13391,7 @@ class DomContainer extends _SharedContainer {
|
|
|
13140
13391
|
case OnRenderProp:
|
|
13141
13392
|
case QCtxAttr:
|
|
13142
13393
|
case QBackRefs:
|
|
13394
|
+
case QCursorBoundary:
|
|
13143
13395
|
getObjectById = this.$getObjectById$;
|
|
13144
13396
|
break;
|
|
13145
13397
|
case ELEMENT_SEQ_IDX:
|
|
@@ -13220,13 +13472,10 @@ class DomContainer extends _SharedContainer {
|
|
|
13220
13472
|
let _locale = undefined;
|
|
13221
13473
|
let localAsyncStore;
|
|
13222
13474
|
if (isServer) {
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
localAsyncStore = new
|
|
13226
|
-
}
|
|
13227
|
-
.catch(() => {
|
|
13228
|
-
// ignore if AsyncLocalStorage is not available
|
|
13229
|
-
});
|
|
13475
|
+
const AsyncLocalStorage = getAsyncLocalStorage();
|
|
13476
|
+
if (AsyncLocalStorage) {
|
|
13477
|
+
localAsyncStore = new AsyncLocalStorage();
|
|
13478
|
+
}
|
|
13230
13479
|
}
|
|
13231
13480
|
/**
|
|
13232
13481
|
* Retrieve the current locale.
|
|
@@ -14160,6 +14409,25 @@ const component$ = (onMount) => {
|
|
|
14160
14409
|
/** @public */
|
|
14161
14410
|
const event$ = implicit$FirstArg(eventQrl);
|
|
14162
14411
|
|
|
14412
|
+
/**
|
|
14413
|
+
* Returns the client build manifest, which includes the mappings from symbols to bundles, the
|
|
14414
|
+
* bundlegraph etc.
|
|
14415
|
+
*
|
|
14416
|
+
* @public
|
|
14417
|
+
*/
|
|
14418
|
+
const getClientManifest = () => {
|
|
14419
|
+
// Keep this first because the magic-string first replaces the `!...` version and it can't replace after that.
|
|
14420
|
+
const manifest = globalThis.__QWIK_MANIFEST__;
|
|
14421
|
+
/**
|
|
14422
|
+
* Keep as-is, this is replaced verbatim with `false` by the qwikVite plugin, so this function
|
|
14423
|
+
* only throws if the build was not done correctly + no manifest was provided on globalThis.
|
|
14424
|
+
*/
|
|
14425
|
+
if (!globalThis.__QWIK_MANIFEST__) {
|
|
14426
|
+
throw new Error(`Client manifest is not available. It should have been automatically injected during the build process. Make sure that @qwik.dev/core is internal to the build.`);
|
|
14427
|
+
}
|
|
14428
|
+
return manifest;
|
|
14429
|
+
};
|
|
14430
|
+
|
|
14163
14431
|
/**
|
|
14164
14432
|
* Render JSX.
|
|
14165
14433
|
*
|
|
@@ -14730,7 +14998,7 @@ const useStylesScopedQrl = (styles) => {
|
|
|
14730
14998
|
*/
|
|
14731
14999
|
// </docs>
|
|
14732
15000
|
const useStylesScoped$ = /*#__PURE__*/ implicit$FirstArg(useStylesScopedQrl);
|
|
14733
|
-
const liveUpdate = isDev && ((import.meta.hot && typeof document !== 'undefined') ||
|
|
15001
|
+
const liveUpdate = isDev && ((import.meta.hot && typeof document !== 'undefined') || qTest);
|
|
14734
15002
|
const _useStyles = (styleQrl, transform, scoped) => {
|
|
14735
15003
|
assertQrl(styleQrl);
|
|
14736
15004
|
// eslint-disable-next-line prefer-const
|
|
@@ -14782,93 +15050,6 @@ const _useStyles = (styleQrl, transform, scoped) => {
|
|
|
14782
15050
|
return styleId;
|
|
14783
15051
|
};
|
|
14784
15052
|
|
|
14785
|
-
const getSignal = (initialState) => {
|
|
14786
|
-
const value = isFunction(initialState) && !isQwikComponent(initialState)
|
|
14787
|
-
? invoke(undefined, initialState)
|
|
14788
|
-
: initialState;
|
|
14789
|
-
return createSignal(value);
|
|
14790
|
-
};
|
|
14791
|
-
// <docs markdown="../readme.md#useSignal">
|
|
14792
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
14793
|
-
// (edit ../readme.md#useSignal instead and run `pnpm docs.sync`)
|
|
14794
|
-
/**
|
|
14795
|
-
* Creates an object with a single reactive `.value` property, that Qwik can track across
|
|
14796
|
-
* serializations.
|
|
14797
|
-
*
|
|
14798
|
-
* Use it to create state for your application. The object has a getter and setter to track reads
|
|
14799
|
-
* and writes of the `.value` property. When the value changes, any functions that read from it will
|
|
14800
|
-
* re-run.
|
|
14801
|
-
*
|
|
14802
|
-
* Prefer `useSignal` over `useStore` when possible, as it is more efficient.
|
|
14803
|
-
*
|
|
14804
|
-
* ### Example
|
|
14805
|
-
*
|
|
14806
|
-
* ```tsx
|
|
14807
|
-
* const Signals = component$(() => {
|
|
14808
|
-
* const counter = useSignal(1);
|
|
14809
|
-
* const text = useSignal('changeme');
|
|
14810
|
-
* const toggle = useSignal(false);
|
|
14811
|
-
*
|
|
14812
|
-
* // useSignal() can also accept a function to calculate the initial value
|
|
14813
|
-
* const state = useSignal(() => {
|
|
14814
|
-
* return expensiveInitialValue();
|
|
14815
|
-
* });
|
|
14816
|
-
*
|
|
14817
|
-
* return (
|
|
14818
|
-
* <div>
|
|
14819
|
-
* <button onClick$={() => counter.value++}>Counter: {counter.value}</button>
|
|
14820
|
-
* {
|
|
14821
|
-
* // pass signal values as the value, the optimizer will make it pass the signal
|
|
14822
|
-
* }
|
|
14823
|
-
* <Child state={state.value} />
|
|
14824
|
-
* {
|
|
14825
|
-
* // signals can be bound to inputs. A property named `bind:x` implies that the property
|
|
14826
|
-
* is a signal
|
|
14827
|
-
* }
|
|
14828
|
-
* <input type="text" bind:value={text} />
|
|
14829
|
-
* <input type="checkbox" bind:checked={toggle} />
|
|
14830
|
-
* </div>
|
|
14831
|
-
* );
|
|
14832
|
-
* });
|
|
14833
|
-
* ```
|
|
14834
|
-
*
|
|
14835
|
-
* @public
|
|
14836
|
-
*/
|
|
14837
|
-
// </docs>
|
|
14838
|
-
const useSignal = (initialState) => {
|
|
14839
|
-
return useConstant((getSignal), initialState);
|
|
14840
|
-
};
|
|
14841
|
-
/**
|
|
14842
|
-
* Stores a value which is retained for the lifetime of the component. Subsequent calls to
|
|
14843
|
-
* `useConstant` will always return the first value given.
|
|
14844
|
-
*
|
|
14845
|
-
* If the value is a function, the function is invoked once to calculate the actual value. You can
|
|
14846
|
-
* then also pass arguments to call the function with, so that you don't need to create a new
|
|
14847
|
-
* function on every render.
|
|
14848
|
-
*
|
|
14849
|
-
* @example
|
|
14850
|
-
*
|
|
14851
|
-
* ```tsx
|
|
14852
|
-
* const fixedRandomValue = useConstant(() => Math.random);
|
|
14853
|
-
* const otherFixedRandomValue = useConstant(Math.random);
|
|
14854
|
-
*
|
|
14855
|
-
* const getConfig = (env: string) => { ... }
|
|
14856
|
-
* const config = useConstant(getConfig, environment);
|
|
14857
|
-
* ```
|
|
14858
|
-
*
|
|
14859
|
-
* @public
|
|
14860
|
-
*/
|
|
14861
|
-
const useConstant = (value, ...args) => {
|
|
14862
|
-
const { val, set } = useSequentialScope();
|
|
14863
|
-
if (val != null) {
|
|
14864
|
-
return val;
|
|
14865
|
-
}
|
|
14866
|
-
// We don't want to create a subscription since we only run this once
|
|
14867
|
-
// Note: We are not using `invoke` here because we don't want to clear the context
|
|
14868
|
-
value = isFunction(value) && !isQwikComponent(value) ? untrack(value, ...args) : value;
|
|
14869
|
-
return set(value);
|
|
14870
|
-
};
|
|
14871
|
-
|
|
14872
15053
|
const creator$2 = (qrl, options) => {
|
|
14873
15054
|
qrl.resolve();
|
|
14874
15055
|
return createComputedSignal(qrl, options);
|
|
@@ -15170,7 +15351,7 @@ const eachCmpTask = async ({ track }) => {
|
|
|
15170
15351
|
const host = context.$hostElement$;
|
|
15171
15352
|
const container = context.$container$;
|
|
15172
15353
|
markVNodeDirty(container, host, 128 /* ChoreBits.RECONCILE */);
|
|
15173
|
-
const isSsr =
|
|
15354
|
+
const isSsr = qTest ? isServerPlatform() : isServer;
|
|
15174
15355
|
if (isSsr) {
|
|
15175
15356
|
await container.$renderPromise$;
|
|
15176
15357
|
}
|
|
@@ -15187,6 +15368,173 @@ const eachCmp = (props) => {
|
|
|
15187
15368
|
const Each = /*#__PURE__*/ componentQrl(
|
|
15188
15369
|
/*#__PURE__*/ inlinedQrl(eachCmp, '_eaC'));
|
|
15189
15370
|
|
|
15371
|
+
const RevealContext = /*#__PURE__*/ createContextId('qk-reveal');
|
|
15372
|
+
const createRevealContext = (props) => {
|
|
15373
|
+
return {
|
|
15374
|
+
order: props.order ?? 'parallel',
|
|
15375
|
+
collapsed: props.collapsed === true,
|
|
15376
|
+
items: [],
|
|
15377
|
+
version: createSignal(0),
|
|
15378
|
+
};
|
|
15379
|
+
};
|
|
15380
|
+
/** @internal */
|
|
15381
|
+
const revealCanReveal = () => {
|
|
15382
|
+
const registration = _captures[0];
|
|
15383
|
+
if (registration === null) {
|
|
15384
|
+
return true;
|
|
15385
|
+
}
|
|
15386
|
+
const reveal = registration.reveal;
|
|
15387
|
+
const current = registration.item;
|
|
15388
|
+
const items = reveal.items;
|
|
15389
|
+
// `version` is monotonic; the branch keeps the subscription read from being dropped by minifiers.
|
|
15390
|
+
if (reveal.version.value < 0) {
|
|
15391
|
+
return false;
|
|
15392
|
+
}
|
|
15393
|
+
switch (reveal.order) {
|
|
15394
|
+
case 'together':
|
|
15395
|
+
for (let i = 0; i < items.length; i++) {
|
|
15396
|
+
if (items[i].boundary.pending.untrackedValue > 0) {
|
|
15397
|
+
return false;
|
|
15398
|
+
}
|
|
15399
|
+
}
|
|
15400
|
+
return true;
|
|
15401
|
+
case 'sequential':
|
|
15402
|
+
for (let i = 0; i < items.length; i++) {
|
|
15403
|
+
const item = items[i];
|
|
15404
|
+
if (item === current) {
|
|
15405
|
+
return true;
|
|
15406
|
+
}
|
|
15407
|
+
if (item.boundary.pending.untrackedValue > 0) {
|
|
15408
|
+
return false;
|
|
15409
|
+
}
|
|
15410
|
+
}
|
|
15411
|
+
return true;
|
|
15412
|
+
case 'reverse':
|
|
15413
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
15414
|
+
const item = items[i];
|
|
15415
|
+
if (item === current) {
|
|
15416
|
+
return true;
|
|
15417
|
+
}
|
|
15418
|
+
if (item.boundary.pending.untrackedValue > 0) {
|
|
15419
|
+
return false;
|
|
15420
|
+
}
|
|
15421
|
+
}
|
|
15422
|
+
return true;
|
|
15423
|
+
default:
|
|
15424
|
+
return true;
|
|
15425
|
+
}
|
|
15426
|
+
};
|
|
15427
|
+
/** @internal */
|
|
15428
|
+
const revealCleanupTask = ({ cleanup }) => {
|
|
15429
|
+
const registration = _captures[0];
|
|
15430
|
+
cleanup(() => {
|
|
15431
|
+
// Keep the SSR registry intact so `reveal.items` serializes for resume.
|
|
15432
|
+
if (qTest ? isServerPlatform() : !isBrowser$1) {
|
|
15433
|
+
return;
|
|
15434
|
+
}
|
|
15435
|
+
const items = registration.reveal.items;
|
|
15436
|
+
const index = items.indexOf(registration.item);
|
|
15437
|
+
if (index !== -1) {
|
|
15438
|
+
items.splice(index, 1);
|
|
15439
|
+
registration.reveal.version.value++;
|
|
15440
|
+
}
|
|
15441
|
+
});
|
|
15442
|
+
};
|
|
15443
|
+
const useRevealBoundary = (boundary) => {
|
|
15444
|
+
const reveal = useContext(RevealContext, null);
|
|
15445
|
+
const registration = useConstant(() => {
|
|
15446
|
+
if (reveal === null) {
|
|
15447
|
+
return null;
|
|
15448
|
+
}
|
|
15449
|
+
const item = { boundary };
|
|
15450
|
+
reveal.items.push(item);
|
|
15451
|
+
return { reveal, item };
|
|
15452
|
+
});
|
|
15453
|
+
if (registration !== null) {
|
|
15454
|
+
useTaskQrl(/*#__PURE__*/ inlinedQrl(revealCleanupTask, '_reT', [registration]), {
|
|
15455
|
+
deferUpdates: false,
|
|
15456
|
+
});
|
|
15457
|
+
}
|
|
15458
|
+
return registration;
|
|
15459
|
+
};
|
|
15460
|
+
/** @internal */
|
|
15461
|
+
const revealCmp = (props) => {
|
|
15462
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
15463
|
+
throw new Error('Reveal is experimental and must be enabled with `experimental: ["suspense"]` in the `qwikVite` plugin.');
|
|
15464
|
+
}
|
|
15465
|
+
const reveal = useConstant(createRevealContext, props);
|
|
15466
|
+
useContextProvider(RevealContext, reveal);
|
|
15467
|
+
return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 0, 'u7_0');
|
|
15468
|
+
};
|
|
15469
|
+
/** @public @experimental */
|
|
15470
|
+
const Reveal = /*#__PURE__*/ componentQrl(
|
|
15471
|
+
/*#__PURE__*/ inlinedQrl(revealCmp, '_reC'));
|
|
15472
|
+
|
|
15473
|
+
const _hf0 = (p0, p1, p2, p3) => ({
|
|
15474
|
+
display: p1.value === 'fallback' &&
|
|
15475
|
+
p0.fallback != null &&
|
|
15476
|
+
p0.fallback !== false &&
|
|
15477
|
+
(p2 === null || p2.value || !p3.reveal.collapsed)
|
|
15478
|
+
? 'contents'
|
|
15479
|
+
: 'none',
|
|
15480
|
+
});
|
|
15481
|
+
const _hf0_str = '{display:p1.value==="fallback"&&p0.fallback!=null&&p0.fallback!==false&&(p2===null||p2.value||!p3.reveal.collapsed)?"contents":"none"}';
|
|
15482
|
+
const _hf1 = (p0, p1, p2) => ({
|
|
15483
|
+
display: (p2 === null || p2.value) && (p1.value === 'content' || p0.showStale) ? 'contents' : 'none',
|
|
15484
|
+
});
|
|
15485
|
+
const _hf1_str = '{display:(p2===null||p2.value)&&(p1.value==="content"||p0.showStale)?"contents":"none"}';
|
|
15486
|
+
/** @internal */
|
|
15487
|
+
const suspenseTask = ({ track, cleanup }) => {
|
|
15488
|
+
const cursorBoundary = _captures[0], props = _captures[1], state = _captures[2], revealRegistration = _captures[3];
|
|
15489
|
+
const pendingCount = track(cursorBoundary.pending);
|
|
15490
|
+
const isBrowserEnv = qTest ? !isServerPlatform() : isBrowser$1;
|
|
15491
|
+
if (revealRegistration !== null && isBrowserEnv) {
|
|
15492
|
+
revealRegistration.reveal.version.value++;
|
|
15493
|
+
}
|
|
15494
|
+
if (!isBrowserEnv || pendingCount === 0) {
|
|
15495
|
+
state.value = 'content';
|
|
15496
|
+
return;
|
|
15497
|
+
}
|
|
15498
|
+
const delayTimer = setTimeout(() => {
|
|
15499
|
+
if (cursorBoundary.pending.value > 0) {
|
|
15500
|
+
state.value = 'fallback';
|
|
15501
|
+
}
|
|
15502
|
+
}, props.delay ?? 0);
|
|
15503
|
+
cleanup(() => clearTimeout(delayTimer));
|
|
15504
|
+
};
|
|
15505
|
+
/** @internal */
|
|
15506
|
+
const suspenseCmp = (props) => {
|
|
15507
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
15508
|
+
throw new Error('Suspense is experimental and must be enabled with `experimental: ["suspense"]` in the `qwikVite` plugin.');
|
|
15509
|
+
}
|
|
15510
|
+
const state = useSignal('content');
|
|
15511
|
+
const cursorBoundary = useCursorBoundary();
|
|
15512
|
+
const revealRegistration = useRevealBoundary(cursorBoundary);
|
|
15513
|
+
const canReveal = useComputedQrl(
|
|
15514
|
+
/*#__PURE__*/ inlinedQrl(revealCanReveal, '_reR', [revealRegistration]));
|
|
15515
|
+
useTaskQrl(
|
|
15516
|
+
/*#__PURE__*/ inlinedQrl(suspenseTask, '_suT', [
|
|
15517
|
+
cursorBoundary,
|
|
15518
|
+
props,
|
|
15519
|
+
state,
|
|
15520
|
+
revealRegistration,
|
|
15521
|
+
]));
|
|
15522
|
+
return /*#__PURE__*/ _jsxSorted(Fragment, null, null, [
|
|
15523
|
+
/*#__PURE__*/ _jsxSorted('div', {
|
|
15524
|
+
style: _fnSignal(_hf0, [props, state, canReveal, revealRegistration], _hf0_str),
|
|
15525
|
+
}, null, _wrapProp(props, 'fallback'), 1, null),
|
|
15526
|
+
/*#__PURE__*/ _jsxSorted('div', null, {
|
|
15527
|
+
style: _fnSignal(_hf1, [props, state, canReveal], _hf1_str),
|
|
15528
|
+
},
|
|
15529
|
+
/*#__PURE__*/ _jsxSorted(Slot, {
|
|
15530
|
+
[QCursorBoundary]: cursorBoundary,
|
|
15531
|
+
}, null, null, 3, 'u6_0'), 1, null),
|
|
15532
|
+
], 1, 'u6_1');
|
|
15533
|
+
};
|
|
15534
|
+
/** @public @experimental */
|
|
15535
|
+
const Suspense = /*#__PURE__*/ componentQrl(
|
|
15536
|
+
/*#__PURE__*/ inlinedQrl(suspenseCmp, '_suC'));
|
|
15537
|
+
|
|
15190
15538
|
// keep this import from core/build so the cjs build works
|
|
15191
15539
|
/**
|
|
15192
15540
|
* @deprecated This is no longer needed as the preloading happens automatically in qrl-class.ts.
|
|
@@ -15195,7 +15543,7 @@ const Each = /*#__PURE__*/ componentQrl(
|
|
|
15195
15543
|
* @alpha
|
|
15196
15544
|
*/
|
|
15197
15545
|
const PrefetchServiceWorker = (opts) => {
|
|
15198
|
-
const isTest =
|
|
15546
|
+
const isTest = qTest;
|
|
15199
15547
|
if (isDev && !isTest) {
|
|
15200
15548
|
const props = {
|
|
15201
15549
|
dangerouslySetInnerHTML: '<!-- PrefetchServiceWorker is disabled in dev mode. -->',
|
|
@@ -15204,7 +15552,7 @@ const PrefetchServiceWorker = (opts) => {
|
|
|
15204
15552
|
}
|
|
15205
15553
|
// if an MFE app has a custom BASE_URL then this will be the correct value
|
|
15206
15554
|
// if you're not using MFE from another codebase then you want to override this value to your custom setup
|
|
15207
|
-
const baseUrl = import.meta.env
|
|
15555
|
+
const baseUrl = import.meta.env?.BASE_URL || '/';
|
|
15208
15556
|
const resolvedOpts = {
|
|
15209
15557
|
path: 'qwik-prefetch-service-worker.js',
|
|
15210
15558
|
...opts,
|
|
@@ -15282,5 +15630,5 @@ if (import.meta.hot) {
|
|
|
15282
15630
|
});
|
|
15283
15631
|
}
|
|
15284
15632
|
|
|
15285
|
-
export { $, Each, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, EMPTY_OBJ as _EMPTY_OBJ, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, _UNINITIALIZED, _VAR_PROPS, _addProjection, _captures, _chk, createQRL as _createQRL, _deserialize, _dumpState, eachCmp as _eaC, eachCmpTask as _eaT, _executeSsrChores, _fnSignal, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, _hmr, isJSXNode as _isJSXNode, isStore as _isStore, isStringifiable as _isStringifiable, isTask as _isTask, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, mapApp_findIndx as _mapApp_findIndx, mapArray_get as _mapArray_get, mapArray_set as _mapArray_set, _noopQrl, _noopQrlDEV, preprocessState as _preprocessState, _qrlSync, qrlToString as _qrlToString, _regSymbol, _removeProjection, _res, _resolveContextWithoutSequentialScope, _restProps, _rsc, _run, _serialize, setEvent as _setEvent, _setProjectionTarget, scheduleTask as _task, _updateProjectionProps, _useHmr, _val, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getElementName as _vnode_getElementName, vnode_getFirstChild as _vnode_getFirstChild, vnode_getProp as _vnode_getProp, vnode_getVNodeForChildNode as _vnode_getVNodeForChildNode, vnode_insertBefore as _vnode_insertBefore, vnode_isElementVNode as _vnode_isElementVNode, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_newVirtual as _vnode_newVirtual, vnode_remove as _vnode_remove, vnode_setProp as _vnode_setProp, vnode_toString as _vnode_toString, _waitUntilRendered, _walkJSX, _wrapProp, _wrapSignal, component$, componentQrl, createAsync$, createAsyncSignal as createAsyncQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, forceStoreEffects, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsync$, useAsyncQrl, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
|
|
15633
|
+
export { $, Each, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, Reveal, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, SkipRender, Slot, Suspense, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, EMPTY_OBJ as _EMPTY_OBJ, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, _UNINITIALIZED, _VAR_PROPS, _addProjection, _captures, _chk, _createDeserializeContainer, createQRL as _createQRL, _deserialize, _dumpState, eachCmp as _eaC, eachCmpTask as _eaT, _executeSsrChores, _fnSignal, getAsyncLocalStorage as _getAsyncLocalStorage, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, _hmr, isJSXNode as _isJSXNode, isStore as _isStore, isStringifiable as _isStringifiable, isTask as _isTask, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, mapApp_findIndx as _mapApp_findIndx, mapArray_get as _mapArray_get, mapArray_set as _mapArray_set, _noopQrl, _noopQrlDEV, preprocessState as _preprocessState, _qrlSync, qrlToString as _qrlToString, _qrlWithChunk, _qrlWithChunkDEV, revealCmp as _reC, revealCanReveal as _reR, revealCleanupTask as _reT, _regSymbol, _removeProjection, _res, _resolveContextWithoutSequentialScope, _restProps, _rsc, _run, _serialize, setEvent as _setEvent, _setProjectionTarget, suspenseCmp as _suC, suspenseTask as _suT, scheduleTask as _task, _updateProjectionProps, _useHmr, _val, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getElementName as _vnode_getElementName, vnode_getFirstChild as _vnode_getFirstChild, vnode_getProp as _vnode_getProp, vnode_getVNodeForChildNode as _vnode_getVNodeForChildNode, vnode_insertBefore as _vnode_insertBefore, vnode_isElementVNode as _vnode_isElementVNode, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_newVirtual as _vnode_newVirtual, vnode_remove as _vnode_remove, vnode_setProp as _vnode_setProp, vnode_toString as _vnode_toString, _waitUntilRendered, _walkJSX, _wrapProp, _wrapSignal, component$, componentQrl, createAsync$, createAsyncSignal as createAsyncQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, forceStoreEffects, getClientManifest, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsync$, useAsyncQrl, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
|
|
15286
15634
|
//# sourceMappingURL=core.mjs.map
|