@qwik.dev/core 2.0.0-beta.35 → 2.0.0-beta.36
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/index.mjs +2 -2
- package/dist/backpatch/package.json +1 -1
- package/dist/backpatch-executor.debug.js +2 -1
- package/dist/backpatch-executor.js +1 -1
- package/dist/build/package.json +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/core-internal.d.ts +183 -39
- package/dist/core.min.mjs +8 -9
- package/dist/core.mjs +2223 -1290
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.mjs +4492 -3645
- package/dist/loader/index.mjs +2 -2
- package/dist/loader/package.json +1 -1
- package/dist/optimizer.d.ts +0 -4
- package/dist/optimizer.mjs +429 -424
- package/dist/out-of-order-executor.debug.js +163 -0
- package/dist/out-of-order-executor.js +1 -0
- package/dist/preloader.mjs +1 -1
- package/dist/qwikloader.debug.js +47 -26
- package/dist/qwikloader.js +1 -1
- package/dist/server.d.ts +4 -0
- package/dist/server.mjs +1160 -143
- package/dist/server.prod.mjs +1231 -428
- package/dist/testing/index.d.ts +75 -20
- package/dist/testing/index.mjs +2966 -1218
- package/dist/testing/package.json +1 -1
- package/dist/worker/package.json +1 -1
- package/package.json +4 -4
- package/public.d.ts +1 -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.36-dev+3268fab
|
|
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
|
|
@@ -328,6 +328,25 @@ const VNodeDataChar = {
|
|
|
328
328
|
BACK_REFS: /* ********** */ 96, // '`' - `q:brefs' - Effect dependencies/subscriptions
|
|
329
329
|
SEPARATOR: /* ********* */ 124, // `|` - Separator char to encode any key/value pairs.
|
|
330
330
|
SLOT: /* ************** */ 126};
|
|
331
|
+
/**
|
|
332
|
+
* Convert a segment-local vnode index into a key for the root container's shared qVNodeRefs map.
|
|
333
|
+
*
|
|
334
|
+
* Out-of-order Suspense segments each start counting vnode refs from 0, but the client merges all
|
|
335
|
+
* segment refs into one root-level map. This uses a Cantor-style pairing function for the
|
|
336
|
+
* zero-based pair `(segmentIndex, localIndex)`, then makes it negative so segment refs cannot
|
|
337
|
+
* collide with root refs, which are non-negative.
|
|
338
|
+
*
|
|
339
|
+
* Examples:
|
|
340
|
+
*
|
|
341
|
+
* - Segment 1, local 0 -> -1
|
|
342
|
+
* - Segment 2, local 0 -> -2
|
|
343
|
+
* - Segment 1, local 1 -> -3
|
|
344
|
+
*/
|
|
345
|
+
const getSegmentVNodeRefId = (segmentId, localIndex) => {
|
|
346
|
+
const segmentIndex = parseInt(segmentId, 10) - 1;
|
|
347
|
+
const diagonal = segmentIndex + localIndex;
|
|
348
|
+
return -((diagonal * (diagonal + 1)) / 2 + localIndex + 1);
|
|
349
|
+
};
|
|
331
350
|
|
|
332
351
|
function escapeHTML(html) {
|
|
333
352
|
let escapedHTML = '';
|
|
@@ -391,6 +410,9 @@ const ComponentStylesPrefixContent = '⚡️';
|
|
|
391
410
|
const QSlot = 'q:slot';
|
|
392
411
|
const QSlotParent = 'q:sparent';
|
|
393
412
|
const QSlotS = 'q:s';
|
|
413
|
+
const QStatePatchAttrSelector = '[q\\:patch]';
|
|
414
|
+
const QSuspenseResolved = 'q:r';
|
|
415
|
+
const QSuspenseResultParent = 'q:rp';
|
|
394
416
|
const QStyle = 'q:style';
|
|
395
417
|
const QStyleSelector = 'style[q\\:style]';
|
|
396
418
|
const QStyleSSelector = 'style[q\\:sstyle]';
|
|
@@ -412,6 +434,7 @@ const QIgnore = 'q:ignore';
|
|
|
412
434
|
const QIgnoreEnd = '/' + QIgnore;
|
|
413
435
|
const QContainerAttr = 'q:container';
|
|
414
436
|
const QContainerAttrEnd = '/' + QContainerAttr;
|
|
437
|
+
const QCursorBoundary = 'q:cursorBoundary';
|
|
415
438
|
const QTemplate = 'q:template';
|
|
416
439
|
// the same selector should be inside the qwik loader
|
|
417
440
|
// and the same selector should be inside the qwik router spa-shim and spa-init
|
|
@@ -444,7 +467,6 @@ const ELEMENT_KEY = 'q:key';
|
|
|
444
467
|
const ELEMENT_PROPS = 'q:props';
|
|
445
468
|
const ELEMENT_SEQ = 'q:seq';
|
|
446
469
|
const ELEMENT_SEQ_IDX = 'q:seqIdx';
|
|
447
|
-
const Q_PREFIX = 'q:';
|
|
448
470
|
const ITERATION_ITEM_SINGLE = 'q:p'; // Single iteration parameter (not an array)
|
|
449
471
|
const ITERATION_ITEM_MULTI = 'q:ps'; // Multiple iteration parameters (array)
|
|
450
472
|
/** Non serializable markers - always begins with `:` character */
|
|
@@ -452,8 +474,7 @@ const NON_SERIALIZABLE_MARKER_PREFIX = ':';
|
|
|
452
474
|
const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
|
|
453
475
|
const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
|
|
454
476
|
const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
|
|
455
|
-
const
|
|
456
|
-
const QNearestCursorBoundary = NON_SERIALIZABLE_MARKER_PREFIX + 'nearestCursorBoundary';
|
|
477
|
+
const NEAREST_CURSOR_BOUNDARY = NON_SERIALIZABLE_MARKER_PREFIX + 'nearestCursorBoundary';
|
|
457
478
|
const Q_PROPS_SEPARATOR = ':';
|
|
458
479
|
const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
|
|
459
480
|
const qwikInspectorAttr = 'data-qwik-inspector';
|
|
@@ -932,8 +953,6 @@ const config = {
|
|
|
932
953
|
const rel = isBrowser && doc.createElement('link').relList?.supports?.('modulepreload')
|
|
933
954
|
? 'modulePreload'
|
|
934
955
|
: 'preload';
|
|
935
|
-
// Global state
|
|
936
|
-
performance.now();
|
|
937
956
|
const isJSRegex = /\.[mc]?js$/;
|
|
938
957
|
const yieldInterval = 1000 / 60;
|
|
939
958
|
|
|
@@ -1178,6 +1197,29 @@ const isObjectEmpty = (obj) => {
|
|
|
1178
1197
|
return true;
|
|
1179
1198
|
};
|
|
1180
1199
|
|
|
1200
|
+
/** @internal */
|
|
1201
|
+
const stringifyRootRefPath = (path) => {
|
|
1202
|
+
let text = String(path[0]);
|
|
1203
|
+
for (let i = 1; i < path.length; i++) {
|
|
1204
|
+
text += ' ' + path[i];
|
|
1205
|
+
}
|
|
1206
|
+
return text;
|
|
1207
|
+
};
|
|
1208
|
+
/** @internal */
|
|
1209
|
+
const writeStringRootRef = (writer, id) => writer.write(String(id));
|
|
1210
|
+
/** @internal */
|
|
1211
|
+
const writeStringRootRefPath = (writer, path) => writer.write(stringifyRootRefPath(path));
|
|
1212
|
+
/** @internal */
|
|
1213
|
+
const createStringStreamWriter = (write) => ({
|
|
1214
|
+
write,
|
|
1215
|
+
writeRootRef(id) {
|
|
1216
|
+
return writeStringRootRef(this, id);
|
|
1217
|
+
},
|
|
1218
|
+
writeRootRefPath(path) {
|
|
1219
|
+
return writeStringRootRefPath(this, path);
|
|
1220
|
+
},
|
|
1221
|
+
});
|
|
1222
|
+
|
|
1181
1223
|
// Pre-allocated common strings to reduce allocation overhead
|
|
1182
1224
|
const CLOSE_TAG = '</';
|
|
1183
1225
|
const ESCAPED_CLOSE_TAG = '<\\/';
|
|
@@ -1191,7 +1233,7 @@ const COMMA = ',';
|
|
|
1191
1233
|
*
|
|
1192
1234
|
* @public
|
|
1193
1235
|
*/
|
|
1194
|
-
const version = "2.0.0-beta.
|
|
1236
|
+
const version = "2.0.0-beta.36-dev+3268fab";
|
|
1195
1237
|
|
|
1196
1238
|
const isNode = (value) => {
|
|
1197
1239
|
return value && typeof value.nodeType === 'number';
|
|
@@ -1203,6 +1245,20 @@ const isElement$1 = (value) => {
|
|
|
1203
1245
|
return value.nodeType === 1;
|
|
1204
1246
|
};
|
|
1205
1247
|
|
|
1248
|
+
/** @internal */
|
|
1249
|
+
const getRootContainer = (container) => {
|
|
1250
|
+
const rootContainer = container.$rootContainer$;
|
|
1251
|
+
return rootContainer || container;
|
|
1252
|
+
};
|
|
1253
|
+
/** @internal */
|
|
1254
|
+
const isOutOfOrderSegmentContainer = (container) => {
|
|
1255
|
+
return container.$isOutOfOrderSegment$;
|
|
1256
|
+
};
|
|
1257
|
+
/** @internal */
|
|
1258
|
+
const isSameContainer = (left, right) => {
|
|
1259
|
+
return getRootContainer(left) === (right ? getRootContainer(right) : null);
|
|
1260
|
+
};
|
|
1261
|
+
|
|
1206
1262
|
/** @internal */
|
|
1207
1263
|
const _EFFECT_BACK_REF = Symbol('backRef');
|
|
1208
1264
|
/** Class for back reference to the EffectSubscription */
|
|
@@ -1554,17 +1610,27 @@ function pauseCursor(cursor, container) {
|
|
|
1554
1610
|
container.$pendingCount$++;
|
|
1555
1611
|
}
|
|
1556
1612
|
function resumeCursor(cursor, container) {
|
|
1557
|
-
|
|
1558
|
-
if (
|
|
1559
|
-
|
|
1560
|
-
if (index !== lastIndex) {
|
|
1561
|
-
pausedCursorQueue[index] = pausedCursorQueue[lastIndex];
|
|
1562
|
-
}
|
|
1563
|
-
pausedCursorQueue.pop();
|
|
1564
|
-
container.$pendingCount$--;
|
|
1613
|
+
removeCursorFromPausedQueue(cursor, container);
|
|
1614
|
+
if (!(cursor.flags & 256 /* VNodeFlags.Cursor */)) {
|
|
1615
|
+
return;
|
|
1565
1616
|
}
|
|
1566
1617
|
addCursorToQueue(container, cursor);
|
|
1567
1618
|
}
|
|
1619
|
+
function abandonCursor(container, targetCursorData, cursor) {
|
|
1620
|
+
const oldCursorData = getCursorData(cursor);
|
|
1621
|
+
if (!oldCursorData || oldCursorData === targetCursorData) {
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
removeCursorFromQueue(cursor, container, false);
|
|
1625
|
+
removeCursorFromPausedQueue(cursor, container);
|
|
1626
|
+
mergeCursorJournalAndBoundaries(targetCursorData, oldCursorData);
|
|
1627
|
+
oldCursorData.afterFlushTasks = null;
|
|
1628
|
+
oldCursorData.extraPromises = null;
|
|
1629
|
+
oldCursorData.journal = null;
|
|
1630
|
+
oldCursorData.boundaries = null;
|
|
1631
|
+
oldCursorData.position = null;
|
|
1632
|
+
oldCursorData.promise = null;
|
|
1633
|
+
}
|
|
1568
1634
|
/**
|
|
1569
1635
|
* Removes a cursor from the global queue.
|
|
1570
1636
|
*
|
|
@@ -1585,7 +1651,22 @@ function removeCursorFromQueue(cursor, container, keepCursorFlag) {
|
|
|
1585
1651
|
// globalCursorQueue.pop();
|
|
1586
1652
|
globalCursorQueue.splice(index, 1);
|
|
1587
1653
|
container.$pendingCount$--;
|
|
1654
|
+
return true;
|
|
1655
|
+
}
|
|
1656
|
+
return false;
|
|
1657
|
+
}
|
|
1658
|
+
function removeCursorFromPausedQueue(cursor, container) {
|
|
1659
|
+
const index = pausedCursorQueue.indexOf(cursor);
|
|
1660
|
+
if (index === -1) {
|
|
1661
|
+
return false;
|
|
1588
1662
|
}
|
|
1663
|
+
const lastIndex = pausedCursorQueue.length - 1;
|
|
1664
|
+
if (index !== lastIndex) {
|
|
1665
|
+
pausedCursorQueue[index] = pausedCursorQueue[lastIndex];
|
|
1666
|
+
}
|
|
1667
|
+
pausedCursorQueue.pop();
|
|
1668
|
+
container.$pendingCount$--;
|
|
1669
|
+
return true;
|
|
1589
1670
|
}
|
|
1590
1671
|
|
|
1591
1672
|
const cursorDatas = new WeakMap();
|
|
@@ -1594,6 +1675,7 @@ const NODE_PROPS_DATA_KEY = ':nodeProps';
|
|
|
1594
1675
|
const NODE_DIFF_DATA_KEY = ':nodeDiff';
|
|
1595
1676
|
const ERROR_DATA_KEY = ':errorData';
|
|
1596
1677
|
const HOST_SIGNAL = ':signal';
|
|
1678
|
+
const INLINE_COMPONENT_DATA_KEY = ':inlineComponentData';
|
|
1597
1679
|
/**
|
|
1598
1680
|
* Sets the cursor position in a cursor vNode.
|
|
1599
1681
|
*
|
|
@@ -1610,6 +1692,9 @@ function mergeCursors(container, newCursorData, oldCursor) {
|
|
|
1610
1692
|
// delete from global cursors queue
|
|
1611
1693
|
removeCursorFromQueue(oldCursor, container);
|
|
1612
1694
|
const oldCursorData = getCursorData(oldCursor);
|
|
1695
|
+
mergeCursorData(newCursorData, oldCursorData);
|
|
1696
|
+
}
|
|
1697
|
+
function mergeCursorData(newCursorData, oldCursorData) {
|
|
1613
1698
|
if (oldCursorData === newCursorData) {
|
|
1614
1699
|
// same cursor data, no need to merge
|
|
1615
1700
|
return;
|
|
@@ -1636,6 +1721,12 @@ function mergeCursors(container, newCursorData, oldCursor) {
|
|
|
1636
1721
|
newCursorData.extraPromises = oldExtraPromises;
|
|
1637
1722
|
}
|
|
1638
1723
|
}
|
|
1724
|
+
mergeCursorJournalAndBoundaries(newCursorData, oldCursorData);
|
|
1725
|
+
}
|
|
1726
|
+
function mergeCursorJournalAndBoundaries(newCursorData, oldCursorData) {
|
|
1727
|
+
if (oldCursorData === newCursorData) {
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1639
1730
|
// merge journal
|
|
1640
1731
|
const oldJournal = oldCursorData.journal;
|
|
1641
1732
|
if (oldJournal && oldJournal.length > 0) {
|
|
@@ -1876,20 +1967,28 @@ class SignalImpl {
|
|
|
1876
1967
|
}
|
|
1877
1968
|
else {
|
|
1878
1969
|
isDev &&
|
|
1879
|
-
assertTrue(!ctx.$container$ || ctx.$container
|
|
1970
|
+
assertTrue(!ctx.$container$ || isSameContainer(ctx.$container$, this.$container$), 'Do not use signals across containers');
|
|
1880
1971
|
}
|
|
1881
1972
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
1882
1973
|
if (effectSubscriber) {
|
|
1883
1974
|
// Let's make sure that we have a reference to this effect.
|
|
1884
1975
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
1885
1976
|
// changes we know who to notify.
|
|
1886
|
-
|
|
1977
|
+
const isOnServer = qTest ? isServerPlatform() : isServer;
|
|
1978
|
+
const effects = (this.$effects$ ||= new Set());
|
|
1979
|
+
const shouldRecordExternalRootEffect = __EXPERIMENTAL__.suspense && isOnServer;
|
|
1980
|
+
ensureContainsSubscription(effects, effectSubscriber);
|
|
1887
1981
|
// But when effect is scheduled in needs to be able to know which signals
|
|
1888
1982
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
1889
1983
|
// to this signal.
|
|
1890
1984
|
ensureContainsBackRef(effectSubscriber, this);
|
|
1891
|
-
|
|
1892
|
-
|
|
1985
|
+
if (isOnServer) {
|
|
1986
|
+
const serializationContainer = getEffectSerializationContainer(ctx.$container$, this.$container$);
|
|
1987
|
+
if (shouldRecordExternalRootEffect) {
|
|
1988
|
+
serializationContainer?.$recordExternalRootEffect$?.(this, effectSubscriber, null);
|
|
1989
|
+
}
|
|
1990
|
+
addQrlToSerializationCtx(effectSubscriber, serializationContainer);
|
|
1991
|
+
}
|
|
1893
1992
|
}
|
|
1894
1993
|
return val;
|
|
1895
1994
|
}
|
|
@@ -3016,7 +3115,7 @@ class WrappedSignalImpl extends SignalImpl {
|
|
|
3016
3115
|
catch (_) {
|
|
3017
3116
|
if (this.$container$ && this.$hostElement$) {
|
|
3018
3117
|
this.$container$.setHostProp(this.$hostElement$, HOST_SIGNAL, this);
|
|
3019
|
-
markVNodeDirty(this.$container$, this.$hostElement$,
|
|
3118
|
+
markVNodeDirty(this.$container$, this.$hostElement$, 32 /* ChoreBits.COMPUTE */);
|
|
3020
3119
|
}
|
|
3021
3120
|
}
|
|
3022
3121
|
// if the computation not failed, we can run the effects directly
|
|
@@ -3072,59 +3171,7 @@ class SubscriptionData {
|
|
|
3072
3171
|
}
|
|
3073
3172
|
}
|
|
3074
3173
|
|
|
3075
|
-
|
|
3076
|
-
* Qwikloader provides the captures string of the QRL when calling a handler. In that case we must
|
|
3077
|
-
* load the QRL captured scope ourselves. Otherwise, we are being called as a QRL and the captures
|
|
3078
|
-
* are already set.
|
|
3079
|
-
*/
|
|
3080
|
-
const maybeScopeFromQL = (captureIds, element) => {
|
|
3081
|
-
if (typeof captureIds === 'string') {
|
|
3082
|
-
const container = getDomContainer(element);
|
|
3083
|
-
setCaptures(deserializeCaptures(container, captureIds));
|
|
3084
|
-
}
|
|
3085
|
-
return null;
|
|
3086
|
-
};
|
|
3087
|
-
/**
|
|
3088
|
-
* Handles events for bind:value
|
|
3089
|
-
*
|
|
3090
|
-
* @internal
|
|
3091
|
-
*/
|
|
3092
|
-
function _val(_, element) {
|
|
3093
|
-
maybeScopeFromQL(this, element);
|
|
3094
|
-
const signal = _captures[0];
|
|
3095
|
-
signal.value = element.type === 'number' ? element.valueAsNumber : element.value;
|
|
3096
|
-
}
|
|
3097
|
-
/**
|
|
3098
|
-
* Handles events for bind:checked
|
|
3099
|
-
*
|
|
3100
|
-
* @internal
|
|
3101
|
-
*/
|
|
3102
|
-
function _chk(_, element) {
|
|
3103
|
-
maybeScopeFromQL(this, element);
|
|
3104
|
-
const signal = _captures[0];
|
|
3105
|
-
signal.value = element.checked;
|
|
3106
|
-
}
|
|
3107
|
-
/**
|
|
3108
|
-
* Resumes selected state (e.g. polling AsyncSignals) by deserializing captures. Used for
|
|
3109
|
-
* document:onQIdle to resume async signals with active polling.
|
|
3110
|
-
*
|
|
3111
|
-
* @internal
|
|
3112
|
-
*/
|
|
3113
|
-
function _res(_, element) {
|
|
3114
|
-
maybeScopeFromQL(this, element);
|
|
3115
|
-
// Captures are deserialized, now trigger computation on AsyncSignals
|
|
3116
|
-
if (_captures) {
|
|
3117
|
-
for (let i = 0; i < _captures.length; i++) {
|
|
3118
|
-
const capture = _captures[i];
|
|
3119
|
-
if (capture instanceof AsyncSignalImpl && capture.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
|
|
3120
|
-
capture.$computeIfNeeded$();
|
|
3121
|
-
}
|
|
3122
|
-
// note that polling async signals will automatically schedule themselves so no action needed
|
|
3123
|
-
}
|
|
3124
|
-
}
|
|
3125
|
-
}
|
|
3126
|
-
|
|
3127
|
-
const _hasOwnProperty$2 = Object.prototype.hasOwnProperty;
|
|
3174
|
+
const _hasOwnProperty$3 = Object.prototype.hasOwnProperty;
|
|
3128
3175
|
// TODO store props as the arrays the vnodes also use?
|
|
3129
3176
|
class JSXNodeImpl {
|
|
3130
3177
|
type;
|
|
@@ -3180,9 +3227,9 @@ const isJSXNode = (n) => {
|
|
|
3180
3227
|
return true;
|
|
3181
3228
|
}
|
|
3182
3229
|
if (isObject(n) &&
|
|
3183
|
-
_hasOwnProperty$
|
|
3184
|
-
_hasOwnProperty$
|
|
3185
|
-
_hasOwnProperty$
|
|
3230
|
+
_hasOwnProperty$3.call(n, 'key') &&
|
|
3231
|
+
_hasOwnProperty$3.call(n, 'props') &&
|
|
3232
|
+
_hasOwnProperty$3.call(n, 'type')) {
|
|
3186
3233
|
if (isPropsProxy(n)) {
|
|
3187
3234
|
return false;
|
|
3188
3235
|
}
|
|
@@ -3196,11 +3243,63 @@ const isJSXNode = (n) => {
|
|
|
3196
3243
|
}
|
|
3197
3244
|
};
|
|
3198
3245
|
|
|
3246
|
+
/**
|
|
3247
|
+
* Qwikloader provides the captures string of the QRL when calling a handler. In that case we must
|
|
3248
|
+
* load the QRL captured scope ourselves. Otherwise, we are being called as a QRL and the captures
|
|
3249
|
+
* are already set.
|
|
3250
|
+
*/
|
|
3251
|
+
const maybeScopeFromQL = (captureIds, element) => {
|
|
3252
|
+
if (typeof captureIds === 'string') {
|
|
3253
|
+
const container = getDomContainer(element);
|
|
3254
|
+
setCaptures(deserializeCaptures(container, captureIds));
|
|
3255
|
+
}
|
|
3256
|
+
return null;
|
|
3257
|
+
};
|
|
3258
|
+
/**
|
|
3259
|
+
* Handles events for bind:value
|
|
3260
|
+
*
|
|
3261
|
+
* @internal
|
|
3262
|
+
*/
|
|
3263
|
+
function _val(_, element) {
|
|
3264
|
+
maybeScopeFromQL(this, element);
|
|
3265
|
+
const signal = _captures[0];
|
|
3266
|
+
signal.value = element.type === 'number' ? element.valueAsNumber : element.value;
|
|
3267
|
+
}
|
|
3268
|
+
/**
|
|
3269
|
+
* Handles events for bind:checked
|
|
3270
|
+
*
|
|
3271
|
+
* @internal
|
|
3272
|
+
*/
|
|
3273
|
+
function _chk(_, element) {
|
|
3274
|
+
maybeScopeFromQL(this, element);
|
|
3275
|
+
const signal = _captures[0];
|
|
3276
|
+
signal.value = element.checked;
|
|
3277
|
+
}
|
|
3278
|
+
/**
|
|
3279
|
+
* Resumes selected state (e.g. polling AsyncSignals) by deserializing captures. Used for
|
|
3280
|
+
* document:onQIdle to resume async signals with active polling.
|
|
3281
|
+
*
|
|
3282
|
+
* @internal
|
|
3283
|
+
*/
|
|
3284
|
+
function _res(_, element) {
|
|
3285
|
+
maybeScopeFromQL(this, element);
|
|
3286
|
+
// Captures are deserialized, now trigger computation on AsyncSignals
|
|
3287
|
+
if (_captures) {
|
|
3288
|
+
for (let i = 0; i < _captures.length; i++) {
|
|
3289
|
+
const capture = _captures[i];
|
|
3290
|
+
if (capture instanceof AsyncSignalImpl && capture.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
|
|
3291
|
+
capture.$computeIfNeeded$();
|
|
3292
|
+
}
|
|
3293
|
+
// note that polling async signals will automatically schedule themselves so no action needed
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3199
3298
|
const BIND_VALUE = 'bind:value';
|
|
3200
3299
|
const BIND_CHECKED = 'bind:checked';
|
|
3201
3300
|
const PASSIVE = 'passive:';
|
|
3202
3301
|
const PREVENT_DEFAULT = 'preventdefault:';
|
|
3203
|
-
const _hasOwnProperty$
|
|
3302
|
+
const _hasOwnProperty$2 = Object.prototype.hasOwnProperty;
|
|
3204
3303
|
const removePassiveMarkers = (props, passiveKeys, preventDefaultKeys, passiveEvents, canMutate = false) => {
|
|
3205
3304
|
let mutableProps = props;
|
|
3206
3305
|
let copied = canMutate;
|
|
@@ -3387,10 +3486,10 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
|
|
|
3387
3486
|
varProps ||= {};
|
|
3388
3487
|
if (bindCheckedSignal) {
|
|
3389
3488
|
// Delete from both varProps and constProps if present
|
|
3390
|
-
if (varProps && _hasOwnProperty$
|
|
3489
|
+
if (varProps && _hasOwnProperty$2.call(varProps, BIND_CHECKED)) {
|
|
3391
3490
|
delete varProps[BIND_CHECKED];
|
|
3392
3491
|
}
|
|
3393
|
-
if (constProps && _hasOwnProperty$
|
|
3492
|
+
if (constProps && _hasOwnProperty$2.call(constProps, BIND_CHECKED)) {
|
|
3394
3493
|
if (!constPropsCopied) {
|
|
3395
3494
|
constProps = { ...constProps };
|
|
3396
3495
|
constPropsCopied = true;
|
|
@@ -3400,7 +3499,7 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
|
|
|
3400
3499
|
varProps.checked = bindCheckedSignal;
|
|
3401
3500
|
const handler = createQRL(null, '_chk', _chk, null, [bindCheckedSignal]);
|
|
3402
3501
|
// Move q-e:input from constProps if it exists
|
|
3403
|
-
if (constProps && _hasOwnProperty$
|
|
3502
|
+
if (constProps && _hasOwnProperty$2.call(constProps, 'q-e:input')) {
|
|
3404
3503
|
if (!constPropsCopied) {
|
|
3405
3504
|
constProps = { ...constProps };
|
|
3406
3505
|
constPropsCopied = true;
|
|
@@ -3413,10 +3512,10 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
|
|
|
3413
3512
|
}
|
|
3414
3513
|
else if (bindValueSignal) {
|
|
3415
3514
|
// Delete from both varProps and constProps if present
|
|
3416
|
-
if (varProps && _hasOwnProperty$
|
|
3515
|
+
if (varProps && _hasOwnProperty$2.call(varProps, BIND_VALUE)) {
|
|
3417
3516
|
delete varProps[BIND_VALUE];
|
|
3418
3517
|
}
|
|
3419
|
-
if (constProps && _hasOwnProperty$
|
|
3518
|
+
if (constProps && _hasOwnProperty$2.call(constProps, BIND_VALUE)) {
|
|
3420
3519
|
if (!constPropsCopied) {
|
|
3421
3520
|
constProps = { ...constProps };
|
|
3422
3521
|
constPropsCopied = true;
|
|
@@ -3426,7 +3525,7 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
|
|
|
3426
3525
|
varProps.value = bindValueSignal;
|
|
3427
3526
|
const handler = createQRL(null, '_val', _val, null, [bindValueSignal]);
|
|
3428
3527
|
// Move q-e:input from constProps if it exists
|
|
3429
|
-
if (constProps && _hasOwnProperty$
|
|
3528
|
+
if (constProps && _hasOwnProperty$2.call(constProps, 'q-e:input')) {
|
|
3430
3529
|
if (!constPropsCopied) {
|
|
3431
3530
|
constProps = { ...constProps };
|
|
3432
3531
|
constPropsCopied = true;
|
|
@@ -3439,7 +3538,7 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
|
|
|
3439
3538
|
}
|
|
3440
3539
|
}
|
|
3441
3540
|
// Transform className -> class
|
|
3442
|
-
if (varProps && _hasOwnProperty$
|
|
3541
|
+
if (varProps && _hasOwnProperty$2.call(varProps, 'className')) {
|
|
3443
3542
|
if (!varPropsCopied) {
|
|
3444
3543
|
varProps = { ...varProps };
|
|
3445
3544
|
varPropsCopied = true;
|
|
@@ -3451,7 +3550,7 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
|
|
|
3451
3550
|
logOnceWarn(`jsx${dev ? ` ${dev.fileName}${dev?.lineNumber ? `:${dev.lineNumber}` : ''}` : ''}: \`className\` is deprecated. Use \`class\` instead.`);
|
|
3452
3551
|
}
|
|
3453
3552
|
}
|
|
3454
|
-
if (constProps && _hasOwnProperty$
|
|
3553
|
+
if (constProps && _hasOwnProperty$2.call(constProps, 'className')) {
|
|
3455
3554
|
if (!constPropsCopied) {
|
|
3456
3555
|
constProps = { ...constProps };
|
|
3457
3556
|
constPropsCopied = true;
|
|
@@ -3563,365 +3662,69 @@ const RenderOnce = (props, key) => {
|
|
|
3563
3662
|
};
|
|
3564
3663
|
|
|
3565
3664
|
/**
|
|
3566
|
-
*
|
|
3567
|
-
*
|
|
3568
|
-
* Component execution can be complex because of:
|
|
3569
|
-
*
|
|
3570
|
-
* - It can by async
|
|
3571
|
-
* - It can contain many tasks which need to be awaited
|
|
3572
|
-
* - Each task can run multiple times if they track signals which change.
|
|
3573
|
-
* - The JSX may be re-generated multiple times of a task needs to be rerun due to signal change.
|
|
3574
|
-
* - It needs to keep track of hook state.
|
|
3575
|
-
*
|
|
3576
|
-
* For `component$`: `renderHost` === `subscriptionHost` For inlined-components: the
|
|
3577
|
-
* `subscriptionHost` is a parent `component$` which needs to re-execute.
|
|
3665
|
+
* Allows to project the children of the current component. `<Slot/>` can only be used within the
|
|
3666
|
+
* context of a component defined with `component$`.
|
|
3578
3667
|
*
|
|
3579
|
-
* @
|
|
3580
|
-
* @param renderHost - VNode into which the component is rendered into.
|
|
3581
|
-
* @param subscriptionHost - VNode which will be re-executed if the component needs to re-render.
|
|
3582
|
-
* @param componentQRL
|
|
3583
|
-
* @param props
|
|
3584
|
-
* @returns
|
|
3668
|
+
* @public
|
|
3585
3669
|
*/
|
|
3586
|
-
const
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3670
|
+
const Slot = (props) => {
|
|
3671
|
+
return _jsxSorted(Virtual, null, { [QSlotS]: '' }, props.children, 0, props.name ?? '');
|
|
3672
|
+
};
|
|
3673
|
+
|
|
3674
|
+
/** @public */
|
|
3675
|
+
const SkipRender = Symbol('skip render');
|
|
3676
|
+
/** @public */
|
|
3677
|
+
const SSRRaw = () => null;
|
|
3678
|
+
/** @public */
|
|
3679
|
+
const SSRComment = () => null;
|
|
3680
|
+
/** @public */
|
|
3681
|
+
const SSRStreamBlock = (props) => {
|
|
3682
|
+
return props.children;
|
|
3683
|
+
};
|
|
3684
|
+
/** @public */
|
|
3685
|
+
const SSRStream = (props, key) => jsx(RenderOnce, { children: jsx(InternalSSRStream, props) }, key);
|
|
3686
|
+
const InternalSSRStream = () => null;
|
|
3687
|
+
|
|
3688
|
+
let _setAttribute = null;
|
|
3689
|
+
const fastSetAttribute = (target, name, value) => {
|
|
3690
|
+
if (!_setAttribute) {
|
|
3691
|
+
_setAttribute = target.setAttribute;
|
|
3591
3692
|
}
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3693
|
+
_setAttribute.call(target, name, value);
|
|
3694
|
+
};
|
|
3695
|
+
let _setAttributeNS = null;
|
|
3696
|
+
const fastSetAttributeNS = (target, namespace, name, value) => {
|
|
3697
|
+
if (!_setAttributeNS) {
|
|
3698
|
+
_setAttributeNS = target.setAttributeNS;
|
|
3598
3699
|
}
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3700
|
+
_setAttributeNS.call(target, namespace, name, value);
|
|
3701
|
+
};
|
|
3702
|
+
function directSetAttribute(element, attrName, attrValue, isSvg) {
|
|
3703
|
+
if (attrValue != null) {
|
|
3704
|
+
if (isSvg) {
|
|
3705
|
+
// only svg elements can have namespace attributes
|
|
3706
|
+
const namespace = getAttributeNamespace(attrName);
|
|
3707
|
+
if (namespace) {
|
|
3708
|
+
fastSetAttributeNS(element, namespace, attrName, attrValue);
|
|
3709
|
+
return;
|
|
3710
|
+
}
|
|
3604
3711
|
}
|
|
3605
|
-
|
|
3712
|
+
fastSetAttribute(element, attrName, attrValue);
|
|
3606
3713
|
}
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3714
|
+
}
|
|
3715
|
+
|
|
3716
|
+
function getFileLocationFromJsx(jsxDev) {
|
|
3717
|
+
if (!jsxDev) {
|
|
3718
|
+
return null;
|
|
3610
3719
|
}
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
componentFn = () => invokeApply(iCtx, inlineComponent, [props || EMPTY_OBJ]);
|
|
3615
|
-
}
|
|
3616
|
-
const isSsr = qTest ? isServerPlatform() : isServer;
|
|
3617
|
-
const executeComponentWithPromiseExceptionRetry = (retryCount = 0) => safeCall(() => {
|
|
3618
|
-
if (!isInlineComponent) {
|
|
3619
|
-
container.setHostProp(renderHost, ELEMENT_SEQ_IDX, null);
|
|
3620
|
-
container.setHostProp(renderHost, USE_ON_LOCAL_SEQ_IDX, null);
|
|
3621
|
-
}
|
|
3622
|
-
if (retryCount > 0 && vnode_isVNode(renderHost)) {
|
|
3623
|
-
clearAllEffects(container, renderHost);
|
|
3624
|
-
}
|
|
3625
|
-
return maybeThen(componentFn(props), (jsx) => maybeThen(iCtx.$waitOn$, () => jsx));
|
|
3626
|
-
}, (jsx) => {
|
|
3627
|
-
// In SSR, check if the component was marked dirty (COMPONENT bit) during execution.
|
|
3628
|
-
// This happens when something completes and updates reactive primitives
|
|
3629
|
-
// while we're waiting on $waitOn$. If so, we need to re-execute the component
|
|
3630
|
-
// to get fresh JSX with updated values.
|
|
3631
|
-
if (isSsr && !isInlineComponent) {
|
|
3632
|
-
const ssrNode = renderHost;
|
|
3633
|
-
if (ssrNode.dirty & 4 /* ChoreBits.COMPONENT */) {
|
|
3634
|
-
ssrNode.dirty &= ~4 /* ChoreBits.COMPONENT */;
|
|
3635
|
-
if (retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
3636
|
-
return executeComponentWithPromiseExceptionRetry(retryCount + 1);
|
|
3637
|
-
}
|
|
3638
|
-
}
|
|
3639
|
-
}
|
|
3640
|
-
const useOnEvents = container.getHostProp(renderHost, USE_ON_LOCAL);
|
|
3641
|
-
if (useOnEvents) {
|
|
3642
|
-
return addUseOnEvents(jsx, useOnEvents);
|
|
3643
|
-
}
|
|
3644
|
-
return jsx;
|
|
3645
|
-
}, (err) => {
|
|
3646
|
-
if (isPromise(err) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
3647
|
-
return err.then(() => executeComponentWithPromiseExceptionRetry(++retryCount));
|
|
3648
|
-
}
|
|
3649
|
-
else {
|
|
3650
|
-
if (retryCount >= MAX_RETRY_ON_PROMISE_COUNT) {
|
|
3651
|
-
throw new Error(`Max retry count of component execution reached`);
|
|
3652
|
-
}
|
|
3653
|
-
throw err;
|
|
3654
|
-
}
|
|
3655
|
-
});
|
|
3656
|
-
return executeComponentWithPromiseExceptionRetry();
|
|
3657
|
-
};
|
|
3658
|
-
/**
|
|
3659
|
-
* Adds `useOn` events to the JSX output.
|
|
3660
|
-
*
|
|
3661
|
-
* @param jsx The JSX output to modify.
|
|
3662
|
-
* @param useOnEvents The `useOn` events to add.
|
|
3663
|
-
* @returns The modified JSX output.
|
|
3664
|
-
*/
|
|
3665
|
-
function addUseOnEvents(jsx, useOnEvents) {
|
|
3666
|
-
const jsxElement = findFirstElementNode(jsx);
|
|
3667
|
-
let jsxResult = jsx;
|
|
3668
|
-
const qVisibleEvent = 'q-e:qvisible';
|
|
3669
|
-
return maybeThen(jsxElement, (jsxElement) => {
|
|
3670
|
-
// headless components are components that don't render a real DOM element
|
|
3671
|
-
const isHeadless = !jsxElement;
|
|
3672
|
-
// placeholder element is a <script> element that is used to add events to the document or window
|
|
3673
|
-
let placeholderElement = null;
|
|
3674
|
-
for (const key in useOnEvents) {
|
|
3675
|
-
if (Object.prototype.hasOwnProperty.call(useOnEvents, key)) {
|
|
3676
|
-
let targetElement = jsxElement;
|
|
3677
|
-
let eventKey = key;
|
|
3678
|
-
if (isHeadless) {
|
|
3679
|
-
// if the component is headless, we need to add the event to the placeholder element
|
|
3680
|
-
if (key === qVisibleEvent ||
|
|
3681
|
-
key.startsWith("q-d:" /* EventNameHtmlScope.document */) ||
|
|
3682
|
-
key.startsWith("q-w:" /* EventNameHtmlScope.window */)) {
|
|
3683
|
-
if (!placeholderElement) {
|
|
3684
|
-
const [createdElement, newJsx] = injectPlaceholderElement(jsxResult);
|
|
3685
|
-
jsxResult = newJsx;
|
|
3686
|
-
placeholderElement = createdElement;
|
|
3687
|
-
}
|
|
3688
|
-
targetElement = placeholderElement;
|
|
3689
|
-
}
|
|
3690
|
-
else {
|
|
3691
|
-
if (isDev) {
|
|
3692
|
-
const sourceLocation = getUseOnSourceLocation(useOnEvents[key].qrls);
|
|
3693
|
-
logWarn('You are trying to add an event "' +
|
|
3694
|
-
key +
|
|
3695
|
-
'" using `useOn` hook, ' +
|
|
3696
|
-
'but a node to which you can add an event is not found. ' +
|
|
3697
|
-
'Please make sure that the component outputs a DOM element.' +
|
|
3698
|
-
(sourceLocation ? ` Offending \`useOn\`: ${sourceLocation}.` : ''));
|
|
3699
|
-
}
|
|
3700
|
-
continue;
|
|
3701
|
-
}
|
|
3702
|
-
}
|
|
3703
|
-
if (targetElement) {
|
|
3704
|
-
if (targetElement.type === 'script' && key === qVisibleEvent) {
|
|
3705
|
-
eventKey = 'q-d:qinit';
|
|
3706
|
-
if (isDev) {
|
|
3707
|
-
const sourceLocation = getUseOnSourceLocation(useOnEvents[key].qrls);
|
|
3708
|
-
logWarn(`You are trying to add the event "${key}" ` +
|
|
3709
|
-
'using the `useVisibleTask$` hook with the "intersection-observer" strategy, ' +
|
|
3710
|
-
'but this only works when the component outputs a DOM element. Falling back to ' +
|
|
3711
|
-
'"document-ready" instead.' +
|
|
3712
|
-
(sourceLocation ? ` Offending \`useVisibleTask$\`: ${sourceLocation}.` : ''));
|
|
3713
|
-
}
|
|
3714
|
-
}
|
|
3715
|
-
addUseOnEvent(targetElement, eventKey, useOnEvents[key]);
|
|
3716
|
-
}
|
|
3717
|
-
}
|
|
3718
|
-
}
|
|
3719
|
-
return jsxResult;
|
|
3720
|
-
});
|
|
3721
|
-
}
|
|
3722
|
-
function getUseOnSourceLocation(eventQrls) {
|
|
3723
|
-
for (let i = 0; i < eventQrls.length; i++) {
|
|
3724
|
-
const eventQrl = eventQrls[i];
|
|
3725
|
-
const task = eventQrl?.getCaptured()?.[0];
|
|
3726
|
-
if (isTask(task)) {
|
|
3727
|
-
const dev = task.$qrl$.dev;
|
|
3728
|
-
if (dev?.file) {
|
|
3729
|
-
return typeof dev.lo === 'number' && typeof dev.hi === 'number'
|
|
3730
|
-
? `${dev.file}:${dev.lo}-${dev.hi}`
|
|
3731
|
-
: dev.file;
|
|
3732
|
-
}
|
|
3733
|
-
}
|
|
3734
|
-
}
|
|
3735
|
-
return null;
|
|
3736
|
-
}
|
|
3737
|
-
/**
|
|
3738
|
-
* Adds an event to the JSX element.
|
|
3739
|
-
*
|
|
3740
|
-
* @param jsxElement The JSX element to add the event to.
|
|
3741
|
-
* @param key The event name.
|
|
3742
|
-
* @param value The event value.
|
|
3743
|
-
*/
|
|
3744
|
-
function addUseOnEvent(jsxElement, key, value) {
|
|
3745
|
-
// These handlers are always there, so they go in constProps
|
|
3746
|
-
const props = (jsxElement.constProps ||= {});
|
|
3747
|
-
const propValue = props[key];
|
|
3748
|
-
const qrls = value.qrls;
|
|
3749
|
-
if (propValue == null) {
|
|
3750
|
-
props[key] = qrls;
|
|
3751
|
-
}
|
|
3752
|
-
else if (Array.isArray(propValue)) {
|
|
3753
|
-
propValue.push(...qrls);
|
|
3754
|
-
}
|
|
3755
|
-
else {
|
|
3756
|
-
props[key] = [propValue, ...qrls];
|
|
3757
|
-
}
|
|
3758
|
-
const varProp = jsxElement.varProps[key];
|
|
3759
|
-
if (varProp) {
|
|
3760
|
-
// we need to demote the handlers to varProps
|
|
3761
|
-
if (Array.isArray(propValue)) {
|
|
3762
|
-
propValue.push(...props[key]);
|
|
3763
|
-
}
|
|
3764
|
-
else {
|
|
3765
|
-
jsxElement.varProps[key] = [propValue, ...qrls];
|
|
3766
|
-
}
|
|
3767
|
-
props[key] = undefined;
|
|
3768
|
-
}
|
|
3769
|
-
const capture = value.capture;
|
|
3770
|
-
const preventdefault = value.preventdefault;
|
|
3771
|
-
const stoppropagation = value.stoppropagation;
|
|
3772
|
-
if (!capture && !preventdefault && !stoppropagation) {
|
|
3773
|
-
return;
|
|
3774
|
-
}
|
|
3775
|
-
const [, eventName] = getEventDataFromHtmlAttribute(key);
|
|
3776
|
-
capture && addUseOnModifier(jsxElement, eventName, 'capture');
|
|
3777
|
-
preventdefault && addUseOnModifier(jsxElement, eventName, 'preventdefault');
|
|
3778
|
-
stoppropagation && addUseOnModifier(jsxElement, eventName, 'stoppropagation');
|
|
3779
|
-
}
|
|
3780
|
-
function addUseOnModifier(jsxElement, eventName, modifier) {
|
|
3781
|
-
const key = `${modifier}:${eventName}`;
|
|
3782
|
-
const varProps = jsxElement.varProps;
|
|
3783
|
-
if (varProps === EMPTY_OBJ) {
|
|
3784
|
-
jsxElement.varProps = {};
|
|
3785
|
-
}
|
|
3786
|
-
jsxElement.varProps[key] = true;
|
|
3787
|
-
}
|
|
3788
|
-
/**
|
|
3789
|
-
* Finds the first element node in the JSX output.
|
|
3790
|
-
*
|
|
3791
|
-
* @param jsx The JSX output to search.
|
|
3792
|
-
* @returns The first element node or null if no element node is found.
|
|
3793
|
-
*/
|
|
3794
|
-
function findFirstElementNode(jsx) {
|
|
3795
|
-
const queue = [jsx];
|
|
3796
|
-
while (queue.length) {
|
|
3797
|
-
const jsx = queue.shift();
|
|
3798
|
-
if (isJSXNode(jsx)) {
|
|
3799
|
-
if (typeof jsx.type === 'string') {
|
|
3800
|
-
return jsx;
|
|
3801
|
-
}
|
|
3802
|
-
queue.push(jsx.children);
|
|
3803
|
-
}
|
|
3804
|
-
else if (isArray(jsx)) {
|
|
3805
|
-
queue.push(...jsx);
|
|
3806
|
-
}
|
|
3807
|
-
else if (isPromise(jsx)) {
|
|
3808
|
-
return maybeThen(jsx, (jsx) => findFirstElementNode(jsx));
|
|
3809
|
-
}
|
|
3810
|
-
else if (isSignal(jsx)) {
|
|
3811
|
-
return findFirstElementNode(jsx.untrackedValue);
|
|
3812
|
-
}
|
|
3813
|
-
}
|
|
3814
|
-
return null;
|
|
3815
|
-
}
|
|
3816
|
-
/**
|
|
3817
|
-
* Injects a placeholder <script> element into the JSX output.
|
|
3818
|
-
*
|
|
3819
|
-
* This is necessary for headless components (components that don't render a real DOM element) to
|
|
3820
|
-
* have an anchor point for `useOn` event listeners that target the document or window.
|
|
3821
|
-
*
|
|
3822
|
-
* @param jsx The JSX output to modify.
|
|
3823
|
-
* @returns A tuple containing the created placeholder element and the modified JSX output.
|
|
3824
|
-
*/
|
|
3825
|
-
function injectPlaceholderElement(jsx) {
|
|
3826
|
-
// For regular JSX nodes, we can append the placeholder to its children.
|
|
3827
|
-
if (isJSXNode(jsx)) {
|
|
3828
|
-
const placeholder = createPlaceholderScriptNode();
|
|
3829
|
-
// Inline components don't always render children, so we wrap them in Fragment which does.
|
|
3830
|
-
if (jsx.type !== Fragment && !isQwikComponent(jsx.type)) {
|
|
3831
|
-
return [placeholder, _jsxSorted(Fragment, null, null, [jsx, placeholder], 0, null)];
|
|
3832
|
-
}
|
|
3833
|
-
if (jsx.children == null) {
|
|
3834
|
-
jsx.children = placeholder;
|
|
3835
|
-
}
|
|
3836
|
-
else if (isArray(jsx.children)) {
|
|
3837
|
-
jsx.children.push(placeholder);
|
|
3838
|
-
}
|
|
3839
|
-
else {
|
|
3840
|
-
jsx.children = [jsx.children, placeholder];
|
|
3841
|
-
}
|
|
3842
|
-
return [placeholder, jsx];
|
|
3843
|
-
}
|
|
3844
|
-
// For primitives, we can't add children, so we wrap them in a fragment.
|
|
3845
|
-
if (isPrimitiveOrNullUndefined(jsx)) {
|
|
3846
|
-
const placeholder = createPlaceholderScriptNode();
|
|
3847
|
-
return [placeholder, _jsxSorted(Fragment, null, null, [jsx, placeholder], 0, null)];
|
|
3848
|
-
}
|
|
3849
|
-
// For an array of nodes, we inject the placeholder into the first element.
|
|
3850
|
-
if (isArray(jsx) && jsx.length > 0) {
|
|
3851
|
-
const [createdElement, _] = injectPlaceholderElement(jsx[0]);
|
|
3852
|
-
return [createdElement, jsx];
|
|
3853
|
-
}
|
|
3854
|
-
// For anything else we do nothing.
|
|
3855
|
-
return [null, jsx];
|
|
3856
|
-
}
|
|
3857
|
-
/** @returns An empty <script> element for adding qwik metadata attributes to */
|
|
3858
|
-
function createPlaceholderScriptNode() {
|
|
3859
|
-
return new JSXNodeImpl('script', null, { hidden: '' }, null, 0, null);
|
|
3860
|
-
}
|
|
3861
|
-
|
|
3862
|
-
/**
|
|
3863
|
-
* Allows to project the children of the current component. `<Slot/>` can only be used within the
|
|
3864
|
-
* context of a component defined with `component$`.
|
|
3865
|
-
*
|
|
3866
|
-
* @public
|
|
3867
|
-
*/
|
|
3868
|
-
const Slot = (props) => {
|
|
3869
|
-
return _jsxSorted(Virtual, null, { [QSlotS]: '' }, props.children, 0, props.name ?? '');
|
|
3870
|
-
};
|
|
3871
|
-
|
|
3872
|
-
/** @public */
|
|
3873
|
-
const SkipRender = Symbol('skip render');
|
|
3874
|
-
/** @public */
|
|
3875
|
-
const SSRRaw = () => null;
|
|
3876
|
-
/** @public */
|
|
3877
|
-
const SSRComment = () => null;
|
|
3878
|
-
/** @public */
|
|
3879
|
-
const SSRStreamBlock = (props) => {
|
|
3880
|
-
return props.children;
|
|
3881
|
-
};
|
|
3882
|
-
/** @public */
|
|
3883
|
-
const SSRStream = (props, key) => jsx(RenderOnce, { children: jsx(InternalSSRStream, props) }, key);
|
|
3884
|
-
const InternalSSRStream = () => null;
|
|
3885
|
-
|
|
3886
|
-
let _setAttribute = null;
|
|
3887
|
-
const fastSetAttribute = (target, name, value) => {
|
|
3888
|
-
if (!_setAttribute) {
|
|
3889
|
-
_setAttribute = target.setAttribute;
|
|
3890
|
-
}
|
|
3891
|
-
_setAttribute.call(target, name, value);
|
|
3892
|
-
};
|
|
3893
|
-
let _setAttributeNS = null;
|
|
3894
|
-
const fastSetAttributeNS = (target, namespace, name, value) => {
|
|
3895
|
-
if (!_setAttributeNS) {
|
|
3896
|
-
_setAttributeNS = target.setAttributeNS;
|
|
3897
|
-
}
|
|
3898
|
-
_setAttributeNS.call(target, namespace, name, value);
|
|
3899
|
-
};
|
|
3900
|
-
function directSetAttribute(element, attrName, attrValue, isSvg) {
|
|
3901
|
-
if (attrValue != null) {
|
|
3902
|
-
if (isSvg) {
|
|
3903
|
-
// only svg elements can have namespace attributes
|
|
3904
|
-
const namespace = getAttributeNamespace(attrName);
|
|
3905
|
-
if (namespace) {
|
|
3906
|
-
fastSetAttributeNS(element, namespace, attrName, attrValue);
|
|
3907
|
-
return;
|
|
3908
|
-
}
|
|
3909
|
-
}
|
|
3910
|
-
fastSetAttribute(element, attrName, attrValue);
|
|
3911
|
-
}
|
|
3912
|
-
}
|
|
3913
|
-
|
|
3914
|
-
function getFileLocationFromJsx(jsxDev) {
|
|
3915
|
-
if (!jsxDev) {
|
|
3916
|
-
return null;
|
|
3917
|
-
}
|
|
3918
|
-
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
3919
|
-
if (sanitizedFileName) {
|
|
3920
|
-
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
3720
|
+
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
3721
|
+
if (sanitizedFileName) {
|
|
3722
|
+
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
3921
3723
|
}
|
|
3922
3724
|
return null;
|
|
3923
3725
|
}
|
|
3924
3726
|
|
|
3727
|
+
const _hasOwnProperty$1 = Object.prototype.hasOwnProperty;
|
|
3925
3728
|
function isSlotProp(prop) {
|
|
3926
3729
|
return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
|
|
3927
3730
|
}
|
|
@@ -3946,6 +3749,16 @@ const _restProps = (props, omit = [], target = {}) => {
|
|
|
3946
3749
|
}
|
|
3947
3750
|
return createPropsProxy(new JSXNodeImpl(null, varPropsTarget, constPropsTarget, null, 0, null));
|
|
3948
3751
|
};
|
|
3752
|
+
function resolveSlotName(host, jsx, container) {
|
|
3753
|
+
const constProps = jsx.constProps;
|
|
3754
|
+
if (constProps && typeof constProps == 'object' && _hasOwnProperty$1.call(constProps, 'name')) {
|
|
3755
|
+
const constValue = constProps.name;
|
|
3756
|
+
if (host && constValue instanceof WrappedSignalImpl) {
|
|
3757
|
+
return trackSignalAndAssignHost(constValue, host, ":" /* EffectProperty.COMPONENT */, container);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
return directGetPropsProxyProp(jsx, 'name') || QDefaultSlot;
|
|
3761
|
+
}
|
|
3949
3762
|
|
|
3950
3763
|
class DeleteOperation {
|
|
3951
3764
|
target;
|
|
@@ -4172,14 +3985,14 @@ function getNearestCursorBoundaryProp(vNode) {
|
|
|
4172
3985
|
if (!__EXPERIMENTAL__.suspense) {
|
|
4173
3986
|
return null;
|
|
4174
3987
|
}
|
|
4175
|
-
return (vnode_getProp(vNode,
|
|
3988
|
+
return (vnode_getProp(vNode, NEAREST_CURSOR_BOUNDARY, null) ||
|
|
4176
3989
|
null);
|
|
4177
3990
|
}
|
|
4178
3991
|
function clearNearestCursorBoundary(vNode) {
|
|
4179
3992
|
if (!__EXPERIMENTAL__.suspense) {
|
|
4180
3993
|
return;
|
|
4181
3994
|
}
|
|
4182
|
-
vnode_setProp(vNode,
|
|
3995
|
+
vnode_setProp(vNode, NEAREST_CURSOR_BOUNDARY, null);
|
|
4183
3996
|
}
|
|
4184
3997
|
function getNearestCursorBoundary(container, vNode) {
|
|
4185
3998
|
if (!__EXPERIMENTAL__.suspense) {
|
|
@@ -4188,7 +4001,7 @@ function getNearestCursorBoundary(container, vNode) {
|
|
|
4188
4001
|
return getNearestCursorBoundaryProp(vNode) || getOwnCursorBoundary(container, vNode);
|
|
4189
4002
|
}
|
|
4190
4003
|
function setNearestCursorBoundary(vNode, boundary) {
|
|
4191
|
-
__EXPERIMENTAL__.suspense && vnode_setProp(vNode,
|
|
4004
|
+
__EXPERIMENTAL__.suspense && vnode_setProp(vNode, NEAREST_CURSOR_BOUNDARY, boundary);
|
|
4192
4005
|
}
|
|
4193
4006
|
/** Updates the nearest cursor boundary cache on a vnode and any already-dirty descendants. */
|
|
4194
4007
|
function updateDirtySubtreeCursorBoundary(container, vNode, boundary) {
|
|
@@ -4732,7 +4545,7 @@ function expectProjection(diffContext) {
|
|
|
4732
4545
|
function expectSlot(diffContext) {
|
|
4733
4546
|
const jsxNode = diffContext.$jsxValue$;
|
|
4734
4547
|
const vHost = vnode_getProjectionParentComponent(diffContext.$vParent$);
|
|
4735
|
-
const slotNameKey =
|
|
4548
|
+
const slotNameKey = resolveSlotName(vHost, jsxNode, diffContext.$container$);
|
|
4736
4549
|
const cursorBoundary = directGetPropsProxyProp(jsxNode, QCursorBoundary) || null;
|
|
4737
4550
|
const vProjectedNode = vHost
|
|
4738
4551
|
? vnode_getProp(vHost, slotNameKey,
|
|
@@ -4775,17 +4588,6 @@ function expectSlot(diffContext) {
|
|
|
4775
4588
|
}
|
|
4776
4589
|
return true;
|
|
4777
4590
|
}
|
|
4778
|
-
function getSlotNameKey(diffContext, vHost) {
|
|
4779
|
-
const jsxNode = diffContext.$jsxValue$;
|
|
4780
|
-
const constProps = jsxNode.constProps;
|
|
4781
|
-
if (constProps && typeof constProps == 'object' && _hasOwnProperty.call(constProps, 'name')) {
|
|
4782
|
-
const constValue = constProps.name;
|
|
4783
|
-
if (vHost && constValue instanceof WrappedSignalImpl) {
|
|
4784
|
-
return trackSignalAndAssignHost(constValue, vHost, ":" /* EffectProperty.COMPONENT */, diffContext.$container$);
|
|
4785
|
-
}
|
|
4786
|
-
}
|
|
4787
|
-
return directGetPropsProxyProp(jsxNode, 'name') || QDefaultSlot;
|
|
4788
|
-
}
|
|
4789
4591
|
function cleanupSideBuffer(diffContext) {
|
|
4790
4592
|
const sideBuffer = diffContext.$vSideBuffer$;
|
|
4791
4593
|
if (sideBuffer) {
|
|
@@ -5161,603 +4963,910 @@ function retrieveChildWithKey(diffContext, nodeName, key) {
|
|
|
5161
4963
|
diffContext.$vSiblings$.set(getSideBufferKey(name, vKey), vNode);
|
|
5162
4964
|
}
|
|
5163
4965
|
}
|
|
5164
|
-
vNode = vNode.nextSibling;
|
|
4966
|
+
vNode = vNode.nextSibling;
|
|
4967
|
+
}
|
|
4968
|
+
}
|
|
4969
|
+
else {
|
|
4970
|
+
if (key === null) {
|
|
4971
|
+
for (let i = 0; i < diffContext.$vSiblingsArray$.length; i += 2) {
|
|
4972
|
+
if (diffContext.$vSiblingsArray$[i] === nodeName) {
|
|
4973
|
+
vNodeWithKey = diffContext.$vSiblingsArray$[i + 1];
|
|
4974
|
+
diffContext.$vSiblingsArray$.splice(i, 2);
|
|
4975
|
+
break;
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
}
|
|
4979
|
+
else {
|
|
4980
|
+
const siblingsKey = getSideBufferKey(nodeName, key);
|
|
4981
|
+
const sibling = diffContext.$vSiblings$.get(siblingsKey);
|
|
4982
|
+
if (sibling) {
|
|
4983
|
+
vNodeWithKey = sibling;
|
|
4984
|
+
diffContext.$vSiblings$.delete(siblingsKey);
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4988
|
+
collectSideBufferSiblings(diffContext, vNodeWithKey);
|
|
4989
|
+
return vNodeWithKey;
|
|
4990
|
+
}
|
|
4991
|
+
function collectSideBufferSiblings(diffContext, targetNode) {
|
|
4992
|
+
if (!targetNode) {
|
|
4993
|
+
if (diffContext.$vCurrent$) {
|
|
4994
|
+
const name = vnode_isElementVNode(diffContext.$vCurrent$)
|
|
4995
|
+
? vnode_getElementName(diffContext.$vCurrent$)
|
|
4996
|
+
: null;
|
|
4997
|
+
const vKey = getKey(diffContext.$vCurrent$) ||
|
|
4998
|
+
getComponentHash(diffContext.$vCurrent$, diffContext.$container$.$getObjectById$);
|
|
4999
|
+
if (vKey != null) {
|
|
5000
|
+
const sideBufferKey = getSideBufferKey(name, vKey);
|
|
5001
|
+
diffContext.$vSideBuffer$ ||= new Map();
|
|
5002
|
+
diffContext.$vSideBuffer$.set(sideBufferKey, diffContext.$vCurrent$);
|
|
5003
|
+
diffContext.$vSiblings$?.delete(sideBufferKey);
|
|
5004
|
+
}
|
|
5005
|
+
}
|
|
5006
|
+
return;
|
|
5007
|
+
}
|
|
5008
|
+
// Walk from vCurrent up to the target node and collect all keyed siblings
|
|
5009
|
+
const boundary = getLevelBoundary(diffContext);
|
|
5010
|
+
let vNode = diffContext.$vCurrent$;
|
|
5011
|
+
while (vNode && vNode !== targetNode && vNode !== boundary) {
|
|
5012
|
+
const name = vnode_isElementVNode(vNode) ? vnode_getElementName(vNode) : null;
|
|
5013
|
+
const vKey = getKey(vNode) ||
|
|
5014
|
+
getComponentHash(vNode, diffContext.$container$.$getObjectById$);
|
|
5015
|
+
if (vKey != null) {
|
|
5016
|
+
const sideBufferKey = getSideBufferKey(name, vKey);
|
|
5017
|
+
diffContext.$vSideBuffer$ ||= new Map();
|
|
5018
|
+
diffContext.$vSideBuffer$.set(sideBufferKey, vNode);
|
|
5019
|
+
diffContext.$vSiblings$?.delete(sideBufferKey);
|
|
5020
|
+
}
|
|
5021
|
+
vNode = vNode.nextSibling;
|
|
5022
|
+
}
|
|
5023
|
+
}
|
|
5024
|
+
function getSideBufferKey(nodeName, key) {
|
|
5025
|
+
if (key == null) {
|
|
5026
|
+
return null;
|
|
5027
|
+
}
|
|
5028
|
+
return nodeName ? nodeName + ':' + key : key;
|
|
5029
|
+
}
|
|
5030
|
+
function deleteFromSideBuffer(diffContext, nodeName, key) {
|
|
5031
|
+
const sbKey = getSideBufferKey(nodeName, key);
|
|
5032
|
+
if (sbKey && diffContext.$vSideBuffer$?.has(sbKey)) {
|
|
5033
|
+
diffContext.$vSideBuffer$.delete(sbKey);
|
|
5034
|
+
return true;
|
|
5035
|
+
}
|
|
5036
|
+
return false;
|
|
5037
|
+
}
|
|
5038
|
+
/**
|
|
5039
|
+
* Shared utility to resolve a keyed node by:
|
|
5040
|
+
*
|
|
5041
|
+
* 1. Scanning forward siblings via `retrieveChildWithKey`
|
|
5042
|
+
* 2. Falling back to the side buffer using the provided `sideBufferKey`
|
|
5043
|
+
* 3. Creating a new node via `createNew` when not found
|
|
5044
|
+
*
|
|
5045
|
+
* If a node is moved from the side buffer, it is inserted before `vCurrent` under
|
|
5046
|
+
* `parentForInsert`. The function updates `vCurrent`/`vNewNode` accordingly and returns the value
|
|
5047
|
+
* from `createNew` when a new node is created.
|
|
5048
|
+
*/
|
|
5049
|
+
function moveOrCreateKeyedNode(diffContext, nodeName, lookupKey, sideBufferKey, parentForInsert, addCurrentToSideBufferOnSideInsert) {
|
|
5050
|
+
// 1) Try to find the node among upcoming siblings
|
|
5051
|
+
diffContext.$vNewNode$ = retrieveChildWithKey(diffContext, nodeName, lookupKey);
|
|
5052
|
+
if (diffContext.$vNewNode$) {
|
|
5053
|
+
if (!sideBufferKey) {
|
|
5054
|
+
vnode_insertBefore(diffContext.$journal$, parentForInsert, diffContext.$vNewNode$, getCurrentInsertBefore(diffContext));
|
|
5055
|
+
}
|
|
5056
|
+
diffContext.$vCurrent$ = diffContext.$vNewNode$;
|
|
5057
|
+
diffContext.$vNewNode$ = null;
|
|
5058
|
+
return false;
|
|
5059
|
+
}
|
|
5060
|
+
// 2) Try side buffer
|
|
5061
|
+
if (sideBufferKey != null) {
|
|
5062
|
+
const buffered = diffContext.$vSideBuffer$?.get(sideBufferKey) || null;
|
|
5063
|
+
if (buffered) {
|
|
5064
|
+
diffContext.$vSideBuffer$.delete(sideBufferKey);
|
|
5065
|
+
if (addCurrentToSideBufferOnSideInsert && diffContext.$vCurrent$) {
|
|
5066
|
+
const currentKey = getKey(diffContext.$vCurrent$) ||
|
|
5067
|
+
getComponentHash(diffContext.$vCurrent$, diffContext.$container$.$getObjectById$);
|
|
5068
|
+
if (currentKey != null) {
|
|
5069
|
+
const currentName = vnode_isElementVNode(diffContext.$vCurrent$)
|
|
5070
|
+
? vnode_getElementName(diffContext.$vCurrent$)
|
|
5071
|
+
: null;
|
|
5072
|
+
const currentSideKey = getSideBufferKey(currentName, currentKey);
|
|
5073
|
+
if (currentSideKey != null) {
|
|
5074
|
+
diffContext.$vSideBuffer$ ||= new Map();
|
|
5075
|
+
diffContext.$vSideBuffer$.set(currentSideKey, diffContext.$vCurrent$);
|
|
5076
|
+
}
|
|
5077
|
+
}
|
|
5078
|
+
}
|
|
5079
|
+
// Only move if the node is not already in the correct position
|
|
5080
|
+
if (buffered !== diffContext.$vCurrent$) {
|
|
5081
|
+
vnode_insertBefore(diffContext.$journal$, parentForInsert, buffered, getCurrentInsertBefore(diffContext));
|
|
5082
|
+
}
|
|
5083
|
+
diffContext.$vCurrent$ = buffered;
|
|
5084
|
+
diffContext.$vNewNode$ = null;
|
|
5085
|
+
return false;
|
|
5086
|
+
}
|
|
5087
|
+
}
|
|
5088
|
+
// 3) Create new
|
|
5089
|
+
return true;
|
|
5090
|
+
}
|
|
5091
|
+
function expectVirtual(diffContext, type, jsxKey) {
|
|
5092
|
+
const checkKey = type === "F" /* VirtualType.Fragment */;
|
|
5093
|
+
const currentKey = getKey(diffContext.$vCurrent$);
|
|
5094
|
+
const currentIsVirtual = diffContext.$vCurrent$ && vnode_isVirtualVNode(diffContext.$vCurrent$);
|
|
5095
|
+
const isSameNode = currentIsVirtual && currentKey === jsxKey && (checkKey ? !!jsxKey : true);
|
|
5096
|
+
if (isSameNode) {
|
|
5097
|
+
// All is good.
|
|
5098
|
+
deleteFromSideBuffer(diffContext, null, currentKey);
|
|
5099
|
+
return;
|
|
5100
|
+
}
|
|
5101
|
+
// For fragments without a key, always create a new virtual node (ensures rerender semantics)
|
|
5102
|
+
if (jsxKey === null || diffContext.$isCreationMode$) {
|
|
5103
|
+
vnode_insertVirtualBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newVirtual()), getInsertBefore(diffContext));
|
|
5104
|
+
diffContext.$vNewNode$.key = jsxKey;
|
|
5105
|
+
isDev && vnode_setProp(diffContext.$vNewNode$, DEBUG_TYPE, type);
|
|
5106
|
+
return;
|
|
5107
|
+
}
|
|
5108
|
+
if (moveOrCreateKeyedNode(diffContext, null, jsxKey, getSideBufferKey(null, jsxKey), diffContext.$vParent$, true)) {
|
|
5109
|
+
vnode_insertVirtualBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newVirtual()), getInsertBefore(diffContext));
|
|
5110
|
+
diffContext.$vNewNode$.key = jsxKey;
|
|
5111
|
+
isDev && vnode_setProp(diffContext.$vNewNode$, DEBUG_TYPE, type);
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
function expectComponent(diffContext, component) {
|
|
5115
|
+
const componentMeta = component[SERIALIZABLE_STATE];
|
|
5116
|
+
let host = (diffContext.$vNewNode$ || diffContext.$vCurrent$);
|
|
5117
|
+
const jsxNode = diffContext.$jsxValue$;
|
|
5118
|
+
if (componentMeta) {
|
|
5119
|
+
const jsxProps = jsxNode.props;
|
|
5120
|
+
// QComponent
|
|
5121
|
+
let shouldRender = false;
|
|
5122
|
+
const [componentQRL] = componentMeta;
|
|
5123
|
+
const componentHash = componentQRL.$hash$;
|
|
5124
|
+
const vNodeComponentHash = getComponentHash(host, diffContext.$container$.$getObjectById$);
|
|
5125
|
+
const lookupKey = jsxNode.key || componentHash;
|
|
5126
|
+
const vNodeLookupKey = getKey(host) || vNodeComponentHash;
|
|
5127
|
+
const lookupKeysAreEqual = lookupKey === vNodeLookupKey;
|
|
5128
|
+
const hashesAreEqual = componentHash === vNodeComponentHash;
|
|
5129
|
+
if (lookupKeysAreEqual) {
|
|
5130
|
+
if (hashesAreEqual) {
|
|
5131
|
+
deleteFromSideBuffer(diffContext, null, lookupKey);
|
|
5132
|
+
}
|
|
5133
|
+
else {
|
|
5134
|
+
insertNewComponent(diffContext, host, componentQRL, jsxProps);
|
|
5135
|
+
host = diffContext.$vNewNode$;
|
|
5136
|
+
shouldRender = true;
|
|
5137
|
+
}
|
|
5138
|
+
}
|
|
5139
|
+
else {
|
|
5140
|
+
if (moveOrCreateKeyedNode(diffContext, null, lookupKey, lookupKey, diffContext.$vParent$)) {
|
|
5141
|
+
insertNewComponent(diffContext, host, componentQRL, jsxProps);
|
|
5142
|
+
shouldRender = true;
|
|
5143
|
+
}
|
|
5144
|
+
host = (diffContext.$vNewNode$ || diffContext.$vCurrent$);
|
|
5145
|
+
}
|
|
5146
|
+
if (host) {
|
|
5147
|
+
const vNodeProps = vnode_getProp(host, ELEMENT_PROPS, diffContext.$container$.$getObjectById$);
|
|
5148
|
+
if (!shouldRender) {
|
|
5149
|
+
const propsChanged = handleProps(host, jsxProps, vNodeProps, diffContext.$container$);
|
|
5150
|
+
// if props changed but key is null we need to insert a new component, because we need to execute hooks etc
|
|
5151
|
+
if (propsChanged && jsxNode.key == null) {
|
|
5152
|
+
insertNewComponent(diffContext, host, componentQRL, jsxProps);
|
|
5153
|
+
host = diffContext.$vNewNode$;
|
|
5154
|
+
shouldRender = true;
|
|
5155
|
+
}
|
|
5156
|
+
shouldRender ||= propsChanged;
|
|
5157
|
+
}
|
|
5158
|
+
if (shouldRender) {
|
|
5159
|
+
// Assign the new QRL instance to the host.
|
|
5160
|
+
// Unfortunately it is created every time, something to fix in the optimizer.
|
|
5161
|
+
vnode_setProp(host, OnRenderProp, componentQRL);
|
|
5162
|
+
/**
|
|
5163
|
+
* Mark host as not deleted. The host could have been marked as deleted if it there was a
|
|
5164
|
+
* cleanup run. Now we found it and want to reuse it, so we need to mark it as not deleted.
|
|
5165
|
+
*/
|
|
5166
|
+
host.flags &= -33 /* VNodeFlags.Deleted */;
|
|
5167
|
+
markVNodeDirty(diffContext.$container$, host, 4 /* ChoreBits.COMPONENT */, diffContext.$cursor$);
|
|
5168
|
+
}
|
|
5165
5169
|
}
|
|
5170
|
+
descendContentToProject(diffContext, jsxNode.children, host);
|
|
5166
5171
|
}
|
|
5167
5172
|
else {
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5173
|
+
const lookupKey = jsxNode.key;
|
|
5174
|
+
const vNodeLookupKey = getKey(host);
|
|
5175
|
+
const lookupKeysAreEqual = lookupKey === vNodeLookupKey;
|
|
5176
|
+
const vNodeComponentHash = getComponentHash(host, diffContext.$container$.$getObjectById$);
|
|
5177
|
+
const isInlineComponent = vNodeComponentHash == null;
|
|
5178
|
+
if ((host && !isInlineComponent) || !host) {
|
|
5179
|
+
insertNewInlineComponent(diffContext);
|
|
5180
|
+
host = diffContext.$vNewNode$;
|
|
5181
|
+
}
|
|
5182
|
+
else if (!lookupKeysAreEqual) {
|
|
5183
|
+
if (moveOrCreateKeyedNode(diffContext, null, lookupKey, lookupKey, diffContext.$vParent$)) {
|
|
5184
|
+
// We did not find the inline component, create it.
|
|
5185
|
+
insertNewInlineComponent(diffContext);
|
|
5175
5186
|
}
|
|
5187
|
+
host = (diffContext.$vNewNode$ || diffContext.$vCurrent$);
|
|
5176
5188
|
}
|
|
5177
5189
|
else {
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5190
|
+
// delete the key from the side buffer if it is the same component
|
|
5191
|
+
deleteFromSideBuffer(diffContext, null, lookupKey);
|
|
5192
|
+
}
|
|
5193
|
+
if (host) {
|
|
5194
|
+
let componentHost = host;
|
|
5195
|
+
// Find the closest component host which has `OnRender` prop. This is need for subscriptions context.
|
|
5196
|
+
while (componentHost &&
|
|
5197
|
+
(vnode_isVirtualVNode(componentHost)
|
|
5198
|
+
? vnode_getProp(componentHost, OnRenderProp, null) === null
|
|
5199
|
+
: true)) {
|
|
5200
|
+
componentHost = componentHost.parent || vnode_getProjectionParentComponent(componentHost);
|
|
5183
5201
|
}
|
|
5202
|
+
setInlineComponentData(host, component, componentHost, jsxNode.props);
|
|
5203
|
+
markVNodeDirty(diffContext.$container$, host, 8 /* ChoreBits.INLINE_COMPONENT */, diffContext.$cursor$);
|
|
5184
5204
|
}
|
|
5185
5205
|
}
|
|
5186
|
-
collectSideBufferSiblings(diffContext, vNodeWithKey);
|
|
5187
|
-
return vNodeWithKey;
|
|
5188
5206
|
}
|
|
5189
|
-
function
|
|
5190
|
-
if (
|
|
5191
|
-
|
|
5192
|
-
const name = vnode_isElementVNode(diffContext.$vCurrent$)
|
|
5193
|
-
? vnode_getElementName(diffContext.$vCurrent$)
|
|
5194
|
-
: null;
|
|
5195
|
-
const vKey = getKey(diffContext.$vCurrent$) ||
|
|
5196
|
-
getComponentHash(diffContext.$vCurrent$, diffContext.$container$.$getObjectById$);
|
|
5197
|
-
if (vKey != null) {
|
|
5198
|
-
const sideBufferKey = getSideBufferKey(name, vKey);
|
|
5199
|
-
diffContext.$vSideBuffer$ ||= new Map();
|
|
5200
|
-
diffContext.$vSideBuffer$.set(sideBufferKey, diffContext.$vCurrent$);
|
|
5201
|
-
diffContext.$vSiblings$?.delete(sideBufferKey);
|
|
5202
|
-
}
|
|
5203
|
-
}
|
|
5204
|
-
return;
|
|
5207
|
+
function insertNewComponent(diffContext, host, componentQRL, jsxProps) {
|
|
5208
|
+
if (host) {
|
|
5209
|
+
clearAllEffects(diffContext.$container$, host);
|
|
5205
5210
|
}
|
|
5206
|
-
|
|
5207
|
-
const
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5211
|
+
vnode_insertVirtualBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newVirtual()), getInsertBefore(diffContext));
|
|
5212
|
+
const jsxNode = diffContext.$jsxValue$;
|
|
5213
|
+
isDev && vnode_setProp(diffContext.$vNewNode$, DEBUG_TYPE, "C" /* VirtualType.Component */);
|
|
5214
|
+
vnode_setProp(diffContext.$vNewNode$, OnRenderProp, componentQRL);
|
|
5215
|
+
vnode_setProp(diffContext.$vNewNode$, ELEMENT_PROPS, jsxProps);
|
|
5216
|
+
diffContext.$vNewNode$.key = jsxNode.key;
|
|
5217
|
+
}
|
|
5218
|
+
function insertNewInlineComponent(diffContext) {
|
|
5219
|
+
vnode_insertVirtualBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newVirtual()), getInsertBefore(diffContext));
|
|
5220
|
+
const jsxNode = diffContext.$jsxValue$;
|
|
5221
|
+
isDev &&
|
|
5222
|
+
vnode_setProp(diffContext.$vNewNode$, DEBUG_TYPE, "I" /* VirtualType.InlineComponent */);
|
|
5223
|
+
vnode_setProp(diffContext.$vNewNode$, ELEMENT_PROPS, jsxNode.props);
|
|
5224
|
+
if (jsxNode.key) {
|
|
5225
|
+
diffContext.$vNewNode$.key = jsxNode.key;
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
function expectText(diffContext, text) {
|
|
5229
|
+
if (diffContext.$vCurrent$ !== null) {
|
|
5230
|
+
const type = vnode_getType(diffContext.$vCurrent$);
|
|
5231
|
+
if (type === 3 /* Text */) {
|
|
5232
|
+
if (text !== vnode_getText(diffContext.$vCurrent$)) {
|
|
5233
|
+
vnode_setText(diffContext.$journal$, diffContext.$vCurrent$, text);
|
|
5234
|
+
return;
|
|
5235
|
+
}
|
|
5236
|
+
return;
|
|
5218
5237
|
}
|
|
5219
|
-
vNode = vNode.nextSibling;
|
|
5220
5238
|
}
|
|
5239
|
+
vnode_insertElementBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newText((qTest ? diffContext.$container$.document : document).createTextNode(text), text)), getCurrentInsertBefore(diffContext));
|
|
5221
5240
|
}
|
|
5222
|
-
|
|
5223
|
-
|
|
5241
|
+
/**
|
|
5242
|
+
* Retrieve the key from the VNode.
|
|
5243
|
+
*
|
|
5244
|
+
* @param vNode - VNode to retrieve the key from
|
|
5245
|
+
* @returns Key
|
|
5246
|
+
*/
|
|
5247
|
+
function getKey(vNode) {
|
|
5248
|
+
if (vNode == null || vnode_isTextVNode(vNode)) {
|
|
5224
5249
|
return null;
|
|
5225
5250
|
}
|
|
5226
|
-
return
|
|
5251
|
+
return vNode.key;
|
|
5227
5252
|
}
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5253
|
+
/**
|
|
5254
|
+
* Retrieve the component hash from the VNode.
|
|
5255
|
+
*
|
|
5256
|
+
* @param vNode - VNode to retrieve the key from
|
|
5257
|
+
* @param getObject - Function to retrieve the object by id for QComponent QRL
|
|
5258
|
+
* @returns Hash
|
|
5259
|
+
*/
|
|
5260
|
+
function getComponentHash(vNode, getObject) {
|
|
5261
|
+
if (vNode == null || vnode_isTextVNode(vNode)) {
|
|
5262
|
+
return null;
|
|
5233
5263
|
}
|
|
5234
|
-
|
|
5264
|
+
const qrl = vnode_getProp(vNode, OnRenderProp, getObject);
|
|
5265
|
+
return qrl ? qrl.$hash$ : null;
|
|
5235
5266
|
}
|
|
5236
5267
|
/**
|
|
5237
|
-
*
|
|
5268
|
+
* Marker class for JSX projection.
|
|
5238
5269
|
*
|
|
5239
|
-
*
|
|
5240
|
-
* 2. Falling back to the side buffer using the provided `sideBufferKey`
|
|
5241
|
-
* 3. Creating a new node via `createNew` when not found
|
|
5270
|
+
* Assume you have component like so
|
|
5242
5271
|
*
|
|
5243
|
-
*
|
|
5244
|
-
*
|
|
5245
|
-
*
|
|
5272
|
+
* ```
|
|
5273
|
+
* <SomeComponent>
|
|
5274
|
+
* some-text
|
|
5275
|
+
* <span q:slot="name">some more text</span>
|
|
5276
|
+
* more-text
|
|
5277
|
+
* </SomeComponent>
|
|
5278
|
+
* ```
|
|
5279
|
+
*
|
|
5280
|
+
* Before the `<SomeCompetent/>` is processed its children are transformed into:
|
|
5281
|
+
*
|
|
5282
|
+
* ```
|
|
5283
|
+
* <Projection q:slot="">
|
|
5284
|
+
* some-text
|
|
5285
|
+
* more-text
|
|
5286
|
+
* </Projection>
|
|
5287
|
+
* <Projection q:slot="name">
|
|
5288
|
+
* <span q:slot="name">some more text</span>
|
|
5289
|
+
* </Projection>
|
|
5290
|
+
* ```
|
|
5246
5291
|
*/
|
|
5247
|
-
function
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
if (
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5292
|
+
function Projection() { }
|
|
5293
|
+
function handleProps(host, jsxProps, vNodeProps, container) {
|
|
5294
|
+
let shouldRender = false;
|
|
5295
|
+
if (vNodeProps) {
|
|
5296
|
+
const constPropsDifferent = handleChangedProps(jsxProps[_CONST_PROPS], vNodeProps[_CONST_PROPS], vNodeProps[_PROPS_HANDLER], container, false);
|
|
5297
|
+
shouldRender ||= constPropsDifferent;
|
|
5298
|
+
const varPropsDifferent = handleChangedProps(jsxProps[_VAR_PROPS], vNodeProps[_VAR_PROPS], vNodeProps[_PROPS_HANDLER], container, true);
|
|
5299
|
+
shouldRender ||= varPropsDifferent;
|
|
5300
|
+
// Update the owner after all props have been synced
|
|
5301
|
+
vNodeProps[_OWNER] = jsxProps[_OWNER];
|
|
5302
|
+
}
|
|
5303
|
+
else if (jsxProps) {
|
|
5304
|
+
// If there is no props instance, create a new one.
|
|
5305
|
+
// We can do this because we are not using the props instance for anything else.
|
|
5306
|
+
vnode_setProp(host, ELEMENT_PROPS, jsxProps);
|
|
5307
|
+
vNodeProps = jsxProps;
|
|
5308
|
+
}
|
|
5309
|
+
return shouldRender;
|
|
5310
|
+
}
|
|
5311
|
+
function handleChangedProps(src, dst, propsHandler, container, triggerEffects = true) {
|
|
5312
|
+
if (isPropsEmpty(src) && isPropsEmpty(dst)) {
|
|
5256
5313
|
return false;
|
|
5257
5314
|
}
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
if (
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5315
|
+
propsHandler.$container$ = container;
|
|
5316
|
+
let changed = false;
|
|
5317
|
+
// Update changed/added props from src
|
|
5318
|
+
if (src) {
|
|
5319
|
+
for (const key in src) {
|
|
5320
|
+
if (key === 'children' || key === QBackRefs) {
|
|
5321
|
+
continue;
|
|
5322
|
+
}
|
|
5323
|
+
if (!dst || src[key] !== dst[key]) {
|
|
5324
|
+
if (triggerEffects) {
|
|
5325
|
+
if (dst) {
|
|
5326
|
+
// Update the value in dst BEFORE triggering effects
|
|
5327
|
+
// so effects see the new value
|
|
5328
|
+
// Note: Value is not triggering effects, because we are modyfing direct VAR_PROPS object
|
|
5329
|
+
dst[key] = src[key];
|
|
5330
|
+
}
|
|
5331
|
+
const didTigger = triggerPropsProxyEffect(propsHandler, key);
|
|
5332
|
+
if (!didTigger) {
|
|
5333
|
+
// If the effect was not triggered, then the prop has changed and we should rerender
|
|
5334
|
+
changed = true;
|
|
5274
5335
|
}
|
|
5275
5336
|
}
|
|
5337
|
+
else {
|
|
5338
|
+
// Early return for const props (no effects)
|
|
5339
|
+
return true;
|
|
5340
|
+
}
|
|
5276
5341
|
}
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
5344
|
+
// Remove props that are in dst but not in src
|
|
5345
|
+
if (dst) {
|
|
5346
|
+
for (const key in dst) {
|
|
5347
|
+
if (key === 'children' || key === QBackRefs) {
|
|
5348
|
+
continue;
|
|
5349
|
+
}
|
|
5350
|
+
if (!src || !_hasOwnProperty.call(src, key)) {
|
|
5351
|
+
if (triggerEffects) {
|
|
5352
|
+
delete dst[key];
|
|
5353
|
+
const didTigger = triggerPropsProxyEffect(propsHandler, key);
|
|
5354
|
+
if (!didTigger) {
|
|
5355
|
+
// If the effect was not triggered, then the prop has changed and we should rerender
|
|
5356
|
+
changed = true;
|
|
5357
|
+
}
|
|
5358
|
+
}
|
|
5280
5359
|
}
|
|
5281
|
-
diffContext.$vCurrent$ = buffered;
|
|
5282
|
-
diffContext.$vNewNode$ = null;
|
|
5283
|
-
return false;
|
|
5284
5360
|
}
|
|
5285
5361
|
}
|
|
5286
|
-
|
|
5287
|
-
return true;
|
|
5362
|
+
return changed;
|
|
5288
5363
|
}
|
|
5289
|
-
function
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
const currentIsVirtual = diffContext.$vCurrent$ && vnode_isVirtualVNode(diffContext.$vCurrent$);
|
|
5293
|
-
const isSameNode = currentIsVirtual && currentKey === jsxKey && (checkKey ? !!jsxKey : true);
|
|
5294
|
-
if (isSameNode) {
|
|
5295
|
-
// All is good.
|
|
5296
|
-
deleteFromSideBuffer(diffContext, null, currentKey);
|
|
5297
|
-
return;
|
|
5364
|
+
function isPropsEmpty(props) {
|
|
5365
|
+
if (!props) {
|
|
5366
|
+
return true;
|
|
5298
5367
|
}
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5368
|
+
return isObjectEmpty(props);
|
|
5369
|
+
}
|
|
5370
|
+
/**
|
|
5371
|
+
* If vnode is removed, it is necessary to release all subscriptions associated with it.
|
|
5372
|
+
*
|
|
5373
|
+
* This function will traverse the vnode tree in depth-first order and release all subscriptions.
|
|
5374
|
+
*
|
|
5375
|
+
* The function takes into account:
|
|
5376
|
+
*
|
|
5377
|
+
* - Projection nodes by not recursing into them.
|
|
5378
|
+
* - Component nodes by recursing into the component content nodes (which may be projected).
|
|
5379
|
+
*
|
|
5380
|
+
* @param cursorRoot - Optional cursor root (vStartNode) to propagate dirty bits to during diff.
|
|
5381
|
+
*/
|
|
5382
|
+
function cleanup(container, journal, vNode, cursorRoot = null) {
|
|
5383
|
+
let vCursor = vNode;
|
|
5384
|
+
const cursorRootData = cursorRoot && isCursor(cursorRoot) ? getCursorData(cursorRoot) : null;
|
|
5385
|
+
// Depth first traversal
|
|
5386
|
+
if (vnode_isTextVNode(vNode)) {
|
|
5387
|
+
markVNodeAsDeleted(vCursor);
|
|
5388
|
+
// Text nodes don't have subscriptions or children;
|
|
5304
5389
|
return;
|
|
5305
5390
|
}
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
}
|
|
5311
|
-
}
|
|
5312
|
-
function expectComponent(diffContext, component) {
|
|
5313
|
-
const componentMeta = component[SERIALIZABLE_STATE];
|
|
5314
|
-
let host = (diffContext.$vNewNode$ || diffContext.$vCurrent$);
|
|
5315
|
-
const jsxNode = diffContext.$jsxValue$;
|
|
5316
|
-
if (componentMeta) {
|
|
5317
|
-
const jsxProps = jsxNode.props;
|
|
5318
|
-
// QComponent
|
|
5319
|
-
let shouldRender = false;
|
|
5320
|
-
const [componentQRL] = componentMeta;
|
|
5321
|
-
const componentHash = componentQRL.$hash$;
|
|
5322
|
-
const vNodeComponentHash = getComponentHash(host, diffContext.$container$.$getObjectById$);
|
|
5323
|
-
const lookupKey = jsxNode.key || componentHash;
|
|
5324
|
-
const vNodeLookupKey = getKey(host) || vNodeComponentHash;
|
|
5325
|
-
const lookupKeysAreEqual = lookupKey === vNodeLookupKey;
|
|
5326
|
-
const hashesAreEqual = componentHash === vNodeComponentHash;
|
|
5327
|
-
if (lookupKeysAreEqual) {
|
|
5328
|
-
if (hashesAreEqual) {
|
|
5329
|
-
deleteFromSideBuffer(diffContext, null, lookupKey);
|
|
5330
|
-
}
|
|
5331
|
-
else {
|
|
5332
|
-
insertNewComponent(diffContext, host, componentQRL, jsxProps);
|
|
5333
|
-
host = diffContext.$vNewNode$;
|
|
5334
|
-
shouldRender = true;
|
|
5335
|
-
}
|
|
5391
|
+
let vParent = null;
|
|
5392
|
+
do {
|
|
5393
|
+
if (cursorRootData && vCursor !== cursorRoot && isCursor(vCursor)) {
|
|
5394
|
+
abandonCursor(container, cursorRootData, vCursor);
|
|
5336
5395
|
}
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5396
|
+
const type = vCursor.flags;
|
|
5397
|
+
if (type & 3 /* VNodeFlags.ELEMENT_OR_VIRTUAL_MASK */) {
|
|
5398
|
+
clearAllEffects(container, vCursor);
|
|
5399
|
+
markVNodeAsDeleted(vCursor);
|
|
5400
|
+
const isComponent = type & 2 /* VNodeFlags.Virtual */ &&
|
|
5401
|
+
vnode_getProp(vCursor, OnRenderProp, null) !== null;
|
|
5402
|
+
if (isComponent) {
|
|
5403
|
+
// cleanup q:seq content
|
|
5404
|
+
const seq = container.getHostProp(vCursor, ELEMENT_SEQ);
|
|
5405
|
+
if (seq) {
|
|
5406
|
+
for (let i = 0; i < seq.length; i++) {
|
|
5407
|
+
const obj = seq[i];
|
|
5408
|
+
if (isObject(obj)) {
|
|
5409
|
+
const objIsTask = isTask(obj);
|
|
5410
|
+
if (objIsTask && obj.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
|
|
5411
|
+
obj.$flags$ |= 16 /* TaskFlags.NEEDS_CLEANUP */;
|
|
5412
|
+
markVNodeDirty(container, vCursor, 128 /* ChoreBits.CLEANUP */, cursorRoot);
|
|
5413
|
+
// don't call cleanupDestroyable yet, do it by the scheduler
|
|
5414
|
+
continue;
|
|
5415
|
+
}
|
|
5416
|
+
else if (obj instanceof SignalImpl || isStore(obj)) {
|
|
5417
|
+
clearAllEffects(container, obj);
|
|
5418
|
+
}
|
|
5419
|
+
if (objIsTask || obj instanceof AsyncSignalImpl) {
|
|
5420
|
+
cleanupDestroyable(obj);
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
// SPECIAL CASE: If we are a component, we need to descend into the projected content and release the content.
|
|
5426
|
+
const attrs = vCursor.props;
|
|
5427
|
+
if (attrs) {
|
|
5428
|
+
const keys = Object.keys(attrs);
|
|
5429
|
+
for (let i = 0; i < keys.length; i++) {
|
|
5430
|
+
const key = keys[i];
|
|
5431
|
+
if (isSlotProp(key)) {
|
|
5432
|
+
const value = attrs[key];
|
|
5433
|
+
if (value) {
|
|
5434
|
+
attrs[key] = null; // prevent infinite loop
|
|
5435
|
+
const projection = typeof value === 'string'
|
|
5436
|
+
? vnode_locate(container.rootVNode, value)
|
|
5437
|
+
: value;
|
|
5438
|
+
let projectionChild = vnode_getFirstChild(projection);
|
|
5439
|
+
while (projectionChild) {
|
|
5440
|
+
cleanup(container, journal, projectionChild, cursorRoot);
|
|
5441
|
+
projectionChild = projectionChild.nextSibling;
|
|
5442
|
+
}
|
|
5443
|
+
cleanupStaleUnclaimedProjection(container, journal, projection);
|
|
5444
|
+
}
|
|
5445
|
+
}
|
|
5446
|
+
}
|
|
5447
|
+
}
|
|
5341
5448
|
}
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
insertNewComponent(diffContext, host, componentQRL, jsxProps);
|
|
5351
|
-
host = diffContext.$vNewNode$;
|
|
5352
|
-
shouldRender = true;
|
|
5449
|
+
const isProjection = vnode_isProjection(vCursor);
|
|
5450
|
+
// Descend into children
|
|
5451
|
+
if (!isProjection) {
|
|
5452
|
+
// Only if it is not a projection
|
|
5453
|
+
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
5454
|
+
if (vFirstChild) {
|
|
5455
|
+
vCursor = vFirstChild;
|
|
5456
|
+
continue;
|
|
5353
5457
|
}
|
|
5354
|
-
shouldRender ||= propsChanged;
|
|
5355
5458
|
}
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
// Unfortunately it is created every time, something to fix in the optimizer.
|
|
5359
|
-
vnode_setProp(host, OnRenderProp, componentQRL);
|
|
5459
|
+
// TODO: probably can be removed
|
|
5460
|
+
else if (vCursor === vNode) {
|
|
5360
5461
|
/**
|
|
5361
|
-
*
|
|
5362
|
-
*
|
|
5462
|
+
* If it is a projection and we are at the root, then we should only walk the children to
|
|
5463
|
+
* materialize the projection content. This is because we could have references in the vnode
|
|
5464
|
+
* refs map which need to be materialized before cleanup.
|
|
5363
5465
|
*/
|
|
5364
|
-
|
|
5365
|
-
|
|
5466
|
+
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
5467
|
+
if (vFirstChild) {
|
|
5468
|
+
vnode_walkVNode(vFirstChild);
|
|
5469
|
+
return;
|
|
5470
|
+
}
|
|
5471
|
+
clearProjectionFromSlotParent(container, vCursor);
|
|
5366
5472
|
}
|
|
5367
5473
|
}
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
else {
|
|
5371
|
-
const lookupKey = jsxNode.key;
|
|
5372
|
-
const vNodeLookupKey = getKey(host);
|
|
5373
|
-
const lookupKeysAreEqual = lookupKey === vNodeLookupKey;
|
|
5374
|
-
const vNodeComponentHash = getComponentHash(host, diffContext.$container$.$getObjectById$);
|
|
5375
|
-
const isInlineComponent = vNodeComponentHash == null;
|
|
5376
|
-
if ((host && !isInlineComponent) || !host) {
|
|
5377
|
-
insertNewInlineComponent(diffContext);
|
|
5378
|
-
host = diffContext.$vNewNode$;
|
|
5474
|
+
else if (type & 4 /* VNodeFlags.Text */) {
|
|
5475
|
+
markVNodeAsDeleted(vCursor);
|
|
5379
5476
|
}
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
}
|
|
5385
|
-
host = (diffContext.$vNewNode$ || diffContext.$vCurrent$);
|
|
5477
|
+
// Out of children
|
|
5478
|
+
if (vCursor === vNode) {
|
|
5479
|
+
// we are where we started, this means that vNode has no children, so we are done.
|
|
5480
|
+
return;
|
|
5386
5481
|
}
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5482
|
+
// Out of children, go to next sibling
|
|
5483
|
+
const vNextSibling = vCursor.nextSibling;
|
|
5484
|
+
if (vNextSibling) {
|
|
5485
|
+
vCursor = vNextSibling;
|
|
5486
|
+
continue;
|
|
5390
5487
|
}
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5488
|
+
// Out of siblings, go to parent
|
|
5489
|
+
vParent = vCursor.parent;
|
|
5490
|
+
while (vParent) {
|
|
5491
|
+
if (vParent === vNode) {
|
|
5492
|
+
// We are back where we started, we are done.
|
|
5493
|
+
return;
|
|
5494
|
+
}
|
|
5495
|
+
const vNextParentSibling = vParent.nextSibling;
|
|
5496
|
+
if (vNextParentSibling) {
|
|
5497
|
+
vCursor = vNextParentSibling;
|
|
5498
|
+
break;
|
|
5399
5499
|
}
|
|
5400
|
-
|
|
5401
|
-
|
|
5500
|
+
vParent = vParent.parent;
|
|
5501
|
+
}
|
|
5502
|
+
if (vParent == null) {
|
|
5503
|
+
// We are done.
|
|
5504
|
+
return;
|
|
5402
5505
|
}
|
|
5506
|
+
} while (true);
|
|
5507
|
+
}
|
|
5508
|
+
function clearProjectionFromSlotParent(container, vNode) {
|
|
5509
|
+
if (!vNode.slotParent) {
|
|
5510
|
+
return;
|
|
5511
|
+
}
|
|
5512
|
+
const slotName = container.getHostProp(vNode, QSlot);
|
|
5513
|
+
if (slotName != null && container.getHostProp(vNode.slotParent, slotName) === vNode) {
|
|
5514
|
+
vnode_setProp(vNode.slotParent, slotName, null);
|
|
5403
5515
|
}
|
|
5404
5516
|
}
|
|
5405
|
-
function
|
|
5406
|
-
|
|
5407
|
-
|
|
5517
|
+
function cleanupStaleUnclaimedProjection(container, journal, projection) {
|
|
5518
|
+
// we are removing a node where the projection would go after slot render.
|
|
5519
|
+
// This is not needed, so we need to cleanup still unclaimed projection
|
|
5520
|
+
const projectionParent = projection.parent;
|
|
5521
|
+
if (projectionParent) {
|
|
5522
|
+
const projectionParentType = projectionParent.flags;
|
|
5523
|
+
if (projectionParentType & 1 /* VNodeFlags.Element */ &&
|
|
5524
|
+
vnode_getElementName(projectionParent) === QTemplate) {
|
|
5525
|
+
// if parent is the q:template element then projection is still unclaimed - remove it
|
|
5526
|
+
clearProjectionFromSlotParent(container, projection);
|
|
5527
|
+
vnode_remove(journal, projectionParent, projection, true);
|
|
5528
|
+
}
|
|
5408
5529
|
}
|
|
5409
|
-
vnode_insertVirtualBefore(diffContext.$journal$, diffContext.$vParent$, (diffContext.$vNewNode$ = vnode_newVirtual()), getInsertBefore(diffContext));
|
|
5410
|
-
const jsxNode = diffContext.$jsxValue$;
|
|
5411
|
-
isDev && vnode_setProp(diffContext.$vNewNode$, DEBUG_TYPE, "C" /* VirtualType.Component */);
|
|
5412
|
-
vnode_setProp(diffContext.$vNewNode$, OnRenderProp, componentQRL);
|
|
5413
|
-
vnode_setProp(diffContext.$vNewNode$, ELEMENT_PROPS, jsxProps);
|
|
5414
|
-
diffContext.$vNewNode$.key = jsxNode.key;
|
|
5415
5530
|
}
|
|
5416
|
-
function
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5531
|
+
function markVNodeAsDeleted(vCursor) {
|
|
5532
|
+
/**
|
|
5533
|
+
* Marks vCursor as deleted. We need to do this to prevent chores from running after the vnode is
|
|
5534
|
+
* removed. (for example signal subscriptions)
|
|
5535
|
+
*/
|
|
5536
|
+
vCursor.flags |= 32 /* VNodeFlags.Deleted */;
|
|
5537
|
+
}
|
|
5538
|
+
function areWrappedSignalsEqual(oldSignal, newSignal) {
|
|
5539
|
+
if (oldSignal === newSignal) {
|
|
5540
|
+
return true;
|
|
5424
5541
|
}
|
|
5542
|
+
return (newSignal.$func$ === oldSignal.$func$ && areArgumentsEqual(newSignal.$args$, oldSignal.$args$));
|
|
5425
5543
|
}
|
|
5426
|
-
function
|
|
5427
|
-
if (
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5544
|
+
function areArgumentsEqual(oldArgs, newArgs) {
|
|
5545
|
+
if (oldArgs === newArgs) {
|
|
5546
|
+
return true;
|
|
5547
|
+
}
|
|
5548
|
+
if (!oldArgs || !newArgs || oldArgs.length !== newArgs.length) {
|
|
5549
|
+
return false;
|
|
5550
|
+
}
|
|
5551
|
+
for (let i = 0; i < oldArgs.length; i++) {
|
|
5552
|
+
if (oldArgs[i] !== newArgs[i]) {
|
|
5553
|
+
return false;
|
|
5435
5554
|
}
|
|
5436
5555
|
}
|
|
5437
|
-
|
|
5556
|
+
return true;
|
|
5438
5557
|
}
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
* @param vNode - VNode to retrieve the key from
|
|
5443
|
-
* @returns Key
|
|
5444
|
-
*/
|
|
5445
|
-
function getKey(vNode) {
|
|
5446
|
-
if (vNode == null || vnode_isTextVNode(vNode)) {
|
|
5447
|
-
return null;
|
|
5558
|
+
function containsWrappedSignal(data, signal) {
|
|
5559
|
+
if (!(signal instanceof WrappedSignalImpl)) {
|
|
5560
|
+
return false;
|
|
5448
5561
|
}
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
* @param vNode - VNode to retrieve the key from
|
|
5455
|
-
* @param getObject - Function to retrieve the object by id for QComponent QRL
|
|
5456
|
-
* @returns Hash
|
|
5457
|
-
*/
|
|
5458
|
-
function getComponentHash(vNode, getObject) {
|
|
5459
|
-
if (vNode == null || vnode_isTextVNode(vNode)) {
|
|
5460
|
-
return null;
|
|
5562
|
+
for (let i = 0; i < data.length; i++) {
|
|
5563
|
+
const item = data[i];
|
|
5564
|
+
if (item instanceof WrappedSignalImpl && areWrappedSignalsEqual(item, signal)) {
|
|
5565
|
+
return true;
|
|
5566
|
+
}
|
|
5461
5567
|
}
|
|
5462
|
-
|
|
5463
|
-
return qrl ? qrl.$hash$ : null;
|
|
5568
|
+
return false;
|
|
5464
5569
|
}
|
|
5570
|
+
|
|
5465
5571
|
/**
|
|
5466
|
-
*
|
|
5572
|
+
* Use `executeComponent` to execute a component.
|
|
5467
5573
|
*
|
|
5468
|
-
*
|
|
5574
|
+
* Component execution can be complex because of:
|
|
5469
5575
|
*
|
|
5470
|
-
*
|
|
5471
|
-
*
|
|
5472
|
-
*
|
|
5473
|
-
*
|
|
5474
|
-
*
|
|
5475
|
-
* </SomeComponent>
|
|
5476
|
-
* ```
|
|
5576
|
+
* - It can by async
|
|
5577
|
+
* - It can contain many tasks which need to be awaited
|
|
5578
|
+
* - Each task can run multiple times if they track signals which change.
|
|
5579
|
+
* - The JSX may be re-generated multiple times of a task needs to be rerun due to signal change.
|
|
5580
|
+
* - It needs to keep track of hook state.
|
|
5477
5581
|
*
|
|
5478
|
-
*
|
|
5582
|
+
* For `component$`: `renderHost` === `subscriptionHost` For inlined-components: the
|
|
5583
|
+
* `subscriptionHost` is a parent `component$` which needs to re-execute.
|
|
5479
5584
|
*
|
|
5480
|
-
*
|
|
5481
|
-
*
|
|
5482
|
-
*
|
|
5483
|
-
*
|
|
5484
|
-
*
|
|
5485
|
-
*
|
|
5486
|
-
* <span q:slot="name">some more text</span>
|
|
5487
|
-
* </Projection>
|
|
5488
|
-
* ```
|
|
5585
|
+
* @param container
|
|
5586
|
+
* @param renderHost - VNode into which the component is rendered into.
|
|
5587
|
+
* @param subscriptionHost - VNode which will be re-executed if the component needs to re-render.
|
|
5588
|
+
* @param componentQRL
|
|
5589
|
+
* @param props
|
|
5590
|
+
* @returns
|
|
5489
5591
|
*/
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
shouldRender ||= constPropsDifferent;
|
|
5496
|
-
const varPropsDifferent = handleChangedProps(jsxProps[_VAR_PROPS], vNodeProps[_VAR_PROPS], vNodeProps[_PROPS_HANDLER], container, true);
|
|
5497
|
-
shouldRender ||= varPropsDifferent;
|
|
5498
|
-
// Update the owner after all props have been synced
|
|
5499
|
-
vNodeProps[_OWNER] = jsxProps[_OWNER];
|
|
5592
|
+
const executeComponent = (container, renderHost, subscriptionHost, componentQRL, props) => {
|
|
5593
|
+
const iCtx = newRenderInvokeContext(container.$locale$, renderHost, container);
|
|
5594
|
+
if (subscriptionHost) {
|
|
5595
|
+
iCtx.$effectSubscriber$ = getSubscriber(subscriptionHost, ":" /* EffectProperty.COMPONENT */);
|
|
5596
|
+
iCtx.$container$ = container;
|
|
5500
5597
|
}
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5598
|
+
let componentFn;
|
|
5599
|
+
container.ensureProjectionResolved(renderHost);
|
|
5600
|
+
let isInlineComponent = false;
|
|
5601
|
+
if (componentQRL === null) {
|
|
5602
|
+
componentQRL = container.getHostProp(renderHost, OnRenderProp);
|
|
5603
|
+
isDev && assertDefined(componentQRL, 'No Component found at this location');
|
|
5506
5604
|
}
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5605
|
+
if (isQrl(componentQRL)) {
|
|
5606
|
+
props = props || container.getHostProp(renderHost, ELEMENT_PROPS) || EMPTY_OBJ;
|
|
5607
|
+
// TODO is this possible? JSXNode handles this, no?
|
|
5608
|
+
if ('children' in props) {
|
|
5609
|
+
delete props.children;
|
|
5610
|
+
}
|
|
5611
|
+
componentFn = componentQRL.getFn(iCtx);
|
|
5512
5612
|
}
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5613
|
+
else if (isQwikComponent(componentQRL)) {
|
|
5614
|
+
const qComponentFn = componentQRL;
|
|
5615
|
+
componentFn = () => invokeApply(iCtx, qComponentFn, [props || EMPTY_OBJ, null, 0]);
|
|
5616
|
+
}
|
|
5617
|
+
else {
|
|
5618
|
+
isInlineComponent = true;
|
|
5619
|
+
const inlineComponent = componentQRL;
|
|
5620
|
+
componentFn = () => invokeApply(iCtx, inlineComponent, [props || EMPTY_OBJ]);
|
|
5621
|
+
}
|
|
5622
|
+
const isSsr = qTest ? isServerPlatform() : isServer;
|
|
5623
|
+
const executeComponentWithPromiseExceptionRetry = (retryCount = 0) => safeCall(() => {
|
|
5624
|
+
if (!isInlineComponent) {
|
|
5625
|
+
container.setHostProp(renderHost, ELEMENT_SEQ_IDX, null);
|
|
5626
|
+
container.setHostProp(renderHost, USE_ON_LOCAL_SEQ_IDX, null);
|
|
5627
|
+
}
|
|
5628
|
+
if (retryCount > 0 && vnode_isVNode(renderHost)) {
|
|
5629
|
+
clearAllEffects(container, renderHost);
|
|
5630
|
+
}
|
|
5631
|
+
return maybeThen(componentFn(props), (jsx) => maybeThen(iCtx.$waitOn$, () => jsx));
|
|
5632
|
+
}, (jsx) => {
|
|
5633
|
+
// In SSR, check if the component was marked dirty (COMPONENT bit) during execution.
|
|
5634
|
+
// This happens when something completes and updates reactive primitives
|
|
5635
|
+
// while we're waiting on $waitOn$. If so, we need to re-execute the component
|
|
5636
|
+
// to get fresh JSX with updated values.
|
|
5637
|
+
if (isSsr && !isInlineComponent) {
|
|
5638
|
+
const ssrNode = renderHost;
|
|
5639
|
+
if (ssrNode.dirty & 4 /* ChoreBits.COMPONENT */) {
|
|
5640
|
+
ssrNode.dirty &= ~4 /* ChoreBits.COMPONENT */;
|
|
5641
|
+
if (retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
5642
|
+
return executeComponentWithPromiseExceptionRetry(retryCount + 1);
|
|
5538
5643
|
}
|
|
5539
5644
|
}
|
|
5540
5645
|
}
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
// If the effect was not triggered, then the prop has changed and we should rerender
|
|
5554
|
-
changed = true;
|
|
5555
|
-
}
|
|
5556
|
-
}
|
|
5646
|
+
const useOnEvents = container.getHostProp(renderHost, USE_ON_LOCAL);
|
|
5647
|
+
if (useOnEvents) {
|
|
5648
|
+
return addUseOnEvents(container, jsx, useOnEvents);
|
|
5649
|
+
}
|
|
5650
|
+
return jsx;
|
|
5651
|
+
}, (err) => {
|
|
5652
|
+
if (isPromise(err) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
5653
|
+
return err.then(() => executeComponentWithPromiseExceptionRetry(++retryCount));
|
|
5654
|
+
}
|
|
5655
|
+
else {
|
|
5656
|
+
if (retryCount >= MAX_RETRY_ON_PROMISE_COUNT) {
|
|
5657
|
+
throw new Error(`Max retry count of component execution reached`);
|
|
5557
5658
|
}
|
|
5659
|
+
throw err;
|
|
5558
5660
|
}
|
|
5559
|
-
}
|
|
5560
|
-
return
|
|
5561
|
-
}
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
return true;
|
|
5565
|
-
}
|
|
5566
|
-
return isObjectEmpty(props);
|
|
5567
|
-
}
|
|
5568
|
-
/**
|
|
5569
|
-
* If vnode is removed, it is necessary to release all subscriptions associated with it.
|
|
5570
|
-
*
|
|
5571
|
-
* This function will traverse the vnode tree in depth-first order and release all subscriptions.
|
|
5572
|
-
*
|
|
5573
|
-
* The function takes into account:
|
|
5574
|
-
*
|
|
5575
|
-
* - Projection nodes by not recursing into them.
|
|
5576
|
-
* - Component nodes by recursing into the component content nodes (which may be projected).
|
|
5661
|
+
});
|
|
5662
|
+
return executeComponentWithPromiseExceptionRetry();
|
|
5663
|
+
};
|
|
5664
|
+
/**
|
|
5665
|
+
* Adds `useOn` events to the JSX output.
|
|
5577
5666
|
*
|
|
5578
|
-
* @param
|
|
5667
|
+
* @param jsx The JSX output to modify.
|
|
5668
|
+
* @param useOnEvents The `useOn` events to add.
|
|
5669
|
+
* @returns The modified JSX output.
|
|
5579
5670
|
*/
|
|
5580
|
-
function
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
//
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
const
|
|
5604
|
-
if (
|
|
5605
|
-
|
|
5606
|
-
markVNodeDirty(container, vCursor, 64 /* ChoreBits.CLEANUP */, cursorRoot);
|
|
5607
|
-
// don't call cleanupDestroyable yet, do it by the scheduler
|
|
5608
|
-
continue;
|
|
5609
|
-
}
|
|
5610
|
-
else if (obj instanceof SignalImpl || isStore(obj)) {
|
|
5611
|
-
clearAllEffects(container, obj);
|
|
5612
|
-
}
|
|
5613
|
-
if (objIsTask || obj instanceof AsyncSignalImpl) {
|
|
5614
|
-
cleanupDestroyable(obj);
|
|
5671
|
+
function addUseOnEvents(container, jsx, useOnEvents) {
|
|
5672
|
+
const jsxElement = findFirstElementNode(jsx);
|
|
5673
|
+
let jsxResult = jsx;
|
|
5674
|
+
const qVisibleEvent = 'q-e:qvisible';
|
|
5675
|
+
return maybeThen(jsxElement, (jsxElement) => {
|
|
5676
|
+
// headless components are components that don't render a real DOM element
|
|
5677
|
+
const isHeadless = !jsxElement;
|
|
5678
|
+
// placeholder element is a <script> element that is used to add events to the document or window
|
|
5679
|
+
let placeholderElement = null;
|
|
5680
|
+
for (const key in useOnEvents) {
|
|
5681
|
+
if (Object.prototype.hasOwnProperty.call(useOnEvents, key)) {
|
|
5682
|
+
let targetElement = jsxElement;
|
|
5683
|
+
let eventKey = key;
|
|
5684
|
+
if (isHeadless) {
|
|
5685
|
+
// if the component is headless, we need to add the event to the placeholder element
|
|
5686
|
+
if (key === qVisibleEvent ||
|
|
5687
|
+
key.startsWith("q-d:" /* EventNameHtmlScope.document */) ||
|
|
5688
|
+
key.startsWith("q-w:" /* EventNameHtmlScope.window */)) {
|
|
5689
|
+
if (!placeholderElement) {
|
|
5690
|
+
placeholderElement = createPlaceholderScriptNode();
|
|
5691
|
+
// A headless component that projects the document root (e.g. wrapping `<head>`/`<body>`
|
|
5692
|
+
// in a `<Slot/>`) would otherwise place the placeholder `<script>` as a direct child of
|
|
5693
|
+
// `<html>`, which is invalid. On the server let the container defer it into `<head>`.
|
|
5694
|
+
const isSsr = qTest ? isServerPlatform() : isServer;
|
|
5695
|
+
if (!(isSsr && container.$deferRootPlaceholder$(placeholderElement))) {
|
|
5696
|
+
jsxResult = injectPlaceholderElement(jsxResult, placeholderElement);
|
|
5615
5697
|
}
|
|
5616
5698
|
}
|
|
5699
|
+
targetElement = placeholderElement;
|
|
5617
5700
|
}
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
if (value) {
|
|
5628
|
-
attrs[key] = null; // prevent infinite loop
|
|
5629
|
-
const projection = typeof value === 'string'
|
|
5630
|
-
? vnode_locate(container.rootVNode, value)
|
|
5631
|
-
: value;
|
|
5632
|
-
let projectionChild = vnode_getFirstChild(projection);
|
|
5633
|
-
while (projectionChild) {
|
|
5634
|
-
cleanup(container, journal, projectionChild, cursorRoot);
|
|
5635
|
-
projectionChild = projectionChild.nextSibling;
|
|
5636
|
-
}
|
|
5637
|
-
cleanupStaleUnclaimedProjection(journal, projection);
|
|
5638
|
-
}
|
|
5701
|
+
else {
|
|
5702
|
+
if (isDev) {
|
|
5703
|
+
const sourceLocation = getUseOnSourceLocation(useOnEvents[key].qrls);
|
|
5704
|
+
logWarn('You are trying to add an event "' +
|
|
5705
|
+
key +
|
|
5706
|
+
'" using `useOn` hook, ' +
|
|
5707
|
+
'but a node to which you can add an event is not found. ' +
|
|
5708
|
+
'Please make sure that the component outputs a DOM element.' +
|
|
5709
|
+
(sourceLocation ? ` Offending \`useOn\`: ${sourceLocation}.` : ''));
|
|
5639
5710
|
}
|
|
5711
|
+
continue;
|
|
5640
5712
|
}
|
|
5641
5713
|
}
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
}
|
|
5653
|
-
// TODO: probably can be removed
|
|
5654
|
-
else if (vCursor === vNode) {
|
|
5655
|
-
/**
|
|
5656
|
-
* If it is a projection and we are at the root, then we should only walk the children to
|
|
5657
|
-
* materialize the projection content. This is because we could have references in the vnode
|
|
5658
|
-
* refs map which need to be materialized before cleanup.
|
|
5659
|
-
*/
|
|
5660
|
-
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
5661
|
-
if (vFirstChild) {
|
|
5662
|
-
vnode_walkVNode(vFirstChild, (vNode) => {
|
|
5663
|
-
/**
|
|
5664
|
-
* Instead of an ID, we store a direct reference to the VNode. This is necessary to
|
|
5665
|
-
* locate the slot's parent in a detached subtree, as the ID would become invalid.
|
|
5666
|
-
*/
|
|
5667
|
-
if (vNode.flags & 2 /* VNodeFlags.Virtual */) {
|
|
5668
|
-
// The QSlotParent is used to find the slot parent during scheduling
|
|
5669
|
-
vNode.slotParent;
|
|
5714
|
+
if (targetElement) {
|
|
5715
|
+
if (targetElement.type === 'script' && key === qVisibleEvent) {
|
|
5716
|
+
eventKey = 'q-d:qinit';
|
|
5717
|
+
if (isDev) {
|
|
5718
|
+
const sourceLocation = getUseOnSourceLocation(useOnEvents[key].qrls);
|
|
5719
|
+
logWarn(`You are trying to add the event "${key}" ` +
|
|
5720
|
+
'using the `useVisibleTask$` hook with the "intersection-observer" strategy, ' +
|
|
5721
|
+
'but this only works when the component outputs a DOM element. Falling back to ' +
|
|
5722
|
+
'"document-ready" instead.' +
|
|
5723
|
+
(sourceLocation ? ` Offending \`useVisibleTask$\`: ${sourceLocation}.` : ''));
|
|
5670
5724
|
}
|
|
5671
|
-
}
|
|
5672
|
-
|
|
5725
|
+
}
|
|
5726
|
+
addUseOnEvent(targetElement, eventKey, useOnEvents[key]);
|
|
5673
5727
|
}
|
|
5674
5728
|
}
|
|
5675
5729
|
}
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
}
|
|
5690
|
-
// Out of siblings, go to parent
|
|
5691
|
-
vParent = vCursor.parent;
|
|
5692
|
-
while (vParent) {
|
|
5693
|
-
if (vParent === vNode) {
|
|
5694
|
-
// We are back where we started, we are done.
|
|
5695
|
-
return;
|
|
5696
|
-
}
|
|
5697
|
-
const vNextParentSibling = vParent.nextSibling;
|
|
5698
|
-
if (vNextParentSibling) {
|
|
5699
|
-
vCursor = vNextParentSibling;
|
|
5700
|
-
break;
|
|
5730
|
+
return jsxResult;
|
|
5731
|
+
});
|
|
5732
|
+
}
|
|
5733
|
+
function getUseOnSourceLocation(eventQrls) {
|
|
5734
|
+
for (let i = 0; i < eventQrls.length; i++) {
|
|
5735
|
+
const eventQrl = eventQrls[i];
|
|
5736
|
+
const task = eventQrl?.getCaptured()?.[0];
|
|
5737
|
+
if (isTask(task)) {
|
|
5738
|
+
const dev = task.$qrl$.dev;
|
|
5739
|
+
if (dev?.file) {
|
|
5740
|
+
return typeof dev.lo === 'number' && typeof dev.hi === 'number'
|
|
5741
|
+
? `${dev.file}:${dev.lo}-${dev.hi}`
|
|
5742
|
+
: dev.file;
|
|
5701
5743
|
}
|
|
5702
|
-
vParent = vParent.parent;
|
|
5703
|
-
}
|
|
5704
|
-
if (vParent == null) {
|
|
5705
|
-
// We are done.
|
|
5706
|
-
return;
|
|
5707
5744
|
}
|
|
5708
|
-
}
|
|
5745
|
+
}
|
|
5746
|
+
return null;
|
|
5709
5747
|
}
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5748
|
+
/**
|
|
5749
|
+
* Adds an event to the JSX element.
|
|
5750
|
+
*
|
|
5751
|
+
* @param jsxElement The JSX element to add the event to.
|
|
5752
|
+
* @param key The event name.
|
|
5753
|
+
* @param value The event value.
|
|
5754
|
+
*/
|
|
5755
|
+
function addUseOnEvent(jsxElement, key, value) {
|
|
5756
|
+
// These handlers are always there, so they go in constProps
|
|
5757
|
+
const props = (jsxElement.constProps ||= {});
|
|
5758
|
+
const propValue = props[key];
|
|
5759
|
+
const qrls = value.qrls;
|
|
5760
|
+
if (propValue == null) {
|
|
5761
|
+
props[key] = qrls;
|
|
5762
|
+
}
|
|
5763
|
+
else if (Array.isArray(propValue)) {
|
|
5764
|
+
propValue.push(...qrls);
|
|
5765
|
+
}
|
|
5766
|
+
else {
|
|
5767
|
+
props[key] = [propValue, ...qrls];
|
|
5768
|
+
}
|
|
5769
|
+
const varProp = jsxElement.varProps[key];
|
|
5770
|
+
if (varProp) {
|
|
5771
|
+
// we need to demote the handlers to varProps
|
|
5772
|
+
if (Array.isArray(propValue)) {
|
|
5773
|
+
propValue.push(...props[key]);
|
|
5720
5774
|
}
|
|
5775
|
+
else {
|
|
5776
|
+
jsxElement.varProps[key] = [propValue, ...qrls];
|
|
5777
|
+
}
|
|
5778
|
+
props[key] = undefined;
|
|
5721
5779
|
}
|
|
5780
|
+
const capture = value.capture;
|
|
5781
|
+
const preventdefault = value.preventdefault;
|
|
5782
|
+
const stoppropagation = value.stoppropagation;
|
|
5783
|
+
if (!capture && !preventdefault && !stoppropagation) {
|
|
5784
|
+
return;
|
|
5785
|
+
}
|
|
5786
|
+
const [, eventName] = getEventDataFromHtmlAttribute(key);
|
|
5787
|
+
capture && addUseOnModifier(jsxElement, eventName, 'capture');
|
|
5788
|
+
preventdefault && addUseOnModifier(jsxElement, eventName, 'preventdefault');
|
|
5789
|
+
stoppropagation && addUseOnModifier(jsxElement, eventName, 'stoppropagation');
|
|
5722
5790
|
}
|
|
5723
|
-
function
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5791
|
+
function addUseOnModifier(jsxElement, eventName, modifier) {
|
|
5792
|
+
const key = `${modifier}:${eventName}`;
|
|
5793
|
+
const varProps = jsxElement.varProps;
|
|
5794
|
+
if (varProps === EMPTY_OBJ) {
|
|
5795
|
+
jsxElement.varProps = {};
|
|
5796
|
+
}
|
|
5797
|
+
jsxElement.varProps[key] = true;
|
|
5729
5798
|
}
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5799
|
+
/**
|
|
5800
|
+
* Finds the first element node in the JSX output.
|
|
5801
|
+
*
|
|
5802
|
+
* @param jsx The JSX output to search.
|
|
5803
|
+
* @returns The first element node or null if no element node is found.
|
|
5804
|
+
*/
|
|
5805
|
+
function findFirstElementNode(jsx) {
|
|
5806
|
+
const queue = [jsx];
|
|
5807
|
+
while (queue.length) {
|
|
5808
|
+
const jsx = queue.shift();
|
|
5809
|
+
if (isJSXNode(jsx)) {
|
|
5810
|
+
if (typeof jsx.type === 'string') {
|
|
5811
|
+
return jsx;
|
|
5812
|
+
}
|
|
5813
|
+
queue.push(jsx.children);
|
|
5814
|
+
}
|
|
5815
|
+
else if (isArray(jsx)) {
|
|
5816
|
+
queue.push(...jsx);
|
|
5817
|
+
}
|
|
5818
|
+
else if (isPromise(jsx)) {
|
|
5819
|
+
return maybeThen(jsx, (jsx) => findFirstElementNode(jsx));
|
|
5820
|
+
}
|
|
5821
|
+
else if (isSignal(jsx)) {
|
|
5822
|
+
return findFirstElementNode(jsx.untrackedValue);
|
|
5823
|
+
}
|
|
5733
5824
|
}
|
|
5734
|
-
return
|
|
5825
|
+
return null;
|
|
5735
5826
|
}
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5827
|
+
/**
|
|
5828
|
+
* Injects a placeholder <script> element into the JSX output.
|
|
5829
|
+
*
|
|
5830
|
+
* This is necessary for headless components (components that don't render a real DOM element) to
|
|
5831
|
+
* have an anchor point for `useOn` event listeners that target the document or window.
|
|
5832
|
+
*
|
|
5833
|
+
* @param jsx The JSX output to modify.
|
|
5834
|
+
* @param placeholder The placeholder element to inject.
|
|
5835
|
+
* @returns The modified JSX output.
|
|
5836
|
+
*/
|
|
5837
|
+
function injectPlaceholderElement(jsx, placeholder) {
|
|
5838
|
+
// For regular JSX nodes, we can append the placeholder to its children.
|
|
5839
|
+
if (isJSXNode(jsx)) {
|
|
5840
|
+
// Inline components don't always render children, so we wrap them in Fragment which does.
|
|
5841
|
+
if (jsx.type !== Fragment && !isQwikComponent(jsx.type)) {
|
|
5842
|
+
return _jsxSorted(Fragment, null, null, [jsx, placeholder], 0, null);
|
|
5843
|
+
}
|
|
5844
|
+
if (jsx.children == null) {
|
|
5845
|
+
jsx.children = placeholder;
|
|
5846
|
+
}
|
|
5847
|
+
else if (isArray(jsx.children)) {
|
|
5848
|
+
jsx.children.push(placeholder);
|
|
5849
|
+
}
|
|
5850
|
+
else {
|
|
5851
|
+
jsx.children = [jsx.children, placeholder];
|
|
5746
5852
|
}
|
|
5853
|
+
return jsx;
|
|
5747
5854
|
}
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
if (!(signal instanceof WrappedSignalImpl)) {
|
|
5752
|
-
return false;
|
|
5855
|
+
// For primitives, we can't add children, so we wrap them in a fragment.
|
|
5856
|
+
if (isPrimitiveOrNullUndefined(jsx)) {
|
|
5857
|
+
return _jsxSorted(Fragment, null, null, [jsx, placeholder], 0, null);
|
|
5753
5858
|
}
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
}
|
|
5859
|
+
// For an array of nodes, we inject the placeholder into the first element.
|
|
5860
|
+
if (isArray(jsx) && jsx.length > 0) {
|
|
5861
|
+
injectPlaceholderElement(jsx[0], placeholder);
|
|
5862
|
+
return jsx;
|
|
5759
5863
|
}
|
|
5760
|
-
|
|
5864
|
+
// For anything else we do nothing.
|
|
5865
|
+
return jsx;
|
|
5866
|
+
}
|
|
5867
|
+
/** @returns An empty <script> element for adding qwik metadata attributes to */
|
|
5868
|
+
function createPlaceholderScriptNode() {
|
|
5869
|
+
return new JSXNodeImpl('script', null, { hidden: '' }, null, 0, null);
|
|
5761
5870
|
}
|
|
5762
5871
|
|
|
5763
5872
|
function collectChildren(first, last = null) {
|
|
@@ -6033,6 +6142,22 @@ function executeTasks(vNode, container, cursorData) {
|
|
|
6033
6142
|
}
|
|
6034
6143
|
return taskPromise;
|
|
6035
6144
|
}
|
|
6145
|
+
function setInlineComponentData(vNode, componentFn, subscriptionHost, jsxProps) {
|
|
6146
|
+
const props = (vNode.props ||= {});
|
|
6147
|
+
props[INLINE_COMPONENT_DATA_KEY] = {
|
|
6148
|
+
componentFn,
|
|
6149
|
+
subscriptionHost,
|
|
6150
|
+
props: jsxProps,
|
|
6151
|
+
};
|
|
6152
|
+
}
|
|
6153
|
+
function getInlineComponentData(vNode) {
|
|
6154
|
+
const props = vNode.props;
|
|
6155
|
+
const data = props?.[INLINE_COMPONENT_DATA_KEY] || null;
|
|
6156
|
+
if (data) {
|
|
6157
|
+
delete props[INLINE_COMPONENT_DATA_KEY];
|
|
6158
|
+
}
|
|
6159
|
+
return data;
|
|
6160
|
+
}
|
|
6036
6161
|
function getNodeDiffPayload(vNode) {
|
|
6037
6162
|
const props = vNode.props;
|
|
6038
6163
|
return props?.[NODE_DIFF_DATA_KEY];
|
|
@@ -6050,7 +6175,7 @@ function setErrorPayload(vNode, error) {
|
|
|
6050
6175
|
props[ERROR_DATA_KEY] = error;
|
|
6051
6176
|
}
|
|
6052
6177
|
function executeErrorWrap(vNode, journal) {
|
|
6053
|
-
vNode.dirty &= -
|
|
6178
|
+
vNode.dirty &= -513 /* ChoreBits.ERROR_WRAP */;
|
|
6054
6179
|
const err = getErrorPayload(vNode);
|
|
6055
6180
|
if (!err) {
|
|
6056
6181
|
return;
|
|
@@ -6071,7 +6196,7 @@ function executeErrorWrap(vNode, journal) {
|
|
|
6071
6196
|
// avoid an infinite loop — those children are now under errored-host, not this host.
|
|
6072
6197
|
// This is safe because CHILDREN is always processed before ERROR_WRAP in the walker,
|
|
6073
6198
|
// so any pre-existing child work has already completed.
|
|
6074
|
-
vNode.dirty &= -
|
|
6199
|
+
vNode.dirty &= -65 /* ChoreBits.CHILDREN */;
|
|
6075
6200
|
vNode.dirtyChildren = null;
|
|
6076
6201
|
}
|
|
6077
6202
|
function executeNodeDiff(vNode, container, journal, cursor) {
|
|
@@ -6104,7 +6229,19 @@ function executeComponentChore(vNode, container, journal, cursor) {
|
|
|
6104
6229
|
return;
|
|
6105
6230
|
}
|
|
6106
6231
|
const props = container.getHostProp(host, ELEMENT_PROPS) || null;
|
|
6107
|
-
|
|
6232
|
+
return executeComponentFunction(container, host, host, componentQRL, props, journal, cursor);
|
|
6233
|
+
}
|
|
6234
|
+
function executeInlineComponentChore(vNode, container, journal, cursor) {
|
|
6235
|
+
vNode.dirty &= -9 /* ChoreBits.INLINE_COMPONENT */;
|
|
6236
|
+
const host = vNode;
|
|
6237
|
+
const inlineComponentData = getInlineComponentData(vNode);
|
|
6238
|
+
if (!inlineComponentData) {
|
|
6239
|
+
return;
|
|
6240
|
+
}
|
|
6241
|
+
return executeComponentFunction(container, host, inlineComponentData.subscriptionHost || container.rootVNode, inlineComponentData.componentFn, inlineComponentData.props, journal, cursor);
|
|
6242
|
+
}
|
|
6243
|
+
function executeComponentFunction(container, host, subscriptionHost, componentFn, props, journal, cursor) {
|
|
6244
|
+
const result = safeCall(() => executeComponent(container, host, subscriptionHost, componentFn, props), (jsx) => {
|
|
6108
6245
|
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
6109
6246
|
return retryOnPromise(() => vnode_diff(container, journal, jsx, host, cursor, addComponentStylePrefix(styleScopedId)));
|
|
6110
6247
|
}, (err) => {
|
|
@@ -6170,7 +6307,7 @@ function setNodeProp(domVNode, journal, property, value, isConst, scopedStyleIdP
|
|
|
6170
6307
|
* @returns Void
|
|
6171
6308
|
*/
|
|
6172
6309
|
function executeNodeProps(vNode, journal) {
|
|
6173
|
-
vNode.dirty &= -
|
|
6310
|
+
vNode.dirty &= -17 /* ChoreBits.NODE_PROPS */;
|
|
6174
6311
|
if (!(vNode.flags & 1 /* VNodeFlags.Element */)) {
|
|
6175
6312
|
return;
|
|
6176
6313
|
}
|
|
@@ -6201,7 +6338,7 @@ function executeNodeProps(vNode, journal) {
|
|
|
6201
6338
|
* @returns Void
|
|
6202
6339
|
*/
|
|
6203
6340
|
function executeCleanup(vNode, container) {
|
|
6204
|
-
vNode.dirty &= -
|
|
6341
|
+
vNode.dirty &= -129 /* ChoreBits.CLEANUP */;
|
|
6205
6342
|
// TODO add promises to extraPromises
|
|
6206
6343
|
const elementSeq = container.getHostProp(vNode, ELEMENT_SEQ);
|
|
6207
6344
|
if (!elementSeq || elementSeq.length === 0) {
|
|
@@ -6228,7 +6365,7 @@ function executeCleanup(vNode, container) {
|
|
|
6228
6365
|
* @returns Promise if computation is async, void otherwise
|
|
6229
6366
|
*/
|
|
6230
6367
|
function executeCompute(vNode, container) {
|
|
6231
|
-
vNode.dirty &= -
|
|
6368
|
+
vNode.dirty &= -33 /* ChoreBits.COMPUTE */;
|
|
6232
6369
|
const target = container.getHostProp(vNode, HOST_SIGNAL);
|
|
6233
6370
|
if (!target) {
|
|
6234
6371
|
return;
|
|
@@ -6254,7 +6391,7 @@ function executeCompute(vNode, container) {
|
|
|
6254
6391
|
* @returns Promise if reconcile is async, void otherwise
|
|
6255
6392
|
*/
|
|
6256
6393
|
function executeReconcile(vNode, container, journal, cursor) {
|
|
6257
|
-
vNode.dirty &= -
|
|
6394
|
+
vNode.dirty &= -257 /* ChoreBits.RECONCILE */;
|
|
6258
6395
|
const host = vNode;
|
|
6259
6396
|
const props = container.getHostProp(host, ELEMENT_PROPS) || null;
|
|
6260
6397
|
if (!props) {
|
|
@@ -6428,16 +6565,9 @@ function executeAfterFlush(container, cursorData) {
|
|
|
6428
6565
|
cursorData.afterFlushTasks = null;
|
|
6429
6566
|
return;
|
|
6430
6567
|
}
|
|
6431
|
-
let visibleTaskPromise;
|
|
6432
6568
|
for (let i = 0; i < visibleTasks.length; i++) {
|
|
6433
6569
|
const task = visibleTasks[i];
|
|
6434
|
-
|
|
6435
|
-
if (isPromise(result)) {
|
|
6436
|
-
visibleTaskPromise = visibleTaskPromise ? visibleTaskPromise.then(() => result) : result;
|
|
6437
|
-
}
|
|
6438
|
-
}
|
|
6439
|
-
if (visibleTaskPromise) {
|
|
6440
|
-
(cursorData.extraPromises ||= []).push(visibleTaskPromise);
|
|
6570
|
+
runTask(task, container, task.$el$);
|
|
6441
6571
|
}
|
|
6442
6572
|
cursorData.afterFlushTasks = null;
|
|
6443
6573
|
}
|
|
@@ -6559,7 +6689,7 @@ function walkCursor(cursor, until) {
|
|
|
6559
6689
|
return;
|
|
6560
6690
|
}
|
|
6561
6691
|
// Skip if the vNode is not dirty
|
|
6562
|
-
if (!(currentVNode.dirty &
|
|
6692
|
+
if (!(currentVNode.dirty & 1023 /* ChoreBits.DIRTY_MASK */)) {
|
|
6563
6693
|
// Move to next node
|
|
6564
6694
|
__EXPERIMENTAL__.suspense && clearNearestCursorBoundary(currentVNode);
|
|
6565
6695
|
setCursorPosition(container, cursorData, getNextVNode(currentVNode, cursor, container));
|
|
@@ -6568,10 +6698,10 @@ function walkCursor(cursor, until) {
|
|
|
6568
6698
|
// Skip if the vNode is deleted
|
|
6569
6699
|
if (currentVNode.flags & 32 /* VNodeFlags.Deleted */) {
|
|
6570
6700
|
// if deleted, run cleanup if needed
|
|
6571
|
-
if (currentVNode.dirty &
|
|
6701
|
+
if (currentVNode.dirty & 128 /* ChoreBits.CLEANUP */) {
|
|
6572
6702
|
executeCleanup(currentVNode, container);
|
|
6573
6703
|
}
|
|
6574
|
-
else if (currentVNode.dirty &
|
|
6704
|
+
else if (currentVNode.dirty & 64 /* ChoreBits.CHILDREN */) {
|
|
6575
6705
|
const next = tryDescendDirtyChildren(container, cursorData, currentVNode, cursor);
|
|
6576
6706
|
if (next !== null) {
|
|
6577
6707
|
currentVNode = next;
|
|
@@ -6579,7 +6709,7 @@ function walkCursor(cursor, until) {
|
|
|
6579
6709
|
}
|
|
6580
6710
|
}
|
|
6581
6711
|
// Clear dirty bits and move to next node
|
|
6582
|
-
currentVNode.dirty &= -
|
|
6712
|
+
currentVNode.dirty &= -1024 /* ChoreBits.DIRTY_MASK */;
|
|
6583
6713
|
setCursorPosition(container, cursorData, getNextVNode(currentVNode, cursor, container));
|
|
6584
6714
|
continue;
|
|
6585
6715
|
}
|
|
@@ -6595,23 +6725,26 @@ function walkCursor(cursor, until) {
|
|
|
6595
6725
|
else if (currentVNode.dirty & 4 /* ChoreBits.COMPONENT */) {
|
|
6596
6726
|
result = executeComponentChore(currentVNode, container, journal, cursor);
|
|
6597
6727
|
}
|
|
6598
|
-
else if (currentVNode.dirty &
|
|
6728
|
+
else if (currentVNode.dirty & 8 /* ChoreBits.INLINE_COMPONENT */) {
|
|
6729
|
+
result = executeInlineComponentChore(currentVNode, container, journal, cursor);
|
|
6730
|
+
}
|
|
6731
|
+
else if (currentVNode.dirty & 256 /* ChoreBits.RECONCILE */) {
|
|
6599
6732
|
result = executeReconcile(currentVNode, container, journal, cursor);
|
|
6600
6733
|
}
|
|
6601
|
-
else if (currentVNode.dirty &
|
|
6734
|
+
else if (currentVNode.dirty & 16 /* ChoreBits.NODE_PROPS */) {
|
|
6602
6735
|
executeNodeProps(currentVNode, journal);
|
|
6603
6736
|
}
|
|
6604
|
-
else if (currentVNode.dirty &
|
|
6737
|
+
else if (currentVNode.dirty & 32 /* ChoreBits.COMPUTE */) {
|
|
6605
6738
|
result = executeCompute(currentVNode, container);
|
|
6606
6739
|
}
|
|
6607
|
-
else if (currentVNode.dirty &
|
|
6740
|
+
else if (currentVNode.dirty & 64 /* ChoreBits.CHILDREN */) {
|
|
6608
6741
|
const next = tryDescendDirtyChildren(container, cursorData, currentVNode, cursor);
|
|
6609
6742
|
if (next !== null) {
|
|
6610
6743
|
currentVNode = next;
|
|
6611
6744
|
continue;
|
|
6612
6745
|
}
|
|
6613
6746
|
}
|
|
6614
|
-
else if (currentVNode.dirty &
|
|
6747
|
+
else if (currentVNode.dirty & 512 /* ChoreBits.ERROR_WRAP */) {
|
|
6615
6748
|
// Must run after CHILDREN so that all descendant chores (e.g. signal text
|
|
6616
6749
|
// NODE_DIFF updates) are flushed before we reparent children into the
|
|
6617
6750
|
// errored-host wrapper element.
|
|
@@ -6625,14 +6758,20 @@ function walkCursor(cursor, until) {
|
|
|
6625
6758
|
if (result && isPromise(result)) {
|
|
6626
6759
|
addCursorBoundary(cursorData, currentVNode);
|
|
6627
6760
|
// Store promise on cursor and pause
|
|
6628
|
-
|
|
6761
|
+
const blockingPromise = result;
|
|
6762
|
+
cursorData.promise = blockingPromise;
|
|
6629
6763
|
pauseCursor(cursor, container);
|
|
6630
6764
|
const host = currentVNode;
|
|
6631
|
-
|
|
6765
|
+
blockingPromise
|
|
6632
6766
|
.catch((error) => {
|
|
6633
|
-
|
|
6767
|
+
if (cursorData.promise === blockingPromise) {
|
|
6768
|
+
container.handleError(error, host);
|
|
6769
|
+
}
|
|
6634
6770
|
})
|
|
6635
6771
|
.finally(() => {
|
|
6772
|
+
if (cursorData.promise !== blockingPromise) {
|
|
6773
|
+
return;
|
|
6774
|
+
}
|
|
6636
6775
|
cursorData.promise = null;
|
|
6637
6776
|
resumeCursor(cursor, container);
|
|
6638
6777
|
triggerCursors();
|
|
@@ -6645,11 +6784,11 @@ function walkCursor(cursor, until) {
|
|
|
6645
6784
|
}
|
|
6646
6785
|
}
|
|
6647
6786
|
isDev &&
|
|
6648
|
-
assertFalse(!!(cursor.dirty &
|
|
6787
|
+
assertFalse(!!(cursor.dirty & 1023 /* ChoreBits.DIRTY_MASK */ && !cursorData.position), 'Cursor is still dirty and position is not set after walking');
|
|
6649
6788
|
finishWalk(container, cursor, cursorData, isRunningOnServer);
|
|
6650
6789
|
}
|
|
6651
6790
|
function finishWalk(container, cursor, cursorData, isServer) {
|
|
6652
|
-
if (!(cursor.dirty &
|
|
6791
|
+
if (!(cursor.dirty & 1023 /* ChoreBits.DIRTY_MASK */)) {
|
|
6653
6792
|
removeCursorFromQueue(cursor, container);
|
|
6654
6793
|
if (!isServer) {
|
|
6655
6794
|
executeFlushPhase(cursor, container);
|
|
@@ -6674,7 +6813,7 @@ function resolveCursor(container) {
|
|
|
6674
6813
|
function tryDescendDirtyChildren(container, cursorData, currentVNode, cursor) {
|
|
6675
6814
|
const dirtyChildren = currentVNode.dirtyChildren;
|
|
6676
6815
|
if (!dirtyChildren || dirtyChildren.length === 0) {
|
|
6677
|
-
currentVNode.dirty &= -
|
|
6816
|
+
currentVNode.dirty &= -65 /* ChoreBits.CHILDREN */;
|
|
6678
6817
|
clearNearestCursorBoundary(currentVNode);
|
|
6679
6818
|
return null;
|
|
6680
6819
|
}
|
|
@@ -6706,21 +6845,21 @@ function partitionDirtyChildren(dirtyChildren, parent) {
|
|
|
6706
6845
|
/** @returns Next vNode to process, or null if traversal is complete */
|
|
6707
6846
|
function getNextVNode(vNode, cursor, container) {
|
|
6708
6847
|
if (vNode === cursor) {
|
|
6709
|
-
if (cursor.dirty &
|
|
6848
|
+
if (cursor.dirty & 1023 /* ChoreBits.DIRTY_MASK */) {
|
|
6710
6849
|
return cursor;
|
|
6711
6850
|
}
|
|
6712
6851
|
return null;
|
|
6713
6852
|
}
|
|
6714
6853
|
// Prefer slotParent (logical owner) for Projections, fall back to parent
|
|
6715
6854
|
let parent = null;
|
|
6716
|
-
if (vNode.slotParent && vNode.slotParent.dirty &
|
|
6855
|
+
if (vNode.slotParent && vNode.slotParent.dirty & 64 /* ChoreBits.CHILDREN */) {
|
|
6717
6856
|
parent = vNode.slotParent;
|
|
6718
6857
|
}
|
|
6719
|
-
else if (vNode.parent && vNode.parent.dirty &
|
|
6858
|
+
else if (vNode.parent && vNode.parent.dirty & 64 /* ChoreBits.CHILDREN */) {
|
|
6720
6859
|
parent = vNode.parent;
|
|
6721
6860
|
}
|
|
6722
6861
|
if (!parent) {
|
|
6723
|
-
if (cursor.dirty &
|
|
6862
|
+
if (cursor.dirty & 1023 /* ChoreBits.DIRTY_MASK */) {
|
|
6724
6863
|
return cursor;
|
|
6725
6864
|
}
|
|
6726
6865
|
return null;
|
|
@@ -6731,7 +6870,7 @@ function getNextVNode(vNode, cursor, container) {
|
|
|
6731
6870
|
let count = len;
|
|
6732
6871
|
while (count-- > 0) {
|
|
6733
6872
|
const nextVNode = dirtyChildren[index];
|
|
6734
|
-
if (nextVNode.dirty &
|
|
6873
|
+
if (nextVNode.dirty & 1023 /* ChoreBits.DIRTY_MASK */) {
|
|
6735
6874
|
if (container && splitCursorBoundary(container, nextVNode)) {
|
|
6736
6875
|
index++;
|
|
6737
6876
|
if (index === len) {
|
|
@@ -6748,7 +6887,7 @@ function getNextVNode(vNode, cursor, container) {
|
|
|
6748
6887
|
}
|
|
6749
6888
|
}
|
|
6750
6889
|
// all array items checked, children are no longer dirty
|
|
6751
|
-
parent.dirty &= -
|
|
6890
|
+
parent.dirty &= -65 /* ChoreBits.CHILDREN */;
|
|
6752
6891
|
parent.dirtyChildren = null;
|
|
6753
6892
|
parent.nextDirtyChildIndex = 0;
|
|
6754
6893
|
__EXPERIMENTAL__.suspense && clearNearestCursorBoundary(parent);
|
|
@@ -6824,13 +6963,13 @@ function findCursor(vNode) {
|
|
|
6824
6963
|
/** @internal */
|
|
6825
6964
|
function _executeSsrChores(container, ssrNode) {
|
|
6826
6965
|
if (!(ssrNode.flags & 1 /* SsrNodeFlags.Updatable */)) {
|
|
6827
|
-
if (ssrNode.dirty &
|
|
6966
|
+
if (ssrNode.dirty & 16 /* ChoreBits.NODE_PROPS */) {
|
|
6828
6967
|
executeNodePropChore(container, ssrNode);
|
|
6829
6968
|
}
|
|
6830
|
-
if (ssrNode.dirty &
|
|
6969
|
+
if (ssrNode.dirty & 32 /* ChoreBits.COMPUTE */) {
|
|
6831
6970
|
executeCompute(ssrNode, container);
|
|
6832
6971
|
}
|
|
6833
|
-
if (isDev && ssrNode.dirty &
|
|
6972
|
+
if (isDev && ssrNode.dirty & 1023 /* ChoreBits.DIRTY_MASK */) {
|
|
6834
6973
|
// We are running on the server.
|
|
6835
6974
|
// On server we can't schedule task for a different host!
|
|
6836
6975
|
// Server is SSR, and therefore scheduling for anything but the current host
|
|
@@ -6845,7 +6984,7 @@ function _executeSsrChores(container, ssrNode) {
|
|
|
6845
6984
|
This is often caused by modifying a signal in an already rendered component during SSR.`;
|
|
6846
6985
|
logWarn(warningMessage);
|
|
6847
6986
|
}
|
|
6848
|
-
ssrNode.dirty &= -
|
|
6987
|
+
ssrNode.dirty &= -1024 /* ChoreBits.DIRTY_MASK */;
|
|
6849
6988
|
return;
|
|
6850
6989
|
}
|
|
6851
6990
|
let promise = null;
|
|
@@ -6855,7 +6994,7 @@ function _executeSsrChores(container, ssrNode) {
|
|
|
6855
6994
|
promise = result;
|
|
6856
6995
|
}
|
|
6857
6996
|
}
|
|
6858
|
-
if (ssrNode.dirty &
|
|
6997
|
+
if (ssrNode.dirty & 256 /* ChoreBits.RECONCILE */) {
|
|
6859
6998
|
const result = executeReconcileChore(container, ssrNode);
|
|
6860
6999
|
promise = promise ? promise.then(() => result) : result;
|
|
6861
7000
|
}
|
|
@@ -6865,7 +7004,7 @@ function _executeSsrChores(container, ssrNode) {
|
|
|
6865
7004
|
// it after $waitOn$ completes and re-execute the component function.
|
|
6866
7005
|
// executeComponent will clear the bit after re-executing.
|
|
6867
7006
|
// Clear all dirty bits EXCEPT COMPONENT
|
|
6868
|
-
ssrNode.dirty &= -
|
|
7007
|
+
ssrNode.dirty &= -1020;
|
|
6869
7008
|
if (promise) {
|
|
6870
7009
|
return promise;
|
|
6871
7010
|
}
|
|
@@ -6893,7 +7032,7 @@ function executeTasksChore(container, ssrNode) {
|
|
|
6893
7032
|
return promise;
|
|
6894
7033
|
}
|
|
6895
7034
|
function executeNodePropChore(container, ssrNode) {
|
|
6896
|
-
ssrNode.dirty &= -
|
|
7035
|
+
ssrNode.dirty &= -17 /* ChoreBits.NODE_PROPS */;
|
|
6897
7036
|
const allPropData = ssrNode.getProp(NODE_PROPS_DATA_KEY);
|
|
6898
7037
|
if (!allPropData || allPropData.size === 0) {
|
|
6899
7038
|
return;
|
|
@@ -6909,7 +7048,7 @@ function executeNodePropChore(container, ssrNode) {
|
|
|
6909
7048
|
}
|
|
6910
7049
|
}
|
|
6911
7050
|
async function executeReconcileChore(container, ssrNode) {
|
|
6912
|
-
ssrNode.dirty &= -
|
|
7051
|
+
ssrNode.dirty &= -257 /* ChoreBits.RECONCILE */;
|
|
6913
7052
|
const host = ssrNode;
|
|
6914
7053
|
const props = container.getHostProp(host, ELEMENT_PROPS) || null;
|
|
6915
7054
|
if (!props) {
|
|
@@ -6942,7 +7081,7 @@ function propagatePath(target) {
|
|
|
6942
7081
|
for (let i = 0; i < reusablePath.length; i++) {
|
|
6943
7082
|
const child = reusablePath[i];
|
|
6944
7083
|
const parent = reusablePath[i + 1] || target;
|
|
6945
|
-
parent.dirty |=
|
|
7084
|
+
parent.dirty |= 64 /* ChoreBits.CHILDREN */;
|
|
6946
7085
|
parent.dirtyChildren ||= [];
|
|
6947
7086
|
if (!parent.dirtyChildren.includes(child)) {
|
|
6948
7087
|
parent.dirtyChildren.push(child);
|
|
@@ -6958,7 +7097,7 @@ function propagateToCursorRoot(container, vNode, cursorRoot) {
|
|
|
6958
7097
|
let cursorBoundary = getOwnCursorBoundary(container, vNode);
|
|
6959
7098
|
let current = vNode.slotParent || vNode.parent;
|
|
6960
7099
|
while (current) {
|
|
6961
|
-
const isDirty = current.dirty &
|
|
7100
|
+
const isDirty = current.dirty & 1023 /* ChoreBits.DIRTY_MASK */;
|
|
6962
7101
|
const currentIsCursor = isCursor(current);
|
|
6963
7102
|
if (__EXPERIMENTAL__.suspense) {
|
|
6964
7103
|
cursorBoundary ||=
|
|
@@ -7052,9 +7191,9 @@ function markVNodeDirty(container, vNode, bits, cursorRoot = null) {
|
|
|
7052
7191
|
}
|
|
7053
7192
|
return;
|
|
7054
7193
|
}
|
|
7055
|
-
const isRealDirty = bits &
|
|
7194
|
+
const isRealDirty = bits & 1023 /* ChoreBits.DIRTY_MASK */;
|
|
7056
7195
|
// If already dirty, no need to propagate again
|
|
7057
|
-
if ((isRealDirty ? prevDirty &
|
|
7196
|
+
if ((isRealDirty ? prevDirty & 1023 /* ChoreBits.DIRTY_MASK */ : prevDirty) || vNode === cursorRoot) {
|
|
7058
7197
|
return;
|
|
7059
7198
|
}
|
|
7060
7199
|
const parent = vNode.slotParent || vNode.parent;
|
|
@@ -7064,12 +7203,12 @@ function markVNodeDirty(container, vNode, bits, cursorRoot = null) {
|
|
|
7064
7203
|
return;
|
|
7065
7204
|
}
|
|
7066
7205
|
// We must attach to a cursor subtree if it exists
|
|
7067
|
-
if (parent && parent.dirty &
|
|
7206
|
+
if (parent && parent.dirty & 1023 /* ChoreBits.DIRTY_MASK */) {
|
|
7068
7207
|
// Dirty parent case: this vnode joins an already scheduled subtree, so inherit the parent's
|
|
7069
7208
|
// nearest boundary unless this vnode owns a boundary itself.
|
|
7070
7209
|
setNearestCursorBoundary(vNode, getOwnCursorBoundary(container, vNode) || getNearestCursorBoundary(container, parent));
|
|
7071
7210
|
if (isRealDirty) {
|
|
7072
|
-
parent.dirty |=
|
|
7211
|
+
parent.dirty |= 64 /* ChoreBits.CHILDREN */;
|
|
7073
7212
|
}
|
|
7074
7213
|
parent.dirtyChildren ||= [];
|
|
7075
7214
|
if (!parent.dirtyChildren.includes(vNode)) {
|
|
@@ -7501,14 +7640,10 @@ function vnode_walkVNode(vNode, callback) {
|
|
|
7501
7640
|
let vCursor = vNode;
|
|
7502
7641
|
// Depth first traversal
|
|
7503
7642
|
if (vnode_isTextVNode(vNode)) {
|
|
7504
|
-
callback?.(vNode, null);
|
|
7505
7643
|
return;
|
|
7506
7644
|
}
|
|
7507
7645
|
let vParent = null;
|
|
7508
7646
|
do {
|
|
7509
|
-
if (callback?.(vCursor, vParent)) {
|
|
7510
|
-
return;
|
|
7511
|
-
}
|
|
7512
7647
|
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
7513
7648
|
if (vFirstChild) {
|
|
7514
7649
|
vCursor = vFirstChild;
|
|
@@ -7700,38 +7835,53 @@ const vnode_locate = (rootVNode, id) => {
|
|
|
7700
7835
|
ensureElementVNode(rootVNode);
|
|
7701
7836
|
let vNode = rootVNode;
|
|
7702
7837
|
const containerElement = rootVNode.node;
|
|
7703
|
-
const
|
|
7838
|
+
const qVNodeRefs = containerElement.qVNodeRefs;
|
|
7704
7839
|
let elementOffset = -1;
|
|
7705
7840
|
let refElement;
|
|
7841
|
+
const localId = typeof id === 'string' ? id : '';
|
|
7706
7842
|
if (typeof id === 'string') {
|
|
7707
7843
|
isDev && assertDefined(qVNodeRefs, 'Missing qVNodeRefs.');
|
|
7708
|
-
elementOffset = parseInt(
|
|
7844
|
+
elementOffset = parseInt(localId);
|
|
7709
7845
|
refElement = qVNodeRefs.get(elementOffset);
|
|
7710
7846
|
}
|
|
7711
7847
|
else {
|
|
7712
7848
|
refElement = id;
|
|
7713
|
-
const
|
|
7714
|
-
|
|
7849
|
+
const qElement = refElement;
|
|
7850
|
+
const cachedVNode = qElement.vNode;
|
|
7851
|
+
if (cachedVNode) {
|
|
7852
|
+
return cachedVNode;
|
|
7853
|
+
}
|
|
7854
|
+
if (__EXPERIMENTAL__.suspense && qElement._qSegment) {
|
|
7855
|
+
vNode = vnode_newUnMaterializedElement(refElement);
|
|
7856
|
+
vnode_ensureElementKeyInflated(vNode);
|
|
7857
|
+
qElement.vNode = vNode;
|
|
7715
7858
|
return vNode;
|
|
7716
7859
|
}
|
|
7717
7860
|
}
|
|
7718
|
-
isDev &&
|
|
7861
|
+
isDev &&
|
|
7862
|
+
assertDefined(refElement, 'Missing refElement ' + (typeof id === 'string' ? `for id ${id}` : ''));
|
|
7719
7863
|
if (!vnode_isVNode(refElement)) {
|
|
7720
7864
|
isDev &&
|
|
7721
7865
|
assertTrue(containerElement.contains(refElement), `Couldn't find the element inside the container while locating the VNode.`);
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
while (parent && parent !== containerElement && !parent.vNode) {
|
|
7726
|
-
parent = parent.parentElement;
|
|
7727
|
-
elementPath.push(parent);
|
|
7866
|
+
if (__EXPERIMENTAL__.suspense && refElement._qSegment) {
|
|
7867
|
+
vNode = refElement.vNode || vnode_newUnMaterializedElement(refElement);
|
|
7868
|
+
vnode_ensureElementKeyInflated(vNode);
|
|
7728
7869
|
}
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7870
|
+
else {
|
|
7871
|
+
// We need to find the vnode.
|
|
7872
|
+
let parent = refElement;
|
|
7873
|
+
const elementPath = [refElement];
|
|
7874
|
+
while (parent && parent !== containerElement && !parent.vNode) {
|
|
7875
|
+
parent = parent.parentElement;
|
|
7876
|
+
elementPath.push(parent);
|
|
7877
|
+
}
|
|
7878
|
+
if (parent.vNode) {
|
|
7879
|
+
vNode = parent.vNode;
|
|
7880
|
+
}
|
|
7881
|
+
// Start at rootVNode and follow the `elementPath` to find the vnode.
|
|
7882
|
+
for (let i = elementPath.length - 2; i >= 0; i--) {
|
|
7883
|
+
vNode = vnode_getVNodeForChildNode(vNode, elementPath[i]);
|
|
7884
|
+
}
|
|
7735
7885
|
}
|
|
7736
7886
|
if (elementOffset != -1) {
|
|
7737
7887
|
refElement.vNode = vNode;
|
|
@@ -7743,11 +7893,11 @@ const vnode_locate = (rootVNode, id) => {
|
|
|
7743
7893
|
}
|
|
7744
7894
|
if (typeof id === 'string') {
|
|
7745
7895
|
// process virtual node search.
|
|
7746
|
-
const idLength =
|
|
7747
|
-
let idx = indexOfAlphanumeric(
|
|
7896
|
+
const idLength = localId.length;
|
|
7897
|
+
let idx = indexOfAlphanumeric(localId, idLength);
|
|
7748
7898
|
let childIdx = 0;
|
|
7749
7899
|
while (idx < idLength) {
|
|
7750
|
-
const ch =
|
|
7900
|
+
const ch = localId.charCodeAt(idx);
|
|
7751
7901
|
childIdx *= 26 /* a-z */;
|
|
7752
7902
|
if (ch >= 97 /* a */) {
|
|
7753
7903
|
// is lowercase
|
|
@@ -7811,9 +7961,10 @@ const vnode_getVNodeForChildNode = (vNode, childElement) => {
|
|
|
7811
7961
|
return child;
|
|
7812
7962
|
};
|
|
7813
7963
|
const indexOfAlphanumeric = (id, length) => {
|
|
7814
|
-
let idx = 0;
|
|
7964
|
+
let idx = id.charCodeAt(0) === 45 /* - */ ? 1 : 0;
|
|
7815
7965
|
while (idx < length) {
|
|
7816
|
-
|
|
7966
|
+
const ch = id.charCodeAt(idx);
|
|
7967
|
+
if (ch >= 48 /* 0 */ && ch <= 57 /* 9 */) {
|
|
7817
7968
|
idx++;
|
|
7818
7969
|
}
|
|
7819
7970
|
else {
|
|
@@ -8211,6 +8362,12 @@ const vnode_getFirstChild = (vnode) => {
|
|
|
8211
8362
|
return null;
|
|
8212
8363
|
}
|
|
8213
8364
|
let vFirstChild = vnode.firstChild;
|
|
8365
|
+
if (__EXPERIMENTAL__.suspense &&
|
|
8366
|
+
vFirstChild === undefined &&
|
|
8367
|
+
vnode_isElementVNode(vnode) &&
|
|
8368
|
+
hasOnlySuspensePlaceholder(vnode.node)) {
|
|
8369
|
+
return null;
|
|
8370
|
+
}
|
|
8214
8371
|
if (vFirstChild === undefined) {
|
|
8215
8372
|
vFirstChild = ensureMaterialized(vnode);
|
|
8216
8373
|
}
|
|
@@ -8232,6 +8389,7 @@ const splitVNodeData = (vNodeData) => {
|
|
|
8232
8389
|
};
|
|
8233
8390
|
const materialize = (vNode, element, firstChild, vNodeData) => {
|
|
8234
8391
|
vnode_ensureElementKeyInflated(vNode);
|
|
8392
|
+
__EXPERIMENTAL__.suspense ? element._qSegment || null : null;
|
|
8235
8393
|
if (vNodeData) {
|
|
8236
8394
|
if (vNodeData.charCodeAt(0) === VNodeDataChar.SEPARATOR &&
|
|
8237
8395
|
vNodeData.charCodeAt(1) === VNodeDataChar.SEPARATOR) {
|
|
@@ -8259,7 +8417,7 @@ const materialize = (vNode, element, firstChild, vNodeData) => {
|
|
|
8259
8417
|
}
|
|
8260
8418
|
else {
|
|
8261
8419
|
// Materialize DOM element from HTML only
|
|
8262
|
-
return materializeFromDOM(vNode, firstChild);
|
|
8420
|
+
return materializeFromDOM(vNode, firstChild, undefined);
|
|
8263
8421
|
}
|
|
8264
8422
|
};
|
|
8265
8423
|
const ensureMaterialized = (vnode) => {
|
|
@@ -8384,13 +8542,13 @@ const fastFirstChild = (node) => {
|
|
|
8384
8542
|
node = node && _fastFirstChild.call(node);
|
|
8385
8543
|
// Handle q:ignore as first child (e.g. qwikify$ Host with reactify$ projections).
|
|
8386
8544
|
// Navigate depth-first to the first q:container-island and return its first element.
|
|
8387
|
-
if (node &&
|
|
8388
|
-
fastNodeType(node) === /* Node.COMMENT_NODE */ 8 &&
|
|
8389
|
-
node.nodeValue?.startsWith(QIgnore)) {
|
|
8545
|
+
if (node && fastNodeType(node) === /* Node.COMMENT_NODE */ 8) {
|
|
8390
8546
|
if (!_fastNextSibling) {
|
|
8391
8547
|
_fastNextSibling = fastGetter(node, 'nextSibling');
|
|
8392
8548
|
}
|
|
8393
|
-
|
|
8549
|
+
if (node.nodeValue?.startsWith(QIgnore)) {
|
|
8550
|
+
return getNodeAfterCommentNode(node, QContainerIsland, _fastNextSibling, _fastFirstChild);
|
|
8551
|
+
}
|
|
8394
8552
|
}
|
|
8395
8553
|
while (node && !fastIsTextOrElement(node)) {
|
|
8396
8554
|
node = fastNextSibling(node);
|
|
@@ -8400,8 +8558,9 @@ const fastFirstChild = (node) => {
|
|
|
8400
8558
|
const fastNamespaceURI = createFastGetter('namespaceURI');
|
|
8401
8559
|
const fastNodeName = createFastGetter('nodeName');
|
|
8402
8560
|
const fastOwnerDocument = createFastGetter('ownerDocument');
|
|
8403
|
-
const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
8561
|
+
const materializeFromDOM = (vParent, firstChild, vData, segmentId) => {
|
|
8404
8562
|
let vFirstChild = null;
|
|
8563
|
+
let idx = 0;
|
|
8405
8564
|
const skipElements = () => {
|
|
8406
8565
|
while (isElement(child) && shouldSkipElement(child)) {
|
|
8407
8566
|
child = fastNextSibling(child);
|
|
@@ -8422,6 +8581,8 @@ const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
|
8422
8581
|
vnode_ensureElementKeyInflated(vNextChild);
|
|
8423
8582
|
}
|
|
8424
8583
|
if (vNextChild) {
|
|
8584
|
+
vNextChild.flags = (vNextChild.flags & 4095 /* VNodeFlagsIndex.mask */) | (idx << 12 /* VNodeFlagsIndex.shift */);
|
|
8585
|
+
idx++;
|
|
8425
8586
|
vNextChild.parent = vParent;
|
|
8426
8587
|
vChild && (vChild.nextSibling = vNextChild);
|
|
8427
8588
|
vNextChild.previousSibling = vChild;
|
|
@@ -8447,7 +8608,7 @@ const materializeFromDOM = (vParent, firstChild, vData) => {
|
|
|
8447
8608
|
container = getDomContainer(vParent.node);
|
|
8448
8609
|
}
|
|
8449
8610
|
const id = consumeValue();
|
|
8450
|
-
container.$setRawState$(parseInt(id), vParent);
|
|
8611
|
+
container.$setRawState$(parseInt(id, 10), vParent);
|
|
8451
8612
|
isDev && vnode_setProp(vParent, ELEMENT_ID, id);
|
|
8452
8613
|
}
|
|
8453
8614
|
else if (peek() === VNodeDataChar.BACK_REFS) {
|
|
@@ -8608,6 +8769,9 @@ function vnode_toString(depth = 20, offset = '', materialize = false, siblings =
|
|
|
8608
8769
|
attrs.push(' ' + key + '=' + qwikDebugToString(value));
|
|
8609
8770
|
}
|
|
8610
8771
|
}
|
|
8772
|
+
if (vnode.slotParent) {
|
|
8773
|
+
attrs.push(' slotParent=(C)');
|
|
8774
|
+
}
|
|
8611
8775
|
}
|
|
8612
8776
|
const name = (colorize ? NAME_COL_PREFIX : '') +
|
|
8613
8777
|
(VirtualTypeName[vnode_getProp(vnode, DEBUG_TYPE, null) || "V" /* VirtualType.Virtual */] ||
|
|
@@ -8678,8 +8842,19 @@ function shouldSkipElement(element) {
|
|
|
8678
8842
|
(element.nodeName === 'STYLE' &&
|
|
8679
8843
|
(element.hasAttribute(QScopedStyle) || element.hasAttribute(QStyle))));
|
|
8680
8844
|
}
|
|
8845
|
+
function hasOnlySuspensePlaceholder(element) {
|
|
8846
|
+
const segmentId = element.getAttribute(QSuspenseResultParent);
|
|
8847
|
+
if (segmentId === null) {
|
|
8848
|
+
return false;
|
|
8849
|
+
}
|
|
8850
|
+
const firstChild = fastFirstChild(element);
|
|
8851
|
+
return (isElement(firstChild) &&
|
|
8852
|
+
firstChild.localName === 'template' &&
|
|
8853
|
+
firstChild.getAttribute(QSuspenseResolved) === segmentId &&
|
|
8854
|
+
fastNextSibling(firstChild) === null);
|
|
8855
|
+
}
|
|
8681
8856
|
const stack = [];
|
|
8682
|
-
function materializeFromVNodeData(vParent, vData, element, child) {
|
|
8857
|
+
function materializeFromVNodeData(vParent, vData, element, child, segmentId) {
|
|
8683
8858
|
let idx = 0;
|
|
8684
8859
|
let vFirst = null;
|
|
8685
8860
|
let vLast = null;
|
|
@@ -8748,7 +8923,7 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
8748
8923
|
container = getDomContainer(element);
|
|
8749
8924
|
}
|
|
8750
8925
|
const id = consumeValue();
|
|
8751
|
-
container.$setRawState$(parseInt(id), vParent);
|
|
8926
|
+
container.$setRawState$(parseInt(id, 10), vParent);
|
|
8752
8927
|
isDev && vnode_setProp(vParent, ELEMENT_ID, id);
|
|
8753
8928
|
}
|
|
8754
8929
|
else if (peek() === VNodeDataChar.PROPS) {
|
|
@@ -8759,7 +8934,7 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
8759
8934
|
let value;
|
|
8760
8935
|
if (isEscapedValue) {
|
|
8761
8936
|
consume();
|
|
8762
|
-
value =
|
|
8937
|
+
value = decodeURIComponent(decodeVNodeDataString(consumeValue()));
|
|
8763
8938
|
consume();
|
|
8764
8939
|
}
|
|
8765
8940
|
else {
|
|
@@ -8798,8 +8973,19 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
8798
8973
|
}
|
|
8799
8974
|
else if (peek() === VNodeDataChar.SEPARATOR) {
|
|
8800
8975
|
// Custom attribute: |key|value
|
|
8801
|
-
const
|
|
8802
|
-
const
|
|
8976
|
+
const keyValue = consumeValue();
|
|
8977
|
+
const key = decodeVNodeDataString(keyValue);
|
|
8978
|
+
const valueSeparatorIdx = nextToConsumeIdx + keyValue.length + 1;
|
|
8979
|
+
const isEscapedValue = getChar(valueSeparatorIdx + 1) === VNodeDataChar.SEPARATOR;
|
|
8980
|
+
let value;
|
|
8981
|
+
if (isEscapedValue) {
|
|
8982
|
+
consume();
|
|
8983
|
+
value = decodeURI(decodeVNodeDataString(consumeValue()));
|
|
8984
|
+
consume();
|
|
8985
|
+
}
|
|
8986
|
+
else {
|
|
8987
|
+
value = decodeVNodeDataString(consumeValue());
|
|
8988
|
+
}
|
|
8803
8989
|
vnode_setProp(vParent, key, value);
|
|
8804
8990
|
}
|
|
8805
8991
|
else if (peek() === VNodeDataChar.CLOSE) {
|
|
@@ -9127,6 +9313,15 @@ const addQrlToSerializationCtx = (effectSubscriber, container) => {
|
|
|
9127
9313
|
}
|
|
9128
9314
|
}
|
|
9129
9315
|
};
|
|
9316
|
+
const getEffectSerializationContainer = (renderContainer, ownerContainer) => {
|
|
9317
|
+
if (renderContainer &&
|
|
9318
|
+
(!ownerContainer ||
|
|
9319
|
+
renderContainer === ownerContainer ||
|
|
9320
|
+
isOutOfOrderSegmentContainer(renderContainer))) {
|
|
9321
|
+
return renderContainer;
|
|
9322
|
+
}
|
|
9323
|
+
return ownerContainer;
|
|
9324
|
+
};
|
|
9130
9325
|
const scheduleEffects = (container, signal, effects) => {
|
|
9131
9326
|
const isRunningOnBrowser = qTest ? !isServerPlatform() : isBrowser$1;
|
|
9132
9327
|
if (effects) {
|
|
@@ -9171,7 +9366,7 @@ const scheduleEffects = (container, signal, effects) => {
|
|
|
9171
9366
|
}
|
|
9172
9367
|
data.set(property, payload);
|
|
9173
9368
|
}
|
|
9174
|
-
markVNodeDirty(container, consumer,
|
|
9369
|
+
markVNodeDirty(container, consumer, 16 /* ChoreBits.NODE_PROPS */);
|
|
9175
9370
|
}
|
|
9176
9371
|
}
|
|
9177
9372
|
};
|
|
@@ -9413,11 +9608,11 @@ class StoreHandler {
|
|
|
9413
9608
|
}
|
|
9414
9609
|
else {
|
|
9415
9610
|
isDev &&
|
|
9416
|
-
assertTrue(!ctx.$container$ || ctx.$container
|
|
9611
|
+
assertTrue(!ctx.$container$ || isSameContainer(ctx.$container$, this.$container$), 'Do not use signals across containers');
|
|
9417
9612
|
}
|
|
9418
9613
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
9419
9614
|
if (effectSubscriber) {
|
|
9420
|
-
addStoreEffect(target, Array.isArray(target) ? STORE_ALL_PROPS : prop, this, effectSubscriber);
|
|
9615
|
+
addStoreEffect(target, Array.isArray(target) ? STORE_ALL_PROPS : prop, this, effectSubscriber, ctx.$container$);
|
|
9421
9616
|
}
|
|
9422
9617
|
}
|
|
9423
9618
|
if (prop === 'toString' && value === Object.prototype.toString) {
|
|
@@ -9471,7 +9666,7 @@ class StoreHandler {
|
|
|
9471
9666
|
if (ctx) {
|
|
9472
9667
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
9473
9668
|
if (effectSubscriber) {
|
|
9474
|
-
addStoreEffect(target, Array.isArray(target) ? STORE_ALL_PROPS : prop, this, effectSubscriber);
|
|
9669
|
+
addStoreEffect(target, Array.isArray(target) ? STORE_ALL_PROPS : prop, this, effectSubscriber, ctx.$container$);
|
|
9475
9670
|
}
|
|
9476
9671
|
}
|
|
9477
9672
|
}
|
|
@@ -9481,7 +9676,7 @@ class StoreHandler {
|
|
|
9481
9676
|
const ctx = tryGetInvokeContext();
|
|
9482
9677
|
const effectSubscriber = ctx?.$effectSubscriber$;
|
|
9483
9678
|
if (effectSubscriber) {
|
|
9484
|
-
addStoreEffect(target, STORE_ALL_PROPS, this, effectSubscriber);
|
|
9679
|
+
addStoreEffect(target, STORE_ALL_PROPS, this, effectSubscriber, ctx.$container$);
|
|
9485
9680
|
}
|
|
9486
9681
|
return Reflect.ownKeys(target);
|
|
9487
9682
|
}
|
|
@@ -9499,7 +9694,7 @@ class StoreHandler {
|
|
|
9499
9694
|
};
|
|
9500
9695
|
}
|
|
9501
9696
|
}
|
|
9502
|
-
function addStoreEffect(target, prop, store, effectSubscription) {
|
|
9697
|
+
function addStoreEffect(target, prop, store, effectSubscription, renderContainer) {
|
|
9503
9698
|
const effectsMap = (store.$effects$ ||= new Map());
|
|
9504
9699
|
let effects = effectsMap.get(prop);
|
|
9505
9700
|
if (!effects) {
|
|
@@ -9509,14 +9704,21 @@ function addStoreEffect(target, prop, store, effectSubscription) {
|
|
|
9509
9704
|
// Let's make sure that we have a reference to this effect.
|
|
9510
9705
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
9511
9706
|
// changes we know who to notify.
|
|
9707
|
+
const isOnServer = qTest ? isServerPlatform() : isServer;
|
|
9708
|
+
const shouldRecordExternalRootEffect = __EXPERIMENTAL__.suspense && store instanceof StoreHandler && isOnServer;
|
|
9512
9709
|
ensureContainsSubscription(effects, effectSubscription);
|
|
9513
9710
|
// But when effect is scheduled in needs to be able to know which signals
|
|
9514
9711
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
9515
9712
|
// to this signal.
|
|
9516
9713
|
ensureContainsBackRef(effectSubscription, target);
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9714
|
+
if (isOnServer) {
|
|
9715
|
+
const serializationContainer = getEffectSerializationContainer(renderContainer, store.$container$);
|
|
9716
|
+
if (shouldRecordExternalRootEffect) {
|
|
9717
|
+
serializationContainer?.$recordExternalRootEffect$?.(target, effectSubscription, prop, effectsMap);
|
|
9718
|
+
}
|
|
9719
|
+
// TODO is this needed with the preloader?
|
|
9720
|
+
addQrlToSerializationCtx(effectSubscription, serializationContainer);
|
|
9721
|
+
}
|
|
9520
9722
|
}
|
|
9521
9723
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
9522
9724
|
target[prop] = value;
|
|
@@ -9637,6 +9839,7 @@ const _typeIdNames = [
|
|
|
9637
9839
|
'PropsProxy',
|
|
9638
9840
|
'SubscriptionData',
|
|
9639
9841
|
'EffectSubscription',
|
|
9842
|
+
'SubscriptionPatch',
|
|
9640
9843
|
];
|
|
9641
9844
|
|
|
9642
9845
|
function qrlToString(serializationContext, qrl, raw) {
|
|
@@ -9697,6 +9900,23 @@ function qrlToString(serializationContext, qrl, raw) {
|
|
|
9697
9900
|
}
|
|
9698
9901
|
return qrlStringInline;
|
|
9699
9902
|
}
|
|
9903
|
+
/** @internal */
|
|
9904
|
+
function qrlToChunks(serializationContext, qrl) {
|
|
9905
|
+
const [chunk, symbol, captures] = qrlToString(serializationContext, qrl, true);
|
|
9906
|
+
const prefix = `${chunk}#${symbol}`;
|
|
9907
|
+
if (!captures) {
|
|
9908
|
+
return prefix;
|
|
9909
|
+
}
|
|
9910
|
+
const chunks = [prefix, '#'];
|
|
9911
|
+
const captureIds = captures.split(' ');
|
|
9912
|
+
for (let i = 0; i < captureIds.length; i++) {
|
|
9913
|
+
if (i > 0) {
|
|
9914
|
+
chunks.push(' ');
|
|
9915
|
+
}
|
|
9916
|
+
chunks.push(Number(captureIds[i]));
|
|
9917
|
+
}
|
|
9918
|
+
return chunks;
|
|
9919
|
+
}
|
|
9700
9920
|
function createQRLWithBackChannel(chunk, symbol, captures, container) {
|
|
9701
9921
|
let qrlImporter = null;
|
|
9702
9922
|
if (isDev && chunk === QRL_RUNTIME_CHUNK) {
|
|
@@ -9716,6 +9936,16 @@ function parseQRL(qrl, container) {
|
|
|
9716
9936
|
}
|
|
9717
9937
|
const QRL_RUNTIME_CHUNK = 'mock-chunk';
|
|
9718
9938
|
|
|
9939
|
+
/** @internal */
|
|
9940
|
+
class SubscriptionPatch {
|
|
9941
|
+
rootId;
|
|
9942
|
+
subscriptions;
|
|
9943
|
+
constructor(rootId = 0, subscriptions = new Set()) {
|
|
9944
|
+
this.rootId = rootId;
|
|
9945
|
+
this.subscriptions = subscriptions;
|
|
9946
|
+
}
|
|
9947
|
+
}
|
|
9948
|
+
|
|
9719
9949
|
/**
|
|
9720
9950
|
* Format:
|
|
9721
9951
|
*
|
|
@@ -9734,6 +9964,7 @@ class Serializer {
|
|
|
9734
9964
|
$s11nWeakRefs$ = new Map();
|
|
9735
9965
|
$parent$;
|
|
9736
9966
|
$qrlMap$ = new Map();
|
|
9967
|
+
$streamedRootLimit$ = 0;
|
|
9737
9968
|
$writer$;
|
|
9738
9969
|
/** We need to determine this at runtime because polyfills may not be loaded a module load time */
|
|
9739
9970
|
$hasTemporal$ = typeof Temporal !== 'undefined';
|
|
@@ -9742,7 +9973,59 @@ class Serializer {
|
|
|
9742
9973
|
this.$writer$ = $serializationContext$.$writer$;
|
|
9743
9974
|
}
|
|
9744
9975
|
async serialize() {
|
|
9745
|
-
|
|
9976
|
+
const previousStreamedRootLimit = this.$streamedRootLimit$;
|
|
9977
|
+
this.$streamedRootLimit$ = 0;
|
|
9978
|
+
try {
|
|
9979
|
+
await this.outputRoots();
|
|
9980
|
+
}
|
|
9981
|
+
finally {
|
|
9982
|
+
this.$streamedRootLimit$ = previousStreamedRootLimit;
|
|
9983
|
+
}
|
|
9984
|
+
}
|
|
9985
|
+
async serializePatch(rootStart, rootIds, extraRootId, streamedRootLimit = rootStart) {
|
|
9986
|
+
const previousStreamedRootLimit = this.$streamedRootLimit$;
|
|
9987
|
+
this.$streamedRootLimit$ = streamedRootLimit;
|
|
9988
|
+
this.$writer$.write(BRACKET_OPEN);
|
|
9989
|
+
this.$serializationContext$.$serializedForwardRefCount$ = 0;
|
|
9990
|
+
try {
|
|
9991
|
+
this.$writer$.write(String(rootStart));
|
|
9992
|
+
this.$writer$.write(COMMA);
|
|
9993
|
+
this.$writer$.write(BRACKET_OPEN);
|
|
9994
|
+
await this.outputSelectedRoots(rootIds);
|
|
9995
|
+
this.$writer$.write(BRACKET_CLOSE);
|
|
9996
|
+
const forwardRefs = this.getForwardRefsPayload();
|
|
9997
|
+
this.$serializationContext$.$serializedForwardRefCount$ = forwardRefs?.length ?? 0;
|
|
9998
|
+
if (forwardRefs || extraRootId !== undefined) {
|
|
9999
|
+
this.$writer$.write(COMMA);
|
|
10000
|
+
if (forwardRefs) {
|
|
10001
|
+
this.outputForwardRefsArray(forwardRefs);
|
|
10002
|
+
}
|
|
10003
|
+
else {
|
|
10004
|
+
this.$writer$.write('0');
|
|
10005
|
+
}
|
|
10006
|
+
}
|
|
10007
|
+
if (extraRootId !== undefined) {
|
|
10008
|
+
this.$writer$.write(COMMA);
|
|
10009
|
+
if (typeof extraRootId === 'number') {
|
|
10010
|
+
this.writeRootRef(extraRootId);
|
|
10011
|
+
}
|
|
10012
|
+
else if (typeof extraRootId === 'string') {
|
|
10013
|
+
this.outputString(extraRootId);
|
|
10014
|
+
}
|
|
10015
|
+
else {
|
|
10016
|
+
this.$writer$.write(QUOTE);
|
|
10017
|
+
this.writeRootRefPath(extraRootId);
|
|
10018
|
+
this.$writer$.write(QUOTE);
|
|
10019
|
+
}
|
|
10020
|
+
}
|
|
10021
|
+
}
|
|
10022
|
+
finally {
|
|
10023
|
+
this.$streamedRootLimit$ = previousStreamedRootLimit;
|
|
10024
|
+
}
|
|
10025
|
+
this.$writer$.write(BRACKET_CLOSE);
|
|
10026
|
+
}
|
|
10027
|
+
$setWriter$(writer) {
|
|
10028
|
+
this.$writer$ = writer;
|
|
9746
10029
|
}
|
|
9747
10030
|
/** Helper to output an array */
|
|
9748
10031
|
outputArray(value, keepUndefined, writeFn) {
|
|
@@ -9803,22 +10086,65 @@ class Serializer {
|
|
|
9803
10086
|
}
|
|
9804
10087
|
return Number(key);
|
|
9805
10088
|
}
|
|
10089
|
+
outputString(value) {
|
|
10090
|
+
const s = this.stringNeedsJsonEscape$(value) ? JSON.stringify(value) : QUOTE + value + QUOTE;
|
|
10091
|
+
let angleBracketIdx = -1;
|
|
10092
|
+
let lastIdx = 0;
|
|
10093
|
+
while ((angleBracketIdx = s.indexOf(CLOSE_TAG, lastIdx)) !== -1) {
|
|
10094
|
+
this.$writer$.write(s.slice(lastIdx, angleBracketIdx));
|
|
10095
|
+
this.$writer$.write(ESCAPED_CLOSE_TAG);
|
|
10096
|
+
lastIdx = angleBracketIdx + 2;
|
|
10097
|
+
}
|
|
10098
|
+
this.$writer$.write(lastIdx === 0 ? s : s.slice(lastIdx));
|
|
10099
|
+
}
|
|
10100
|
+
writeRootRef(id) {
|
|
10101
|
+
this.$writer$.writeRootRef(id);
|
|
10102
|
+
}
|
|
10103
|
+
writeRootRefPath(path) {
|
|
10104
|
+
this.$writer$.writeRootRefPath(path);
|
|
10105
|
+
}
|
|
10106
|
+
outputStringChunks(chunks) {
|
|
10107
|
+
this.$writer$.write(QUOTE);
|
|
10108
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
10109
|
+
const chunk = chunks[i];
|
|
10110
|
+
if (typeof chunk === 'string') {
|
|
10111
|
+
this.$writer$.write(chunk);
|
|
10112
|
+
}
|
|
10113
|
+
else if (typeof chunk === 'number') {
|
|
10114
|
+
this.writeRootRef(chunk);
|
|
10115
|
+
}
|
|
10116
|
+
else {
|
|
10117
|
+
this.writeRootRefPath(chunk.path);
|
|
10118
|
+
}
|
|
10119
|
+
}
|
|
10120
|
+
this.$writer$.write(QUOTE);
|
|
10121
|
+
}
|
|
9806
10122
|
/** Output a type,value pair. If the value is an array, it calls writeValue on each item. */
|
|
9807
10123
|
output(type, value, keepUndefined) {
|
|
9808
|
-
if (
|
|
10124
|
+
if (type === 1 /* TypeIds.RootRef */) {
|
|
10125
|
+
this.$writer$.write(type + COMMA);
|
|
10126
|
+
if (typeof value === 'number') {
|
|
10127
|
+
this.writeRootRef(value);
|
|
10128
|
+
}
|
|
10129
|
+
else if (typeof value === 'string') {
|
|
10130
|
+
this.outputString(value);
|
|
10131
|
+
}
|
|
10132
|
+
else {
|
|
10133
|
+
this.$writer$.write(QUOTE);
|
|
10134
|
+
this.writeRootRefPath(value);
|
|
10135
|
+
this.$writer$.write(QUOTE);
|
|
10136
|
+
}
|
|
10137
|
+
}
|
|
10138
|
+
else if (type === 9 /* TypeIds.QRL */ && Array.isArray(value)) {
|
|
10139
|
+
this.$writer$.write(type + COMMA);
|
|
10140
|
+
this.outputStringChunks(value);
|
|
10141
|
+
}
|
|
10142
|
+
else if (typeof value === 'number') {
|
|
9809
10143
|
this.$writer$.write(type + COMMA + value);
|
|
9810
10144
|
}
|
|
9811
10145
|
else if (typeof value === 'string') {
|
|
9812
|
-
const s = this.stringNeedsJsonEscape$(value) ? JSON.stringify(value) : QUOTE + value + QUOTE;
|
|
9813
10146
|
this.$writer$.write(type + COMMA);
|
|
9814
|
-
|
|
9815
|
-
let lastIdx = 0;
|
|
9816
|
-
while ((angleBracketIdx = s.indexOf(CLOSE_TAG, lastIdx)) !== -1) {
|
|
9817
|
-
this.$writer$.write(s.slice(lastIdx, angleBracketIdx));
|
|
9818
|
-
this.$writer$.write(ESCAPED_CLOSE_TAG);
|
|
9819
|
-
lastIdx = angleBracketIdx + 2;
|
|
9820
|
-
}
|
|
9821
|
-
this.$writer$.write(lastIdx === 0 ? s : s.slice(lastIdx));
|
|
10147
|
+
this.outputString(value);
|
|
9822
10148
|
}
|
|
9823
10149
|
else {
|
|
9824
10150
|
this.$writer$.write(type + COMMA);
|
|
@@ -9844,16 +10170,19 @@ class Serializer {
|
|
|
9844
10170
|
return this.$serializationContext$.$markSeen$(value, this.$parent$, index);
|
|
9845
10171
|
}
|
|
9846
10172
|
}
|
|
10173
|
+
else if (seen.$parent$ && this.isSeenInStreamedRoot(seen)) {
|
|
10174
|
+
seen = this.$serializationContext$.$addDuplicateRoot$(value);
|
|
10175
|
+
}
|
|
9847
10176
|
// Now that we saw it a second time, make sure it's a root
|
|
9848
10177
|
if (seen.$parent$) {
|
|
9849
10178
|
// Note, this means it was output before so we always need a backref
|
|
9850
10179
|
// Special case: we're a root so instead of adding a backref, we replace ourself
|
|
9851
10180
|
if (!this.$parent$) {
|
|
9852
|
-
this.$serializationContext$.$promoteToRoot$(seen, index);
|
|
10181
|
+
this.$serializationContext$.$promoteToRoot$(seen, value, index);
|
|
9853
10182
|
value = this.$serializationContext$.$roots$[index];
|
|
9854
10183
|
}
|
|
9855
10184
|
else {
|
|
9856
|
-
this.$serializationContext$.$promoteToRoot$(seen);
|
|
10185
|
+
this.$serializationContext$.$promoteToRoot$(seen, value);
|
|
9857
10186
|
}
|
|
9858
10187
|
}
|
|
9859
10188
|
// Check if there was a weakref to us
|
|
@@ -9869,6 +10198,12 @@ class Serializer {
|
|
|
9869
10198
|
}
|
|
9870
10199
|
this.output(1 /* TypeIds.RootRef */, rootIdx);
|
|
9871
10200
|
}
|
|
10201
|
+
isSeenInStreamedRoot(ref) {
|
|
10202
|
+
while (ref.$parent$) {
|
|
10203
|
+
ref = ref.$parent$;
|
|
10204
|
+
}
|
|
10205
|
+
return ref.$index$ < this.$streamedRootLimit$;
|
|
10206
|
+
}
|
|
9872
10207
|
// First check for scalars, then do objects with seen checks
|
|
9873
10208
|
// Make sure to only get the SeenRef once, it's expensive
|
|
9874
10209
|
writeValue(value, index) {
|
|
@@ -9947,9 +10282,24 @@ class Serializer {
|
|
|
9947
10282
|
let data;
|
|
9948
10283
|
if (chunk !== '') {
|
|
9949
10284
|
// not a sync QRL, replace all parts with string references
|
|
9950
|
-
data =
|
|
10285
|
+
data = [
|
|
10286
|
+
this.$serializationContext$.$addRoot$(chunk),
|
|
10287
|
+
'#',
|
|
10288
|
+
this.$serializationContext$.$addRoot$(symbol),
|
|
10289
|
+
];
|
|
10290
|
+
if (captures) {
|
|
10291
|
+
const captureIds = captures.split(' ');
|
|
10292
|
+
data.push('#');
|
|
10293
|
+
for (let i = 0; i < captureIds.length; i++) {
|
|
10294
|
+
if (i > 0) {
|
|
10295
|
+
data.push(' ');
|
|
10296
|
+
}
|
|
10297
|
+
data.push(Number(captureIds[i]));
|
|
10298
|
+
}
|
|
10299
|
+
}
|
|
9951
10300
|
// Since we map QRLs to strings, we need to keep track of this secondary mapping
|
|
9952
|
-
const
|
|
10301
|
+
const qrlKey = data.join('');
|
|
10302
|
+
const existing = this.$qrlMap$.get(qrlKey);
|
|
9953
10303
|
if (existing) {
|
|
9954
10304
|
// We encountered the same QRL again, make it a root
|
|
9955
10305
|
const ref = this.$serializationContext$.$addRoot$(existing);
|
|
@@ -9957,7 +10307,7 @@ class Serializer {
|
|
|
9957
10307
|
return;
|
|
9958
10308
|
}
|
|
9959
10309
|
else {
|
|
9960
|
-
this.$qrlMap$.set(
|
|
10310
|
+
this.$qrlMap$.set(qrlKey, value);
|
|
9961
10311
|
}
|
|
9962
10312
|
}
|
|
9963
10313
|
else {
|
|
@@ -10026,6 +10376,9 @@ class Serializer {
|
|
|
10026
10376
|
// TODO no data if [null, true]
|
|
10027
10377
|
this.output(40 /* TypeIds.EffectSubscription */, [value.consumer, value.property, value.data]);
|
|
10028
10378
|
}
|
|
10379
|
+
else if (value instanceof SubscriptionPatch) {
|
|
10380
|
+
this.output(41 /* TypeIds.SubscriptionPatch */, [value.rootId, value.subscriptions]);
|
|
10381
|
+
}
|
|
10029
10382
|
else if (isStore(value)) {
|
|
10030
10383
|
const storeHandler = getStoreHandler(value);
|
|
10031
10384
|
const storeTarget = getStoreTarget(value);
|
|
@@ -10079,7 +10432,7 @@ class Serializer {
|
|
|
10079
10432
|
}
|
|
10080
10433
|
}
|
|
10081
10434
|
else if (this.$serializationContext$.$isDomRef$(value)) {
|
|
10082
|
-
value.$ssrNode
|
|
10435
|
+
this.$serializationContext$.$markSsrNodeForSerialization$(value.$ssrNode$, 16 /* VNodeDataFlag.SERIALIZE */);
|
|
10083
10436
|
this.output(11 /* TypeIds.RefVNode */, value.$ssrNode$.id);
|
|
10084
10437
|
}
|
|
10085
10438
|
else if (value instanceof SignalImpl) {
|
|
@@ -10204,23 +10557,22 @@ class Serializer {
|
|
|
10204
10557
|
}
|
|
10205
10558
|
else if (this.$serializationContext$.$isSsrNode$(value)) {
|
|
10206
10559
|
const rootIndex = this.$serializationContext$.$addRoot$(value);
|
|
10207
|
-
this.$serializationContext$.$setProp$(value, ELEMENT_ID,
|
|
10560
|
+
this.$serializationContext$.$setProp$(value, ELEMENT_ID, rootIndex);
|
|
10208
10561
|
// we need to output before the vnode overwrites its values
|
|
10209
10562
|
this.output(10 /* TypeIds.VNode */, value.id);
|
|
10210
10563
|
const vNodeData = value.vnodeData;
|
|
10211
10564
|
if (vNodeData) {
|
|
10212
|
-
discoverValuesForVNodeData(vNodeData, (vNodeDataValue) =>
|
|
10213
|
-
|
|
10565
|
+
discoverValuesForVNodeData(vNodeData, (vNodeDataValue) => {
|
|
10566
|
+
this.$serializationContext$.$addRoot$(vNodeDataValue);
|
|
10567
|
+
});
|
|
10568
|
+
this.$serializationContext$.$markSsrNodeForSerialization$(value, 16 /* VNodeDataFlag.SERIALIZE */);
|
|
10214
10569
|
}
|
|
10215
10570
|
if (value.children) {
|
|
10216
10571
|
// Mark child vnode data for serialization (structure only, no value discovery needed)
|
|
10217
10572
|
const childrenLength = value.children.length;
|
|
10218
10573
|
for (let i = 0; i < childrenLength; i++) {
|
|
10219
10574
|
const child = value.children[i];
|
|
10220
|
-
|
|
10221
|
-
if (childVNodeData) {
|
|
10222
|
-
childVNodeData[0] |= 16 /* VNodeDataFlag.SERIALIZE */;
|
|
10223
|
-
}
|
|
10575
|
+
this.$serializationContext$.$markSsrNodeForSerialization$(child, 16 /* VNodeDataFlag.SERIALIZE */);
|
|
10224
10576
|
}
|
|
10225
10577
|
}
|
|
10226
10578
|
}
|
|
@@ -10313,7 +10665,7 @@ class Serializer {
|
|
|
10313
10665
|
this.$s11nWeakRefs$.set(obj, forwardRefId);
|
|
10314
10666
|
this.$forwardRefs$[forwardRefId] = -1;
|
|
10315
10667
|
}
|
|
10316
|
-
this.output(2 /* TypeIds.ForwardRef */, forwardRefId);
|
|
10668
|
+
this.output(2 /* TypeIds.ForwardRef */, this.getForwardRefId(forwardRefId));
|
|
10317
10669
|
}
|
|
10318
10670
|
}
|
|
10319
10671
|
else if (vnode_isVNode(value)) {
|
|
@@ -10335,16 +10687,16 @@ class Serializer {
|
|
|
10335
10687
|
this.$forwardRefs$[forwardRefId] = this.$serializationContext$.$addRoot$(classCreator(false, err));
|
|
10336
10688
|
});
|
|
10337
10689
|
this.$promises$.add(promise);
|
|
10338
|
-
return forwardRefId;
|
|
10690
|
+
return this.getForwardRefId(forwardRefId);
|
|
10339
10691
|
}
|
|
10340
|
-
|
|
10341
|
-
this.$
|
|
10692
|
+
getForwardRefId(localId) {
|
|
10693
|
+
return this.$serializationContext$.$forwardRefOffset$ + localId;
|
|
10694
|
+
}
|
|
10695
|
+
async outputPendingRoots() {
|
|
10696
|
+
let rootsWritten = 0;
|
|
10342
10697
|
const { $roots$ } = this.$serializationContext$;
|
|
10343
10698
|
while (this.$rootIdx$ < $roots$.length || this.$promises$.size) {
|
|
10344
|
-
|
|
10345
|
-
this.$writer$.write(COMMA);
|
|
10346
|
-
}
|
|
10347
|
-
let separator = false;
|
|
10699
|
+
let separator = rootsWritten > 0;
|
|
10348
10700
|
for (; this.$rootIdx$ < $roots$.length; this.$rootIdx$++) {
|
|
10349
10701
|
if (separator) {
|
|
10350
10702
|
this.$writer$.write(COMMA);
|
|
@@ -10353,6 +10705,7 @@ class Serializer {
|
|
|
10353
10705
|
separator = true;
|
|
10354
10706
|
}
|
|
10355
10707
|
this.writeValue($roots$[this.$rootIdx$], this.$rootIdx$);
|
|
10708
|
+
rootsWritten++;
|
|
10356
10709
|
}
|
|
10357
10710
|
if (this.$promises$.size) {
|
|
10358
10711
|
try {
|
|
@@ -10363,24 +10716,77 @@ class Serializer {
|
|
|
10363
10716
|
}
|
|
10364
10717
|
}
|
|
10365
10718
|
}
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
10719
|
+
return rootsWritten;
|
|
10720
|
+
}
|
|
10721
|
+
async outputSelectedRoots(rootIds) {
|
|
10722
|
+
let separator = false;
|
|
10723
|
+
let i = 0;
|
|
10724
|
+
while (i < rootIds.length || this.$promises$.size) {
|
|
10725
|
+
if (i < rootIds.length) {
|
|
10726
|
+
if (separator) {
|
|
10727
|
+
this.$writer$.write(COMMA);
|
|
10728
|
+
}
|
|
10729
|
+
else {
|
|
10730
|
+
separator = true;
|
|
10731
|
+
}
|
|
10732
|
+
const rootId = rootIds[i++];
|
|
10733
|
+
this.writeValue(this.$serializationContext$.$roots$[rootId], rootId);
|
|
10734
|
+
continue;
|
|
10735
|
+
}
|
|
10736
|
+
try {
|
|
10737
|
+
await Promise.race(this.$promises$);
|
|
10738
|
+
}
|
|
10739
|
+
catch {
|
|
10740
|
+
// ignore rejections, they will be serialized as rejected promises
|
|
10741
|
+
}
|
|
10742
|
+
}
|
|
10743
|
+
}
|
|
10744
|
+
getForwardRefsPayload() {
|
|
10745
|
+
let lastIdx = this.$forwardRefs$.length - 1;
|
|
10746
|
+
while (lastIdx >= 0 && this.$forwardRefs$[lastIdx] === -1) {
|
|
10747
|
+
lastIdx--;
|
|
10748
|
+
}
|
|
10749
|
+
if (lastIdx < 0) {
|
|
10750
|
+
return null;
|
|
10751
|
+
}
|
|
10752
|
+
return lastIdx === this.$forwardRefs$.length - 1
|
|
10753
|
+
? this.$forwardRefs$
|
|
10754
|
+
: this.$forwardRefs$.slice(0, lastIdx + 1);
|
|
10755
|
+
}
|
|
10756
|
+
outputForwardRefsArray(forwardRefs) {
|
|
10757
|
+
this.outputArray(forwardRefs, true, (value) => {
|
|
10758
|
+
if (typeof value === 'string') {
|
|
10759
|
+
this.outputString(value);
|
|
10760
|
+
}
|
|
10761
|
+
else if (Array.isArray(value)) {
|
|
10762
|
+
this.$writer$.write(QUOTE);
|
|
10763
|
+
this.writeRootRefPath(value);
|
|
10764
|
+
this.$writer$.write(QUOTE);
|
|
10370
10765
|
}
|
|
10371
|
-
|
|
10766
|
+
else {
|
|
10767
|
+
this.writeRootRef(value);
|
|
10768
|
+
}
|
|
10769
|
+
});
|
|
10770
|
+
}
|
|
10771
|
+
async outputRoots() {
|
|
10772
|
+
this.$writer$.write(BRACKET_OPEN);
|
|
10773
|
+
const rootsWritten = await this.outputPendingRoots();
|
|
10774
|
+
const forwardRefs = this.getForwardRefsPayload();
|
|
10775
|
+
this.$serializationContext$.$rootStateRootCount$ = this.$serializationContext$.$roots$.length;
|
|
10776
|
+
this.$serializationContext$.$hasRootStateForwardRefs$ = !!forwardRefs;
|
|
10777
|
+
const forwardRefCount = forwardRefs?.length ?? 0;
|
|
10778
|
+
if (forwardRefs) {
|
|
10779
|
+
if (rootsWritten > 0) {
|
|
10372
10780
|
this.$writer$.write(COMMA);
|
|
10373
|
-
this.$writer$.write(14 /* TypeIds.ForwardRefs */ + COMMA);
|
|
10374
|
-
const out = lastIdx === this.$forwardRefs$.length - 1
|
|
10375
|
-
? this.$forwardRefs$
|
|
10376
|
-
: this.$forwardRefs$.slice(0, lastIdx + 1);
|
|
10377
|
-
// We could also implement RLE of -1 values
|
|
10378
|
-
this.outputArray(out, true, (value) => {
|
|
10379
|
-
this.$writer$.write(String(value));
|
|
10380
|
-
});
|
|
10381
10781
|
}
|
|
10782
|
+
this.$writer$.write(14 /* TypeIds.ForwardRefs */ + COMMA);
|
|
10783
|
+
this.outputForwardRefsArray(forwardRefs);
|
|
10382
10784
|
}
|
|
10383
10785
|
this.$writer$.write(BRACKET_CLOSE);
|
|
10786
|
+
this.$serializationContext$.$serializedRootCount$ =
|
|
10787
|
+
this.$serializationContext$.$roots$.length +
|
|
10788
|
+
(this.$serializationContext$.$hasRootStateForwardRefs$ ? 1 : 0);
|
|
10789
|
+
this.$serializationContext$.$serializedForwardRefCount$ = forwardRefCount;
|
|
10384
10790
|
}
|
|
10385
10791
|
}
|
|
10386
10792
|
class PromiseResult {
|
|
@@ -10427,6 +10833,7 @@ const discoverValuesForVNodeData = (vnodeData, callback) => {
|
|
|
10427
10833
|
const attrValue = value[key];
|
|
10428
10834
|
if (attrValue == null ||
|
|
10429
10835
|
typeof attrValue === 'string' ||
|
|
10836
|
+
(typeof attrValue === 'number' && key === ELEMENT_ID) ||
|
|
10430
10837
|
(key === ELEMENT_PROPS && isObjectEmpty(attrValue))) {
|
|
10431
10838
|
continue;
|
|
10432
10839
|
}
|
|
@@ -10492,13 +10899,24 @@ class SerializationContextImpl {
|
|
|
10492
10899
|
$writer$;
|
|
10493
10900
|
$seenObjsMap$ = new Map();
|
|
10494
10901
|
$syncFnMap$ = new Map();
|
|
10902
|
+
$syncFnOffset$ = 0;
|
|
10495
10903
|
$syncFns$ = [];
|
|
10496
10904
|
$roots$ = [];
|
|
10905
|
+
$rootObjs$ = [];
|
|
10906
|
+
$onAddRoot$;
|
|
10907
|
+
$forwardRefOffset$ = 0;
|
|
10908
|
+
$serializedRootCount$ = 0;
|
|
10909
|
+
$serializedForwardRefCount$ = 0;
|
|
10910
|
+
$rootStateRootCount$ = 0;
|
|
10911
|
+
$hasRootStateForwardRefs$ = false;
|
|
10497
10912
|
$eagerResume$ = new Set();
|
|
10498
10913
|
$eventQrls$ = new Set();
|
|
10499
10914
|
$eventNames$ = new Set();
|
|
10500
10915
|
$renderSymbols$ = new Set();
|
|
10501
10916
|
$serializer$;
|
|
10917
|
+
$markSsrNodeForSerialization$ = (node, flags) => {
|
|
10918
|
+
node.vnodeData[0] |= flags;
|
|
10919
|
+
};
|
|
10502
10920
|
constructor(
|
|
10503
10921
|
/**
|
|
10504
10922
|
* Node constructor, for instanceof checks.
|
|
@@ -10518,7 +10936,14 @@ class SerializationContextImpl {
|
|
|
10518
10936
|
this.$serializer$ = new Serializer(this);
|
|
10519
10937
|
}
|
|
10520
10938
|
async $serialize$() {
|
|
10521
|
-
|
|
10939
|
+
await this.$serializer$.serialize();
|
|
10940
|
+
}
|
|
10941
|
+
async $serializePatch$(rootStart, rootIds, extraRootId, streamedRootLimit) {
|
|
10942
|
+
await this.$serializer$.serializePatch(rootStart, rootIds, extraRootId, streamedRootLimit);
|
|
10943
|
+
}
|
|
10944
|
+
$setWriter$(writer) {
|
|
10945
|
+
this.$writer$ = writer;
|
|
10946
|
+
this.$serializer$.$setWriter$(writer);
|
|
10522
10947
|
}
|
|
10523
10948
|
getSeenRef(obj) {
|
|
10524
10949
|
return this.$seenObjsMap$.get(obj);
|
|
@@ -10529,8 +10954,8 @@ class SerializationContextImpl {
|
|
|
10529
10954
|
return ref;
|
|
10530
10955
|
}
|
|
10531
10956
|
/**
|
|
10532
|
-
* Returns a path
|
|
10533
|
-
*
|
|
10957
|
+
* Returns a path representing the path from roots through all parents to the object. Format: [3,
|
|
10958
|
+
* 2, 0] where each number is the index within its parent, from root to leaf.
|
|
10534
10959
|
*/
|
|
10535
10960
|
$getObjectPath$(ref) {
|
|
10536
10961
|
// Traverse up through parent references to build a path
|
|
@@ -10541,16 +10966,23 @@ class SerializationContextImpl {
|
|
|
10541
10966
|
}
|
|
10542
10967
|
// Now we are at root, but it could be a backref
|
|
10543
10968
|
path.unshift(ref.$index$);
|
|
10544
|
-
return path
|
|
10969
|
+
return path;
|
|
10545
10970
|
}
|
|
10546
|
-
$promoteToRoot$(ref, index) {
|
|
10971
|
+
$promoteToRoot$(ref, obj, index) {
|
|
10547
10972
|
const path = this.$getObjectPath$(ref);
|
|
10973
|
+
const isNewRoot = index === undefined;
|
|
10548
10974
|
if (index === undefined) {
|
|
10549
10975
|
index = this.$roots$.length;
|
|
10550
10976
|
}
|
|
10551
10977
|
this.$roots$[index] = new SerializationBackRef(path);
|
|
10978
|
+
if (isNewRoot) {
|
|
10979
|
+
this.$rootObjs$[index] = obj;
|
|
10980
|
+
}
|
|
10552
10981
|
ref.$parent$ = null;
|
|
10553
10982
|
ref.$index$ = index;
|
|
10983
|
+
if (isNewRoot) {
|
|
10984
|
+
this.$onAddRoot$?.(index, this.$roots$[index], obj);
|
|
10985
|
+
}
|
|
10554
10986
|
}
|
|
10555
10987
|
$addRoot$(obj, returnRef = false) {
|
|
10556
10988
|
let seen = this.$seenObjsMap$.get(obj);
|
|
@@ -10564,15 +10996,34 @@ class SerializationContextImpl {
|
|
|
10564
10996
|
};
|
|
10565
10997
|
this.$seenObjsMap$.set(obj, seen);
|
|
10566
10998
|
this.$roots$.push(obj);
|
|
10999
|
+
this.$rootObjs$.push(obj);
|
|
11000
|
+
this.$onAddRoot$?.(index, obj, obj);
|
|
10567
11001
|
}
|
|
10568
11002
|
else {
|
|
10569
11003
|
if (seen.$parent$) {
|
|
10570
|
-
this.$promoteToRoot$(seen);
|
|
11004
|
+
this.$promoteToRoot$(seen, obj);
|
|
10571
11005
|
}
|
|
10572
11006
|
index = seen.$index$;
|
|
10573
11007
|
}
|
|
10574
11008
|
return returnRef ? seen : index;
|
|
10575
11009
|
}
|
|
11010
|
+
$addDuplicateRoot$(obj) {
|
|
11011
|
+
const index = this.$roots$.length;
|
|
11012
|
+
const ref = { $index$: index };
|
|
11013
|
+
this.$seenObjsMap$.set(obj, ref);
|
|
11014
|
+
this.$roots$.push(obj);
|
|
11015
|
+
this.$rootObjs$.push(obj);
|
|
11016
|
+
this.$onAddRoot$?.(index, obj, obj);
|
|
11017
|
+
return ref;
|
|
11018
|
+
}
|
|
11019
|
+
$commitRoot$(root, obj) {
|
|
11020
|
+
const index = this.$roots$.length;
|
|
11021
|
+
const ref = { $index$: index };
|
|
11022
|
+
this.$seenObjsMap$.set(obj, ref);
|
|
11023
|
+
this.$roots$.push(root);
|
|
11024
|
+
this.$rootObjs$.push(obj);
|
|
11025
|
+
return index;
|
|
11026
|
+
}
|
|
10576
11027
|
$isSsrNode$(obj) {
|
|
10577
11028
|
return this.NodeConstructor ? obj instanceof this.NodeConstructor : false;
|
|
10578
11029
|
}
|
|
@@ -10590,7 +11041,7 @@ class SerializationContextImpl {
|
|
|
10590
11041
|
}
|
|
10591
11042
|
let id = this.$syncFnMap$.get(funcStr);
|
|
10592
11043
|
if (id === undefined) {
|
|
10593
|
-
id = this.$syncFns$.length;
|
|
11044
|
+
id = this.$syncFnOffset$ + this.$syncFns$.length;
|
|
10594
11045
|
this.$syncFnMap$.set(funcStr, id);
|
|
10595
11046
|
if (isFullFn) {
|
|
10596
11047
|
this.$syncFns$.push(funcStr);
|
|
@@ -10605,6 +11056,15 @@ class SerializationContextImpl {
|
|
|
10605
11056
|
}
|
|
10606
11057
|
return id;
|
|
10607
11058
|
}
|
|
11059
|
+
$setSyncFnOffset$(offset, existingFns) {
|
|
11060
|
+
this.$syncFnOffset$ = offset;
|
|
11061
|
+
if (existingFns) {
|
|
11062
|
+
this.$syncFnMap$.clear();
|
|
11063
|
+
for (let i = 0; i < existingFns.length; i++) {
|
|
11064
|
+
this.$syncFnMap$.set(existingFns[i], i);
|
|
11065
|
+
}
|
|
11066
|
+
}
|
|
11067
|
+
}
|
|
10608
11068
|
}
|
|
10609
11069
|
const createSerializationContext = (
|
|
10610
11070
|
/**
|
|
@@ -10618,12 +11078,11 @@ NodeConstructor,
|
|
|
10618
11078
|
DomRefConstructor, symbolToChunkResolver, setProp, storeProxyMap, writer) => {
|
|
10619
11079
|
if (!writer) {
|
|
10620
11080
|
const buffer = [];
|
|
10621
|
-
writer = {
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
},
|
|
11081
|
+
writer = Object.assign(createStringStreamWriter((text) => {
|
|
11082
|
+
buffer.push(text);
|
|
11083
|
+
}), {
|
|
10625
11084
|
toString: () => buffer.join(''),
|
|
10626
|
-
};
|
|
11085
|
+
});
|
|
10627
11086
|
}
|
|
10628
11087
|
isDomRef = (DomRefConstructor ? (obj) => obj instanceof DomRefConstructor : (() => false));
|
|
10629
11088
|
return new SerializationContextImpl(NodeConstructor, DomRefConstructor, symbolToChunkResolver, setProp, storeProxyMap, writer);
|
|
@@ -10881,15 +11340,16 @@ const constantToName = (code) => {
|
|
|
10881
11340
|
* @returns The preprocessed state data
|
|
10882
11341
|
* @internal
|
|
10883
11342
|
*/
|
|
10884
|
-
function preprocessState(data, container) {
|
|
11343
|
+
function preprocessState(data, container, segmentId, startIndex = 0) {
|
|
10885
11344
|
const isRootDeepRef = (type, value) => {
|
|
10886
|
-
return type === 1 /* TypeIds.RootRef */ && typeof value === 'string';
|
|
11345
|
+
return type === 1 /* TypeIds.RootRef */ && typeof value === 'string' && value.indexOf(' ') !== -1;
|
|
10887
11346
|
};
|
|
10888
11347
|
const isForwardRefsMap = (type) => {
|
|
10889
11348
|
return type === 14 /* TypeIds.ForwardRefs */;
|
|
10890
11349
|
};
|
|
10891
11350
|
const processRootRef = (index) => {
|
|
10892
11351
|
const rootRefPath = data[index + 1].split(' ');
|
|
11352
|
+
const firstRefIndex = parseInt(rootRefPath[0], 10);
|
|
10893
11353
|
let object = data;
|
|
10894
11354
|
let objectType = 1 /* TypeIds.RootRef */;
|
|
10895
11355
|
let typeIndex = 0;
|
|
@@ -10897,12 +11357,13 @@ function preprocessState(data, container) {
|
|
|
10897
11357
|
let parent = null;
|
|
10898
11358
|
for (let i = 0; i < rootRefPath.length; i++) {
|
|
10899
11359
|
parent = object;
|
|
10900
|
-
typeIndex = parseInt(rootRefPath[i], 10) * 2;
|
|
11360
|
+
typeIndex = (i === 0 ? firstRefIndex : parseInt(rootRefPath[i], 10)) * 2;
|
|
10901
11361
|
valueIndex = typeIndex + 1;
|
|
10902
|
-
|
|
10903
|
-
|
|
11362
|
+
const objectArray = object;
|
|
11363
|
+
objectType = objectArray[typeIndex];
|
|
11364
|
+
object = objectArray[valueIndex];
|
|
10904
11365
|
if (objectType === 1 /* TypeIds.RootRef */) {
|
|
10905
|
-
const rootRef = object;
|
|
11366
|
+
const rootRef = typeof object === 'string' ? parseInt(object, 10) : object;
|
|
10906
11367
|
const rootRefTypeIndex = rootRef * 2;
|
|
10907
11368
|
objectType = data[rootRefTypeIndex];
|
|
10908
11369
|
object = data[rootRefTypeIndex + 1];
|
|
@@ -10915,7 +11376,7 @@ function preprocessState(data, container) {
|
|
|
10915
11376
|
data[index] = objectType;
|
|
10916
11377
|
data[index + 1] = object;
|
|
10917
11378
|
};
|
|
10918
|
-
for (let i =
|
|
11379
|
+
for (let i = startIndex; i < data.length; i += 2) {
|
|
10919
11380
|
if (isRootDeepRef(data[i], data[i + 1])) {
|
|
10920
11381
|
processRootRef(i);
|
|
10921
11382
|
}
|
|
@@ -10934,10 +11395,7 @@ const allocate = (container, typeId, value) => {
|
|
|
10934
11395
|
case 1 /* TypeIds.RootRef */:
|
|
10935
11396
|
return container.$getObjectById$(value);
|
|
10936
11397
|
case 2 /* TypeIds.ForwardRef */:
|
|
10937
|
-
|
|
10938
|
-
return _UNINITIALIZED;
|
|
10939
|
-
}
|
|
10940
|
-
const rootRef = container.$forwardRefs$[value];
|
|
11398
|
+
const rootRef = container.$getForwardRef$(value);
|
|
10941
11399
|
if (rootRef === -1 || rootRef === undefined) {
|
|
10942
11400
|
return _UNINITIALIZED;
|
|
10943
11401
|
}
|
|
@@ -11093,6 +11551,8 @@ const allocate = (container, typeId, value) => {
|
|
|
11093
11551
|
return new SubscriptionData({});
|
|
11094
11552
|
case 40 /* TypeIds.EffectSubscription */:
|
|
11095
11553
|
return new EffectSubscription(null, null, null, null);
|
|
11554
|
+
case 41 /* TypeIds.SubscriptionPatch */:
|
|
11555
|
+
return new SubscriptionPatch();
|
|
11096
11556
|
default:
|
|
11097
11557
|
throw qError(18 /* QError.serializeErrorCannotAllocate */, [typeId]);
|
|
11098
11558
|
}
|
|
@@ -11219,6 +11679,8 @@ const _fnSignal = (fn, args, fnStr) => {
|
|
|
11219
11679
|
class _SharedContainer {
|
|
11220
11680
|
$version$;
|
|
11221
11681
|
$storeProxyMap$;
|
|
11682
|
+
$rootContainer$ = null;
|
|
11683
|
+
$isOutOfOrderSegment$ = false;
|
|
11222
11684
|
/// Current language locale
|
|
11223
11685
|
$locale$;
|
|
11224
11686
|
/// Retrieve Object from paused serialized state.
|
|
@@ -11257,6 +11719,24 @@ function isAsyncGenerator(value) {
|
|
|
11257
11719
|
return !!value[Symbol.asyncIterator];
|
|
11258
11720
|
}
|
|
11259
11721
|
|
|
11722
|
+
const InternalServerComponentSymbol = Symbol('qInternalServerComponent');
|
|
11723
|
+
/** @internal */
|
|
11724
|
+
const createInternalServerComponent = (handler) => {
|
|
11725
|
+
const component = (() => {
|
|
11726
|
+
throw new Error('Internal server component must be handled by the SSR renderer.');
|
|
11727
|
+
});
|
|
11728
|
+
component[InternalServerComponentSymbol] = handler;
|
|
11729
|
+
return component;
|
|
11730
|
+
};
|
|
11731
|
+
/** @internal */
|
|
11732
|
+
const isInternalServerComponent = (type) => {
|
|
11733
|
+
return typeof type === 'function' && InternalServerComponentSymbol in type;
|
|
11734
|
+
};
|
|
11735
|
+
/** @internal */
|
|
11736
|
+
const getInternalServerComponentHandler = (type) => {
|
|
11737
|
+
return type[InternalServerComponentSymbol];
|
|
11738
|
+
};
|
|
11739
|
+
|
|
11260
11740
|
const applyInlineComponent = (ssr, componentHost, inlineComponentFunction, jsx) => {
|
|
11261
11741
|
const host = ssr.getOrCreateLastNode();
|
|
11262
11742
|
return executeComponent(ssr, host, componentHost, inlineComponentFunction, jsx.props);
|
|
@@ -11303,7 +11783,10 @@ async function _walkJSX(ssr, value, options) {
|
|
|
11303
11783
|
stack.push(await stack.pop());
|
|
11304
11784
|
}
|
|
11305
11785
|
else {
|
|
11306
|
-
|
|
11786
|
+
const result = value.apply(ssr);
|
|
11787
|
+
if (isPromise(result)) {
|
|
11788
|
+
await result;
|
|
11789
|
+
}
|
|
11307
11790
|
}
|
|
11308
11791
|
continue;
|
|
11309
11792
|
}
|
|
@@ -11392,16 +11875,23 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
11392
11875
|
else if (type === 'body') {
|
|
11393
11876
|
enqueue(ssr.additionalBodyNodes);
|
|
11394
11877
|
}
|
|
11395
|
-
else
|
|
11396
|
-
ssr
|
|
11397
|
-
ssr.
|
|
11398
|
-
|
|
11878
|
+
else {
|
|
11879
|
+
const innerSSR = ssr;
|
|
11880
|
+
if (!ssr.isHtml && !innerSSR._didAddQwikLoader && !ssr.$noScriptHere$) {
|
|
11881
|
+
ssr.emitQwikLoaderAtTopIfNeeded();
|
|
11882
|
+
ssr.emitPreloaderPre();
|
|
11883
|
+
innerSSR._didAddQwikLoader = true;
|
|
11884
|
+
}
|
|
11399
11885
|
}
|
|
11400
11886
|
const children = jsx.children;
|
|
11401
11887
|
children != null && enqueue(children);
|
|
11402
11888
|
}
|
|
11403
11889
|
else if (isFunction(type)) {
|
|
11404
|
-
if (
|
|
11890
|
+
if (__EXPERIMENTAL__.suspense && isInternalServerComponent(type)) {
|
|
11891
|
+
enqueue(() => getInternalServerComponentHandler(type)(ssr, jsx, options, enqueue));
|
|
11892
|
+
return;
|
|
11893
|
+
}
|
|
11894
|
+
else if (type === Fragment) {
|
|
11405
11895
|
const attrs = jsx.key != null ? { [ELEMENT_KEY]: jsx.key } : {};
|
|
11406
11896
|
if (isDev) {
|
|
11407
11897
|
attrs[DEBUG_TYPE] = "F" /* VirtualType.Fragment */; // Add debug info.
|
|
@@ -11425,7 +11915,7 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
11425
11915
|
ssr.openProjection(projectionAttrs);
|
|
11426
11916
|
const host = componentFrame.componentNode;
|
|
11427
11917
|
const node = ssr.getOrCreateLastNode();
|
|
11428
|
-
const slotName =
|
|
11918
|
+
const slotName = resolveSlotName(host, jsx, ssr);
|
|
11429
11919
|
projectionAttrs[QSlot] = slotName;
|
|
11430
11920
|
enqueue(setParentOptions(options, options.currentStyleScoped, options.parentComponentFrame));
|
|
11431
11921
|
enqueue(ssr.closeProjection);
|
|
@@ -11491,7 +11981,7 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
11491
11981
|
componentFrame.distributeChildrenIntoSlots(jsx.children, options.currentStyleScoped, options.parentComponentFrame);
|
|
11492
11982
|
const jsxOutput = applyQwikComponentBody(ssr, jsx, type);
|
|
11493
11983
|
enqueue(setParentOptions(options, options.currentStyleScoped, options.parentComponentFrame));
|
|
11494
|
-
enqueue(ssr.closeComponent);
|
|
11984
|
+
enqueue(() => ssr.closeComponent());
|
|
11495
11985
|
if (isPromise(jsxOutput)) {
|
|
11496
11986
|
// Defer reading QScopedStyle until after the promise resolves
|
|
11497
11987
|
enqueue(async () => {
|
|
@@ -11537,16 +12027,6 @@ function maybeAddPollingAsyncSignalToEagerResume(serializationCtx, signal) {
|
|
|
11537
12027
|
}
|
|
11538
12028
|
}
|
|
11539
12029
|
}
|
|
11540
|
-
function getSlotName(host, jsx, ssr) {
|
|
11541
|
-
const constProps = jsx.constProps;
|
|
11542
|
-
if (constProps && typeof constProps == 'object' && 'name' in constProps) {
|
|
11543
|
-
const constValue = constProps.name;
|
|
11544
|
-
if (constValue instanceof WrappedSignalImpl) {
|
|
11545
|
-
return trackSignalAndAssignHost(constValue, host, ":" /* EffectProperty.COMPONENT */, ssr);
|
|
11546
|
-
}
|
|
11547
|
-
}
|
|
11548
|
-
return directGetPropsProxyProp(jsx, 'name') || QDefaultSlot;
|
|
11549
|
-
}
|
|
11550
12030
|
function appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue) {
|
|
11551
12031
|
if (qwikInspectorAttrValue && (!jsx.constProps || !(qwikInspectorAttr in jsx.constProps))) {
|
|
11552
12032
|
(jsx.constProps ||= {})[qwikInspectorAttr] = qwikInspectorAttrValue;
|
|
@@ -11698,7 +12178,19 @@ function setEvent(serializationCtx, key, rawValue, hasMovedCaptures) {
|
|
|
11698
12178
|
let value = null;
|
|
11699
12179
|
const qrls = rawValue;
|
|
11700
12180
|
const appendToValue = (valueToAppend) => {
|
|
11701
|
-
|
|
12181
|
+
if (value == null) {
|
|
12182
|
+
value = valueToAppend;
|
|
12183
|
+
}
|
|
12184
|
+
else if (typeof value === 'string' && typeof valueToAppend === 'string') {
|
|
12185
|
+
value += '|' + valueToAppend;
|
|
12186
|
+
}
|
|
12187
|
+
else {
|
|
12188
|
+
value = [
|
|
12189
|
+
...(typeof value === 'string' ? [value] : value),
|
|
12190
|
+
'|',
|
|
12191
|
+
...(typeof valueToAppend === 'string' ? [valueToAppend] : valueToAppend),
|
|
12192
|
+
];
|
|
12193
|
+
}
|
|
11702
12194
|
};
|
|
11703
12195
|
const getQrlString = (qrl) => {
|
|
11704
12196
|
/**
|
|
@@ -11710,7 +12202,7 @@ function setEvent(serializationCtx, key, rawValue, hasMovedCaptures) {
|
|
|
11710
12202
|
if (!qrl.$symbol$.startsWith('_') && (qrl.$captures$?.length || hasMovedCaptures)) {
|
|
11711
12203
|
qrl = createQRL(null, '_run', _run, null, [qrl]);
|
|
11712
12204
|
}
|
|
11713
|
-
return
|
|
12205
|
+
return qrlToChunks(serializationCtx, qrl);
|
|
11714
12206
|
};
|
|
11715
12207
|
if (Array.isArray(qrls)) {
|
|
11716
12208
|
for (let i = 0; i < qrls.length; i++) {
|
|
@@ -12284,6 +12776,13 @@ const inflate = (container, target, typeId, data) => {
|
|
|
12284
12776
|
restoreEffectBackRefForConsumer(effectSub);
|
|
12285
12777
|
break;
|
|
12286
12778
|
}
|
|
12779
|
+
case 41 /* TypeIds.SubscriptionPatch */: {
|
|
12780
|
+
const patch = target;
|
|
12781
|
+
const d = data;
|
|
12782
|
+
patch.rootId = d[0];
|
|
12783
|
+
patch.subscriptions = d[1];
|
|
12784
|
+
break;
|
|
12785
|
+
}
|
|
12287
12786
|
default:
|
|
12288
12787
|
throw qError(16 /* QError.serializeErrorNotImplemented */, [typeId]);
|
|
12289
12788
|
}
|
|
@@ -12391,11 +12890,9 @@ const wrapDeserializerProxy = (container, data) => {
|
|
|
12391
12890
|
class DeserializationHandler {
|
|
12392
12891
|
$container$;
|
|
12393
12892
|
$data$;
|
|
12394
|
-
$length$;
|
|
12395
12893
|
constructor($container$, $data$) {
|
|
12396
12894
|
this.$container$ = $container$;
|
|
12397
12895
|
this.$data$ = $data$;
|
|
12398
|
-
this.$length$ = this.$data$.length / 2;
|
|
12399
12896
|
}
|
|
12400
12897
|
get(target, property, receiver) {
|
|
12401
12898
|
if (property === SERIALIZER_PROXY_UNWRAP) {
|
|
@@ -12407,7 +12904,7 @@ class DeserializationHandler {
|
|
|
12407
12904
|
: typeof property === 'string'
|
|
12408
12905
|
? parseInt(property, 10)
|
|
12409
12906
|
: NaN;
|
|
12410
|
-
if (Number.isNaN(i) || i < 0 || i >= this.$length
|
|
12907
|
+
if (Number.isNaN(i) || i < 0 || i >= this.$data$.length / 2) {
|
|
12411
12908
|
return Reflect.get(target, property, receiver);
|
|
12412
12909
|
}
|
|
12413
12910
|
// The serialized data is an array with 2 values for each item
|
|
@@ -12494,6 +12991,7 @@ function _createDeserializeContainer(stateData) {
|
|
|
12494
12991
|
let state;
|
|
12495
12992
|
const container = {
|
|
12496
12993
|
$getObjectById$: (id) => getObjectById(id, state),
|
|
12994
|
+
$getForwardRef$: (id) => container.$forwardRefs$?.[Number(id)],
|
|
12497
12995
|
getSyncFn: (_) => {
|
|
12498
12996
|
const fn = () => { };
|
|
12499
12997
|
return fn;
|
|
@@ -12886,59 +13384,265 @@ const isRecoverable = (err) => {
|
|
|
12886
13384
|
return true;
|
|
12887
13385
|
};
|
|
12888
13386
|
|
|
13387
|
+
/** @internal */
|
|
13388
|
+
const canRevealRegistration = (registration, isPending = (item) => item.boundary.pending.untrackedValue > 0) => {
|
|
13389
|
+
if (registration === null) {
|
|
13390
|
+
return true;
|
|
13391
|
+
}
|
|
13392
|
+
const reveal = registration.reveal;
|
|
13393
|
+
const current = registration.item;
|
|
13394
|
+
const items = reveal.items;
|
|
13395
|
+
switch (reveal.order) {
|
|
13396
|
+
case 'together':
|
|
13397
|
+
for (let i = 0; i < items.length; i++) {
|
|
13398
|
+
if (isPending(items[i])) {
|
|
13399
|
+
return false;
|
|
13400
|
+
}
|
|
13401
|
+
}
|
|
13402
|
+
return true;
|
|
13403
|
+
case 'sequential':
|
|
13404
|
+
for (let i = 0; i < items.length; i++) {
|
|
13405
|
+
const item = items[i];
|
|
13406
|
+
if (item === current) {
|
|
13407
|
+
return true;
|
|
13408
|
+
}
|
|
13409
|
+
if (isPending(item)) {
|
|
13410
|
+
return false;
|
|
13411
|
+
}
|
|
13412
|
+
}
|
|
13413
|
+
return true;
|
|
13414
|
+
case 'reverse':
|
|
13415
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
13416
|
+
const item = items[i];
|
|
13417
|
+
if (item === current) {
|
|
13418
|
+
return true;
|
|
13419
|
+
}
|
|
13420
|
+
if (isPending(item)) {
|
|
13421
|
+
return false;
|
|
13422
|
+
}
|
|
13423
|
+
}
|
|
13424
|
+
return true;
|
|
13425
|
+
default:
|
|
13426
|
+
return true;
|
|
13427
|
+
}
|
|
13428
|
+
};
|
|
13429
|
+
|
|
13430
|
+
/** @internal */
|
|
13431
|
+
const SUSPENSE_QRL_SYMBOL = '_suC';
|
|
13432
|
+
const outOfOrderRevealIds = new WeakMap();
|
|
13433
|
+
/** @internal */
|
|
13434
|
+
class OutOfOrderRevealCoordinator {
|
|
13435
|
+
id;
|
|
13436
|
+
collapsed;
|
|
13437
|
+
count = 0;
|
|
13438
|
+
pendingItems = new Set();
|
|
13439
|
+
orderCode;
|
|
13440
|
+
constructor(id, order, collapsed) {
|
|
13441
|
+
this.id = id;
|
|
13442
|
+
this.collapsed = collapsed;
|
|
13443
|
+
this.orderCode = getOutOfOrderRevealOrderCode(order);
|
|
13444
|
+
}
|
|
13445
|
+
register(registration) {
|
|
13446
|
+
this.pendingItems.add(registration.item);
|
|
13447
|
+
const index = this.count++;
|
|
13448
|
+
return {
|
|
13449
|
+
attrs: ` q:g="${this.id}" q:i="${index}" q:o="${this.orderCode}"` + (this.collapsed ? ' q:c' : ''),
|
|
13450
|
+
showFallback: this.canReveal(registration) || !this.collapsed,
|
|
13451
|
+
resolve: () => {
|
|
13452
|
+
this.pendingItems.delete(registration.item);
|
|
13453
|
+
},
|
|
13454
|
+
};
|
|
13455
|
+
}
|
|
13456
|
+
canReveal(registration) {
|
|
13457
|
+
return canRevealRegistration(registration, (item) => this.pendingItems.has(item));
|
|
13458
|
+
}
|
|
13459
|
+
script() {
|
|
13460
|
+
return this.count === 0 ? '' : `qO.g(${this.id},${this.count},"${this.orderCode}");`;
|
|
13461
|
+
}
|
|
13462
|
+
}
|
|
13463
|
+
/** @internal */
|
|
13464
|
+
const createOutOfOrderRevealCoordinator = (order, collapsed) => {
|
|
13465
|
+
if (!isOutOfOrderStreaming()) {
|
|
13466
|
+
return null;
|
|
13467
|
+
}
|
|
13468
|
+
const container = tryGetInvokeContext()?.$container$;
|
|
13469
|
+
let id = 0;
|
|
13470
|
+
if (container) {
|
|
13471
|
+
id = (outOfOrderRevealIds.get(container) || 0) + 1;
|
|
13472
|
+
outOfOrderRevealIds.set(container, id);
|
|
13473
|
+
}
|
|
13474
|
+
return new OutOfOrderRevealCoordinator(id, order, collapsed);
|
|
13475
|
+
};
|
|
13476
|
+
const getOutOfOrderRevealOrderCode = (order) => {
|
|
13477
|
+
switch (order) {
|
|
13478
|
+
case 'sequential':
|
|
13479
|
+
return 's';
|
|
13480
|
+
case 'reverse':
|
|
13481
|
+
return 'r';
|
|
13482
|
+
case 'together':
|
|
13483
|
+
return 't';
|
|
13484
|
+
default:
|
|
13485
|
+
return 'p';
|
|
13486
|
+
}
|
|
13487
|
+
};
|
|
13488
|
+
/** @internal */
|
|
13489
|
+
const isOutOfOrderStreaming = () => {
|
|
13490
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
13491
|
+
return false;
|
|
13492
|
+
}
|
|
13493
|
+
const container = tryGetInvokeContext()?.$container$;
|
|
13494
|
+
return container?.outOfOrderStreaming === true && !isOutOfOrderSegmentContainer(container);
|
|
13495
|
+
};
|
|
13496
|
+
/** @internal */
|
|
13497
|
+
const nextOutOfOrderSuspenseId = () => {
|
|
13498
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
13499
|
+
return 0;
|
|
13500
|
+
}
|
|
13501
|
+
const container = tryGetInvokeContext()?.$container$;
|
|
13502
|
+
if (container?.outOfOrderStreaming !== true) {
|
|
13503
|
+
return 0;
|
|
13504
|
+
}
|
|
13505
|
+
return container?.nextOutOfOrderId?.() ?? 0;
|
|
13506
|
+
};
|
|
13507
|
+
/** @internal */
|
|
13508
|
+
const applySubscriptionPatches = (container, patches) => {
|
|
13509
|
+
if (!__EXPERIMENTAL__.suspense || !patches) {
|
|
13510
|
+
return;
|
|
13511
|
+
}
|
|
13512
|
+
for (let i = 0; i < patches.length; i++) {
|
|
13513
|
+
const patch = patches[i];
|
|
13514
|
+
const root = container.$getObjectById$(patch.rootId);
|
|
13515
|
+
const subscriptions = patch.subscriptions;
|
|
13516
|
+
if (root instanceof SignalImpl) {
|
|
13517
|
+
if (subscriptions instanceof Set) {
|
|
13518
|
+
mergeSubscriptionSet(container, root, root, (root.$effects$ ||= new Set()), subscriptions);
|
|
13519
|
+
}
|
|
13520
|
+
}
|
|
13521
|
+
else {
|
|
13522
|
+
if (!(subscriptions instanceof Map)) {
|
|
13523
|
+
continue;
|
|
13524
|
+
}
|
|
13525
|
+
const handler = getStoreHandler(root);
|
|
13526
|
+
const target = getStoreTarget(root);
|
|
13527
|
+
if (!handler || !target) {
|
|
13528
|
+
continue;
|
|
13529
|
+
}
|
|
13530
|
+
const effectsMap = (handler.$effects$ ||= new Map());
|
|
13531
|
+
for (const [storeProp, subscriptionSet] of subscriptions) {
|
|
13532
|
+
let rootEffects = effectsMap.get(storeProp);
|
|
13533
|
+
if (!rootEffects) {
|
|
13534
|
+
rootEffects = new Set();
|
|
13535
|
+
effectsMap.set(storeProp, rootEffects);
|
|
13536
|
+
}
|
|
13537
|
+
mergeSubscriptionSet(container, handler, target, rootEffects, subscriptionSet);
|
|
13538
|
+
}
|
|
13539
|
+
}
|
|
13540
|
+
}
|
|
13541
|
+
};
|
|
13542
|
+
const mergeSubscriptionSet = (container, producer, backRef, rootEffects, patchEffects) => {
|
|
13543
|
+
let newEffects;
|
|
13544
|
+
for (const effect of patchEffects) {
|
|
13545
|
+
if (!rootEffects.has(effect)) {
|
|
13546
|
+
rootEffects.add(effect);
|
|
13547
|
+
(newEffects ||= new Set()).add(effect);
|
|
13548
|
+
}
|
|
13549
|
+
(effect.backRef ||= new Set()).add(backRef);
|
|
13550
|
+
}
|
|
13551
|
+
if (newEffects) {
|
|
13552
|
+
scheduleEffects(container, producer, newEffects);
|
|
13553
|
+
}
|
|
13554
|
+
};
|
|
13555
|
+
|
|
13556
|
+
const processedStatePatchScripts = new WeakMap();
|
|
13557
|
+
/** @internal */
|
|
13558
|
+
const processSegmentStateScripts = (container, segmentId) => {
|
|
13559
|
+
if (!__EXPERIMENTAL__.suspense) {
|
|
13560
|
+
return;
|
|
13561
|
+
}
|
|
13562
|
+
const stateContainer = container;
|
|
13563
|
+
const qwikStates = stateContainer.element.querySelectorAll(`${stateScriptSelector(stateContainer.$instanceHash$)}${QStatePatchAttrSelector}`);
|
|
13564
|
+
const processedScripts = getProcessedStatePatchScripts(container);
|
|
13565
|
+
for (let i = 0; i < qwikStates.length; i++) {
|
|
13566
|
+
const stateScript = qwikStates[i];
|
|
13567
|
+
if (segmentId !== undefined && stateScript.getAttribute(QSuspenseResolved) !== segmentId) {
|
|
13568
|
+
continue;
|
|
13569
|
+
}
|
|
13570
|
+
if (processedScripts.has(stateScript)) {
|
|
13571
|
+
continue;
|
|
13572
|
+
}
|
|
13573
|
+
processedScripts.add(stateScript);
|
|
13574
|
+
processStatePatch(container, stateContainer, stateScript.textContent);
|
|
13575
|
+
}
|
|
13576
|
+
};
|
|
13577
|
+
const getProcessedStatePatchScripts = (container) => {
|
|
13578
|
+
let processedScripts = processedStatePatchScripts.get(container);
|
|
13579
|
+
if (!processedScripts) {
|
|
13580
|
+
processedScripts = new WeakSet();
|
|
13581
|
+
processedStatePatchScripts.set(container, processedScripts);
|
|
13582
|
+
}
|
|
13583
|
+
return processedScripts;
|
|
13584
|
+
};
|
|
13585
|
+
const stateScriptSelector = (instanceHash) => {
|
|
13586
|
+
return `script[type="qwik/state"][q\\:instance="${instanceHash}"]`;
|
|
13587
|
+
};
|
|
13588
|
+
const processStatePatch = (container, stateContainer, textContent) => {
|
|
13589
|
+
if (textContent) {
|
|
13590
|
+
const [rootStart, rawStateData, forwardRefs, subscriptionPatchRootId] = JSON.parse(textContent);
|
|
13591
|
+
appendStatePatchRoots(container, stateContainer, rootStart, rawStateData);
|
|
13592
|
+
mergeForwardRefs(stateContainer, forwardRefs || undefined);
|
|
13593
|
+
applySubscriptionPatches(container, subscriptionPatchRootId === undefined
|
|
13594
|
+
? undefined
|
|
13595
|
+
: stateContainer.$getObjectById$(subscriptionPatchRootId));
|
|
13596
|
+
}
|
|
13597
|
+
};
|
|
13598
|
+
const appendStatePatchRoots = (container, stateContainer, rootStart, rawStateData) => {
|
|
13599
|
+
const currentRootCount = stateContainer.$rawStateData$.length / 2;
|
|
13600
|
+
if (rootStart !== currentRootCount) {
|
|
13601
|
+
if (qDev) {
|
|
13602
|
+
throw new Error(`Invalid Qwik state patch root start: expected ${currentRootCount}, received ${rootStart}.`);
|
|
13603
|
+
}
|
|
13604
|
+
return;
|
|
13605
|
+
}
|
|
13606
|
+
for (let i = 0; i < rawStateData.length; i++) {
|
|
13607
|
+
stateContainer.$rawStateData$[rootStart * 2 + i] = rawStateData[i];
|
|
13608
|
+
}
|
|
13609
|
+
preprocessState(stateContainer.$rawStateData$, container, undefined, rootStart * 2);
|
|
13610
|
+
stateContainer.$stateData$ = wrapDeserializerProxy(container, stateContainer.$rawStateData$);
|
|
13611
|
+
stateContainer.$stateData$.length = stateContainer.$rawStateData$.length / 2;
|
|
13612
|
+
stateContainer.$rootForwardRefs$ = stateContainer.$forwardRefs$;
|
|
13613
|
+
};
|
|
13614
|
+
const mergeForwardRefs = (stateContainer, forwardRefs) => {
|
|
13615
|
+
if (!forwardRefs) {
|
|
13616
|
+
return;
|
|
13617
|
+
}
|
|
13618
|
+
const rootForwardRefs = (stateContainer.$rootForwardRefs$ ||= []);
|
|
13619
|
+
for (let i = 0; i < forwardRefs.length; i++) {
|
|
13620
|
+
const ref = forwardRefs[i];
|
|
13621
|
+
if (ref !== undefined) {
|
|
13622
|
+
rootForwardRefs.push(ref);
|
|
13623
|
+
}
|
|
13624
|
+
}
|
|
13625
|
+
stateContainer.$forwardRefs$ = rootForwardRefs;
|
|
13626
|
+
};
|
|
13627
|
+
|
|
12889
13628
|
// NOTE: we want to move this function to qwikloader, and therefore this function should not have any external dependencies
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
|
|
12897
|
-
|
|
12898
|
-
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
*
|
|
12903
|
-
* Below is an example of the kinds of constructs which need to be handled when dealing with
|
|
12904
|
-
* VNodeData deserialization.
|
|
12905
|
-
*
|
|
12906
|
-
* ```
|
|
12907
|
-
* <html q:container="paused">
|
|
12908
|
-
* <body>
|
|
12909
|
-
* <div q:container="paused">
|
|
12910
|
-
* <script type="qwik/vnode">...</script>
|
|
12911
|
-
* </div>
|
|
12912
|
-
* <div q:container="html">...</div>
|
|
12913
|
-
* before
|
|
12914
|
-
* <!--q:container=ABC-->
|
|
12915
|
-
* ...
|
|
12916
|
-
* <!--/q:container-->
|
|
12917
|
-
* after
|
|
12918
|
-
* <!--q:ignore=FOO-->
|
|
12919
|
-
* ...
|
|
12920
|
-
* <!--q:container-island=BAR-->
|
|
12921
|
-
* <div>some interactive island</div>
|
|
12922
|
-
* <!--/q:container-island-->
|
|
12923
|
-
* ...
|
|
12924
|
-
* <!--/q:ignore-->
|
|
12925
|
-
* <textarea q:container="text">...</textarea>
|
|
12926
|
-
* <script type="qwik/vnode">...</script>
|
|
12927
|
-
* </body>
|
|
12928
|
-
* </html>
|
|
12929
|
-
* ```
|
|
12930
|
-
*
|
|
12931
|
-
* Each `qwik/vnode` script assumes that the elements are numbered in depth first order. For this
|
|
12932
|
-
* reason, whenever the `processVNodeData` comes across a `q:container` it must ignore its
|
|
12933
|
-
* children.
|
|
12934
|
-
*
|
|
12935
|
-
* IMPLEMENTATION:
|
|
12936
|
-
*
|
|
12937
|
-
* - Stack to keep track of the current `q:container` being processed.
|
|
12938
|
-
* - Attach all `qwik/vnode` scripts (not the data contain within them) to the `q:container` element.
|
|
12939
|
-
* - Walk the tree and process each `q:container` element.
|
|
12940
|
-
*/
|
|
13629
|
+
function processOutOfOrderSegmentVNodeData(document, segmentId, contentNode) {
|
|
13630
|
+
if (!__EXPERIMENTAL__.suspense || !contentNode) {
|
|
13631
|
+
return;
|
|
13632
|
+
}
|
|
13633
|
+
const qContainerElement = contentNode.closest('[q\\:container]');
|
|
13634
|
+
const script = qContainerElement?.querySelector(`script[type="qwik/vnode"][q\\:r="${segmentId}"]:not([q\\:patch])`);
|
|
13635
|
+
processVNodeDataImpl(document, segmentId, qContainerElement, contentNode, script?.textContent || undefined);
|
|
13636
|
+
const patches = qContainerElement?.querySelectorAll(`script[type="qwik/vnode"][q\\:r="${segmentId}"][q\\:patch]`);
|
|
13637
|
+
for (let i = 0; patches && i < patches.length; i++) {
|
|
13638
|
+
document.qProcessVNodeDataPatch?.(patches[i]);
|
|
13639
|
+
}
|
|
13640
|
+
}
|
|
12941
13641
|
function processVNodeData(document) {
|
|
13642
|
+
processVNodeDataImpl(document);
|
|
13643
|
+
document.qVNodeDataProcessed = true;
|
|
13644
|
+
}
|
|
13645
|
+
function processVNodeDataImpl(document, segmentId, segmentContainer, segmentContent, segmentVNodeData) {
|
|
12942
13646
|
const Q_CONTAINER = 'q:container';
|
|
12943
13647
|
const Q_CONTAINER_END = '/' + Q_CONTAINER;
|
|
12944
13648
|
const Q_PROPS_SEPARATOR = ':';
|
|
@@ -12947,8 +13651,11 @@ function processVNodeData(document) {
|
|
|
12947
13651
|
const Q_IGNORE_END = '/' + Q_IGNORE;
|
|
12948
13652
|
const Q_CONTAINER_ISLAND = 'q:container-island';
|
|
12949
13653
|
const Q_CONTAINER_ISLAND_END = '/' + Q_CONTAINER_ISLAND;
|
|
13654
|
+
const Q_SUSPENSE_RESOLVED = 'q:r';
|
|
13655
|
+
const Q_SUSPENSE_RESULT_PARENT = 'q:rp';
|
|
13656
|
+
const Q_PATCH = 'q:patch';
|
|
12950
13657
|
const qDocument = document;
|
|
12951
|
-
const vNodeDataMap =
|
|
13658
|
+
const vNodeDataMap = (qDocument.qVNodeData ||= new WeakMap());
|
|
12952
13659
|
const prototype = document.body;
|
|
12953
13660
|
const getter = (prototype, name) => {
|
|
12954
13661
|
let getter;
|
|
@@ -12968,9 +13675,20 @@ function processVNodeData(document) {
|
|
|
12968
13675
|
const scripts = element.querySelectorAll('script[type="qwik/vnode"]');
|
|
12969
13676
|
for (let i = 0; i < scripts.length; i++) {
|
|
12970
13677
|
const script = scripts[i];
|
|
12971
|
-
const
|
|
12972
|
-
|
|
12973
|
-
|
|
13678
|
+
const qContainer = script.closest('[q\\:container]');
|
|
13679
|
+
qContainer.qVNodeRefs ||= new Map();
|
|
13680
|
+
if (script.hasAttribute(Q_PATCH)) {
|
|
13681
|
+
qDocument.qProcessVNodeDataPatch?.(script);
|
|
13682
|
+
continue;
|
|
13683
|
+
}
|
|
13684
|
+
const scriptContent = script.textContent;
|
|
13685
|
+
const segment = __EXPERIMENTAL__.suspense && script.getAttribute(Q_SUSPENSE_RESOLVED);
|
|
13686
|
+
if (segment) {
|
|
13687
|
+
(qContainer.qSegmentVnodeData ||= new Map()).set(segment, scriptContent);
|
|
13688
|
+
}
|
|
13689
|
+
else {
|
|
13690
|
+
qContainer.qVnodeData = scriptContent;
|
|
13691
|
+
}
|
|
12974
13692
|
}
|
|
12975
13693
|
const shadowRoots = element.querySelectorAll('[q\\:shadowroot]');
|
|
12976
13694
|
for (let i = 0; i < shadowRoots.length; i++) {
|
|
@@ -12979,7 +13697,6 @@ function processVNodeData(document) {
|
|
|
12979
13697
|
shadowRoot && attachVnodeDataAndRefs(shadowRoot);
|
|
12980
13698
|
}
|
|
12981
13699
|
};
|
|
12982
|
-
attachVnodeDataAndRefs(document);
|
|
12983
13700
|
/**
|
|
12984
13701
|
* Looks up which type of node this is in a monomorphic way which should be faster.
|
|
12985
13702
|
*
|
|
@@ -12988,17 +13705,16 @@ function processVNodeData(document) {
|
|
|
12988
13705
|
const getFastNodeType = (node) => {
|
|
12989
13706
|
const nodeType = getNodeType.call(node);
|
|
12990
13707
|
if (nodeType === 1 /* Node.ELEMENT_NODE */) {
|
|
12991
|
-
|
|
12992
|
-
if (qContainer === null) {
|
|
12993
|
-
if (hasAttribute.call(node, Q_SHADOW_ROOT)) {
|
|
12994
|
-
return 6 /* NodeType.ELEMENT_SHADOW_ROOT_WRAPPER */;
|
|
12995
|
-
}
|
|
12996
|
-
const isQElement = hasAttribute.call(node, Q_PROPS_SEPARATOR);
|
|
12997
|
-
return isQElement ? 2 /* NodeType.ELEMENT */ : 0 /* NodeType.OTHER */;
|
|
12998
|
-
}
|
|
12999
|
-
else {
|
|
13708
|
+
if (getAttribute.call(node, Q_CONTAINER) !== null) {
|
|
13000
13709
|
return 3 /* NodeType.ELEMENT_CONTAINER */;
|
|
13001
13710
|
}
|
|
13711
|
+
if (hasAttribute.call(node, Q_SHADOW_ROOT)) {
|
|
13712
|
+
return 6 /* NodeType.ELEMENT_SHADOW_ROOT_WRAPPER */;
|
|
13713
|
+
}
|
|
13714
|
+
if (__EXPERIMENTAL__.suspense && getAttribute.call(node, Q_SUSPENSE_RESULT_PARENT) !== null) {
|
|
13715
|
+
return 130 /* NodeType.ELEMENT_SUSPENSE_RESULT_PARENT */;
|
|
13716
|
+
}
|
|
13717
|
+
return hasAttribute.call(node, Q_PROPS_SEPARATOR) ? 2 /* NodeType.ELEMENT */ : 0 /* NodeType.OTHER */;
|
|
13002
13718
|
}
|
|
13003
13719
|
else if (nodeType === 8 /* Node.COMMENT_NODE */) {
|
|
13004
13720
|
const nodeValue = node.nodeValue || ''; // nodeValue is monomorphic so it does not need fast path
|
|
@@ -13036,7 +13752,8 @@ function processVNodeData(document) {
|
|
|
13036
13752
|
* @param exitNode The node which represents the last node and we should exit.
|
|
13037
13753
|
* @param qVNodeRefs Place to store the VNodeRefs
|
|
13038
13754
|
*/
|
|
13039
|
-
const walkContainer = (walker, containerNode, node, exitNode, vData, qVNodeRefs,
|
|
13755
|
+
const walkContainer = (walker, containerNode, node, exitNode, vData, qVNodeRefs, qContainerElement, segmentId) => {
|
|
13756
|
+
const isSegment = __EXPERIMENTAL__.suspense && segmentId !== undefined;
|
|
13040
13757
|
const vData_length = vData.length;
|
|
13041
13758
|
/// Stores the current element index as the TreeWalker traverses the DOM.
|
|
13042
13759
|
let elementIdx = 0;
|
|
@@ -13052,7 +13769,6 @@ function processVNodeData(document) {
|
|
|
13052
13769
|
let elementsToSkip = 0;
|
|
13053
13770
|
while (isSeparator((ch = vData.charCodeAt(vData_start)))) {
|
|
13054
13771
|
// Keep consuming the separators and incrementing the vNodeIndex
|
|
13055
|
-
// console.log('ADVANCE', vNodeElementIndex, ch, ch - 33);
|
|
13056
13772
|
elementsToSkip += 1 << (ch - VNodeDataSeparator.ADVANCE_1);
|
|
13057
13773
|
vData_start++;
|
|
13058
13774
|
if (vData_start >= vData_length) {
|
|
@@ -13075,8 +13791,7 @@ function processVNodeData(document) {
|
|
|
13075
13791
|
while (cursor && !(nextNode = nextSibling(cursor))) {
|
|
13076
13792
|
cursor = cursor.parentNode;
|
|
13077
13793
|
}
|
|
13078
|
-
|
|
13079
|
-
walkContainer(walker, container, node, nextNode, container.qVnodeData || '', container.qVNodeRefs);
|
|
13794
|
+
walkContainer(walker, container, node, nextNode, container.qVnodeData || '', container.qVNodeRefs, container);
|
|
13080
13795
|
}
|
|
13081
13796
|
else if (nodeType === 16 /* NodeType.COMMENT_IGNORE_START */) {
|
|
13082
13797
|
let islandNode = node;
|
|
@@ -13086,7 +13801,6 @@ function processVNodeData(document) {
|
|
|
13086
13801
|
throw new Error(`Island inside <!--${node?.nodeValue}--> not found!`);
|
|
13087
13802
|
}
|
|
13088
13803
|
} while (getFastNodeType(islandNode) !== 65 /* NodeType.COMMENT_ISLAND_START */);
|
|
13089
|
-
nextNode = null;
|
|
13090
13804
|
}
|
|
13091
13805
|
else if (nodeType === 64 /* NodeType.COMMENT_ISLAND_END */) {
|
|
13092
13806
|
// Walk forward to find either the next container-island or the end of the q:ignore block.
|
|
@@ -13112,8 +13826,7 @@ function processVNodeData(document) {
|
|
|
13112
13826
|
throw new Error(`<!--${node?.nodeValue}--> not closed!`);
|
|
13113
13827
|
}
|
|
13114
13828
|
} while (getFastNodeType(nextNode) !== 8 /* NodeType.COMMENT_SKIP_END */);
|
|
13115
|
-
|
|
13116
|
-
walkContainer(walker, node, node, nextNode, '', null);
|
|
13829
|
+
walkContainer(walker, node, node, nextNode, '', null, qContainerElement);
|
|
13117
13830
|
}
|
|
13118
13831
|
else if (nodeType === 6 /* NodeType.ELEMENT_SHADOW_ROOT_WRAPPER */) {
|
|
13119
13832
|
// If we are in a shadow root, we need to get the shadow root element.
|
|
@@ -13123,10 +13836,14 @@ function processVNodeData(document) {
|
|
|
13123
13836
|
if (shadowRoot) {
|
|
13124
13837
|
walkContainer(
|
|
13125
13838
|
// we need to create a new walker for the shadow root
|
|
13126
|
-
document.createTreeWalker(shadowRoot, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */), null, shadowRoot, null, '', null);
|
|
13839
|
+
document.createTreeWalker(shadowRoot, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */), null, shadowRoot, null, '', null, null);
|
|
13127
13840
|
}
|
|
13128
13841
|
}
|
|
13129
13842
|
if ((nodeType & 2 /* NodeType.ELEMENT */) === 2 /* NodeType.ELEMENT */) {
|
|
13843
|
+
if (isSegment && node !== containerNode) {
|
|
13844
|
+
const element = node;
|
|
13845
|
+
element._qSegment = segmentId;
|
|
13846
|
+
}
|
|
13130
13847
|
if (vNodeElementIndex < elementIdx) {
|
|
13131
13848
|
// VNodeData needs to catch up with the elementIdx
|
|
13132
13849
|
if (vNodeElementIndex === -1) {
|
|
@@ -13135,8 +13852,7 @@ function processVNodeData(document) {
|
|
|
13135
13852
|
vData_start = vData_end;
|
|
13136
13853
|
if (vData_start < vData_length) {
|
|
13137
13854
|
vNodeElementIndex += howManyElementsToSkip();
|
|
13138
|
-
|
|
13139
|
-
if (shouldStoreRef) {
|
|
13855
|
+
if (ch === VNodeDataSeparator.REFERENCE) {
|
|
13140
13856
|
// if we need to store the ref handle it here.
|
|
13141
13857
|
needsToStoreRef = vNodeElementIndex;
|
|
13142
13858
|
vData_start++;
|
|
@@ -13154,29 +13870,78 @@ function processVNodeData(document) {
|
|
|
13154
13870
|
vNodeElementIndex = Number.MAX_SAFE_INTEGER;
|
|
13155
13871
|
}
|
|
13156
13872
|
}
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
// vNodeElementIndex,
|
|
13163
|
-
// (node as any).outerHTML,
|
|
13164
|
-
// elementIdx === vNodeElementIndex ? vData.substring(vData_start, vData_end) : ''
|
|
13165
|
-
// );
|
|
13873
|
+
const contentBoundaryId = __EXPERIMENTAL__.suspense &&
|
|
13874
|
+
!isSegment &&
|
|
13875
|
+
nodeType === 130 /* NodeType.ELEMENT_SUSPENSE_RESULT_PARENT */
|
|
13876
|
+
? getAttribute.call(node, Q_SUSPENSE_RESULT_PARENT)
|
|
13877
|
+
: null;
|
|
13166
13878
|
if (elementIdx === vNodeElementIndex) {
|
|
13167
|
-
if (needsToStoreRef === elementIdx) {
|
|
13168
|
-
qVNodeRefs.set(elementIdx, node);
|
|
13879
|
+
if (needsToStoreRef === elementIdx && !(isSegment && node === containerNode)) {
|
|
13880
|
+
qVNodeRefs.set(isSegment ? getSegmentVNodeRefId(segmentId, elementIdx) : elementIdx, node);
|
|
13881
|
+
}
|
|
13882
|
+
const data = vData.substring(vData_start, vData_end);
|
|
13883
|
+
if (isSegment && node === containerNode) {
|
|
13884
|
+
const existing = vNodeDataMap.get(node);
|
|
13885
|
+
if (existing === undefined || existing === '') {
|
|
13886
|
+
vNodeDataMap.set(node, data);
|
|
13887
|
+
}
|
|
13888
|
+
else if (existing.charCodeAt(0) === VNodeDataChar.SEPARATOR &&
|
|
13889
|
+
existing.charCodeAt(1) === VNodeDataChar.SEPARATOR &&
|
|
13890
|
+
!existing.endsWith(data)) {
|
|
13891
|
+
vNodeDataMap.set(node, existing + data);
|
|
13892
|
+
}
|
|
13893
|
+
}
|
|
13894
|
+
else {
|
|
13895
|
+
vNodeDataMap.set(node, data);
|
|
13169
13896
|
}
|
|
13170
|
-
const instructions = vData.substring(vData_start, vData_end);
|
|
13171
|
-
vNodeDataMap.set(node, instructions);
|
|
13172
13897
|
}
|
|
13173
13898
|
elementIdx++;
|
|
13899
|
+
if (__EXPERIMENTAL__.suspense && contentBoundaryId !== null) {
|
|
13900
|
+
processSuspenseContentSegment(qContainerElement, node, contentBoundaryId);
|
|
13901
|
+
nextNode = nextSibling(node);
|
|
13902
|
+
if (nextNode) {
|
|
13903
|
+
walker.currentNode = nextNode;
|
|
13904
|
+
}
|
|
13905
|
+
}
|
|
13174
13906
|
}
|
|
13175
13907
|
} while ((node = nextNode || walker.nextNode()));
|
|
13176
13908
|
};
|
|
13909
|
+
const processVNodeDataScope = (qContainerElement, contentNode, vData, scopeSegmentId) => {
|
|
13910
|
+
qContainerElement.qVNodeRefs ||= new Map();
|
|
13911
|
+
const scopeWalker = document.createTreeWalker(document, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */);
|
|
13912
|
+
scopeWalker.currentNode = contentNode;
|
|
13913
|
+
walkContainer(scopeWalker, contentNode, contentNode, nextSibling(contentNode), vData, qContainerElement.qVNodeRefs, qContainerElement, scopeSegmentId);
|
|
13914
|
+
};
|
|
13915
|
+
const processSuspenseContentSegment = __EXPERIMENTAL__.suspense
|
|
13916
|
+
? (qContainerElement, contentNode, boundaryId, vData) => {
|
|
13917
|
+
vData ||= qContainerElement?.qSegmentVnodeData?.get(boundaryId);
|
|
13918
|
+
if (qContainerElement && vData) {
|
|
13919
|
+
processVNodeDataScope(qContainerElement, contentNode, vData, boundaryId);
|
|
13920
|
+
}
|
|
13921
|
+
}
|
|
13922
|
+
: null;
|
|
13923
|
+
qDocument.qProcessVNodeDataPatch = (script) => {
|
|
13924
|
+
const qContainerElement = script?.closest('[q\\:container]');
|
|
13925
|
+
const patchSegment = script?.getAttribute(Q_SUSPENSE_RESOLVED);
|
|
13926
|
+
const contentNode = qContainerElement &&
|
|
13927
|
+
(patchSegment
|
|
13928
|
+
? qContainerElement.querySelector(`[q\\:rp="${patchSegment}"]`)
|
|
13929
|
+
: qContainerElement);
|
|
13930
|
+
if (qContainerElement && contentNode) {
|
|
13931
|
+
processVNodeDataScope(qContainerElement, contentNode, script.textContent, patchSegment || undefined);
|
|
13932
|
+
}
|
|
13933
|
+
};
|
|
13934
|
+
if (__EXPERIMENTAL__.suspense && segmentId !== undefined) {
|
|
13935
|
+
if (segmentContainer && segmentContent && segmentVNodeData) {
|
|
13936
|
+
segmentContainer.qVNodeRefs ||= new Map();
|
|
13937
|
+
processSuspenseContentSegment(segmentContainer, segmentContent, segmentId, segmentVNodeData);
|
|
13938
|
+
}
|
|
13939
|
+
return;
|
|
13940
|
+
}
|
|
13941
|
+
attachVnodeDataAndRefs(document);
|
|
13177
13942
|
// Walk the tree and process each `q:container` element.
|
|
13178
13943
|
const walker = document.createTreeWalker(document, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */);
|
|
13179
|
-
walkContainer(walker, null, walker.firstChild(), null, '', null);
|
|
13944
|
+
walkContainer(walker, null, walker.firstChild(), null, '', null, null);
|
|
13180
13945
|
}
|
|
13181
13946
|
const isSeparator = (ch) =>
|
|
13182
13947
|
/* `!` */ VNodeDataSeparator.ADVANCE_1 <= ch && ch <= VNodeDataSeparator.ADVANCE_8192; /* `.` */
|
|
@@ -13228,9 +13993,15 @@ function getDomContainerFromQContainerElement(qContainerElement) {
|
|
|
13228
13993
|
function _getQContainerElement(element) {
|
|
13229
13994
|
return element.closest(QContainerSelector);
|
|
13230
13995
|
}
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
|
|
13996
|
+
function getOutOfOrderStreamingScript(boundaryId, content) {
|
|
13997
|
+
const segmentId = String(boundaryId);
|
|
13998
|
+
const qContainerElement = content?.closest(QContainerSelector);
|
|
13999
|
+
const qContainer = qContainerElement?.qContainer;
|
|
14000
|
+
if (qContainer) {
|
|
14001
|
+
processOutOfOrderSegmentVNodeData(qContainer.element.ownerDocument, segmentId, content);
|
|
14002
|
+
processSegmentStateScripts(qContainer, segmentId);
|
|
14003
|
+
}
|
|
14004
|
+
}
|
|
13234
14005
|
/** @internal */
|
|
13235
14006
|
class DomContainer extends _SharedContainer {
|
|
13236
14007
|
element;
|
|
@@ -13245,6 +14016,7 @@ class DomContainer extends _SharedContainer {
|
|
|
13245
14016
|
vNodeLocate = (id) => vnode_locate(this.rootVNode, id);
|
|
13246
14017
|
$rawStateData$;
|
|
13247
14018
|
$stateData$;
|
|
14019
|
+
$rootForwardRefs$ = null;
|
|
13248
14020
|
$styleIds$ = null;
|
|
13249
14021
|
constructor(element) {
|
|
13250
14022
|
super({}, element.getAttribute(QLocaleAttr));
|
|
@@ -13261,20 +14033,20 @@ class DomContainer extends _SharedContainer {
|
|
|
13261
14033
|
this.$rawStateData$ = [];
|
|
13262
14034
|
this.$stateData$ = [];
|
|
13263
14035
|
const document = this.element.ownerDocument;
|
|
13264
|
-
if (!document.
|
|
14036
|
+
if (!document.qVNodeDataProcessed) {
|
|
13265
14037
|
processVNodeData(document);
|
|
13266
14038
|
}
|
|
14039
|
+
if (__EXPERIMENTAL__.suspense && document.querySelector('template[q\\:r]')) {
|
|
14040
|
+
document.qProcessOOOS ||= getOutOfOrderStreamingScript;
|
|
14041
|
+
}
|
|
13267
14042
|
this.$qFuncs$ = getQFuncs(document, this.$instanceHash$) || EMPTY_ARRAY;
|
|
13268
14043
|
this.$setServerData$();
|
|
13269
14044
|
element.setAttribute(QContainerAttr, "resumed" /* QContainerValue.RESUMED */);
|
|
13270
14045
|
element.qContainer = this;
|
|
13271
14046
|
element.qDestroy = () => this.$destroy$();
|
|
13272
|
-
|
|
13273
|
-
if (
|
|
13274
|
-
|
|
13275
|
-
this.$rawStateData$ = JSON.parse(lastState.textContent);
|
|
13276
|
-
preprocessState(this.$rawStateData$, this);
|
|
13277
|
-
this.$stateData$ = wrapDeserializerProxy(this, this.$rawStateData$);
|
|
14047
|
+
this.$processRootStateScript$();
|
|
14048
|
+
if (__EXPERIMENTAL__.suspense) {
|
|
14049
|
+
processSegmentStateScripts(this);
|
|
13278
14050
|
}
|
|
13279
14051
|
this.$hoistStyles$();
|
|
13280
14052
|
if (!qTest && element.isConnected) {
|
|
@@ -13291,8 +14063,34 @@ class DomContainer extends _SharedContainer {
|
|
|
13291
14063
|
el.qContainer = undefined;
|
|
13292
14064
|
el.qVnodeData = undefined;
|
|
13293
14065
|
el.qVNodeRefs = undefined;
|
|
14066
|
+
if (__EXPERIMENTAL__.suspense) {
|
|
14067
|
+
el.qSegmentVnodeData = undefined;
|
|
14068
|
+
}
|
|
13294
14069
|
el.removeAttribute(QContainerAttr);
|
|
13295
|
-
el.ownerDocument
|
|
14070
|
+
const document = el.ownerDocument;
|
|
14071
|
+
const hasContainers = document.querySelector(QContainerSelector) !== null;
|
|
14072
|
+
if (!hasContainers) {
|
|
14073
|
+
document.qVNodeData = undefined;
|
|
14074
|
+
document.qVNodeDataProcessed = undefined;
|
|
14075
|
+
document.qProcessVNodeDataPatch = undefined;
|
|
14076
|
+
}
|
|
14077
|
+
if (__EXPERIMENTAL__.suspense) {
|
|
14078
|
+
if (!hasContainers) {
|
|
14079
|
+
document.qProcessOOOS = undefined;
|
|
14080
|
+
}
|
|
14081
|
+
}
|
|
14082
|
+
}
|
|
14083
|
+
$processRootStateScript$() {
|
|
14084
|
+
const rootState = this.element.querySelector(`${this.$stateScriptSelector$()}:not(${QStatePatchAttrSelector})`);
|
|
14085
|
+
if (rootState) {
|
|
14086
|
+
this.$rawStateData$ = JSON.parse(rootState.textContent);
|
|
14087
|
+
preprocessState(this.$rawStateData$, this);
|
|
14088
|
+
this.$rootForwardRefs$ = this.$forwardRefs$;
|
|
14089
|
+
this.$stateData$ = wrapDeserializerProxy(this, this.$rawStateData$);
|
|
14090
|
+
}
|
|
14091
|
+
}
|
|
14092
|
+
$stateScriptSelector$() {
|
|
14093
|
+
return `script[type="qwik/state"][q\\:instance="${this.$instanceHash$}"]`;
|
|
13296
14094
|
}
|
|
13297
14095
|
/**
|
|
13298
14096
|
* The first time we render we need to hoist the styles. (Meaning we need to move all styles from
|
|
@@ -13326,7 +14124,7 @@ class DomContainer extends _SharedContainer {
|
|
|
13326
14124
|
if (qDev && host) {
|
|
13327
14125
|
if (typeof document !== 'undefined') {
|
|
13328
14126
|
setErrorPayload(host, err);
|
|
13329
|
-
markVNodeDirty(this, host,
|
|
14127
|
+
markVNodeDirty(this, host, 512 /* ChoreBits.ERROR_WRAP */);
|
|
13330
14128
|
}
|
|
13331
14129
|
if (err && err instanceof Error) {
|
|
13332
14130
|
if (!('hostElement' in err)) {
|
|
@@ -13423,6 +14221,9 @@ class DomContainer extends _SharedContainer {
|
|
|
13423
14221
|
$getObjectById$ = (id) => {
|
|
13424
14222
|
return getObjectById(id, this.$stateData$);
|
|
13425
14223
|
};
|
|
14224
|
+
$getForwardRef$(id) {
|
|
14225
|
+
return this.$rootForwardRefs$?.[id];
|
|
14226
|
+
}
|
|
13426
14227
|
getSyncFn(id) {
|
|
13427
14228
|
const fn = this.$qFuncs$[id];
|
|
13428
14229
|
isDev && assertTrue(typeof fn === 'function', 'Invalid reference: ' + id);
|
|
@@ -14562,7 +15363,8 @@ const intToStr = (nu) => {
|
|
|
14562
15363
|
return nu.toString(36);
|
|
14563
15364
|
};
|
|
14564
15365
|
const getNextUniqueIndex = (container) => {
|
|
14565
|
-
|
|
15366
|
+
const rootContainer = getRootContainer(container);
|
|
15367
|
+
return intToStr(rootContainer.$currentUniqueId$++);
|
|
14566
15368
|
};
|
|
14567
15369
|
|
|
14568
15370
|
/** @public */
|
|
@@ -15350,7 +16152,7 @@ const eachCmpTask = async ({ track }) => {
|
|
|
15350
16152
|
const context = tryGetInvokeContext();
|
|
15351
16153
|
const host = context.$hostElement$;
|
|
15352
16154
|
const container = context.$container$;
|
|
15353
|
-
markVNodeDirty(container, host,
|
|
16155
|
+
markVNodeDirty(container, host, 256 /* ChoreBits.RECONCILE */);
|
|
15354
16156
|
const isSsr = qTest ? isServerPlatform() : isServer;
|
|
15355
16157
|
if (isSsr) {
|
|
15356
16158
|
await container.$renderPromise$;
|
|
@@ -15380,49 +16182,17 @@ const createRevealContext = (props) => {
|
|
|
15380
16182
|
/** @internal */
|
|
15381
16183
|
const revealCanReveal = () => {
|
|
15382
16184
|
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
16185
|
// `version` is monotonic; the branch keeps the subscription read from being dropped by minifiers.
|
|
15390
|
-
if (reveal.version.value < 0) {
|
|
16186
|
+
if (registration !== null && registration.reveal.version.value < 0) {
|
|
15391
16187
|
return false;
|
|
15392
16188
|
}
|
|
15393
|
-
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
|
|
15397
|
-
|
|
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;
|
|
16189
|
+
if (qTest ? isServerPlatform() : !isBrowser$1) {
|
|
16190
|
+
const ooos = registration?.reveal.ooos;
|
|
16191
|
+
if (ooos) {
|
|
16192
|
+
return ooos.canReveal(registration);
|
|
16193
|
+
}
|
|
15425
16194
|
}
|
|
16195
|
+
return canRevealRegistration(registration);
|
|
15426
16196
|
};
|
|
15427
16197
|
/** @internal */
|
|
15428
16198
|
const revealCleanupTask = ({ cleanup }) => {
|
|
@@ -15457,6 +16227,15 @@ const useRevealBoundary = (boundary) => {
|
|
|
15457
16227
|
}
|
|
15458
16228
|
return registration;
|
|
15459
16229
|
};
|
|
16230
|
+
const getOutOfOrderCoordinator = (reveal) => {
|
|
16231
|
+
const coordinator = reveal.ooos;
|
|
16232
|
+
if (coordinator) {
|
|
16233
|
+
return coordinator;
|
|
16234
|
+
}
|
|
16235
|
+
const nextCoordinator = createOutOfOrderRevealCoordinator(reveal.order, reveal.collapsed);
|
|
16236
|
+
reveal.ooos = noSerialize(nextCoordinator);
|
|
16237
|
+
return nextCoordinator;
|
|
16238
|
+
};
|
|
15460
16239
|
/** @internal */
|
|
15461
16240
|
const revealCmp = (props) => {
|
|
15462
16241
|
if (!__EXPERIMENTAL__.suspense) {
|
|
@@ -15464,11 +16243,32 @@ const revealCmp = (props) => {
|
|
|
15464
16243
|
}
|
|
15465
16244
|
const reveal = useConstant(createRevealContext, props);
|
|
15466
16245
|
useContextProvider(RevealContext, reveal);
|
|
16246
|
+
const isServerEnv = qTest ? isServerPlatform() : !isBrowser$1;
|
|
16247
|
+
if (__EXPERIMENTAL__.suspense && isServerEnv && isOutOfOrderStreaming()) {
|
|
16248
|
+
const coordinator = getOutOfOrderCoordinator(reveal);
|
|
16249
|
+
return /*#__PURE__*/ _jsxSorted(SSRRevealSlot, {
|
|
16250
|
+
coordinator,
|
|
16251
|
+
}, null, null, 0, 'u7_0');
|
|
16252
|
+
}
|
|
15467
16253
|
return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 0, 'u7_0');
|
|
15468
16254
|
};
|
|
15469
16255
|
/** @public @experimental */
|
|
15470
16256
|
const Reveal = /*#__PURE__*/ componentQrl(
|
|
15471
16257
|
/*#__PURE__*/ inlinedQrl(revealCmp, '_reC'));
|
|
16258
|
+
const SSRRevealSlot = __EXPERIMENTAL__.suspense
|
|
16259
|
+
? /*#__PURE__*/ createInternalServerComponent((ssr, jsx, _options, enqueue) => {
|
|
16260
|
+
const coordinator = jsx.varProps.coordinator;
|
|
16261
|
+
enqueue(() => {
|
|
16262
|
+
const script = coordinator.script();
|
|
16263
|
+
if (!script) {
|
|
16264
|
+
return;
|
|
16265
|
+
}
|
|
16266
|
+
ssr.emitOutOfOrderExecutorIfNeeded();
|
|
16267
|
+
ssr.emitInlineScript(script);
|
|
16268
|
+
});
|
|
16269
|
+
enqueue(/*#__PURE__*/ _jsxSorted(Slot, null, null, null, 0, 'u7_0'));
|
|
16270
|
+
})
|
|
16271
|
+
: null;
|
|
15472
16272
|
|
|
15473
16273
|
const _hf0 = (p0, p1, p2, p3) => ({
|
|
15474
16274
|
display: p1.value === 'fallback' &&
|
|
@@ -15480,9 +16280,9 @@ const _hf0 = (p0, p1, p2, p3) => ({
|
|
|
15480
16280
|
});
|
|
15481
16281
|
const _hf0_str = '{display:p1.value==="fallback"&&p0.fallback!=null&&p0.fallback!==false&&(p2===null||p2.value||!p3.reveal.collapsed)?"contents":"none"}';
|
|
15482
16282
|
const _hf1 = (p0, p1, p2) => ({
|
|
15483
|
-
display: (
|
|
16283
|
+
display: (p1.value === 'content' || p0.showStale) && (p2 === null || p2.value) ? 'contents' : 'none',
|
|
15484
16284
|
});
|
|
15485
|
-
const _hf1_str = '{display:(
|
|
16285
|
+
const _hf1_str = '{display:(p1.value==="content"||p0.showStale)&&(p2===null||p2.value)?"contents":"none"}';
|
|
15486
16286
|
/** @internal */
|
|
15487
16287
|
const suspenseTask = ({ track, cleanup }) => {
|
|
15488
16288
|
const cursorBoundary = _captures[0], props = _captures[1], state = _captures[2], revealRegistration = _captures[3];
|
|
@@ -15519,21 +16319,154 @@ const suspenseCmp = (props) => {
|
|
|
15519
16319
|
state,
|
|
15520
16320
|
revealRegistration,
|
|
15521
16321
|
]));
|
|
15522
|
-
|
|
15523
|
-
|
|
16322
|
+
const isServerEnv = qTest ? isServerPlatform() : !isBrowser$1;
|
|
16323
|
+
const isServerOutOfOrder = isServerEnv && isOutOfOrderStreaming();
|
|
16324
|
+
const outOfOrderBoundaryId = isServerOutOfOrder ? nextOutOfOrderSuspenseId() : 0;
|
|
16325
|
+
const outOfOrderRevealBoundary = isServerOutOfOrder
|
|
16326
|
+
? (revealRegistration?.reveal.ooos?.register(revealRegistration) ?? null)
|
|
16327
|
+
: null;
|
|
16328
|
+
const showOutOfOrderFallback = isServerOutOfOrder && shouldRenderFallback(props.fallback, outOfOrderRevealBoundary);
|
|
16329
|
+
const outOfOrderBoundaryState = showOutOfOrderFallback && isPositiveDelay(props.delay)
|
|
16330
|
+
? { contentResolved: false, delayTimer: null }
|
|
16331
|
+
: null;
|
|
16332
|
+
const outOfOrderFallbackStyle = isServerOutOfOrder
|
|
16333
|
+
? /*#__PURE__*/ _fnSignal(_hf0, [props, state, canReveal, revealRegistration], _hf0_str)
|
|
16334
|
+
: null;
|
|
16335
|
+
const contentStyle = /*#__PURE__*/ _fnSignal(_hf1, [props, state, canReveal], _hf1_str);
|
|
16336
|
+
const fallbackHost = (isServerOutOfOrder
|
|
16337
|
+
? /*#__PURE__*/ _jsxSorted(SSRFallback, {
|
|
16338
|
+
boundary: outOfOrderBoundaryState,
|
|
16339
|
+
delay: props.delay,
|
|
16340
|
+
fallbackStyle: outOfOrderFallbackStyle,
|
|
16341
|
+
showFallback: showOutOfOrderFallback,
|
|
16342
|
+
state,
|
|
16343
|
+
}, null, _wrapProp(props, 'fallback'), 1, null)
|
|
16344
|
+
: /*#__PURE__*/ _jsxSorted('div', {
|
|
15524
16345
|
style: _fnSignal(_hf0, [props, state, canReveal, revealRegistration], _hf0_str),
|
|
15525
|
-
}, null, _wrapProp(props, 'fallback'), 1, null)
|
|
15526
|
-
|
|
15527
|
-
|
|
15528
|
-
|
|
15529
|
-
|
|
15530
|
-
|
|
15531
|
-
|
|
15532
|
-
|
|
16346
|
+
}, null, _wrapProp(props, 'fallback'), 1, null));
|
|
16347
|
+
return [
|
|
16348
|
+
fallbackHost,
|
|
16349
|
+
/*#__PURE__*/ _jsxSorted('div', null, isServerOutOfOrder
|
|
16350
|
+
? {
|
|
16351
|
+
[QSuspenseResultParent]: String(outOfOrderBoundaryId),
|
|
16352
|
+
style: contentStyle,
|
|
16353
|
+
}
|
|
16354
|
+
: {
|
|
16355
|
+
style: contentStyle,
|
|
16356
|
+
},
|
|
16357
|
+
/*#__PURE__*/ _jsxSorted(isServerOutOfOrder ? SSRDeferredSlot : Slot, isServerOutOfOrder
|
|
16358
|
+
? {
|
|
16359
|
+
[QCursorBoundary]: cursorBoundary,
|
|
16360
|
+
boundary: outOfOrderBoundaryState,
|
|
16361
|
+
boundaryId: outOfOrderBoundaryId,
|
|
16362
|
+
contentStyle,
|
|
16363
|
+
reveal: outOfOrderRevealBoundary,
|
|
16364
|
+
}
|
|
16365
|
+
: {
|
|
16366
|
+
[QCursorBoundary]: cursorBoundary,
|
|
16367
|
+
}, null, null, 3, 'u6_0'), 1, null),
|
|
16368
|
+
];
|
|
15533
16369
|
};
|
|
15534
16370
|
/** @public @experimental */
|
|
15535
16371
|
const Suspense = /*#__PURE__*/ componentQrl(
|
|
15536
|
-
/*#__PURE__*/ inlinedQrl(suspenseCmp,
|
|
16372
|
+
/*#__PURE__*/ inlinedQrl(suspenseCmp, SUSPENSE_QRL_SYMBOL));
|
|
16373
|
+
const SSRFallback = __EXPERIMENTAL__.suspense
|
|
16374
|
+
? /*#__PURE__*/ createInternalServerComponent((ssr, jsx, _options, enqueue) => {
|
|
16375
|
+
const boundaryState = jsx.varProps.boundary;
|
|
16376
|
+
const delay = jsx.varProps.delay;
|
|
16377
|
+
const fallbackStyle = jsx.varProps.fallbackStyle;
|
|
16378
|
+
const showFallback = jsx.varProps.showFallback === true;
|
|
16379
|
+
const state = jsx.varProps.state;
|
|
16380
|
+
if (showFallback && !isPositiveDelay(delay)) {
|
|
16381
|
+
state.value = 'fallback';
|
|
16382
|
+
}
|
|
16383
|
+
else if (boundaryState && showFallback && isPositiveDelay(delay)) {
|
|
16384
|
+
enqueue(() => scheduleOutOfOrderFallbackDelay(ssr, boundaryState, state, delay));
|
|
16385
|
+
}
|
|
16386
|
+
enqueue(
|
|
16387
|
+
/*#__PURE__*/ _jsxSorted('div', {
|
|
16388
|
+
style: fallbackStyle,
|
|
16389
|
+
}, null, jsx.children, 1, null));
|
|
16390
|
+
})
|
|
16391
|
+
: null;
|
|
16392
|
+
const SSRDeferredSlot = __EXPERIMENTAL__.suspense
|
|
16393
|
+
? /*#__PURE__*/ createInternalServerComponent(async (ssr, jsx, options) => {
|
|
16394
|
+
const boundaryId = jsx.varProps.boundaryId ?? ssr.nextOutOfOrderId();
|
|
16395
|
+
const contentSegment = `${boundaryId}`;
|
|
16396
|
+
const boundaryState = jsx.varProps.boundary;
|
|
16397
|
+
const contentStyle = jsx.varProps.contentStyle;
|
|
16398
|
+
const revealBoundary = jsx.varProps.reveal;
|
|
16399
|
+
const content = ssr.segment(contentSegment, createClaimedDeferredSlot(ssr, jsx, options), options);
|
|
16400
|
+
writeOutOfOrderPlaceholder(ssr, boundaryId);
|
|
16401
|
+
ssr.emitOutOfOrderExecutorIfNeeded();
|
|
16402
|
+
ssr.queueOutOfOrderSegment(content.then((rendered) => emitRenderedOutOfOrderSegment(ssr, boundaryId, contentSegment, rendered, contentStyle, revealBoundary, boundaryState)));
|
|
16403
|
+
})
|
|
16404
|
+
: null;
|
|
16405
|
+
function createClaimedDeferredSlot(ssr, jsx, options) {
|
|
16406
|
+
const componentFrame = options.parentComponentFrame;
|
|
16407
|
+
if (!componentFrame) {
|
|
16408
|
+
return /*#__PURE__*/ _jsxSorted(Slot, jsx.varProps, jsx.constProps, jsx.children, jsx.flags, jsx.key);
|
|
16409
|
+
}
|
|
16410
|
+
const slotName = resolveSlotName(componentFrame.componentNode, jsx, ssr);
|
|
16411
|
+
const slotDefaultChildren = (jsx.children || null);
|
|
16412
|
+
const slotChildren = componentFrame.claimChildrenForSlot(slotName) || slotDefaultChildren;
|
|
16413
|
+
if (slotDefaultChildren && slotChildren !== slotDefaultChildren) {
|
|
16414
|
+
ssr.addUnclaimedProjection(componentFrame, QDefaultSlot, slotDefaultChildren);
|
|
16415
|
+
}
|
|
16416
|
+
return /*#__PURE__*/ _jsxSorted(Slot, jsx.varProps, jsx.constProps, slotChildren, jsx.flags, jsx.key);
|
|
16417
|
+
}
|
|
16418
|
+
async function emitRenderedOutOfOrderSegment(ssr, boundaryId, segmentId, rendered, contentStyle, revealBoundary, boundaryState) {
|
|
16419
|
+
markOutOfOrderContentResolved(boundaryState);
|
|
16420
|
+
revealBoundary?.resolve();
|
|
16421
|
+
await ssr.$runQueuedRender$(async () => {
|
|
16422
|
+
ssr.addRoot(contentStyle);
|
|
16423
|
+
const result = await rendered.container.$finalizeOutOfOrderSegment$(segmentId, rendered);
|
|
16424
|
+
writeOutOfOrderResolvedTemplate(ssr, boundaryId, result.html, revealBoundary);
|
|
16425
|
+
ssr.emitOutOfOrderSegmentScripts(result.scripts);
|
|
16426
|
+
ssr.emitInlineScript(`qO(${boundaryId})`);
|
|
16427
|
+
// qO() is the browser-visible handoff for this segment, so flush it immediately.
|
|
16428
|
+
await ssr.streamHandler.flush();
|
|
16429
|
+
});
|
|
16430
|
+
}
|
|
16431
|
+
function markOutOfOrderContentResolved(boundaryState) {
|
|
16432
|
+
if (!boundaryState) {
|
|
16433
|
+
return;
|
|
16434
|
+
}
|
|
16435
|
+
boundaryState.contentResolved = true;
|
|
16436
|
+
if (boundaryState.delayTimer) {
|
|
16437
|
+
clearTimeout(boundaryState.delayTimer);
|
|
16438
|
+
boundaryState.delayTimer = null;
|
|
16439
|
+
}
|
|
16440
|
+
}
|
|
16441
|
+
function scheduleOutOfOrderFallbackDelay(ssr, boundaryState, state, delay) {
|
|
16442
|
+
boundaryState.delayTimer = setTimeout(() => {
|
|
16443
|
+
boundaryState.delayTimer = null;
|
|
16444
|
+
void ssr.$runQueuedRender$(async () => {
|
|
16445
|
+
if (boundaryState.contentResolved) {
|
|
16446
|
+
return;
|
|
16447
|
+
}
|
|
16448
|
+
state.value = 'fallback';
|
|
16449
|
+
ssr.emitBackpatchDataAndExecutorIfNeeded();
|
|
16450
|
+
await ssr.streamHandler.flush();
|
|
16451
|
+
});
|
|
16452
|
+
}, delay);
|
|
16453
|
+
}
|
|
16454
|
+
function isPositiveDelay(delay) {
|
|
16455
|
+
return typeof delay === 'number' && Number.isFinite(delay) && delay > 0;
|
|
16456
|
+
}
|
|
16457
|
+
function shouldRenderFallback(fallback, revealBoundary) {
|
|
16458
|
+
return (fallback != null &&
|
|
16459
|
+
fallback !== false &&
|
|
16460
|
+
(revealBoundary === null || revealBoundary.showFallback));
|
|
16461
|
+
}
|
|
16462
|
+
function writeOutOfOrderPlaceholder(ssr, boundaryId) {
|
|
16463
|
+
ssr.write(`<template ${QSuspenseResolved}="${boundaryId}"></template>`);
|
|
16464
|
+
}
|
|
16465
|
+
function writeOutOfOrderResolvedTemplate(ssr, boundaryId, html, revealBoundary) {
|
|
16466
|
+
ssr.write(`<template ${QSuspenseResolved}="${boundaryId}"${revealBoundary?.attrs ?? ''}>`);
|
|
16467
|
+
ssr.write(html);
|
|
16468
|
+
ssr.write('</template>');
|
|
16469
|
+
}
|
|
15537
16470
|
|
|
15538
16471
|
// keep this import from core/build so the cjs build works
|
|
15539
16472
|
/**
|
|
@@ -15630,5 +16563,5 @@ if (import.meta.hot) {
|
|
|
15630
16563
|
});
|
|
15631
16564
|
}
|
|
15632
16565
|
|
|
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 };
|
|
16566
|
+
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, SubscriptionPatch as _SubscriptionPatch, _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 };
|
|
15634
16567
|
//# sourceMappingURL=core.mjs.map
|