@qwik.dev/core 2.0.0-beta.40 → 2.0.0-beta.42
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 +2 -2
- package/dist/core-internal.d.ts +97 -72
- package/dist/core.min.mjs +11 -9
- package/dist/core.mjs +733 -144
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.mjs +3895 -3334
- package/dist/error-swap-executor.debug.js +37 -0
- package/dist/error-swap-executor.js +1 -0
- package/dist/loader/index.mjs +2 -2
- package/dist/loader/package.json +1 -1
- package/dist/optimizer.d.ts +3 -7
- package/dist/optimizer.mjs +52 -68
- package/dist/out-of-order-executor.debug.js +12 -12
- package/dist/qwikloader.debug.js +1 -1
- package/dist/qwikloader.js +1 -1
- package/dist/server.d.ts +27 -0
- package/dist/server.mjs +100 -40
- package/dist/server.prod.mjs +853 -785
- package/dist/starters/adapters/cloudflare-workers/adapters/cloudflare-workers/vite.config.ts +3 -3
- package/dist/starters/adapters/cloudflare-workers/src/entry.cloudflare-pages.tsx +4 -5
- package/dist/starters/features/compiled-i18n/src/components/locale-selector/locale-selector.tsx +1 -1
- package/dist/starters/features/compiled-i18n/src/routes/plugin@compiled-i18n.ts +1 -1
- package/dist/starters/features/cypress/src/actions/example.action.ts +1 -1
- package/dist/starters/features/cypress/src/components/example/example.cy.tsx +4 -4
- package/dist/starters/features/cypress/src/loaders/example.loader.ts +1 -1
- package/dist/testing/index.d.ts +11 -2
- package/dist/testing/index.mjs +6568 -6298
- package/dist/testing/package.json +1 -1
- package/dist/worker/package.json +1 -1
- package/handlers.mjs +3 -0
- package/package.json +3 -3
- package/public.d.ts +3 -3
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.42-dev+3473a49
|
|
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
|
|
@@ -29,6 +29,9 @@ const STYLE = qDev
|
|
|
29
29
|
const logError = (message, ...optionalParams) => {
|
|
30
30
|
return createAndLogError(false, message, ...optionalParams);
|
|
31
31
|
};
|
|
32
|
+
const logErrorAndThrowAsync = (message, ...optionalParams) => {
|
|
33
|
+
return createAndLogError(true, message, ...optionalParams);
|
|
34
|
+
};
|
|
32
35
|
const throwErrorAndStop = (message, ...optionalParams) => {
|
|
33
36
|
const error = createAndLogError(false, message, ...optionalParams);
|
|
34
37
|
// eslint-disable-next-line no-debugger
|
|
@@ -418,6 +421,8 @@ const QSlotS = 'q:s';
|
|
|
418
421
|
const QStatePatchAttrSelector = '[q\\:patch]';
|
|
419
422
|
const QSuspenseResolved = 'q:r';
|
|
420
423
|
const QSuspenseResultParent = 'q:rp';
|
|
424
|
+
const QErrorContentHost = 'q:ebc';
|
|
425
|
+
const QErrorFallbackHost = 'q:ebf';
|
|
421
426
|
const QStyle = 'q:style';
|
|
422
427
|
const QStyleSelector = 'style[q\\:style]';
|
|
423
428
|
const QStyleSSelector = 'style[q\\:sstyle]';
|
|
@@ -489,8 +494,13 @@ const debugStyleScopeIdPrefixAttr = '__scopedStyleIdPrefix__';
|
|
|
489
494
|
|
|
490
495
|
const MAX_RETRY_ON_PROMISE_COUNT = 100;
|
|
491
496
|
const isPromise = (value) => {
|
|
492
|
-
|
|
493
|
-
|
|
497
|
+
try {
|
|
498
|
+
// not using "value instanceof Promise" to have zone.js support
|
|
499
|
+
return !!value && typeof value == 'object' && typeof value.then === 'function';
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
494
504
|
};
|
|
495
505
|
const safeCall = (call, thenFn, rejectFn) => {
|
|
496
506
|
try {
|
|
@@ -518,8 +528,13 @@ const delay = (timeout) => {
|
|
|
518
528
|
});
|
|
519
529
|
};
|
|
520
530
|
const checkError = (e) => {
|
|
521
|
-
|
|
522
|
-
|
|
531
|
+
try {
|
|
532
|
+
if (isServer && e instanceof ReferenceError && e.message.includes('window')) {
|
|
533
|
+
e.message = 'It seems like you forgot to add "if (isBrowser) {...}" here:' + e.message;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch {
|
|
537
|
+
// ignore
|
|
523
538
|
}
|
|
524
539
|
};
|
|
525
540
|
const justThrow = (e) => {
|
|
@@ -1266,7 +1281,7 @@ const COMMA = ',';
|
|
|
1266
1281
|
*
|
|
1267
1282
|
* @public
|
|
1268
1283
|
*/
|
|
1269
|
-
const version = "2.0.0-beta.
|
|
1284
|
+
const version = "2.0.0-beta.42-dev+3473a49";
|
|
1270
1285
|
|
|
1271
1286
|
const isNode = (value) => {
|
|
1272
1287
|
return value && typeof value.nodeType === 'number';
|
|
@@ -2656,9 +2671,9 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
2656
2671
|
super.value = result;
|
|
2657
2672
|
}
|
|
2658
2673
|
/**
|
|
2659
|
-
* Invoke the compute fn with the ComputeCtx argument. CTX_ARG signals (
|
|
2660
|
-
* only track via its explicit track(). Computeds auto-track every synchronous read
|
|
2661
|
-
* the first await they must use the explicit track() too.
|
|
2674
|
+
* Invoke the compute fn with the ComputeCtx argument. CTX_ARG signals (createAsyncQrl,
|
|
2675
|
+
* useResource$) only track via its explicit track(). Computeds auto-track every synchronous read
|
|
2676
|
+
* instead; after the first await they must use the explicit track() too.
|
|
2662
2677
|
*/
|
|
2663
2678
|
$invokeComputeFn$(fn, job) {
|
|
2664
2679
|
const computeFn = fn;
|
|
@@ -3043,14 +3058,6 @@ const createSignal = createSignal$1;
|
|
|
3043
3058
|
* @public
|
|
3044
3059
|
*/
|
|
3045
3060
|
const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedSignal);
|
|
3046
|
-
/**
|
|
3047
|
-
* Create a signal holding a `.value` which is calculated from the given async function (QRL). The
|
|
3048
|
-
* standalone version of `useAsync$`.
|
|
3049
|
-
*
|
|
3050
|
-
* @deprecated Use `createComputed$` instead, it has async support now.
|
|
3051
|
-
* @public
|
|
3052
|
-
*/
|
|
3053
|
-
const createAsync$ = /*#__PURE__*/ implicit$FirstArg(createAsyncSignal);
|
|
3054
3061
|
/**
|
|
3055
3062
|
* Create a signal that holds a custom serializable value. See {@link useSerializer$} for more
|
|
3056
3063
|
* details.
|
|
@@ -3784,11 +3791,48 @@ function getFileLocationFromJsx(jsxDev) {
|
|
|
3784
3791
|
}
|
|
3785
3792
|
|
|
3786
3793
|
const _hasOwnProperty$1 = Object.prototype.hasOwnProperty;
|
|
3794
|
+
const _propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
3787
3795
|
function isSlotProp(prop) {
|
|
3788
3796
|
return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
|
|
3789
3797
|
}
|
|
3798
|
+
function hasSlotProps(props) {
|
|
3799
|
+
if (props) {
|
|
3800
|
+
for (const prop in props) {
|
|
3801
|
+
if (isSlotProp(prop)) {
|
|
3802
|
+
return true;
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
return false;
|
|
3807
|
+
}
|
|
3790
3808
|
/** @internal */
|
|
3791
3809
|
const _restProps = (props, omit = [], target = {}) => {
|
|
3810
|
+
// The optimizer can apply this transform to plain, non-component objects and
|
|
3811
|
+
// even primitives (e.g. destructuring a string). Guard `isPropsProxy`, whose
|
|
3812
|
+
// `in` check throws on primitives, then fall back to native object-rest
|
|
3813
|
+
// copying so the transform cannot silently lose data.
|
|
3814
|
+
if (!isObject(props) || !isPropsProxy(props)) {
|
|
3815
|
+
// Match native rest-destructuring: `({ ...rest }) => …` throws on nullish.
|
|
3816
|
+
if (props == null) {
|
|
3817
|
+
throw new TypeError(`Cannot destructure '${props}' as it is ${props}.`);
|
|
3818
|
+
}
|
|
3819
|
+
// Box primitives so they get native ToObject rest semantics (e.g. 'ab' -> {0:'a',1:'b'}).
|
|
3820
|
+
const source = Object(props);
|
|
3821
|
+
const keys = Reflect.ownKeys(source);
|
|
3822
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3823
|
+
const key = keys[i];
|
|
3824
|
+
if (_propertyIsEnumerable.call(source, key) &&
|
|
3825
|
+
(typeof key === 'symbol' || !omit.includes(key))) {
|
|
3826
|
+
Object.defineProperty(target, key, {
|
|
3827
|
+
value: source[key],
|
|
3828
|
+
enumerable: true,
|
|
3829
|
+
configurable: true,
|
|
3830
|
+
writable: true,
|
|
3831
|
+
});
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
return target;
|
|
3835
|
+
}
|
|
3792
3836
|
let constPropsTarget = null;
|
|
3793
3837
|
const constProps = props[_CONST_PROPS];
|
|
3794
3838
|
if (constProps) {
|
|
@@ -4003,7 +4047,12 @@ function addCursorBoundary(cursorData, vNode) {
|
|
|
4003
4047
|
if (!__EXPERIMENTAL__.suspense) {
|
|
4004
4048
|
return;
|
|
4005
4049
|
}
|
|
4006
|
-
|
|
4050
|
+
let boundary = null;
|
|
4051
|
+
let current = vNode;
|
|
4052
|
+
while (current && !boundary) {
|
|
4053
|
+
boundary = getNearestCursorBoundary(current);
|
|
4054
|
+
current = current.slotParent || current.parent;
|
|
4055
|
+
}
|
|
4007
4056
|
if (!boundary) {
|
|
4008
4057
|
return;
|
|
4009
4058
|
}
|
|
@@ -4150,7 +4199,7 @@ function runEventHandlerQRL(handler, event, element, ctx) {
|
|
|
4150
4199
|
if (!(hostElement.flags & 32 /* VNodeFlags.Deleted */)) {
|
|
4151
4200
|
return invokeApply(ctx, realHandler, [event, element]);
|
|
4152
4201
|
}
|
|
4153
|
-
}, (err) => container.handleError(err, hostElement));
|
|
4202
|
+
}, (err) => container.handleError(err, hostElement, "event" /* ErrorBoundaryPhase.Event */));
|
|
4154
4203
|
}
|
|
4155
4204
|
/**
|
|
4156
4205
|
* This is called by qwik-loader to run a QRL. It has to be synchronous when possible.
|
|
@@ -9316,7 +9365,10 @@ const runTask = (task, container, host) => {
|
|
|
9316
9365
|
return pendingTask;
|
|
9317
9366
|
}
|
|
9318
9367
|
task.$flags$ &= -5 /* TaskFlags.DIRTY */;
|
|
9319
|
-
const handleError = (reason) =>
|
|
9368
|
+
const handleError = (reason) => {
|
|
9369
|
+
tagErrorPhase(reason, "hook" /* ErrorBoundaryPhase.Hook */);
|
|
9370
|
+
container.handleError(reason, host, "hook" /* ErrorBoundaryPhase.Hook */);
|
|
9371
|
+
};
|
|
9320
9372
|
let taskPromise = null;
|
|
9321
9373
|
const result = maybeThen(cleanupAsyncDestroyable(task, handleError), () => {
|
|
9322
9374
|
const iCtx = newInvokeContext(container.$locale$, host, TaskEvent);
|
|
@@ -9386,6 +9438,10 @@ function scheduleTask(_event, element) {
|
|
|
9386
9438
|
setCaptures(deserializeCaptureDeltas(container, this));
|
|
9387
9439
|
}
|
|
9388
9440
|
const task = _captures[0];
|
|
9441
|
+
if (!task.$el$) {
|
|
9442
|
+
// An ErrorBoundary tore the host down; the task has nothing left to run against.
|
|
9443
|
+
return;
|
|
9444
|
+
}
|
|
9389
9445
|
task.$flags$ |= 4 /* TaskFlags.DIRTY */;
|
|
9390
9446
|
markVNodeDirty(container, task.$el$, 1 /* ChoreBits.TASKS */);
|
|
9391
9447
|
});
|
|
@@ -9650,7 +9706,12 @@ const getStoreHandler = (value) => {
|
|
|
9650
9706
|
return value[STORE_HANDLER];
|
|
9651
9707
|
};
|
|
9652
9708
|
const getStoreTarget = (value) => {
|
|
9653
|
-
|
|
9709
|
+
try {
|
|
9710
|
+
return value?.[STORE_TARGET] || null;
|
|
9711
|
+
}
|
|
9712
|
+
catch {
|
|
9713
|
+
return null;
|
|
9714
|
+
}
|
|
9654
9715
|
};
|
|
9655
9716
|
/**
|
|
9656
9717
|
* Force a store to recompute and schedule effects.
|
|
@@ -9751,11 +9812,17 @@ class StoreHandler {
|
|
|
9751
9812
|
return this.toString;
|
|
9752
9813
|
}
|
|
9753
9814
|
const flags = this.$flags$;
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9815
|
+
let shouldWrapRecursively = false;
|
|
9816
|
+
if (flags & 1 /* StoreFlags.RECURSIVE */ && isObject(value)) {
|
|
9817
|
+
try {
|
|
9818
|
+
shouldWrapRecursively =
|
|
9819
|
+
!Object.isFrozen(value) && !isStore(value) && !Object.isFrozen(target);
|
|
9820
|
+
}
|
|
9821
|
+
catch {
|
|
9822
|
+
// ignore
|
|
9823
|
+
}
|
|
9824
|
+
}
|
|
9825
|
+
if (shouldWrapRecursively) {
|
|
9759
9826
|
return getOrCreateStore(value, this.$flags$, this.$container$);
|
|
9760
9827
|
}
|
|
9761
9828
|
return value;
|
|
@@ -10708,8 +10775,9 @@ class Serializer {
|
|
|
10708
10775
|
}
|
|
10709
10776
|
const out = [value.$computeQrl$, value.$effects$];
|
|
10710
10777
|
if (isAsync) {
|
|
10778
|
+
const untrackedError = value.$untrackedError$;
|
|
10711
10779
|
// After SSR, the signal is never loading, so no need to send it
|
|
10712
|
-
out.push(value.$loadingEffects$, value.$errorEffects$,
|
|
10780
|
+
out.push(value.$loadingEffects$, value.$errorEffects$, untrackedError === undefined || isDev ? untrackedError : redactToGeneric(untrackedError));
|
|
10713
10781
|
out.push(asyncFlags || undefined);
|
|
10714
10782
|
}
|
|
10715
10783
|
if (v !== NEEDS_COMPUTATION || concurrency !== undefined || timeout !== undefined) {
|
|
@@ -10746,8 +10814,9 @@ class Serializer {
|
|
|
10746
10814
|
}
|
|
10747
10815
|
else if (value instanceof Error) {
|
|
10748
10816
|
const out = [value.message];
|
|
10749
|
-
|
|
10750
|
-
|
|
10817
|
+
for (const entry of Object.entries(value)) {
|
|
10818
|
+
out.push(entry[0], entry[1]);
|
|
10819
|
+
}
|
|
10751
10820
|
/// In production we don't want to leak the stack trace.
|
|
10752
10821
|
if (isDev) {
|
|
10753
10822
|
out.push('stack', value.stack);
|
|
@@ -10755,15 +10824,20 @@ class Serializer {
|
|
|
10755
10824
|
this.output(23 /* TypeIds.Error */, out);
|
|
10756
10825
|
}
|
|
10757
10826
|
else if (this.$serializationContext$.$isSsrNode$(value)) {
|
|
10827
|
+
// Paired with ssr-container's vnode-data INERT skip: drop the state root AND the path together.
|
|
10828
|
+
if (value.vnodeData &&
|
|
10829
|
+
value.vnodeData[0] & 32 /* VNodeDataFlag.INERT */ &&
|
|
10830
|
+
/[A-Za-z]/.test(value.id)) {
|
|
10831
|
+
this.output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
|
|
10832
|
+
return;
|
|
10833
|
+
}
|
|
10758
10834
|
const rootIndex = this.$serializationContext$.$addRoot$(value);
|
|
10759
10835
|
this.$serializationContext$.$setProp$(value, ELEMENT_ID, rootIndex);
|
|
10760
10836
|
// we need to output before the vnode overwrites its values
|
|
10761
10837
|
this.output(10 /* TypeIds.VNode */, value.id);
|
|
10762
10838
|
const vNodeData = value.vnodeData;
|
|
10763
10839
|
if (vNodeData) {
|
|
10764
|
-
discoverValuesForVNodeData(vNodeData,
|
|
10765
|
-
this.$serializationContext$.$addRoot$(vNodeDataValue);
|
|
10766
|
-
});
|
|
10840
|
+
discoverValuesForVNodeData(vNodeData, this.$serializationContext$);
|
|
10767
10841
|
this.$serializationContext$.$markSsrNodeForSerialization$(value, 16 /* VNodeDataFlag.SERIALIZE */);
|
|
10768
10842
|
}
|
|
10769
10843
|
if (value.children) {
|
|
@@ -11047,9 +11121,9 @@ function getCustomSerializerPromise(signal, value) {
|
|
|
11047
11121
|
return data;
|
|
11048
11122
|
});
|
|
11049
11123
|
}
|
|
11050
|
-
const discoverValuesForVNodeData = (vnodeData,
|
|
11124
|
+
const discoverValuesForVNodeData = (vnodeData, serializationContext) => {
|
|
11051
11125
|
const length = vnodeData.length;
|
|
11052
|
-
for (let i =
|
|
11126
|
+
for (let i = 1; i < length; i++) {
|
|
11053
11127
|
const value = vnodeData[i];
|
|
11054
11128
|
if (isSsrAttrs(value)) {
|
|
11055
11129
|
for (const key in value) {
|
|
@@ -11062,7 +11136,7 @@ const discoverValuesForVNodeData = (vnodeData, callback) => {
|
|
|
11062
11136
|
shouldSkipComponentProps(value, attrValue)))) {
|
|
11063
11137
|
continue;
|
|
11064
11138
|
}
|
|
11065
|
-
|
|
11139
|
+
serializationContext.$addRoot$(attrValue);
|
|
11066
11140
|
}
|
|
11067
11141
|
}
|
|
11068
11142
|
}
|
|
@@ -12048,15 +12122,23 @@ const applyQwikComponentBody = (ssr, jsx, component) => {
|
|
|
12048
12122
|
|
|
12049
12123
|
class MaybeAsyncSignal {
|
|
12050
12124
|
}
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12125
|
+
// we need to differentiate between JSX functions and ssr container functions for error boundary
|
|
12126
|
+
// JSX functions need to be skipped after error boundary catch an error
|
|
12127
|
+
class InvokeJSXFunction {
|
|
12128
|
+
}
|
|
12129
|
+
const openBoundaryContentScope = (ssr, contentHost) => {
|
|
12130
|
+
const enclosing = ssr.$errorContentHost$;
|
|
12131
|
+
ssr.$errorContentHost$ = contentHost;
|
|
12132
|
+
return () => {
|
|
12133
|
+
ssr.$errorContentHost$ = enclosing;
|
|
12134
|
+
};
|
|
12135
|
+
};
|
|
12136
|
+
const isInsideFailedBoundaryContent = (ssr) => {
|
|
12137
|
+
const contentHost = ssr.$errorContentHost$;
|
|
12138
|
+
return !!contentHost && (contentHost.vnodeData[0] & 32 /* VNodeDataFlag.INERT */) !== 0;
|
|
12139
|
+
};
|
|
12140
|
+
const markPromiseHandled = (promise) => {
|
|
12141
|
+
promise.catch(() => { });
|
|
12060
12142
|
};
|
|
12061
12143
|
function setParentOptions(mutable, styleScoped, parentComponentFrame) {
|
|
12062
12144
|
return () => {
|
|
@@ -12069,23 +12151,43 @@ async function _walkJSX(ssr, value, options) {
|
|
|
12069
12151
|
const stack = [value];
|
|
12070
12152
|
const enqueue = (value) => stack.push(value);
|
|
12071
12153
|
const enqueuePromise = (promise) => {
|
|
12072
|
-
markPromiseHandled(
|
|
12154
|
+
markPromiseHandled(promise);
|
|
12073
12155
|
stack.push(promise);
|
|
12074
12156
|
stack.push(Promise);
|
|
12075
12157
|
};
|
|
12076
12158
|
const drain = async () => {
|
|
12077
12159
|
while (stack.length) {
|
|
12160
|
+
let phase = "render" /* ErrorBoundaryPhase.Render */;
|
|
12078
12161
|
try {
|
|
12079
12162
|
const value = stack.pop();
|
|
12080
12163
|
// Reference equality first (no prototype walk), then typeof
|
|
12081
12164
|
if (value === MaybeAsyncSignal) {
|
|
12082
12165
|
const trackFn = stack.pop();
|
|
12166
|
+
if (__EXPERIMENTAL__.errorBoundary && isInsideFailedBoundaryContent(ssr)) {
|
|
12167
|
+
continue;
|
|
12168
|
+
}
|
|
12169
|
+
phase = "hook" /* ErrorBoundaryPhase.Hook */;
|
|
12083
12170
|
await retryOnPromise(() => stack.push(trackFn()));
|
|
12084
12171
|
continue;
|
|
12085
12172
|
}
|
|
12173
|
+
if (__EXPERIMENTAL__.errorBoundary && value === InvokeJSXFunction) {
|
|
12174
|
+
const fnChild = stack.pop();
|
|
12175
|
+
if (isInsideFailedBoundaryContent(ssr)) {
|
|
12176
|
+
continue;
|
|
12177
|
+
}
|
|
12178
|
+
const result = fnChild.apply(ssr);
|
|
12179
|
+
if (isPromise(result)) {
|
|
12180
|
+
await result;
|
|
12181
|
+
}
|
|
12182
|
+
continue;
|
|
12183
|
+
}
|
|
12086
12184
|
if (typeof value === 'function') {
|
|
12087
12185
|
if (value === Promise) {
|
|
12088
|
-
|
|
12186
|
+
const pending = stack.pop();
|
|
12187
|
+
if (__EXPERIMENTAL__.errorBoundary && isInsideFailedBoundaryContent(ssr)) {
|
|
12188
|
+
continue;
|
|
12189
|
+
}
|
|
12190
|
+
stack.push(await pending);
|
|
12089
12191
|
}
|
|
12090
12192
|
else {
|
|
12091
12193
|
const result = value.apply(ssr);
|
|
@@ -12095,8 +12197,17 @@ async function _walkJSX(ssr, value, options) {
|
|
|
12095
12197
|
}
|
|
12096
12198
|
continue;
|
|
12097
12199
|
}
|
|
12200
|
+
if (__EXPERIMENTAL__.errorBoundary && isInsideFailedBoundaryContent(ssr)) {
|
|
12201
|
+
if (isPromise(value)) {
|
|
12202
|
+
value.catch(() => { });
|
|
12203
|
+
}
|
|
12204
|
+
continue;
|
|
12205
|
+
}
|
|
12098
12206
|
processJSXNode(ssr, enqueue, enqueuePromise, value, options);
|
|
12099
12207
|
}
|
|
12208
|
+
catch (err) {
|
|
12209
|
+
ssr.handleError(err, ssr.getOrCreateLastNode(), phase);
|
|
12210
|
+
}
|
|
12100
12211
|
finally {
|
|
12101
12212
|
const pendingFlush = ssr.streamHandler.waitForPendingFlush();
|
|
12102
12213
|
if (isPromise(pendingFlush)) {
|
|
@@ -12107,6 +12218,12 @@ async function _walkJSX(ssr, value, options) {
|
|
|
12107
12218
|
};
|
|
12108
12219
|
await drain();
|
|
12109
12220
|
}
|
|
12221
|
+
function enqueueJSX(enqueue, value) {
|
|
12222
|
+
enqueue(value);
|
|
12223
|
+
if (__EXPERIMENTAL__.errorBoundary && typeof value === 'function') {
|
|
12224
|
+
enqueue(InvokeJSXFunction);
|
|
12225
|
+
}
|
|
12226
|
+
}
|
|
12110
12227
|
function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
12111
12228
|
// console.log('processJSXNode', value);
|
|
12112
12229
|
if (value == null) {
|
|
@@ -12124,7 +12241,7 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12124
12241
|
else if (typeof value === 'object') {
|
|
12125
12242
|
if (Array.isArray(value)) {
|
|
12126
12243
|
for (let i = value.length - 1; i >= 0; i--) {
|
|
12127
|
-
enqueue
|
|
12244
|
+
enqueueJSX(enqueue, value[i]);
|
|
12128
12245
|
}
|
|
12129
12246
|
}
|
|
12130
12247
|
else if (isSignal(value)) {
|
|
@@ -12143,19 +12260,28 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12143
12260
|
}
|
|
12144
12261
|
else if (isAsyncGenerator(value)) {
|
|
12145
12262
|
enqueue(async () => {
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12263
|
+
if (__EXPERIMENTAL__.errorBoundary && isInsideFailedBoundaryContent(ssr)) {
|
|
12264
|
+
return;
|
|
12265
|
+
}
|
|
12266
|
+
const freshWalkOptions = () => ({
|
|
12267
|
+
currentStyleScoped: options.currentStyleScoped,
|
|
12268
|
+
parentComponentFrame: options.parentComponentFrame,
|
|
12269
|
+
});
|
|
12270
|
+
try {
|
|
12271
|
+
for await (const chunk of value) {
|
|
12272
|
+
await _walkJSX(ssr, chunk, freshWalkOptions());
|
|
12273
|
+
await ssr.streamHandler.flush();
|
|
12274
|
+
}
|
|
12275
|
+
}
|
|
12276
|
+
catch (err) {
|
|
12277
|
+
ssr.handleError(err, ssr.getOrCreateLastNode(), "render" /* ErrorBoundaryPhase.Render */);
|
|
12278
|
+
await _walkJSX(ssr, null, freshWalkOptions());
|
|
12152
12279
|
}
|
|
12153
12280
|
});
|
|
12154
12281
|
}
|
|
12155
12282
|
else {
|
|
12156
12283
|
const jsx = value;
|
|
12157
12284
|
const type = jsx.type;
|
|
12158
|
-
// Below, JSXChildren allows functions and regexes, but we assume the dev only uses those as appropriate.
|
|
12159
12285
|
if (typeof type === 'string') {
|
|
12160
12286
|
appendClassIfScopedStyleExists(jsx, options.currentStyleScoped);
|
|
12161
12287
|
let qwikInspectorAttrValue = null;
|
|
@@ -12169,6 +12295,9 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12169
12295
|
if (innerHTML) {
|
|
12170
12296
|
ssr.htmlNode(innerHTML);
|
|
12171
12297
|
}
|
|
12298
|
+
if (__EXPERIMENTAL__.errorBoundary && directGetPropsProxyProp(jsx, QErrorContentHost)) {
|
|
12299
|
+
enqueue(openBoundaryContentScope(ssr, ssr.getOrCreateLastNode()));
|
|
12300
|
+
}
|
|
12172
12301
|
enqueue(ssr.closeElement);
|
|
12173
12302
|
if (type === 'head') {
|
|
12174
12303
|
ssr.emitQwikLoaderAtTopIfNeeded();
|
|
@@ -12187,10 +12316,11 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12187
12316
|
}
|
|
12188
12317
|
}
|
|
12189
12318
|
const children = jsx.children;
|
|
12190
|
-
children != null && enqueue
|
|
12319
|
+
children != null && enqueueJSX(enqueue, children);
|
|
12191
12320
|
}
|
|
12192
12321
|
else if (isFunction(type)) {
|
|
12193
|
-
if (__EXPERIMENTAL__.suspense
|
|
12322
|
+
if ((__EXPERIMENTAL__.suspense || __EXPERIMENTAL__.errorBoundary) &&
|
|
12323
|
+
isInternalServerComponent(type)) {
|
|
12194
12324
|
enqueue(() => getInternalServerComponentHandler(type)(ssr, jsx, options, enqueue));
|
|
12195
12325
|
return;
|
|
12196
12326
|
}
|
|
@@ -12201,9 +12331,8 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12201
12331
|
}
|
|
12202
12332
|
ssr.openFragment(attrs);
|
|
12203
12333
|
enqueue(ssr.closeFragment);
|
|
12204
|
-
// In theory we could get functions or regexes, but we assume all is well
|
|
12205
12334
|
const children = jsx.children;
|
|
12206
|
-
children != null && enqueue
|
|
12335
|
+
children != null && enqueueJSX(enqueue, children);
|
|
12207
12336
|
}
|
|
12208
12337
|
else if (type === Slot) {
|
|
12209
12338
|
const componentFrame = options.parentComponentFrame;
|
|
@@ -12225,7 +12354,7 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12225
12354
|
if (slotDefaultChildren && slotChildren !== slotDefaultChildren) {
|
|
12226
12355
|
ssr.addUnclaimedProjection(componentFrame, QDefaultSlot, slotDefaultChildren);
|
|
12227
12356
|
}
|
|
12228
|
-
enqueue
|
|
12357
|
+
enqueueJSX(enqueue, slotChildren);
|
|
12229
12358
|
enqueue(setParentOptions(options, componentFrame.projectionScopedStyle, componentFrame.projectionComponentFrame));
|
|
12230
12359
|
}
|
|
12231
12360
|
else {
|
|
@@ -12272,7 +12401,7 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12272
12401
|
else if (type === SSRStreamBlock) {
|
|
12273
12402
|
ssr.streamHandler.streamBlockStart();
|
|
12274
12403
|
enqueue(() => ssr.streamHandler.streamBlockEnd());
|
|
12275
|
-
enqueue
|
|
12404
|
+
enqueueJSX(enqueue, jsx.children);
|
|
12276
12405
|
}
|
|
12277
12406
|
else if (isQwikComponent(type)) {
|
|
12278
12407
|
// prod: use new instance of an object for props, we always modify props for a component
|
|
@@ -12282,13 +12411,13 @@ function processJSXNode(ssr, enqueue, enqueuePromise, value, options) {
|
|
|
12282
12411
|
}
|
|
12283
12412
|
ssr.openComponent(componentAttrs);
|
|
12284
12413
|
const host = ssr.getOrCreateLastNode();
|
|
12414
|
+
enqueue(setParentOptions(options, options.currentStyleScoped, options.parentComponentFrame));
|
|
12415
|
+
enqueue(() => ssr.closeComponent());
|
|
12285
12416
|
const componentFrame = ssr.getParentComponentFrame();
|
|
12286
12417
|
componentFrame.distributeChildrenIntoSlots(jsx.children, options.currentStyleScoped, options.parentComponentFrame);
|
|
12287
12418
|
const jsxOutput = applyQwikComponentBody(ssr, jsx, type);
|
|
12288
|
-
enqueue(setParentOptions(options, options.currentStyleScoped, options.parentComponentFrame));
|
|
12289
|
-
enqueue(() => ssr.closeComponent());
|
|
12290
12419
|
if (isPromise(jsxOutput)) {
|
|
12291
|
-
markPromiseHandled(
|
|
12420
|
+
markPromiseHandled(jsxOutput);
|
|
12292
12421
|
// Defer reading QScopedStyle until after the promise resolves
|
|
12293
12422
|
enqueue(async () => {
|
|
12294
12423
|
await ssr.streamHandler.flush();
|
|
@@ -12340,6 +12469,99 @@ function appendClassIfScopedStyleExists(jsx, styleScoped) {
|
|
|
12340
12469
|
}
|
|
12341
12470
|
}
|
|
12342
12471
|
|
|
12472
|
+
/** @internal */
|
|
12473
|
+
function handleSSRError(container, err, host, phase) {
|
|
12474
|
+
if (!__EXPERIMENTAL__.errorBoundary || (qDev && !isRecoverable(err))) {
|
|
12475
|
+
throw err;
|
|
12476
|
+
}
|
|
12477
|
+
for (let boundaryNode = host; boundaryNode; boundaryNode = boundaryNode.parentComponent) {
|
|
12478
|
+
const errorStore = getOwnSSRErrorBoundaryStore(boundaryNode);
|
|
12479
|
+
if (!errorStore || !errorStore.$fallback$) {
|
|
12480
|
+
continue;
|
|
12481
|
+
}
|
|
12482
|
+
if (container.$isOutOfOrderSegment$ && errorStore.$emitFallback$) {
|
|
12483
|
+
throw err;
|
|
12484
|
+
}
|
|
12485
|
+
markBoundaryErrored(errorStore, err, phase);
|
|
12486
|
+
getRootContainer(container).$hasBoundaryError$ = true;
|
|
12487
|
+
if (container.$isOutOfOrderSegment$) {
|
|
12488
|
+
markErrorFromDeferredSegment(errorStore);
|
|
12489
|
+
}
|
|
12490
|
+
markErrorBoundaryContentInert(container, boundaryNode, errorStore);
|
|
12491
|
+
return;
|
|
12492
|
+
}
|
|
12493
|
+
throw err;
|
|
12494
|
+
}
|
|
12495
|
+
function markErrorBoundaryContentInert(container, boundaryNode, errorStore) {
|
|
12496
|
+
const ancestorOwners = new Map();
|
|
12497
|
+
let boundaryContentOwner = null;
|
|
12498
|
+
let depth = 0;
|
|
12499
|
+
for (let node = boundaryNode; node; node = node.parentComponent) {
|
|
12500
|
+
if (node.id) {
|
|
12501
|
+
ancestorOwners.set(node.id, { node, depth: depth++ });
|
|
12502
|
+
}
|
|
12503
|
+
if (node !== boundaryNode && !boundaryContentOwner) {
|
|
12504
|
+
const store = getOwnSSRErrorBoundaryStore(node);
|
|
12505
|
+
if (store?.error !== undefined || !hasSlotProps(node.getProp(ELEMENT_PROPS))) {
|
|
12506
|
+
boundaryContentOwner = node;
|
|
12507
|
+
}
|
|
12508
|
+
}
|
|
12509
|
+
}
|
|
12510
|
+
const topmostSevered = { node: null, depth: -1 };
|
|
12511
|
+
const children = boundaryNode.children;
|
|
12512
|
+
if (children) {
|
|
12513
|
+
for (let i = 0; i < children.length; i++) {
|
|
12514
|
+
markErrorSubtreeInert(container, children[i], ancestorOwners, topmostSevered);
|
|
12515
|
+
}
|
|
12516
|
+
}
|
|
12517
|
+
if (topmostSevered.node) {
|
|
12518
|
+
const immediateContentOwner = topmostSevered.node.parentComponent;
|
|
12519
|
+
if (topmostSevered.node === boundaryNode) {
|
|
12520
|
+
container.$retainForResume$(boundaryContentOwner);
|
|
12521
|
+
}
|
|
12522
|
+
else if (immediateContentOwner?.id) {
|
|
12523
|
+
container.$retainForResume$(immediateContentOwner);
|
|
12524
|
+
errorStore.projectedContentOwner = immediateContentOwner;
|
|
12525
|
+
}
|
|
12526
|
+
}
|
|
12527
|
+
}
|
|
12528
|
+
function getOwnSSRErrorBoundaryStore(node) {
|
|
12529
|
+
const ctx = node.getProp(QCtxAttr);
|
|
12530
|
+
return ctx ? mapArray_get(ctx, ERROR_CONTEXT.id, 0) : null;
|
|
12531
|
+
}
|
|
12532
|
+
function markErrorSubtreeInert(container, node, ancestorOwners, topmostSevered) {
|
|
12533
|
+
node.vnodeData[0] |= 32 /* VNodeDataFlag.INERT */;
|
|
12534
|
+
const ownerId = node.getProp(QSlotParent);
|
|
12535
|
+
if (ownerId) {
|
|
12536
|
+
const owner = ancestorOwners.get(ownerId);
|
|
12537
|
+
if (owner) {
|
|
12538
|
+
owner.node.removeProp(node.getProp(QSlot) ?? QDefaultSlot);
|
|
12539
|
+
if (owner.depth > topmostSevered.depth) {
|
|
12540
|
+
topmostSevered.node = owner.node;
|
|
12541
|
+
topmostSevered.depth = owner.depth;
|
|
12542
|
+
}
|
|
12543
|
+
}
|
|
12544
|
+
}
|
|
12545
|
+
// Element consumers keep materializing when inert, so their bindings would keep patching hidden
|
|
12546
|
+
// DOM; virtual ones can't materialize and would leave producers pointing at a dead node.
|
|
12547
|
+
clearAllEffects(container, node);
|
|
12548
|
+
const seq = node.getProp(ELEMENT_SEQ);
|
|
12549
|
+
if (seq) {
|
|
12550
|
+
for (let i = 0; i < seq.length; i++) {
|
|
12551
|
+
const item = seq[i];
|
|
12552
|
+
if (isTask(item)) {
|
|
12553
|
+
clearAllEffects(container, item);
|
|
12554
|
+
}
|
|
12555
|
+
}
|
|
12556
|
+
}
|
|
12557
|
+
const children = node.children;
|
|
12558
|
+
if (children) {
|
|
12559
|
+
for (let i = 0; i < children.length; i++) {
|
|
12560
|
+
markErrorSubtreeInert(container, children[i], ancestorOwners, topmostSevered);
|
|
12561
|
+
}
|
|
12562
|
+
}
|
|
12563
|
+
}
|
|
12564
|
+
|
|
12343
12565
|
// <docs markdown="../readme.md#useLexicalScope">
|
|
12344
12566
|
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
12345
12567
|
// (edit ../readme.md#useLexicalScope instead and run `pnpm docs.sync`)
|
|
@@ -12420,7 +12642,7 @@ const useResourceQrl = (qrl, opts) => {
|
|
|
12420
12642
|
* const Cmp = component$(() => {
|
|
12421
12643
|
* const city = useSignal('');
|
|
12422
12644
|
*
|
|
12423
|
-
* const weather =
|
|
12645
|
+
* const weather = useComputed$(async ({ track, cleanup, abortSignal }) => {
|
|
12424
12646
|
* const cityName = track(city);
|
|
12425
12647
|
* const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
|
|
12426
12648
|
* signal: abortSignal,
|
|
@@ -12434,7 +12656,7 @@ const useResourceQrl = (qrl, opts) => {
|
|
|
12434
12656
|
* <input name="city" bind:value={city} />
|
|
12435
12657
|
* <div>
|
|
12436
12658
|
* Temperature:{' '}
|
|
12437
|
-
* {weather.
|
|
12659
|
+
* {weather.pending
|
|
12438
12660
|
* ? 'Loading...'
|
|
12439
12661
|
* : weather.error
|
|
12440
12662
|
* ? `Error: ${weather.error.message}`
|
|
@@ -12445,8 +12667,8 @@ const useResourceQrl = (qrl, opts) => {
|
|
|
12445
12667
|
* });
|
|
12446
12668
|
* ```
|
|
12447
12669
|
*
|
|
12448
|
-
* @deprecated Use `
|
|
12449
|
-
*
|
|
12670
|
+
* @deprecated Use `useComputed$` instead. Read the `pending` and `error` properties from the
|
|
12671
|
+
* returned signal to determine the status.
|
|
12450
12672
|
* @public
|
|
12451
12673
|
*/
|
|
12452
12674
|
const Resource = ({ value, onResolved, onPending, onRejected, }) => {
|
|
@@ -13817,14 +14039,179 @@ const _resolveContextWithoutSequentialScope = (context) => {
|
|
|
13817
14039
|
};
|
|
13818
14040
|
|
|
13819
14041
|
const ERROR_CONTEXT = /*#__PURE__*/ createContextId('qk-error');
|
|
13820
|
-
const
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
14042
|
+
const ERROR_BOUNDARY_QRL_SYMBOL = '_ebC';
|
|
14043
|
+
const safeRead = (read, fallback) => {
|
|
14044
|
+
try {
|
|
14045
|
+
return read();
|
|
14046
|
+
}
|
|
14047
|
+
catch {
|
|
14048
|
+
return fallback;
|
|
14049
|
+
}
|
|
14050
|
+
};
|
|
14051
|
+
const isRecoverable = (err) => safeRead(() => !(err instanceof Error && 'plugin' in err), true);
|
|
14052
|
+
const GENERIC_BOUNDARY_ERROR_MESSAGE = 'An error occurred';
|
|
14053
|
+
const errorBoundaryDigest = (err) => hashCode(safeRead(() => err instanceof Error ? `${err.name}: ${err.message}\n${err.stack ?? ''}` : String(err), 'unknown'));
|
|
14054
|
+
const REDACTED = /*#__PURE__*/ Symbol();
|
|
14055
|
+
const redactToGeneric = (err) => {
|
|
14056
|
+
const redacted = new Error(GENERIC_BOUNDARY_ERROR_MESSAGE);
|
|
14057
|
+
redacted.digest = errorBoundaryDigest(err);
|
|
14058
|
+
Object.defineProperty(redacted, REDACTED, { value: true });
|
|
14059
|
+
return redacted;
|
|
14060
|
+
};
|
|
14061
|
+
const toBoundaryError = (raw) => {
|
|
14062
|
+
if (raw instanceof Error) {
|
|
14063
|
+
return raw;
|
|
14064
|
+
}
|
|
14065
|
+
let message;
|
|
14066
|
+
try {
|
|
14067
|
+
message = String(raw);
|
|
14068
|
+
}
|
|
14069
|
+
catch {
|
|
14070
|
+
try {
|
|
14071
|
+
message = Object.prototype.toString.call(raw);
|
|
13824
14072
|
}
|
|
14073
|
+
catch {
|
|
14074
|
+
message = GENERIC_BOUNDARY_ERROR_MESSAGE;
|
|
14075
|
+
}
|
|
14076
|
+
}
|
|
14077
|
+
const wrapped = new Error(message);
|
|
14078
|
+
wrapped.cause = raw;
|
|
14079
|
+
return wrapped;
|
|
14080
|
+
};
|
|
14081
|
+
const isReadableProjection = (projected) => safeRead(() => {
|
|
14082
|
+
void projected.message;
|
|
14083
|
+
void projected.name;
|
|
14084
|
+
for (const key in projected) {
|
|
14085
|
+
void projected[key];
|
|
13825
14086
|
}
|
|
13826
14087
|
return true;
|
|
14088
|
+
}, false);
|
|
14089
|
+
const redactBoundaryErrorForDisplay = (error, showRaw, transformError) => {
|
|
14090
|
+
try {
|
|
14091
|
+
if (transformError) {
|
|
14092
|
+
const projected = transformError(error);
|
|
14093
|
+
if (projected instanceof Error) {
|
|
14094
|
+
return isReadableProjection(projected) ? projected : redactToGeneric(error);
|
|
14095
|
+
}
|
|
14096
|
+
if (projected != null) {
|
|
14097
|
+
if (showRaw && isPromise(projected)) {
|
|
14098
|
+
logWarn('transformError must return synchronously; an async one redacts every error.');
|
|
14099
|
+
}
|
|
14100
|
+
return redactToGeneric(error);
|
|
14101
|
+
}
|
|
14102
|
+
}
|
|
14103
|
+
if (safeRead(() => error instanceof Error && REDACTED in error, false)) {
|
|
14104
|
+
return error;
|
|
14105
|
+
}
|
|
14106
|
+
if (!showRaw) {
|
|
14107
|
+
return redactToGeneric(error);
|
|
14108
|
+
}
|
|
14109
|
+
if (error instanceof Error) {
|
|
14110
|
+
return error;
|
|
14111
|
+
}
|
|
14112
|
+
const rawMessage = error?.message;
|
|
14113
|
+
if (typeof rawMessage === 'string') {
|
|
14114
|
+
const wrapped = new Error(rawMessage);
|
|
14115
|
+
wrapped.cause = error;
|
|
14116
|
+
return wrapped;
|
|
14117
|
+
}
|
|
14118
|
+
return toBoundaryError(error);
|
|
14119
|
+
}
|
|
14120
|
+
catch {
|
|
14121
|
+
return redactToGeneric(error);
|
|
14122
|
+
}
|
|
14123
|
+
};
|
|
14124
|
+
const fireOnError = (onError, error, phase, boundaryId) => {
|
|
14125
|
+
if (!onError) {
|
|
14126
|
+
return;
|
|
14127
|
+
}
|
|
14128
|
+
try {
|
|
14129
|
+
const digest = errorBoundaryDigest(error);
|
|
14130
|
+
void Promise.resolve(onError(toBoundaryError(error), { phase, boundaryId, digest })).catch(logError);
|
|
14131
|
+
}
|
|
14132
|
+
catch (e) {
|
|
14133
|
+
logError(e);
|
|
14134
|
+
}
|
|
14135
|
+
};
|
|
14136
|
+
const boundariesWithDeferredError = /*#__PURE__*/ new WeakSet();
|
|
14137
|
+
const markErrorFromDeferredSegment = (store) => {
|
|
14138
|
+
boundariesWithDeferredError.add(store);
|
|
13827
14139
|
};
|
|
14140
|
+
const isErrorFromDeferredSegment = (store) => boundariesWithDeferredError.has(store);
|
|
14141
|
+
const ERROR_PHASE = /*#__PURE__*/ Symbol('qErrorPhase');
|
|
14142
|
+
const tagErrorPhase = (err, phase) => {
|
|
14143
|
+
try {
|
|
14144
|
+
Object.defineProperty(err, ERROR_PHASE, { value: phase, configurable: true });
|
|
14145
|
+
}
|
|
14146
|
+
catch {
|
|
14147
|
+
// ignore
|
|
14148
|
+
}
|
|
14149
|
+
};
|
|
14150
|
+
const getTaggedErrorPhase = (err) => safeRead(() => err?.[ERROR_PHASE], undefined);
|
|
14151
|
+
const markBoundaryErrored = (store, error, phase = "render" /* ErrorBoundaryPhase.Render */) => {
|
|
14152
|
+
// `null` would collide with the capture-only sentinel, so wrap every nullish throw.
|
|
14153
|
+
store.error = error == null ? toBoundaryError(error) : error;
|
|
14154
|
+
const onError = store.$onError$;
|
|
14155
|
+
if (onError) {
|
|
14156
|
+
fireOnError(onError, error, getTaggedErrorPhase(error) ?? phase, store.boundaryId ?? '');
|
|
14157
|
+
}
|
|
14158
|
+
};
|
|
14159
|
+
const handleQError = (e) => {
|
|
14160
|
+
const detail = e
|
|
14161
|
+
.detail;
|
|
14162
|
+
if (detail?.importError) {
|
|
14163
|
+
return;
|
|
14164
|
+
}
|
|
14165
|
+
const source = detail.element;
|
|
14166
|
+
// The listener is document-wide, so only this document's elements may route through it.
|
|
14167
|
+
if (!source || source.ownerDocument !== e.currentTarget) {
|
|
14168
|
+
return;
|
|
14169
|
+
}
|
|
14170
|
+
// A destroyed container clears this back-pointer, so a stale target resolves to nothing.
|
|
14171
|
+
const container = source.closest(QContainerSelector)?.qContainer;
|
|
14172
|
+
const host = container?.vNodeLocate(source);
|
|
14173
|
+
if (!container || !host) {
|
|
14174
|
+
return;
|
|
14175
|
+
}
|
|
14176
|
+
try {
|
|
14177
|
+
container.handleError(detail.error, host, "event" /* ErrorBoundaryPhase.Event */);
|
|
14178
|
+
}
|
|
14179
|
+
catch (handlerError) {
|
|
14180
|
+
logError(handlerError);
|
|
14181
|
+
}
|
|
14182
|
+
};
|
|
14183
|
+
/**
|
|
14184
|
+
* One listener per document, routed by target, so no container is retained by the document. The
|
|
14185
|
+
* marker lives on the document so a second bundle on the page reuses it instead of
|
|
14186
|
+
* double-handling.
|
|
14187
|
+
*/
|
|
14188
|
+
function installQErrorListener(doc) {
|
|
14189
|
+
if (!doc.qErrorHandler) {
|
|
14190
|
+
doc.qErrorHandler = handleQError;
|
|
14191
|
+
doc.addEventListener?.('qerror', handleQError);
|
|
14192
|
+
}
|
|
14193
|
+
}
|
|
14194
|
+
function handleDevError(container, err, host) {
|
|
14195
|
+
if (typeof document !== 'undefined') {
|
|
14196
|
+
setErrorPayload(host, err);
|
|
14197
|
+
markVNodeDirty(container, host, 512 /* ChoreBits.ERROR_WRAP */);
|
|
14198
|
+
}
|
|
14199
|
+
try {
|
|
14200
|
+
if (err instanceof Error && !('hostElement' in err)) {
|
|
14201
|
+
err['hostElement'] = String(host);
|
|
14202
|
+
}
|
|
14203
|
+
}
|
|
14204
|
+
catch {
|
|
14205
|
+
// ignore
|
|
14206
|
+
}
|
|
14207
|
+
if (!isRecoverable(err)) {
|
|
14208
|
+
throw err;
|
|
14209
|
+
}
|
|
14210
|
+
}
|
|
14211
|
+
function getOwnErrorBoundaryStore(container, host) {
|
|
14212
|
+
const ctx = container.getHostProp(host, QCtxAttr);
|
|
14213
|
+
return ctx ? mapArray_get(ctx, ERROR_CONTEXT.id, 0) : null;
|
|
14214
|
+
}
|
|
13828
14215
|
|
|
13829
14216
|
/** @internal */
|
|
13830
14217
|
const canRevealRegistration = (registration, isPending = (item) => item.boundary.untrackedValue > 0) => {
|
|
@@ -14702,6 +15089,9 @@ class DomContainer extends _SharedContainer {
|
|
|
14702
15089
|
this.$setServerData$();
|
|
14703
15090
|
element.qContainer = this;
|
|
14704
15091
|
element.qDestroy = () => this.$destroy$();
|
|
15092
|
+
if (__EXPERIMENTAL__.errorBoundary) {
|
|
15093
|
+
installQErrorListener(this.document);
|
|
15094
|
+
}
|
|
14705
15095
|
this.$containerDataProcessState$ = 1 /* ContainerDataProcessState.ProcessingVNode */;
|
|
14706
15096
|
processVNodeData(document, element);
|
|
14707
15097
|
onVNodeDataReady(document, () => {
|
|
@@ -14797,29 +15187,48 @@ class DomContainer extends _SharedContainer {
|
|
|
14797
15187
|
this.$stateData$[id] = vParent;
|
|
14798
15188
|
}
|
|
14799
15189
|
parseQRL(qrlStr) {
|
|
14800
|
-
|
|
14801
|
-
return qrl;
|
|
15190
|
+
return parseQRL(qrlStr, this);
|
|
14802
15191
|
}
|
|
14803
|
-
handleError(err, host) {
|
|
15192
|
+
handleError(err, host, phase = "render" /* ErrorBoundaryPhase.Render */) {
|
|
14804
15193
|
if (qDev && host) {
|
|
14805
|
-
|
|
14806
|
-
|
|
14807
|
-
|
|
14808
|
-
|
|
14809
|
-
if (
|
|
14810
|
-
if (!('hostElement' in err)) {
|
|
14811
|
-
err['hostElement'] = String(host);
|
|
14812
|
-
}
|
|
14813
|
-
}
|
|
14814
|
-
if (!isRecoverable(err)) {
|
|
15194
|
+
handleDevError(this, err, host);
|
|
15195
|
+
}
|
|
15196
|
+
if (!__EXPERIMENTAL__.errorBoundary) {
|
|
15197
|
+
const errorStore = host && this.resolveContext(host, ERROR_CONTEXT);
|
|
15198
|
+
if (!errorStore) {
|
|
14815
15199
|
throw err;
|
|
14816
15200
|
}
|
|
15201
|
+
errorStore.error = err;
|
|
15202
|
+
return;
|
|
14817
15203
|
}
|
|
14818
|
-
|
|
14819
|
-
|
|
14820
|
-
|
|
15204
|
+
// `null` would collide with the capture-only sentinel, so wrap every nullish throw.
|
|
15205
|
+
const storedError = err == null ? toBoundaryError(err) : err;
|
|
15206
|
+
let current = host;
|
|
15207
|
+
while (current) {
|
|
15208
|
+
const boundaryHost = this.resolveContextHost(current, ERROR_CONTEXT);
|
|
15209
|
+
if (!boundaryHost) {
|
|
15210
|
+
break;
|
|
15211
|
+
}
|
|
15212
|
+
const store = getOwnErrorBoundaryStore(this, boundaryHost);
|
|
15213
|
+
if (store && store.error === undefined) {
|
|
15214
|
+
store.error = storedError;
|
|
15215
|
+
const boundaryProps = this.getHostProp(boundaryHost, ELEMENT_PROPS);
|
|
15216
|
+
fireOnError(boundaryProps?.onError$, err, phase, store.boundaryId ?? '');
|
|
15217
|
+
markVNodeDirty(this, boundaryHost, 4 /* ChoreBits.COMPONENT */);
|
|
15218
|
+
return;
|
|
15219
|
+
}
|
|
15220
|
+
// Capture-only sentinel for the ErrorProvider test spy; folds away in prod builds.
|
|
15221
|
+
if (qTest && store && store.error === null) {
|
|
15222
|
+
store.error = storedError;
|
|
15223
|
+
return;
|
|
15224
|
+
}
|
|
15225
|
+
if (boundaryHost.dirty & 4 /* ChoreBits.COMPONENT */) {
|
|
15226
|
+
logError(err);
|
|
15227
|
+
return;
|
|
15228
|
+
}
|
|
15229
|
+
current = this.getParentHost(boundaryHost);
|
|
14821
15230
|
}
|
|
14822
|
-
|
|
15231
|
+
logErrorAndThrowAsync(err);
|
|
14823
15232
|
}
|
|
14824
15233
|
setContext(host, context, value) {
|
|
14825
15234
|
let ctx = this.getHostProp(host, QCtxAttr);
|
|
@@ -14829,14 +15238,20 @@ class DomContainer extends _SharedContainer {
|
|
|
14829
15238
|
mapArray_set(ctx, context.id, value, 0, true);
|
|
14830
15239
|
}
|
|
14831
15240
|
resolveContext(host, contextId) {
|
|
15241
|
+
const found = this.resolveContextHost(host, contextId);
|
|
15242
|
+
return found
|
|
15243
|
+
? mapArray_get(this.getHostProp(found, QCtxAttr), contextId.id, 0)
|
|
15244
|
+
: undefined;
|
|
15245
|
+
}
|
|
15246
|
+
resolveContextHost(host, contextId) {
|
|
14832
15247
|
while (host) {
|
|
14833
15248
|
const ctx = this.getHostProp(host, QCtxAttr);
|
|
14834
15249
|
if (ctx != null && mapArray_has(ctx, contextId.id, 0)) {
|
|
14835
|
-
return
|
|
15250
|
+
return host;
|
|
14836
15251
|
}
|
|
14837
15252
|
host = this.getParentHost(host);
|
|
14838
15253
|
}
|
|
14839
|
-
return
|
|
15254
|
+
return null;
|
|
14840
15255
|
}
|
|
14841
15256
|
getParentHost(host) {
|
|
14842
15257
|
let vNode = host.parent;
|
|
@@ -16587,13 +17002,13 @@ const _useStyles = (styleQrl, transform, scoped) => {
|
|
|
16587
17002
|
return styleId;
|
|
16588
17003
|
};
|
|
16589
17004
|
|
|
16590
|
-
const creator$
|
|
17005
|
+
const creator$1 = (qrl, options) => {
|
|
16591
17006
|
qrl.resolve();
|
|
16592
17007
|
return createComputedSignal(qrl, options);
|
|
16593
17008
|
};
|
|
16594
17009
|
/** @internal */
|
|
16595
17010
|
const useComputedQrl = (qrl, options) => {
|
|
16596
|
-
return useConstant((creator$
|
|
17011
|
+
return useConstant((creator$1), qrl, options);
|
|
16597
17012
|
};
|
|
16598
17013
|
/**
|
|
16599
17014
|
* Creates a computed signal which is calculated from the given function. A computed signal is a
|
|
@@ -16613,12 +17028,12 @@ const useComputedQrl = (qrl, options) => {
|
|
|
16613
17028
|
*/
|
|
16614
17029
|
const useComputed$ = implicit$FirstArg(useComputedQrl);
|
|
16615
17030
|
|
|
16616
|
-
const creator
|
|
17031
|
+
const creator = (qrl) => {
|
|
16617
17032
|
qrl.resolve();
|
|
16618
17033
|
return createSerializerSignal(qrl);
|
|
16619
17034
|
};
|
|
16620
17035
|
/** @internal */
|
|
16621
|
-
const useSerializerQrl = (qrl) => useConstant((creator
|
|
17036
|
+
const useSerializerQrl = (qrl) => useConstant((creator), qrl);
|
|
16622
17037
|
/**
|
|
16623
17038
|
* Creates a signal which holds a custom serializable value. It requires that the value implements
|
|
16624
17039
|
* the `CustomSerializable` type, which means having a function under the `[SerializeSymbol]`
|
|
@@ -16848,49 +17263,217 @@ const useTask$ = /*#__PURE__*/ implicit$FirstArg(useTaskQrl);
|
|
|
16848
17263
|
// We need to cast to help out the api extractor
|
|
16849
17264
|
const useVisibleTask$ = /*#__PURE__*/ implicit$FirstArg(useVisibleTaskQrl);
|
|
16850
17265
|
|
|
16851
|
-
const
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
/**
|
|
16856
|
-
* @deprecated Use `useComputed$` instead, it has async support now.
|
|
16857
|
-
* @internal
|
|
16858
|
-
*/
|
|
16859
|
-
const useAsyncQrl = (qrl, options) => {
|
|
16860
|
-
return useConstant((creator), qrl, options);
|
|
16861
|
-
};
|
|
16862
|
-
/**
|
|
16863
|
-
* Creates an AsyncSignal which holds the result of the given async function. If the function uses
|
|
16864
|
-
* `track()` to track reactive state, and that state changes, the AsyncSignal is recalculated, and
|
|
16865
|
-
* if the result changed, all tasks which are tracking the AsyncSignal will be re-run and all
|
|
16866
|
-
* subscribers (components, tasks etc) that read the AsyncSignal will be updated.
|
|
16867
|
-
*
|
|
16868
|
-
* If the async function throws an error, the AsyncSignal will capture the error and set the `error`
|
|
16869
|
-
* property. The error can be cleared by re-running the async function successfully.
|
|
16870
|
-
*
|
|
16871
|
-
* While the async function is running, the `loading` property will be set to `true`. Once the
|
|
16872
|
-
* function completes, `loading` will be set to `false`.
|
|
16873
|
-
*
|
|
16874
|
-
* If the value has not yet been resolved, reading the AsyncSignal will throw a Promise, which will
|
|
16875
|
-
* retry the component or task once the value resolves.
|
|
16876
|
-
*
|
|
16877
|
-
* If the value has been resolved, but the async function is re-running, reading the AsyncSignal
|
|
16878
|
-
* will subscribe to it and return the last resolved value until the new value is ready. As soon as
|
|
16879
|
-
* the new value is ready, the subscribers will be updated.
|
|
16880
|
-
*
|
|
16881
|
-
* @deprecated Use `useComputed$` instead, it has async support now. It auto-tracks synchronous
|
|
16882
|
-
* reads; after the first `await`, use the provided `track()` like before.
|
|
16883
|
-
* @public
|
|
16884
|
-
*/
|
|
16885
|
-
const useAsync$ = implicit$FirstArg(useAsyncQrl);
|
|
16886
|
-
|
|
16887
|
-
/** @public */
|
|
16888
|
-
const useErrorBoundary = () => {
|
|
16889
|
-
const error = useStore({ error: undefined });
|
|
17266
|
+
const createErrorBoundaryStore = () => Object.defineProperty({ error: undefined }, 'error', { enumerable: false });
|
|
17267
|
+
/** @internal */
|
|
17268
|
+
const useErrorBoundaryStore = () => {
|
|
17269
|
+
const error = useStore(createErrorBoundaryStore);
|
|
16890
17270
|
useContextProvider(ERROR_CONTEXT, error);
|
|
16891
17271
|
return error;
|
|
16892
17272
|
};
|
|
16893
17273
|
|
|
17274
|
+
/** Finalizes a deferred segment and emits its swap scripts; shared by Suspense and ErrorBoundary. */
|
|
17275
|
+
async function finalizeAndSwapOutOfOrderSegment(ssr, boundaryId, rendered, revealBoundary) {
|
|
17276
|
+
const segmentId = String(boundaryId);
|
|
17277
|
+
const result = await rendered.container.$finalizeOutOfOrderSegment$(segmentId, rendered);
|
|
17278
|
+
ssr.write(`<template ${QSuspenseResolved}="${boundaryId}"${revealBoundary?.attrs ?? ''}>`);
|
|
17279
|
+
ssr.write(result.html);
|
|
17280
|
+
ssr.write('</template>');
|
|
17281
|
+
ssr.emitOutOfOrderSegmentScripts(result.scripts);
|
|
17282
|
+
ssr.emitOutOfOrderExecutorIfNeeded();
|
|
17283
|
+
ssr.emitInlineScript(`qO(${boundaryId})`);
|
|
17284
|
+
const errorSwapIds = rendered.container.$errorSwapIds$;
|
|
17285
|
+
if (__EXPERIMENTAL__.errorBoundary && errorSwapIds?.length) {
|
|
17286
|
+
ssr.emitErrorSwapExecutorIfNeeded();
|
|
17287
|
+
for (let i = 0; i < errorSwapIds.length; i++) {
|
|
17288
|
+
ssr.emitInlineScript(`qErr(${errorSwapIds[i]})`);
|
|
17289
|
+
}
|
|
17290
|
+
}
|
|
17291
|
+
// qO() is the browser-visible handoff for this segment, so flush it immediately.
|
|
17292
|
+
await ssr.streamHandler.flush();
|
|
17293
|
+
}
|
|
17294
|
+
|
|
17295
|
+
/** @internal */
|
|
17296
|
+
const errorBoundaryReset = () => {
|
|
17297
|
+
const [host] = _captures;
|
|
17298
|
+
// this is executed only on client
|
|
17299
|
+
const container = tryGetInvokeContext()?.$container$;
|
|
17300
|
+
const isBrowserEnv = qTest ? !isServerPlatform() : isBrowser$1;
|
|
17301
|
+
if (isBrowserEnv && host && container) {
|
|
17302
|
+
resetErrorBoundary(container, host);
|
|
17303
|
+
}
|
|
17304
|
+
};
|
|
17305
|
+
const RESET_KEY_SUFFIX = '\0';
|
|
17306
|
+
/** @internal */
|
|
17307
|
+
function resetErrorBoundary(container, host) {
|
|
17308
|
+
const boundaryHost = container.resolveContextHost(host, ERROR_CONTEXT);
|
|
17309
|
+
if (!boundaryHost) {
|
|
17310
|
+
return;
|
|
17311
|
+
}
|
|
17312
|
+
const store = getOwnErrorBoundaryStore(container, boundaryHost);
|
|
17313
|
+
if (!store) {
|
|
17314
|
+
return;
|
|
17315
|
+
}
|
|
17316
|
+
scheduleBoundaryContentReset(container, boundaryHost, store.projectedContentOwner ?? null);
|
|
17317
|
+
store.error = undefined;
|
|
17318
|
+
}
|
|
17319
|
+
function scheduleBoundaryContentReset(container, boundaryHost, recordedContentOwner) {
|
|
17320
|
+
let resetHost = boundaryHost;
|
|
17321
|
+
let contentOwner = null;
|
|
17322
|
+
let vNode = vnode_getProjectionParentOrParent(boundaryHost);
|
|
17323
|
+
let crossedProjection = false;
|
|
17324
|
+
while (vNode) {
|
|
17325
|
+
if (vnode_isVirtualVNode(vNode)) {
|
|
17326
|
+
if (vnode_getProp(vNode, QSlot, null) !== null) {
|
|
17327
|
+
crossedProjection = true;
|
|
17328
|
+
}
|
|
17329
|
+
else if (vnode_getProp(vNode, OnRenderProp, null) !== null) {
|
|
17330
|
+
if (!crossedProjection) {
|
|
17331
|
+
const ownerBoundary = getOwnErrorBoundaryStore(container, vNode);
|
|
17332
|
+
if (!ownerBoundary || ownerBoundary.error !== undefined) {
|
|
17333
|
+
if (contentOwner) {
|
|
17334
|
+
resetHost = contentOwner;
|
|
17335
|
+
}
|
|
17336
|
+
contentOwner = vNode;
|
|
17337
|
+
if (ownerBoundary?.error !== undefined || !hasSlotProps(vNode.props)) {
|
|
17338
|
+
break;
|
|
17339
|
+
}
|
|
17340
|
+
}
|
|
17341
|
+
}
|
|
17342
|
+
crossedProjection = false;
|
|
17343
|
+
}
|
|
17344
|
+
}
|
|
17345
|
+
vNode = vnode_getProjectionParentOrParent(vNode);
|
|
17346
|
+
}
|
|
17347
|
+
if (recordedContentOwner && recordedContentOwner !== contentOwner) {
|
|
17348
|
+
resetHost = contentOwner ?? resetHost;
|
|
17349
|
+
contentOwner = recordedContentOwner;
|
|
17350
|
+
}
|
|
17351
|
+
if (contentOwner) {
|
|
17352
|
+
// Force keyed diff to recreate emptied projected content.
|
|
17353
|
+
resetHost.key = `${resetHost.key ?? ''}${RESET_KEY_SUFFIX}`;
|
|
17354
|
+
markVNodeDirty(container, contentOwner, 4 /* ChoreBits.COMPONENT */);
|
|
17355
|
+
}
|
|
17356
|
+
else {
|
|
17357
|
+
markVNodeDirty(container, boundaryHost, 4 /* ChoreBits.COMPONENT */);
|
|
17358
|
+
}
|
|
17359
|
+
}
|
|
17360
|
+
const renderFallbackOrLastResort = (fallbackQrl, error, reset) => {
|
|
17361
|
+
return fallbackQrl(error, reset).catch((err) => {
|
|
17362
|
+
if (fallbackQrl.resolved !== undefined) {
|
|
17363
|
+
throw err;
|
|
17364
|
+
}
|
|
17365
|
+
return /*#__PURE__*/ _jsxSorted('div', { role: 'alert' }, null, 'Something went wrong.', 0, null);
|
|
17366
|
+
});
|
|
17367
|
+
};
|
|
17368
|
+
const buildSSRErrorBoundaryHosts = (store, container) => {
|
|
17369
|
+
const boundaryId = container?.nextOutOfOrderId(false) ?? 0;
|
|
17370
|
+
return [
|
|
17371
|
+
/*#__PURE__*/ _jsxSorted('div', {
|
|
17372
|
+
[QErrorContentHost]: String(boundaryId),
|
|
17373
|
+
style: 'display:contents',
|
|
17374
|
+
}, null,
|
|
17375
|
+
/*#__PURE__*/ _jsxSorted(Slot, null, null, null, 0, null), 1, null),
|
|
17376
|
+
/*#__PURE__*/ _jsxSorted(SSRErrorFallbackHost, {
|
|
17377
|
+
boundaryId,
|
|
17378
|
+
store,
|
|
17379
|
+
}, null, null, 1, null),
|
|
17380
|
+
];
|
|
17381
|
+
};
|
|
17382
|
+
/** @internal */
|
|
17383
|
+
const errorBoundaryCmp = (props) => {
|
|
17384
|
+
if (!__EXPERIMENTAL__.errorBoundary) {
|
|
17385
|
+
throw new Error('<ErrorBoundary> requires the `errorBoundary` experimental feature. Enable it in your Qwik Vite config: qwikVite({ experimental: ["errorBoundary"] }).');
|
|
17386
|
+
}
|
|
17387
|
+
const store = useErrorBoundaryStore();
|
|
17388
|
+
const invokeCtx = tryGetInvokeContext();
|
|
17389
|
+
const container = invokeCtx?.$container$;
|
|
17390
|
+
if (container && (getStoreTarget(store) ?? store).boundaryId === undefined) {
|
|
17391
|
+
store.boundaryId = getNextUniqueIndex(container);
|
|
17392
|
+
}
|
|
17393
|
+
const isServerEnv = qTest ? isServerPlatform() : !isBrowser$1;
|
|
17394
|
+
if (!isServerEnv && store.error === undefined) {
|
|
17395
|
+
return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 0, null);
|
|
17396
|
+
}
|
|
17397
|
+
const reset = /*#__PURE__*/ inlinedQrl(errorBoundaryReset, '_ebR', [invokeCtx?.$hostElement$]);
|
|
17398
|
+
if (isServerEnv) {
|
|
17399
|
+
const fallbackQrl = props.fallback$;
|
|
17400
|
+
store.$fallback$ = noSerialize((error) => fallbackQrl(error, reset));
|
|
17401
|
+
const onErrorQrl = props.onError$;
|
|
17402
|
+
if (onErrorQrl) {
|
|
17403
|
+
store.$onError$ = noSerialize((error, info) => onErrorQrl(error, info));
|
|
17404
|
+
}
|
|
17405
|
+
return buildSSRErrorBoundaryHosts(store, container);
|
|
17406
|
+
}
|
|
17407
|
+
const displayError = redactBoundaryErrorForDisplay(store.error, true);
|
|
17408
|
+
return /*#__PURE__*/ _jsxSorted(Fragment, null, null, renderFallbackOrLastResort(props.fallback$, displayError, reset), 0, null);
|
|
17409
|
+
};
|
|
17410
|
+
/** Renders `fallback$` instead of its children when a descendant throws. @public @experimental */
|
|
17411
|
+
const ErrorBoundary =
|
|
17412
|
+
/*#__PURE__*/ componentQrl(
|
|
17413
|
+
/*#__PURE__*/ inlinedQrl(errorBoundaryCmp, ERROR_BOUNDARY_QRL_SYMBOL));
|
|
17414
|
+
const consumeSSRErrorFallback = (ssr, store) => {
|
|
17415
|
+
const fallback = store.$fallback$;
|
|
17416
|
+
delete store.$fallback$;
|
|
17417
|
+
const projected = redactBoundaryErrorForDisplay(store.error, isDev, ssr.$transformError$);
|
|
17418
|
+
return fallback(projected);
|
|
17419
|
+
};
|
|
17420
|
+
const SSRErrorFallbackRenderer = __EXPERIMENTAL__.errorBoundary
|
|
17421
|
+
? /*#__PURE__*/ createInternalServerComponent((ssr, jsx, options, enqueue) => {
|
|
17422
|
+
const boundaryId = jsx.varProps.boundaryId;
|
|
17423
|
+
const store = jsx.varProps.store;
|
|
17424
|
+
if (jsx.varProps.deliverLate) {
|
|
17425
|
+
const streamFallback = async (error) => {
|
|
17426
|
+
if (!store.$fallback$) {
|
|
17427
|
+
return;
|
|
17428
|
+
}
|
|
17429
|
+
// The catch site already recorded it; marking again refires onError$.
|
|
17430
|
+
if (store.error !== error) {
|
|
17431
|
+
markBoundaryErrored(store, error, "render" /* ErrorBoundaryPhase.Render */);
|
|
17432
|
+
}
|
|
17433
|
+
const segment = await ssr.segment(`${boundaryId}`, consumeSSRErrorFallback(ssr, store), options);
|
|
17434
|
+
// qErr hides the errored content host and strips its broadcast handlers.
|
|
17435
|
+
segment.container.$registerErrorSwap$(boundaryId);
|
|
17436
|
+
await ssr.$runQueuedRender$(() => finalizeAndSwapOutOfOrderSegment(ssr, boundaryId, segment, null));
|
|
17437
|
+
};
|
|
17438
|
+
store.$emitFallback$ = noSerialize(streamFallback);
|
|
17439
|
+
ssr.write(`<template ${QSuspenseResolved}="${boundaryId}"></template>`);
|
|
17440
|
+
if (store.error !== undefined) {
|
|
17441
|
+
return streamFallback(store.error);
|
|
17442
|
+
}
|
|
17443
|
+
return;
|
|
17444
|
+
}
|
|
17445
|
+
if (store.error === undefined || !store.$fallback$) {
|
|
17446
|
+
return;
|
|
17447
|
+
}
|
|
17448
|
+
if (isOutOfOrderSegmentContainer(ssr)) {
|
|
17449
|
+
ssr.$registerErrorSwap$(boundaryId);
|
|
17450
|
+
}
|
|
17451
|
+
else {
|
|
17452
|
+
enqueue(() => {
|
|
17453
|
+
ssr.emitErrorSwapExecutorIfNeeded();
|
|
17454
|
+
ssr.emitInlineScript(`qErr(${boundaryId})`);
|
|
17455
|
+
});
|
|
17456
|
+
}
|
|
17457
|
+
enqueue(consumeSSRErrorFallback(ssr, store));
|
|
17458
|
+
})
|
|
17459
|
+
: null;
|
|
17460
|
+
const SSRErrorFallbackHost = __EXPERIMENTAL__.errorBoundary
|
|
17461
|
+
? /*#__PURE__*/ createInternalServerComponent((ssr, jsx, _options, enqueue) => {
|
|
17462
|
+
const boundaryId = jsx.varProps.boundaryId;
|
|
17463
|
+
const store = jsx.varProps.store;
|
|
17464
|
+
const deliverLate = __EXPERIMENTAL__.suspense &&
|
|
17465
|
+
ssr.outOfOrderStreaming &&
|
|
17466
|
+
!isOutOfOrderSegmentContainer(ssr) &&
|
|
17467
|
+
(store.error === undefined || isErrorFromDeferredSegment(store));
|
|
17468
|
+
enqueue(
|
|
17469
|
+
/*#__PURE__*/ _jsxSorted('div', {
|
|
17470
|
+
[deliverLate ? QSuspenseResultParent : QErrorFallbackHost]: String(boundaryId),
|
|
17471
|
+
style: 'display:none',
|
|
17472
|
+
}, null,
|
|
17473
|
+
/*#__PURE__*/ _jsxSorted(SSRErrorFallbackRenderer, { boundaryId, store, deliverLate }, null, null, 1, null), 1, null));
|
|
17474
|
+
})
|
|
17475
|
+
: null;
|
|
17476
|
+
|
|
16894
17477
|
/** @internal */
|
|
16895
17478
|
const eachCmpTask = async ({ track }) => {
|
|
16896
17479
|
const props = _captures[0];
|
|
@@ -17181,10 +17764,23 @@ const SSRDeferredSlot = __EXPERIMENTAL__.suspense
|
|
|
17181
17764
|
const boundaryState = jsx.varProps.boundary;
|
|
17182
17765
|
const contentStyle = jsx.varProps.contentStyle;
|
|
17183
17766
|
const revealBoundary = jsx.varProps.reveal;
|
|
17767
|
+
const errorBoundaryStore = __EXPERIMENTAL__.errorBoundary && options.parentComponentFrame
|
|
17768
|
+
? ssr.resolveContext(options.parentComponentFrame.componentNode, ERROR_CONTEXT)
|
|
17769
|
+
: undefined;
|
|
17184
17770
|
const content = ssr.segment(contentSegment, createClaimedDeferredSlot(ssr, jsx, options), options);
|
|
17185
17771
|
ssr.write(`<template ${QSuspenseResolved}="${boundaryId}"></template>`);
|
|
17186
17772
|
ssr.emitOutOfOrderExecutorIfNeeded();
|
|
17187
|
-
ssr.queueOutOfOrderSegment(content
|
|
17773
|
+
ssr.queueOutOfOrderSegment(content
|
|
17774
|
+
.then((rendered) => emitRenderedOutOfOrderSegment(ssr, boundaryId, rendered, contentStyle, revealBoundary, boundaryState))
|
|
17775
|
+
.catch((error) => {
|
|
17776
|
+
if (errorBoundaryStore?.$emitFallback$) {
|
|
17777
|
+
return errorBoundaryStore.$emitFallback$(error);
|
|
17778
|
+
}
|
|
17779
|
+
if (errorBoundaryStore?.error !== undefined) {
|
|
17780
|
+
return;
|
|
17781
|
+
}
|
|
17782
|
+
throw error;
|
|
17783
|
+
}));
|
|
17188
17784
|
})
|
|
17189
17785
|
: null;
|
|
17190
17786
|
function createClaimedDeferredSlot(ssr, jsx, options) {
|
|
@@ -17200,7 +17796,7 @@ function createClaimedDeferredSlot(ssr, jsx, options) {
|
|
|
17200
17796
|
}
|
|
17201
17797
|
return /*#__PURE__*/ _jsxSorted(Slot, jsx.varProps, jsx.constProps, slotChildren, jsx.flags, jsx.key);
|
|
17202
17798
|
}
|
|
17203
|
-
async function emitRenderedOutOfOrderSegment(ssr, boundaryId,
|
|
17799
|
+
async function emitRenderedOutOfOrderSegment(ssr, boundaryId, rendered, contentStyle, revealBoundary, boundaryState) {
|
|
17204
17800
|
if (boundaryState) {
|
|
17205
17801
|
boundaryState.contentResolved = true;
|
|
17206
17802
|
if (boundaryState.delayTimer) {
|
|
@@ -17211,14 +17807,7 @@ async function emitRenderedOutOfOrderSegment(ssr, boundaryId, segmentId, rendere
|
|
|
17211
17807
|
revealBoundary?.resolve();
|
|
17212
17808
|
await ssr.$runQueuedRender$(async () => {
|
|
17213
17809
|
ssr.addRoot(contentStyle);
|
|
17214
|
-
|
|
17215
|
-
ssr.write(`<template ${QSuspenseResolved}="${boundaryId}"${revealBoundary?.attrs ?? ''}>`);
|
|
17216
|
-
ssr.write(result.html);
|
|
17217
|
-
ssr.write('</template>');
|
|
17218
|
-
ssr.emitOutOfOrderSegmentScripts(result.scripts);
|
|
17219
|
-
ssr.emitInlineScript(`qO(${boundaryId})`);
|
|
17220
|
-
// qO() is the browser-visible handoff for this segment, so flush it immediately.
|
|
17221
|
-
await ssr.streamHandler.flush();
|
|
17810
|
+
await finalizeAndSwapOutOfOrderSegment(ssr, boundaryId, rendered, revealBoundary);
|
|
17222
17811
|
});
|
|
17223
17812
|
}
|
|
17224
17813
|
function scheduleOutOfOrderFallbackDelay(ssr, boundaryState, state) {
|
|
@@ -17333,5 +17922,5 @@ if (import.meta.hot) {
|
|
|
17333
17922
|
});
|
|
17334
17923
|
}
|
|
17335
17924
|
|
|
17336
|
-
export { $, Each, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, Reveal, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, Show, SkipRender, Slot, Suspense, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, ELEMENT_SEQ as _ELEMENT_SEQ, EMPTY_ARRAY as _EMPTY_ARRAY, EMPTY_OBJ as _EMPTY_OBJ, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, SubscriptionPatch as _SubscriptionPatch, Task as _Task, _UNINITIALIZED, _VAR_PROPS, _addProjection, _captures, _chk, _createDeserializeContainer, createQRL as _createQRL, createStore as _createStore, delay as _delay, _deserialize, _dumpState, eachCmp as _eaC, eachCmpTask as _eaT, _executeSsrChores, _fnSignal, getAsyncLocalStorage as _getAsyncLocalStorage, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, getSubscriber as _getSubscriber, _getVarProps, _hasStoreEffects, _hmr, _injectAsyncSignalValue, invoke as _invoke, 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, _markSignalAsExternallyOwned, newInvokeContext as _newInvokeContext, _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, retryOnPromise as _retryOnPromise, _rsc, _run, _serialize, setEvent as _setEvent, _setProjectionTarget, showCmp as _shC, showCmpTask as _shT, 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,
|
|
17925
|
+
export { $, Each, ErrorBoundary, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, Reveal, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, Show, SkipRender, Slot, Suspense, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, ELEMENT_SEQ as _ELEMENT_SEQ, EMPTY_ARRAY as _EMPTY_ARRAY, EMPTY_OBJ as _EMPTY_OBJ, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, SubscriptionPatch as _SubscriptionPatch, Task as _Task, _UNINITIALIZED, _VAR_PROPS, _addProjection, _captures, _chk, _createDeserializeContainer, createQRL as _createQRL, createStore as _createStore, delay as _delay, _deserialize, _dumpState, eachCmp as _eaC, eachCmpTask as _eaT, errorBoundaryCmp as _ebC, errorBoundaryReset as _ebR, _executeSsrChores, _fnSignal, getAsyncLocalStorage as _getAsyncLocalStorage, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, getSubscriber as _getSubscriber, _getVarProps, handleSSRError as _handleSSRError, _hasStoreEffects, _hmr, _injectAsyncSignalValue, invoke as _invoke, 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, _markSignalAsExternallyOwned, newInvokeContext as _newInvokeContext, _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, retryOnPromise as _retryOnPromise, _rsc, _run, _serialize, setEvent as _setEvent, _setProjectionTarget, showCmp as _shC, showCmpTask as _shT, 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, 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, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
|
|
17337
17926
|
//# sourceMappingURL=core.mjs.map
|