@qwik.dev/core 2.0.0-beta.14 → 2.0.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backpatch/package.json +1 -1
- package/dist/build/package.json +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/core-internal.d.ts +60 -27
- package/dist/core.min.mjs +1 -1
- package/dist/core.mjs +379 -174
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.mjs +237 -140
- package/dist/loader/index.mjs +2 -2
- package/dist/loader/package.json +1 -1
- package/dist/optimizer.mjs +140 -147
- package/dist/qwikloader.debug.js +38 -10
- package/dist/qwikloader.js +1 -1
- package/dist/server.mjs +5 -5
- package/dist/starters/features/csr/package.json +1 -1
- package/dist/testing/index.d.ts +7 -6
- package/dist/testing/index.mjs +306 -151
- package/dist/testing/package.json +1 -1
- package/package.json +2 -2
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.16-dev+a83ccf3
|
|
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
|
|
@@ -14,7 +14,7 @@ import { p } from '@qwik.dev/core/preloader';
|
|
|
14
14
|
*
|
|
15
15
|
* @public
|
|
16
16
|
*/
|
|
17
|
-
const version = "2.0.0-beta.
|
|
17
|
+
const version = "2.0.0-beta.16-dev+a83ccf3";
|
|
18
18
|
|
|
19
19
|
// same as isDev but separate so we can test
|
|
20
20
|
const qDev = globalThis.qDev !== false;
|
|
@@ -251,7 +251,6 @@ const ELEMENT_KEY = 'q:key';
|
|
|
251
251
|
const ELEMENT_PROPS = 'q:props';
|
|
252
252
|
const ELEMENT_SEQ = 'q:seq';
|
|
253
253
|
const ELEMENT_SEQ_IDX = 'q:seqIdx';
|
|
254
|
-
const Q_PREFIX = 'q:';
|
|
255
254
|
/** Non serializable markers - always begins with `:` character */
|
|
256
255
|
const NON_SERIALIZABLE_MARKER_PREFIX = ':';
|
|
257
256
|
const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
|
|
@@ -916,7 +915,7 @@ const STORE_ALL_PROPS = Symbol('store.all');
|
|
|
916
915
|
class SignalImpl {
|
|
917
916
|
$untrackedValue$;
|
|
918
917
|
/** Store a list of effects which are dependent on this signal. */
|
|
919
|
-
$effects$ =
|
|
918
|
+
$effects$ = undefined;
|
|
920
919
|
$container$ = null;
|
|
921
920
|
$wrappedSignal$ = null;
|
|
922
921
|
constructor(container, value) {
|
|
@@ -928,7 +927,7 @@ class SignalImpl {
|
|
|
928
927
|
* remained the same object
|
|
929
928
|
*/
|
|
930
929
|
force() {
|
|
931
|
-
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
930
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, this, this.$effects$);
|
|
932
931
|
}
|
|
933
932
|
get untrackedValue() {
|
|
934
933
|
return this.$untrackedValue$;
|
|
@@ -943,7 +942,7 @@ class SignalImpl {
|
|
|
943
942
|
set value(value) {
|
|
944
943
|
if (value !== this.$untrackedValue$) {
|
|
945
944
|
this.$untrackedValue$ = value;
|
|
946
|
-
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
945
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, this, this.$effects$);
|
|
947
946
|
}
|
|
948
947
|
}
|
|
949
948
|
// prevent accidental use as value
|
|
@@ -1005,6 +1004,8 @@ const _CONST_PROPS = Symbol('CONST');
|
|
|
1005
1004
|
const _VAR_PROPS = Symbol('VAR');
|
|
1006
1005
|
/** @internal */
|
|
1007
1006
|
const _OWNER = Symbol('OWNER');
|
|
1007
|
+
/** @internal */
|
|
1008
|
+
const _PROPS_HANDLER = Symbol('PROPS_HANDLER');
|
|
1008
1009
|
/** @internal @deprecated v1 compat */
|
|
1009
1010
|
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
1010
1011
|
/** @internal */
|
|
@@ -1080,6 +1081,13 @@ const getEventDataFromHtmlAttribute = (htmlKey) => {
|
|
|
1080
1081
|
}
|
|
1081
1082
|
return ['document', htmlKey.substring(12)];
|
|
1082
1083
|
};
|
|
1084
|
+
const getScopedEventName = (scope, eventName) => {
|
|
1085
|
+
const suffix = ':' + eventName;
|
|
1086
|
+
return scope ? scope + suffix : suffix;
|
|
1087
|
+
};
|
|
1088
|
+
const getLoaderScopedEventName = (scope, scopedEvent) => {
|
|
1089
|
+
return scope ? '-' + scopedEvent : scopedEvent;
|
|
1090
|
+
};
|
|
1083
1091
|
|
|
1084
1092
|
/** @internal */
|
|
1085
1093
|
const EMPTY_ARRAY = [];
|
|
@@ -1093,6 +1101,8 @@ function createPropsProxy(owner) {
|
|
|
1093
1101
|
}
|
|
1094
1102
|
class PropsProxyHandler {
|
|
1095
1103
|
owner;
|
|
1104
|
+
$effects$ = undefined;
|
|
1105
|
+
$container$ = null;
|
|
1096
1106
|
constructor(owner) {
|
|
1097
1107
|
this.owner = owner;
|
|
1098
1108
|
}
|
|
@@ -1101,12 +1111,15 @@ class PropsProxyHandler {
|
|
|
1101
1111
|
if (prop === _CONST_PROPS) {
|
|
1102
1112
|
return this.owner.constProps;
|
|
1103
1113
|
}
|
|
1104
|
-
if (prop === _VAR_PROPS) {
|
|
1114
|
+
else if (prop === _VAR_PROPS) {
|
|
1105
1115
|
return this.owner.varProps;
|
|
1106
1116
|
}
|
|
1107
|
-
if (prop === _OWNER) {
|
|
1117
|
+
else if (prop === _OWNER) {
|
|
1108
1118
|
return this.owner;
|
|
1109
1119
|
}
|
|
1120
|
+
else if (prop === _PROPS_HANDLER) {
|
|
1121
|
+
return this;
|
|
1122
|
+
}
|
|
1110
1123
|
let value;
|
|
1111
1124
|
if (prop === 'children') {
|
|
1112
1125
|
value = this.owner.children;
|
|
@@ -1119,6 +1132,9 @@ class PropsProxyHandler {
|
|
|
1119
1132
|
}
|
|
1120
1133
|
}
|
|
1121
1134
|
value = directGetPropsProxyProp(this.owner, prop);
|
|
1135
|
+
if (prop in this.owner.varProps) {
|
|
1136
|
+
addPropsProxyEffect(this, prop);
|
|
1137
|
+
}
|
|
1122
1138
|
}
|
|
1123
1139
|
// a proxied value that the optimizer made
|
|
1124
1140
|
return value instanceof WrappedSignalImpl && value.$flags$ & 4 /* WrappedSignalFlags.UNWRAP */
|
|
@@ -1133,6 +1149,12 @@ class PropsProxyHandler {
|
|
|
1133
1149
|
else if (prop === 'children') {
|
|
1134
1150
|
this.owner.children = value;
|
|
1135
1151
|
}
|
|
1152
|
+
else if (prop === _CONST_PROPS) {
|
|
1153
|
+
this.owner.constProps = value;
|
|
1154
|
+
}
|
|
1155
|
+
else if (prop === _VAR_PROPS) {
|
|
1156
|
+
this.owner.varProps = value;
|
|
1157
|
+
}
|
|
1136
1158
|
else {
|
|
1137
1159
|
if (typeof prop === 'string' && typeof this.owner.type === 'string') {
|
|
1138
1160
|
const attr = jsxEventToHtmlAttribute(prop);
|
|
@@ -1150,12 +1172,18 @@ class PropsProxyHandler {
|
|
|
1150
1172
|
else if (!(prop in this.owner.varProps)) {
|
|
1151
1173
|
this.owner.toSort = true;
|
|
1152
1174
|
}
|
|
1153
|
-
this.owner.varProps[prop]
|
|
1175
|
+
if (this.owner.varProps[prop] !== value) {
|
|
1176
|
+
this.owner.varProps[prop] = value;
|
|
1177
|
+
triggerPropsProxyEffect(this, prop);
|
|
1178
|
+
}
|
|
1154
1179
|
}
|
|
1155
1180
|
return true;
|
|
1156
1181
|
}
|
|
1157
1182
|
deleteProperty(_, prop) {
|
|
1158
1183
|
let didDelete = delete this.owner.varProps[prop];
|
|
1184
|
+
if (didDelete) {
|
|
1185
|
+
triggerPropsProxyEffect(this, prop);
|
|
1186
|
+
}
|
|
1159
1187
|
if (this.owner.constProps) {
|
|
1160
1188
|
didDelete = delete this.owner.constProps[prop] || didDelete;
|
|
1161
1189
|
}
|
|
@@ -1172,13 +1200,19 @@ class PropsProxyHandler {
|
|
|
1172
1200
|
else if (prop === _CONST_PROPS || prop === _VAR_PROPS) {
|
|
1173
1201
|
return true;
|
|
1174
1202
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
if (
|
|
1178
|
-
prop
|
|
1203
|
+
const inVarProps = prop in this.owner.varProps;
|
|
1204
|
+
if (typeof prop === 'string') {
|
|
1205
|
+
if (inVarProps) {
|
|
1206
|
+
addPropsProxyEffect(this, prop);
|
|
1207
|
+
}
|
|
1208
|
+
if (typeof this.owner.type === 'string') {
|
|
1209
|
+
const attr = jsxEventToHtmlAttribute(prop);
|
|
1210
|
+
if (attr) {
|
|
1211
|
+
prop = attr;
|
|
1212
|
+
}
|
|
1179
1213
|
}
|
|
1180
1214
|
}
|
|
1181
|
-
return
|
|
1215
|
+
return inVarProps || (this.owner.constProps ? prop in this.owner.constProps : false);
|
|
1182
1216
|
}
|
|
1183
1217
|
getOwnPropertyDescriptor(_, p) {
|
|
1184
1218
|
const value = p === 'children'
|
|
@@ -1207,6 +1241,34 @@ class PropsProxyHandler {
|
|
|
1207
1241
|
return out;
|
|
1208
1242
|
}
|
|
1209
1243
|
}
|
|
1244
|
+
const addPropsProxyEffect = (propsProxy, prop) => {
|
|
1245
|
+
// Lazily grab the container from the invoke context
|
|
1246
|
+
const ctx = tryGetInvokeContext();
|
|
1247
|
+
if (ctx) {
|
|
1248
|
+
if (propsProxy.$container$ === null) {
|
|
1249
|
+
if (ctx.$container$) {
|
|
1250
|
+
propsProxy.$container$ = ctx.$container$;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
else {
|
|
1254
|
+
assertTrue(!ctx.$container$ || ctx.$container$ === propsProxy.$container$, 'Do not use props across containers');
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
const effectSubscriber = ctx?.$effectSubscriber$;
|
|
1258
|
+
if (effectSubscriber) {
|
|
1259
|
+
addStoreEffect(propsProxy.owner._proxy, prop, propsProxy, effectSubscriber);
|
|
1260
|
+
}
|
|
1261
|
+
};
|
|
1262
|
+
const triggerPropsProxyEffect = (propsProxy, prop) => {
|
|
1263
|
+
const effects = getEffects$1(propsProxy.$effects$, prop);
|
|
1264
|
+
if (effects) {
|
|
1265
|
+
propsProxy.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, propsProxy, effects);
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
function getEffects$1(effects, prop) {
|
|
1269
|
+
// TODO: Handle STORE_ALL_PROPS
|
|
1270
|
+
return effects?.get(prop);
|
|
1271
|
+
}
|
|
1210
1272
|
/**
|
|
1211
1273
|
* Instead of using PropsProxyHandler getter (which could create a component-level subscription).
|
|
1212
1274
|
* Use this function to get the props directly from a const or var props.
|
|
@@ -1290,6 +1352,7 @@ const trackFn = (target, container) => (obj, prop) => {
|
|
|
1290
1352
|
return obj.value;
|
|
1291
1353
|
}
|
|
1292
1354
|
else if (isObject(obj) && isStore(obj)) {
|
|
1355
|
+
// TODO: handle props proxy
|
|
1293
1356
|
// track whole store
|
|
1294
1357
|
addStoreEffect(getStoreTarget(obj), STORE_ALL_PROPS, getStoreHandler(obj), ctx.$effectSubscriber$);
|
|
1295
1358
|
return obj;
|
|
@@ -1340,7 +1403,7 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
1340
1403
|
*/
|
|
1341
1404
|
$computeQrl$;
|
|
1342
1405
|
$flags$;
|
|
1343
|
-
[_EFFECT_BACK_REF] =
|
|
1406
|
+
[_EFFECT_BACK_REF] = undefined;
|
|
1344
1407
|
constructor(container, fn,
|
|
1345
1408
|
// We need a separate flag to know when the computation needs running because
|
|
1346
1409
|
// we need the old value to know if effects need running after computation
|
|
@@ -1354,7 +1417,7 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
1354
1417
|
}
|
|
1355
1418
|
invalidate() {
|
|
1356
1419
|
this.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
1357
|
-
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
1420
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, this, this.$effects$);
|
|
1358
1421
|
}
|
|
1359
1422
|
/**
|
|
1360
1423
|
* Use this to force running subscribers, for example when the calculated value has mutated but
|
|
@@ -1422,13 +1485,13 @@ class ComputedSignalImpl extends SignalImpl {
|
|
|
1422
1485
|
*/
|
|
1423
1486
|
class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
1424
1487
|
$untrackedLoading$ = false;
|
|
1425
|
-
$untrackedError$ =
|
|
1426
|
-
$loadingEffects$ =
|
|
1427
|
-
$errorEffects$ =
|
|
1488
|
+
$untrackedError$ = undefined;
|
|
1489
|
+
$loadingEffects$ = undefined;
|
|
1490
|
+
$errorEffects$ = undefined;
|
|
1428
1491
|
$destroy$;
|
|
1429
1492
|
$promiseValue$ = NEEDS_COMPUTATION;
|
|
1430
1493
|
$promise$ = null;
|
|
1431
|
-
[_EFFECT_BACK_REF] =
|
|
1494
|
+
[_EFFECT_BACK_REF] = undefined;
|
|
1432
1495
|
constructor(container, fn, flags = 1 /* SignalFlags.INVALID */) {
|
|
1433
1496
|
super(container, fn, flags);
|
|
1434
1497
|
}
|
|
@@ -1442,7 +1505,7 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
|
1442
1505
|
set untrackedLoading(value) {
|
|
1443
1506
|
if (value !== this.$untrackedLoading$) {
|
|
1444
1507
|
this.$untrackedLoading$ = value;
|
|
1445
|
-
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
1508
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, this, this.$loadingEffects$);
|
|
1446
1509
|
}
|
|
1447
1510
|
}
|
|
1448
1511
|
get untrackedLoading() {
|
|
@@ -1455,7 +1518,7 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
|
1455
1518
|
set untrackedError(value) {
|
|
1456
1519
|
if (value !== this.$untrackedError$) {
|
|
1457
1520
|
this.$untrackedError$ = value;
|
|
1458
|
-
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
1521
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, this, this.$errorEffects$);
|
|
1459
1522
|
}
|
|
1460
1523
|
}
|
|
1461
1524
|
get untrackedError() {
|
|
@@ -1486,7 +1549,7 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
|
1486
1549
|
if (isPromise(untrackedValue)) {
|
|
1487
1550
|
const isFirstComputation = this.$promiseValue$ === NEEDS_COMPUTATION;
|
|
1488
1551
|
this.untrackedLoading = true;
|
|
1489
|
-
this.untrackedError =
|
|
1552
|
+
this.untrackedError = undefined;
|
|
1490
1553
|
if (this.$promiseValue$ !== NEEDS_COMPUTATION) {
|
|
1491
1554
|
// skip cleanup after resuming
|
|
1492
1555
|
cleanupDestroyable(this);
|
|
@@ -1495,7 +1558,7 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
|
|
|
1495
1558
|
.then((promiseValue) => {
|
|
1496
1559
|
this.$promiseValue$ = promiseValue;
|
|
1497
1560
|
this.untrackedLoading = false;
|
|
1498
|
-
this.untrackedError =
|
|
1561
|
+
this.untrackedError = undefined;
|
|
1499
1562
|
if (this.setValue(promiseValue)) {
|
|
1500
1563
|
scheduleEffects(this.$container$, this, this.$effects$);
|
|
1501
1564
|
}
|
|
@@ -1728,25 +1791,32 @@ const _wrapProp = (...args) => {
|
|
|
1728
1791
|
}
|
|
1729
1792
|
if (isPropsProxy(obj)) {
|
|
1730
1793
|
const constProps = obj[_CONST_PROPS];
|
|
1794
|
+
const varProps = obj[_VAR_PROPS];
|
|
1731
1795
|
if (constProps && prop in constProps) {
|
|
1732
1796
|
// Const props don't need wrapping
|
|
1733
1797
|
return constProps[prop];
|
|
1734
1798
|
}
|
|
1799
|
+
else if (prop in varProps) {
|
|
1800
|
+
const value = varProps[prop];
|
|
1801
|
+
return wrapIfNotSignal(value, args);
|
|
1802
|
+
}
|
|
1735
1803
|
}
|
|
1736
1804
|
else {
|
|
1737
1805
|
const target = getStoreTarget(obj);
|
|
1738
1806
|
if (target) {
|
|
1739
1807
|
const value = target[prop];
|
|
1740
|
-
|
|
1741
|
-
? // If the value is already a signal, we don't need to wrap it again
|
|
1742
|
-
value
|
|
1743
|
-
: getWrapped(args);
|
|
1744
|
-
return wrappedValue;
|
|
1808
|
+
return wrapIfNotSignal(value, args);
|
|
1745
1809
|
}
|
|
1746
1810
|
}
|
|
1747
1811
|
// the object is not reactive, so we can just return the value
|
|
1748
1812
|
return obj[prop];
|
|
1749
1813
|
};
|
|
1814
|
+
const wrapIfNotSignal = (value, args) => {
|
|
1815
|
+
return (isSignal(value)
|
|
1816
|
+
? // If the value is already a signal, we don't need to wrap it again
|
|
1817
|
+
value
|
|
1818
|
+
: getWrapped(args));
|
|
1819
|
+
};
|
|
1750
1820
|
/** @internal @deprecated v1 compat */
|
|
1751
1821
|
const _wrapSignal = (obj, prop) => {
|
|
1752
1822
|
const r = _wrapProp(obj, prop);
|
|
@@ -1761,8 +1831,8 @@ class WrappedSignalImpl extends SignalImpl {
|
|
|
1761
1831
|
$func$;
|
|
1762
1832
|
$funcStr$;
|
|
1763
1833
|
$flags$;
|
|
1764
|
-
$hostElement$ =
|
|
1765
|
-
[_EFFECT_BACK_REF] =
|
|
1834
|
+
$hostElement$ = undefined;
|
|
1835
|
+
[_EFFECT_BACK_REF] = undefined;
|
|
1766
1836
|
constructor(container, fn, args, fnStr,
|
|
1767
1837
|
// We need a separate flag to know when the computation needs running because
|
|
1768
1838
|
// we need the old value to know if effects need running after computation
|
|
@@ -1838,7 +1908,7 @@ class WrappedSignalImpl extends SignalImpl {
|
|
|
1838
1908
|
|
|
1839
1909
|
/** Class for back reference to the EffectSubscription */
|
|
1840
1910
|
let BackRef$1 = class BackRef {
|
|
1841
|
-
[_EFFECT_BACK_REF] =
|
|
1911
|
+
[_EFFECT_BACK_REF] = undefined;
|
|
1842
1912
|
};
|
|
1843
1913
|
function clearAllEffects(container, consumer) {
|
|
1844
1914
|
if (vnode_isVNode(consumer) && vnode_isElementVNode(consumer)) {
|
|
@@ -1851,6 +1921,7 @@ function clearAllEffects(container, consumer) {
|
|
|
1851
1921
|
for (const [, effect] of effects) {
|
|
1852
1922
|
clearEffectSubscription(container, effect);
|
|
1853
1923
|
}
|
|
1924
|
+
effects.clear();
|
|
1854
1925
|
}
|
|
1855
1926
|
function clearEffectSubscription(container, effect) {
|
|
1856
1927
|
const backRefs = effect[2 /* EffectSubscriptionProp.BACK_REF */];
|
|
@@ -1864,12 +1935,17 @@ function clearEffectSubscription(container, effect) {
|
|
|
1864
1935
|
else if (producer instanceof AsyncComputedSignalImpl) {
|
|
1865
1936
|
clearAsyncComputedSignal(producer, effect);
|
|
1866
1937
|
}
|
|
1938
|
+
else if (isPropsProxy(producer)) {
|
|
1939
|
+
const propsHandler = producer[_PROPS_HANDLER];
|
|
1940
|
+
clearStoreOrProps(propsHandler, effect);
|
|
1941
|
+
}
|
|
1867
1942
|
else if (container.$storeProxyMap$.has(producer)) {
|
|
1868
1943
|
const target = container.$storeProxyMap$.get(producer);
|
|
1869
1944
|
const storeHandler = getStoreHandler(target);
|
|
1870
|
-
|
|
1945
|
+
clearStoreOrProps(storeHandler, effect);
|
|
1871
1946
|
}
|
|
1872
1947
|
}
|
|
1948
|
+
backRefs.clear();
|
|
1873
1949
|
}
|
|
1874
1950
|
function clearSignal(container, producer, effect) {
|
|
1875
1951
|
const effects = producer.$effects$;
|
|
@@ -1877,7 +1953,7 @@ function clearSignal(container, producer, effect) {
|
|
|
1877
1953
|
effects.delete(effect);
|
|
1878
1954
|
}
|
|
1879
1955
|
if (producer instanceof WrappedSignalImpl) {
|
|
1880
|
-
producer.$hostElement$ =
|
|
1956
|
+
producer.$hostElement$ = undefined;
|
|
1881
1957
|
clearAllEffects(container, producer);
|
|
1882
1958
|
}
|
|
1883
1959
|
}
|
|
@@ -1891,14 +1967,14 @@ function clearAsyncComputedSignal(producer, effect) {
|
|
|
1891
1967
|
pendingEffects.delete(effect);
|
|
1892
1968
|
}
|
|
1893
1969
|
}
|
|
1894
|
-
function
|
|
1970
|
+
function clearStoreOrProps(producer, effect) {
|
|
1895
1971
|
const effects = producer?.$effects$;
|
|
1896
1972
|
if (effects) {
|
|
1897
|
-
for (const [
|
|
1973
|
+
for (const [prop, propEffects] of effects.entries()) {
|
|
1898
1974
|
if (propEffects.has(effect)) {
|
|
1899
1975
|
propEffects.delete(effect);
|
|
1900
1976
|
if (propEffects.size === 0) {
|
|
1901
|
-
effects.delete(
|
|
1977
|
+
effects.delete(prop);
|
|
1902
1978
|
}
|
|
1903
1979
|
}
|
|
1904
1980
|
}
|
|
@@ -2711,23 +2787,22 @@ const vnode_applyJournal = (journal) => {
|
|
|
2711
2787
|
key = 'class';
|
|
2712
2788
|
}
|
|
2713
2789
|
const value = journal[idx++];
|
|
2790
|
+
const shouldRemove = value == null || value === false;
|
|
2714
2791
|
if (isBooleanAttr(element, key)) {
|
|
2715
2792
|
element[key] = parseBoolean(value);
|
|
2716
2793
|
}
|
|
2717
|
-
else if (key === 'value' && key in element) {
|
|
2718
|
-
element.value = String(value);
|
|
2719
|
-
}
|
|
2720
2794
|
else if (key === dangerouslySetInnerHTML) {
|
|
2721
2795
|
element.innerHTML = value;
|
|
2722
2796
|
element.setAttribute(QContainerAttr, "html" /* QContainerValue.HTML */);
|
|
2723
2797
|
}
|
|
2798
|
+
else if (shouldRemove) {
|
|
2799
|
+
element.removeAttribute(key);
|
|
2800
|
+
}
|
|
2801
|
+
else if (key === 'value' && key in element) {
|
|
2802
|
+
element.value = String(value);
|
|
2803
|
+
}
|
|
2724
2804
|
else {
|
|
2725
|
-
|
|
2726
|
-
element.removeAttribute(key);
|
|
2727
|
-
}
|
|
2728
|
-
else {
|
|
2729
|
-
element.setAttribute(key, String(value));
|
|
2730
|
-
}
|
|
2805
|
+
element.setAttribute(key, String(value));
|
|
2731
2806
|
}
|
|
2732
2807
|
break;
|
|
2733
2808
|
case 3 /* VNodeJournalOpCode.HoistStyles */:
|
|
@@ -3467,6 +3542,7 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
3467
3542
|
const nodeIsElement = isElement(node);
|
|
3468
3543
|
return !nodeIsElement || (nodeIsElement && shouldSkipElement(node));
|
|
3469
3544
|
};
|
|
3545
|
+
let components = null;
|
|
3470
3546
|
processVNodeData$1(vData, (peek, consumeValue, consume, getChar, nextToConsumeIdx) => {
|
|
3471
3547
|
if (isNumber(peek())) {
|
|
3472
3548
|
// Element counts get encoded as numbers.
|
|
@@ -3493,6 +3569,7 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
3493
3569
|
vParent.setAttr(QScopedStyle, consumeValue(), null);
|
|
3494
3570
|
}
|
|
3495
3571
|
else if (peek() === VNodeDataChar.RENDER_FN) {
|
|
3572
|
+
(components ||= []).push(vParent);
|
|
3496
3573
|
vParent.setAttr(OnRenderProp, consumeValue(), null);
|
|
3497
3574
|
}
|
|
3498
3575
|
else if (peek() === VNodeDataChar.ID) {
|
|
@@ -3588,6 +3665,15 @@ function materializeFromVNodeData(vParent, vData, element, child) {
|
|
|
3588
3665
|
// Text nodes get encoded as alphanumeric characters.
|
|
3589
3666
|
}
|
|
3590
3667
|
});
|
|
3668
|
+
if (components) {
|
|
3669
|
+
if (!container) {
|
|
3670
|
+
container = getDomContainer(element);
|
|
3671
|
+
}
|
|
3672
|
+
for (const component of components) {
|
|
3673
|
+
container.ensureProjectionResolved(component);
|
|
3674
|
+
}
|
|
3675
|
+
components = null;
|
|
3676
|
+
}
|
|
3591
3677
|
vParent.lastChild = vLast;
|
|
3592
3678
|
return vFirst;
|
|
3593
3679
|
}
|
|
@@ -4338,14 +4424,14 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
|
|
|
4338
4424
|
for (const k in varProps) {
|
|
4339
4425
|
if (k === 'children') {
|
|
4340
4426
|
children ||= varProps.children;
|
|
4341
|
-
varProps.children
|
|
4427
|
+
delete varProps.children;
|
|
4342
4428
|
}
|
|
4343
4429
|
else if (k === 'key') {
|
|
4344
4430
|
key ||= varProps.key;
|
|
4345
|
-
varProps.key
|
|
4431
|
+
delete varProps.key;
|
|
4346
4432
|
}
|
|
4347
4433
|
else if (constProps && k in constProps) {
|
|
4348
|
-
varProps[k]
|
|
4434
|
+
delete varProps[k];
|
|
4349
4435
|
}
|
|
4350
4436
|
}
|
|
4351
4437
|
}
|
|
@@ -5771,8 +5857,9 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
5771
5857
|
else if (isSignal(jsxValue)) {
|
|
5772
5858
|
expectVirtual("S" /* VirtualType.WrappedSignal */, null);
|
|
5773
5859
|
const unwrappedSignal = jsxValue instanceof WrappedSignalImpl ? jsxValue.$unwrapIfSignal$() : jsxValue;
|
|
5774
|
-
const
|
|
5775
|
-
|
|
5860
|
+
const hasUnwrappedSignal = vCurrent?.[_EFFECT_BACK_REF]
|
|
5861
|
+
?.get("." /* EffectProperty.VNODE */)?.[2 /* EffectSubscriptionProp.BACK_REF */]?.has(unwrappedSignal);
|
|
5862
|
+
if (!hasUnwrappedSignal) {
|
|
5776
5863
|
const vHost = (vNewNode || vCurrent);
|
|
5777
5864
|
descend(resolveSignalAndDescend(() => trackSignalAndAssignHost(unwrappedSignal, vHost, "." /* EffectProperty.VNODE */, container)), true);
|
|
5778
5865
|
}
|
|
@@ -6195,15 +6282,17 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6195
6282
|
if (isHtmlAttributeAnEventName(key)) {
|
|
6196
6283
|
const data = getEventDataFromHtmlAttribute(key);
|
|
6197
6284
|
if (data) {
|
|
6198
|
-
const scope = data
|
|
6199
|
-
const
|
|
6285
|
+
const [scope, eventName] = data;
|
|
6286
|
+
const scopedEvent = getScopedEventName(scope, eventName);
|
|
6287
|
+
const loaderScopedEvent = getLoaderScopedEventName(scope, scopedEvent);
|
|
6200
6288
|
if (eventName) {
|
|
6201
|
-
vNewNode.setProp(HANDLER_PREFIX + ':' +
|
|
6289
|
+
vNewNode.setProp(HANDLER_PREFIX + ':' + scopedEvent, value);
|
|
6202
6290
|
if (scope) {
|
|
6203
6291
|
// window and document need attrs so qwik loader can find them
|
|
6204
6292
|
vNewNode.setAttr(key, '', journal);
|
|
6205
6293
|
}
|
|
6206
|
-
|
|
6294
|
+
// register an event for qwik loader (window/document prefixed with '-')
|
|
6295
|
+
registerQwikLoaderEvent(loaderScopedEvent);
|
|
6207
6296
|
}
|
|
6208
6297
|
}
|
|
6209
6298
|
needsQDispatchEventPatch = true;
|
|
@@ -6357,10 +6446,37 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6357
6446
|
let srcIdx = 0;
|
|
6358
6447
|
let dstIdx = 0;
|
|
6359
6448
|
let patchEventDispatch = false;
|
|
6360
|
-
|
|
6361
|
-
|
|
6449
|
+
/**
|
|
6450
|
+
* Optimized setAttribute that bypasses redundant checks when we already know:
|
|
6451
|
+
*
|
|
6452
|
+
* - The index in dstAttrs (no need for binary search)
|
|
6453
|
+
* - The vnode is ElementVNode (no instanceof check)
|
|
6454
|
+
* - The value has changed (no comparison needed)
|
|
6455
|
+
*/
|
|
6456
|
+
const setAttributeDirect = (vnode, key, value, dstIdx, isNewKey) => {
|
|
6457
|
+
const serializedValue = value != null ? serializeAttribute(key, value, scopedStyleIdPrefix) : null;
|
|
6458
|
+
if (isNewKey) {
|
|
6459
|
+
// Adding new key - splice into sorted position
|
|
6460
|
+
if (serializedValue != null) {
|
|
6461
|
+
dstAttrs.splice(dstIdx, 0, key, serializedValue);
|
|
6462
|
+
journal.push(2 /* VNodeJournalOpCode.SetAttribute */, vnode.element, key, serializedValue);
|
|
6463
|
+
}
|
|
6464
|
+
}
|
|
6465
|
+
else {
|
|
6466
|
+
// Updating or removing existing key at dstIdx
|
|
6467
|
+
if (serializedValue != null) {
|
|
6468
|
+
// Update existing value
|
|
6469
|
+
dstAttrs[dstIdx + 1] = serializedValue;
|
|
6470
|
+
journal.push(2 /* VNodeJournalOpCode.SetAttribute */, vnode.element, key, serializedValue);
|
|
6471
|
+
}
|
|
6472
|
+
else {
|
|
6473
|
+
// Remove key (value is null)
|
|
6474
|
+
dstAttrs.splice(dstIdx, 2);
|
|
6475
|
+
journal.push(2 /* VNodeJournalOpCode.SetAttribute */, vnode.element, key, null);
|
|
6476
|
+
}
|
|
6477
|
+
}
|
|
6362
6478
|
};
|
|
6363
|
-
const record = (key, value) => {
|
|
6479
|
+
const record = (key, value, dstIdx, isNewKey) => {
|
|
6364
6480
|
if (key.startsWith(':')) {
|
|
6365
6481
|
vnode.setProp(key, value);
|
|
6366
6482
|
return;
|
|
@@ -6404,20 +6520,31 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6404
6520
|
}
|
|
6405
6521
|
}
|
|
6406
6522
|
if (isPromise(value)) {
|
|
6523
|
+
// For async values, we can't use the known index since it will be stale by the time
|
|
6524
|
+
// the promise resolves. Do a binary search to find the current index.
|
|
6407
6525
|
const vHost = vnode;
|
|
6408
|
-
const attributePromise = value.then((resolvedValue) =>
|
|
6526
|
+
const attributePromise = value.then((resolvedValue) => {
|
|
6527
|
+
const idx = mapApp_findIndx(dstAttrs, key, 0);
|
|
6528
|
+
const isNewKey = idx < 0;
|
|
6529
|
+
const currentDstIdx = isNewKey ? idx ^ -1 : idx;
|
|
6530
|
+
setAttributeDirect(vHost, key, resolvedValue, currentDstIdx, isNewKey);
|
|
6531
|
+
});
|
|
6409
6532
|
asyncAttributePromises.push(attributePromise);
|
|
6410
6533
|
return;
|
|
6411
6534
|
}
|
|
6412
|
-
|
|
6535
|
+
// Always use optimized direct path - we know the index from the merge algorithm
|
|
6536
|
+
setAttributeDirect(vnode, key, value, dstIdx, isNewKey);
|
|
6413
6537
|
};
|
|
6414
6538
|
const recordJsxEvent = (key, value) => {
|
|
6415
6539
|
const data = getEventDataFromHtmlAttribute(key);
|
|
6416
6540
|
if (data) {
|
|
6417
6541
|
const [scope, eventName] = data;
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6542
|
+
const scopedEvent = getScopedEventName(scope, eventName);
|
|
6543
|
+
const loaderScopedEvent = getLoaderScopedEventName(scope, scopedEvent);
|
|
6544
|
+
// Pass dummy index values since ':' prefixed keys take early return via setProp
|
|
6545
|
+
record(':' + scopedEvent, value, 0, false);
|
|
6546
|
+
// register an event for qwik loader (window/document prefixed with '-')
|
|
6547
|
+
registerQwikLoaderEvent(loaderScopedEvent);
|
|
6421
6548
|
patchEventDispatch = true;
|
|
6422
6549
|
}
|
|
6423
6550
|
};
|
|
@@ -6426,8 +6553,8 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6426
6553
|
while (srcIdx < srcAttrs.length || dstIdx < dstAttrs.length) {
|
|
6427
6554
|
const srcKey = srcIdx < srcAttrs.length ? srcAttrs[srcIdx] : undefined;
|
|
6428
6555
|
const dstKey = dstIdx < dstAttrs.length ? dstAttrs[dstIdx] : undefined;
|
|
6429
|
-
// Skip special keys in destination
|
|
6430
|
-
if (dstKey?.startsWith(HANDLER_PREFIX)
|
|
6556
|
+
// Skip special keys in destination HANDLER_PREFIX
|
|
6557
|
+
if (dstKey?.startsWith(HANDLER_PREFIX)) {
|
|
6431
6558
|
dstIdx += 2; // skip key and value
|
|
6432
6559
|
continue;
|
|
6433
6560
|
}
|
|
@@ -6438,7 +6565,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6438
6565
|
dstIdx += 2; // skip key and value
|
|
6439
6566
|
}
|
|
6440
6567
|
else {
|
|
6441
|
-
record(dstKey, null);
|
|
6568
|
+
record(dstKey, null, dstIdx, false);
|
|
6442
6569
|
// After removal, dstAttrs shrinks by 2, so don't advance dstIdx
|
|
6443
6570
|
}
|
|
6444
6571
|
}
|
|
@@ -6449,7 +6576,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6449
6576
|
recordJsxEvent(srcKey, srcValue);
|
|
6450
6577
|
}
|
|
6451
6578
|
else {
|
|
6452
|
-
record(srcKey, srcValue);
|
|
6579
|
+
record(srcKey, srcValue, dstIdx, true);
|
|
6453
6580
|
}
|
|
6454
6581
|
srcIdx += 2; // skip key and value
|
|
6455
6582
|
// After addition, dstAttrs grows by 2 at sorted position, advance dstIdx
|
|
@@ -6465,7 +6592,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6465
6592
|
recordJsxEvent(srcKey, srcValue);
|
|
6466
6593
|
}
|
|
6467
6594
|
else {
|
|
6468
|
-
record(srcKey, srcValue);
|
|
6595
|
+
record(srcKey, srcValue, dstIdx, false);
|
|
6469
6596
|
}
|
|
6470
6597
|
}
|
|
6471
6598
|
else if (isEventHandler && !vnode.element.qDispatchEvent) {
|
|
@@ -6483,7 +6610,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6483
6610
|
recordJsxEvent(srcKey, srcValue);
|
|
6484
6611
|
}
|
|
6485
6612
|
else {
|
|
6486
|
-
record(srcKey, srcValue);
|
|
6613
|
+
record(srcKey, srcValue, dstIdx, true);
|
|
6487
6614
|
}
|
|
6488
6615
|
srcIdx += 2; // skip key and value
|
|
6489
6616
|
// After addition, dstAttrs grows at sorted position (before dstIdx), advance dstIdx
|
|
@@ -6496,7 +6623,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6496
6623
|
dstIdx += 2; // skip key and value
|
|
6497
6624
|
}
|
|
6498
6625
|
else {
|
|
6499
|
-
record(dstKey, null);
|
|
6626
|
+
record(dstKey, null, dstIdx, false);
|
|
6500
6627
|
// After removal, dstAttrs shrinks at dstIdx, so don't advance dstIdx
|
|
6501
6628
|
}
|
|
6502
6629
|
}
|
|
@@ -6698,32 +6825,11 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
|
6698
6825
|
deleteFromSideBuffer(null, lookupKey);
|
|
6699
6826
|
}
|
|
6700
6827
|
if (host) {
|
|
6701
|
-
|
|
6702
|
-
let propsAreDifferent = false;
|
|
6828
|
+
const vNodeProps = host.getProp(ELEMENT_PROPS, container.$getObjectById$);
|
|
6703
6829
|
if (!shouldRender) {
|
|
6704
|
-
|
|
6705
|
-
propsDiffer(jsxProps[_CONST_PROPS], vNodeProps?.[_CONST_PROPS]) ||
|
|
6706
|
-
propsDiffer(jsxProps[_VAR_PROPS], vNodeProps?.[_VAR_PROPS]);
|
|
6707
|
-
shouldRender = shouldRender || propsAreDifferent;
|
|
6830
|
+
shouldRender ||= handleProps(host, jsxProps, vNodeProps, container);
|
|
6708
6831
|
}
|
|
6709
6832
|
if (shouldRender) {
|
|
6710
|
-
if (propsAreDifferent) {
|
|
6711
|
-
if (vNodeProps) {
|
|
6712
|
-
// Reuse the same props instance, qrls can use the current props instance
|
|
6713
|
-
// as a capture ref, so we can't change it.
|
|
6714
|
-
// We need to do this directly, because normally we would subscribe to the signals
|
|
6715
|
-
// if any signal is there.
|
|
6716
|
-
vNodeProps[_CONST_PROPS] = jsxProps[_CONST_PROPS];
|
|
6717
|
-
vNodeProps[_VAR_PROPS] = jsxProps[_VAR_PROPS];
|
|
6718
|
-
vNodeProps[_OWNER] = jsxProps[_OWNER];
|
|
6719
|
-
}
|
|
6720
|
-
else if (jsxProps) {
|
|
6721
|
-
// If there is no props instance, create a new one.
|
|
6722
|
-
// We can do this because we are not using the props instance for anything else.
|
|
6723
|
-
host.setProp(ELEMENT_PROPS, jsxProps);
|
|
6724
|
-
vNodeProps = jsxProps;
|
|
6725
|
-
}
|
|
6726
|
-
}
|
|
6727
6833
|
// Assign the new QRL instance to the host.
|
|
6728
6834
|
// Unfortunately it is created every time, something to fix in the optimizer.
|
|
6729
6835
|
host.setProp(OnRenderProp, componentQRL);
|
|
@@ -6860,7 +6966,37 @@ function getComponentHash(vNode, getObject) {
|
|
|
6860
6966
|
* ```
|
|
6861
6967
|
*/
|
|
6862
6968
|
function Projection() { }
|
|
6863
|
-
function
|
|
6969
|
+
function handleProps(host, jsxProps, vNodeProps, container) {
|
|
6970
|
+
let shouldRender = false;
|
|
6971
|
+
let propsAreDifferent = false;
|
|
6972
|
+
if (vNodeProps) {
|
|
6973
|
+
const effects = vNodeProps[_PROPS_HANDLER].$effects$;
|
|
6974
|
+
const constPropsDifferent = handleChangedProps(jsxProps[_CONST_PROPS], vNodeProps[_CONST_PROPS], vNodeProps[_PROPS_HANDLER], container, false);
|
|
6975
|
+
propsAreDifferent = constPropsDifferent;
|
|
6976
|
+
shouldRender ||= constPropsDifferent;
|
|
6977
|
+
if (effects && effects.size > 0) {
|
|
6978
|
+
const varPropsDifferent = handleChangedProps(jsxProps[_VAR_PROPS], vNodeProps[_VAR_PROPS], vNodeProps[_PROPS_HANDLER], container);
|
|
6979
|
+
propsAreDifferent ||= varPropsDifferent;
|
|
6980
|
+
// don't mark as should render, effects will take care of it
|
|
6981
|
+
// shouldRender ||= varPropsDifferent;
|
|
6982
|
+
}
|
|
6983
|
+
}
|
|
6984
|
+
if (propsAreDifferent) {
|
|
6985
|
+
if (vNodeProps) {
|
|
6986
|
+
// Reuse the same props instance, qrls can use the current props instance
|
|
6987
|
+
// as a capture ref, so we can't change it.
|
|
6988
|
+
vNodeProps[_OWNER] = jsxProps[_OWNER];
|
|
6989
|
+
}
|
|
6990
|
+
else if (jsxProps) {
|
|
6991
|
+
// If there is no props instance, create a new one.
|
|
6992
|
+
// We can do this because we are not using the props instance for anything else.
|
|
6993
|
+
host.setProp(ELEMENT_PROPS, jsxProps);
|
|
6994
|
+
vNodeProps = jsxProps;
|
|
6995
|
+
}
|
|
6996
|
+
}
|
|
6997
|
+
return shouldRender;
|
|
6998
|
+
}
|
|
6999
|
+
function handleChangedProps(src, dst, propsHandler, container, triggerEffects = true) {
|
|
6864
7000
|
const srcEmpty = isPropsEmpty(src);
|
|
6865
7001
|
const dstEmpty = isPropsEmpty(dst);
|
|
6866
7002
|
if (srcEmpty && dstEmpty) {
|
|
@@ -6888,15 +7024,23 @@ function propsDiffer(src, dst) {
|
|
|
6888
7024
|
if (srcLen !== dstLen) {
|
|
6889
7025
|
return true;
|
|
6890
7026
|
}
|
|
7027
|
+
let changed = false;
|
|
7028
|
+
propsHandler.$container$ = container;
|
|
6891
7029
|
for (const key of srcKeys) {
|
|
6892
7030
|
if (key === 'children' || key === QBackRefs) {
|
|
6893
7031
|
continue;
|
|
6894
7032
|
}
|
|
6895
7033
|
if (!Object.prototype.hasOwnProperty.call(dst, key) || src[key] !== dst[key]) {
|
|
6896
|
-
|
|
7034
|
+
changed = true;
|
|
7035
|
+
if (triggerEffects) {
|
|
7036
|
+
triggerPropsProxyEffect(propsHandler, key);
|
|
7037
|
+
}
|
|
7038
|
+
else {
|
|
7039
|
+
return true;
|
|
7040
|
+
}
|
|
6897
7041
|
}
|
|
6898
7042
|
}
|
|
6899
|
-
return
|
|
7043
|
+
return changed;
|
|
6900
7044
|
}
|
|
6901
7045
|
function isPropsEmpty(props) {
|
|
6902
7046
|
if (!props) {
|
|
@@ -7179,7 +7323,8 @@ function findAncestorBlockingChore(chore, type) {
|
|
|
7179
7323
|
if (blockingChore.$type$ < 16 /* ChoreType.VISIBLE */ &&
|
|
7180
7324
|
blockingChore.$type$ !== 3 /* ChoreType.TASK */ &&
|
|
7181
7325
|
blockingChore.$type$ !== 1 /* ChoreType.QRL_RESOLVE */ &&
|
|
7182
|
-
blockingChore.$type$ !== 2 /* ChoreType.RUN_QRL */
|
|
7326
|
+
blockingChore.$type$ !== 2 /* ChoreType.RUN_QRL */ &&
|
|
7327
|
+
blockingChore.$state$ === ChoreState.NONE) {
|
|
7183
7328
|
return blockingChore;
|
|
7184
7329
|
}
|
|
7185
7330
|
}
|
|
@@ -7204,19 +7349,25 @@ function findBlockingChore(chore, choreQueue, blockedChores, runningChores, cont
|
|
|
7204
7349
|
// Check in choreQueue
|
|
7205
7350
|
// TODO(perf): better to iterate in reverse order?
|
|
7206
7351
|
for (const candidate of choreQueue) {
|
|
7207
|
-
if (candidate.$type$ === rule.blockingType &&
|
|
7352
|
+
if (candidate.$type$ === rule.blockingType &&
|
|
7353
|
+
rule.match(chore, candidate, container) &&
|
|
7354
|
+
candidate.$state$ === ChoreState.NONE) {
|
|
7208
7355
|
return candidate;
|
|
7209
7356
|
}
|
|
7210
7357
|
}
|
|
7211
7358
|
// Check in blockedChores
|
|
7212
7359
|
for (const candidate of blockedChores) {
|
|
7213
|
-
if (candidate.$type$ === rule.blockingType &&
|
|
7360
|
+
if (candidate.$type$ === rule.blockingType &&
|
|
7361
|
+
rule.match(chore, candidate, container) &&
|
|
7362
|
+
candidate.$state$ === ChoreState.NONE) {
|
|
7214
7363
|
return candidate;
|
|
7215
7364
|
}
|
|
7216
7365
|
}
|
|
7217
7366
|
// Check in runningChores
|
|
7218
7367
|
for (const candidate of runningChores) {
|
|
7219
|
-
if (candidate.$type$ === rule.blockingType &&
|
|
7368
|
+
if (candidate.$type$ === rule.blockingType &&
|
|
7369
|
+
rule.match(chore, candidate, container) &&
|
|
7370
|
+
candidate.$state$ !== ChoreState.FAILED) {
|
|
7220
7371
|
return candidate;
|
|
7221
7372
|
}
|
|
7222
7373
|
}
|
|
@@ -7242,7 +7393,9 @@ function findBlockingChoreForVisible(chore, runningChores, container) {
|
|
|
7242
7393
|
continue;
|
|
7243
7394
|
}
|
|
7244
7395
|
for (const candidate of runningChores) {
|
|
7245
|
-
if (candidate.$type$ === rule.blockingType &&
|
|
7396
|
+
if (candidate.$type$ === rule.blockingType &&
|
|
7397
|
+
rule.match(chore, candidate, container) &&
|
|
7398
|
+
candidate.$state$ !== ChoreState.FAILED) {
|
|
7246
7399
|
return candidate;
|
|
7247
7400
|
}
|
|
7248
7401
|
}
|
|
@@ -7483,6 +7636,7 @@ function choreComparator(a, b) {
|
|
|
7483
7636
|
if (a.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
|
|
7484
7637
|
b.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
|
|
7485
7638
|
((a.$target$ instanceof StoreHandler && b.$target$ instanceof StoreHandler) ||
|
|
7639
|
+
(a.$target$ instanceof PropsProxyHandler && b.$target$ instanceof PropsProxyHandler) ||
|
|
7486
7640
|
(a.$target$ instanceof AsyncComputedSignalImpl &&
|
|
7487
7641
|
b.$target$ instanceof AsyncComputedSignalImpl)) &&
|
|
7488
7642
|
a.$payload$ !== b.$payload$) {
|
|
@@ -7685,16 +7839,18 @@ This is often caused by modifying a signal in an already rendered component duri
|
|
|
7685
7839
|
}
|
|
7686
7840
|
const shouldBlock = chore.$type$ !== 1 /* ChoreType.QRL_RESOLVE */ && chore.$type$ !== 2 /* ChoreType.RUN_QRL */;
|
|
7687
7841
|
if (shouldBlock) {
|
|
7842
|
+
const runningChore = getRunningChore(chore);
|
|
7843
|
+
if (runningChore) {
|
|
7844
|
+
if (isResourceChore(runningChore)) {
|
|
7845
|
+
addBlockedChore(chore, runningChore, blockedChores);
|
|
7846
|
+
}
|
|
7847
|
+
return chore;
|
|
7848
|
+
}
|
|
7688
7849
|
const blockingChore = findBlockingChore(chore, choreQueue, blockedChores, runningChores, container);
|
|
7689
7850
|
if (blockingChore) {
|
|
7690
7851
|
addBlockedChore(chore, blockingChore, blockedChores);
|
|
7691
7852
|
return chore;
|
|
7692
7853
|
}
|
|
7693
|
-
const runningChore = getRunningChore(chore);
|
|
7694
|
-
if (runningChore) {
|
|
7695
|
-
addBlockedChore(chore, runningChore, blockedChores);
|
|
7696
|
-
return chore;
|
|
7697
|
-
}
|
|
7698
7854
|
}
|
|
7699
7855
|
addChoreAndIncrementBlockingCounter(chore, choreQueue);
|
|
7700
7856
|
const runImmediately = (isServer && type === 6 /* ChoreType.COMPONENT */) || type === 2 /* ChoreType.RUN_QRL */;
|
|
@@ -7852,7 +8008,7 @@ This is often caused by modifying a signal in an already rendered component duri
|
|
|
7852
8008
|
applyJournalFlush();
|
|
7853
8009
|
const blockingChore = findBlockingChoreForVisible(chore, runningChores, container);
|
|
7854
8010
|
if (blockingChore && blockingChore.$state$ === ChoreState.RUNNING) {
|
|
7855
|
-
|
|
8011
|
+
(blockingChore.$blockedChores$ ||= new ChoreArray()).add(chore);
|
|
7856
8012
|
continue;
|
|
7857
8013
|
}
|
|
7858
8014
|
}
|
|
@@ -8095,7 +8251,15 @@ function addChore(chore, choreArray) {
|
|
|
8095
8251
|
function vNodeAlreadyDeleted(chore) {
|
|
8096
8252
|
return !!(chore.$host$ && vnode_isVNode(chore.$host$) && chore.$host$.flags & 32 /* VNodeFlags.Deleted */);
|
|
8097
8253
|
}
|
|
8254
|
+
function isResourceChore(chore) {
|
|
8255
|
+
return (chore.$type$ === 3 /* ChoreType.TASK */ &&
|
|
8256
|
+
!!chore.$payload$ &&
|
|
8257
|
+
!!(chore.$payload$.$flags$ & 4 /* TaskFlags.RESOURCE */));
|
|
8258
|
+
}
|
|
8098
8259
|
function addBlockedChore(blockedChore, blockingChore, blockedChores) {
|
|
8260
|
+
if (!isResourceChore(blockedChore) && choreComparator(blockedChore, blockingChore) === 0) {
|
|
8261
|
+
return;
|
|
8262
|
+
}
|
|
8099
8263
|
(blockingChore.$blockedChores$ ||= new ChoreArray()).add(blockedChore);
|
|
8100
8264
|
blockedChores.add(blockedChore);
|
|
8101
8265
|
if (vnode_isVNode(blockedChore.$host$)) {
|
|
@@ -8194,9 +8358,9 @@ function debugTrace(action, arg, queue, blockedChores) {
|
|
|
8194
8358
|
}
|
|
8195
8359
|
}
|
|
8196
8360
|
// Blocked chores section
|
|
8197
|
-
if (blockedChores && blockedChores.
|
|
8361
|
+
if (blockedChores && blockedChores.length > 0) {
|
|
8198
8362
|
lines.push('');
|
|
8199
|
-
lines.push(`🚫 Blocked Chores (${blockedChores.
|
|
8363
|
+
lines.push(`🚫 Blocked Chores (${blockedChores.length} items):`);
|
|
8200
8364
|
Array.from(blockedChores).forEach((chore, index) => {
|
|
8201
8365
|
const type = debugChoreTypeToString(chore.$type$);
|
|
8202
8366
|
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
@@ -8272,16 +8436,16 @@ async function serialize(serializationContext) {
|
|
|
8272
8436
|
let parent;
|
|
8273
8437
|
const qrlMap = new Map();
|
|
8274
8438
|
/** Helper to output an array */
|
|
8275
|
-
const outputArray = (value,
|
|
8439
|
+
const outputArray = (value, keepUndefined, writeFn) => {
|
|
8276
8440
|
$writer$.write('[');
|
|
8277
8441
|
let separator = false;
|
|
8278
8442
|
let length;
|
|
8279
|
-
if (
|
|
8443
|
+
if (keepUndefined) {
|
|
8280
8444
|
length = value.length;
|
|
8281
8445
|
}
|
|
8282
8446
|
else {
|
|
8283
8447
|
length = value.length - 1;
|
|
8284
|
-
while (length >= 0 && value[length] ===
|
|
8448
|
+
while (length >= 0 && value[length] === undefined) {
|
|
8285
8449
|
length--;
|
|
8286
8450
|
}
|
|
8287
8451
|
length++;
|
|
@@ -8298,7 +8462,7 @@ async function serialize(serializationContext) {
|
|
|
8298
8462
|
$writer$.write(']');
|
|
8299
8463
|
};
|
|
8300
8464
|
/** Output a type,value pair. If the value is an array, it calls writeValue on each item. */
|
|
8301
|
-
const output = (type, value,
|
|
8465
|
+
const output = (type, value, keepUndefined) => {
|
|
8302
8466
|
$writer$.write(`${type},`);
|
|
8303
8467
|
if (typeof value === 'number') {
|
|
8304
8468
|
$writer$.write(value.toString());
|
|
@@ -8315,7 +8479,7 @@ async function serialize(serializationContext) {
|
|
|
8315
8479
|
$writer$.write(lastIdx === 0 ? s : s.slice(lastIdx));
|
|
8316
8480
|
}
|
|
8317
8481
|
else {
|
|
8318
|
-
outputArray(value,
|
|
8482
|
+
outputArray(value, !!keepUndefined, (valueItem, idx) => {
|
|
8319
8483
|
writeValue(valueItem, idx);
|
|
8320
8484
|
});
|
|
8321
8485
|
}
|
|
@@ -8506,7 +8670,12 @@ async function serialize(serializationContext) {
|
|
|
8506
8670
|
const writeObjectValue = (value) => {
|
|
8507
8671
|
if (isPropsProxy(value)) {
|
|
8508
8672
|
const owner = value[_OWNER];
|
|
8509
|
-
output(32 /* TypeIds.PropsProxy */, [
|
|
8673
|
+
output(32 /* TypeIds.PropsProxy */, [
|
|
8674
|
+
_serializationWeakRef(owner),
|
|
8675
|
+
owner.varProps,
|
|
8676
|
+
owner.constProps,
|
|
8677
|
+
value[_PROPS_HANDLER].$effects$,
|
|
8678
|
+
]);
|
|
8510
8679
|
}
|
|
8511
8680
|
else if (value instanceof SubscriptionData) {
|
|
8512
8681
|
output(33 /* TypeIds.SubscriptionData */, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
|
|
@@ -8536,7 +8705,7 @@ async function serialize(serializationContext) {
|
|
|
8536
8705
|
}
|
|
8537
8706
|
}
|
|
8538
8707
|
const out = [storeTarget, flags, effects, ...innerStores];
|
|
8539
|
-
while (out[out.length - 1]
|
|
8708
|
+
while (out[out.length - 1] === undefined) {
|
|
8540
8709
|
out.pop();
|
|
8541
8710
|
}
|
|
8542
8711
|
output(29 /* TypeIds.Store */, out);
|
|
@@ -8546,7 +8715,7 @@ async function serialize(serializationContext) {
|
|
|
8546
8715
|
const result = value[SerializerSymbol](value);
|
|
8547
8716
|
if (isPromise(result)) {
|
|
8548
8717
|
const forwardRef = resolvePromise(result, $addRoot$, (resolved, resolvedValue) => {
|
|
8549
|
-
return new PromiseResult(28 /* TypeIds.SerializerSignal */, resolved, resolvedValue,
|
|
8718
|
+
return new PromiseResult(28 /* TypeIds.SerializerSignal */, resolved, resolvedValue, undefined, undefined);
|
|
8550
8719
|
});
|
|
8551
8720
|
output(2 /* TypeIds.ForwardRef */, forwardRef);
|
|
8552
8721
|
}
|
|
@@ -8581,10 +8750,16 @@ async function serialize(serializationContext) {
|
|
|
8581
8750
|
else if (value instanceof SignalImpl) {
|
|
8582
8751
|
if (value instanceof SerializerSignalImpl) {
|
|
8583
8752
|
addPreloadQrl(value.$computeQrl$);
|
|
8584
|
-
const
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8753
|
+
const maybeValue = getCustomSerializerPromise(value, value.$untrackedValue$);
|
|
8754
|
+
if (isPromise(maybeValue)) {
|
|
8755
|
+
const forwardRefId = resolvePromise(maybeValue, $addRoot$, (resolved, resolvedValue) => {
|
|
8756
|
+
return new PromiseResult(28 /* TypeIds.SerializerSignal */, resolved, resolvedValue, value.$effects$, value.$computeQrl$);
|
|
8757
|
+
});
|
|
8758
|
+
output(2 /* TypeIds.ForwardRef */, forwardRefId);
|
|
8759
|
+
}
|
|
8760
|
+
else {
|
|
8761
|
+
output(28 /* TypeIds.SerializerSignal */, [value.$computeQrl$, value.$effects$, maybeValue]);
|
|
8762
|
+
}
|
|
8588
8763
|
return;
|
|
8589
8764
|
}
|
|
8590
8765
|
if (value instanceof WrappedSignalImpl) {
|
|
@@ -8617,13 +8792,28 @@ async function serialize(serializationContext) {
|
|
|
8617
8792
|
if (isAsync) {
|
|
8618
8793
|
out.push(value.$loadingEffects$, value.$errorEffects$, value.$untrackedLoading$, value.$untrackedError$);
|
|
8619
8794
|
}
|
|
8795
|
+
let keepUndefined = false;
|
|
8620
8796
|
if (v !== NEEDS_COMPUTATION) {
|
|
8621
8797
|
out.push(v);
|
|
8798
|
+
if (!isAsync && v === undefined) {
|
|
8799
|
+
/**
|
|
8800
|
+
* If value is undefined, we need to keep it in the output. If we don't do that, later
|
|
8801
|
+
* during resuming, the value will be set to symbol(invalid) with flag invalid, and
|
|
8802
|
+
* thats is incorrect.
|
|
8803
|
+
*/
|
|
8804
|
+
keepUndefined = true;
|
|
8805
|
+
}
|
|
8622
8806
|
}
|
|
8623
|
-
output(isAsync ? 27 /* TypeIds.AsyncComputedSignal */ : 26 /* TypeIds.ComputedSignal */, out);
|
|
8807
|
+
output(isAsync ? 27 /* TypeIds.AsyncComputedSignal */ : 26 /* TypeIds.ComputedSignal */, out, keepUndefined);
|
|
8624
8808
|
}
|
|
8625
8809
|
else {
|
|
8626
|
-
|
|
8810
|
+
const v = value.$untrackedValue$;
|
|
8811
|
+
const keepUndefined = v === undefined;
|
|
8812
|
+
const out = [v];
|
|
8813
|
+
if (value.$effects$) {
|
|
8814
|
+
out.push(...value.$effects$);
|
|
8815
|
+
}
|
|
8816
|
+
output(24 /* TypeIds.Signal */, out, keepUndefined);
|
|
8627
8817
|
}
|
|
8628
8818
|
}
|
|
8629
8819
|
else if (value instanceof URL) {
|
|
@@ -8707,9 +8897,9 @@ async function serialize(serializationContext) {
|
|
|
8707
8897
|
value.varProps,
|
|
8708
8898
|
value.constProps,
|
|
8709
8899
|
value.children,
|
|
8710
|
-
value.toSort ||
|
|
8900
|
+
value.toSort || undefined,
|
|
8711
8901
|
];
|
|
8712
|
-
while (out[out.length - 1]
|
|
8902
|
+
while (out[out.length - 1] === undefined) {
|
|
8713
8903
|
out.pop();
|
|
8714
8904
|
}
|
|
8715
8905
|
output(31 /* TypeIds.JSXNode */, out);
|
|
@@ -8723,7 +8913,7 @@ async function serialize(serializationContext) {
|
|
|
8723
8913
|
value[_EFFECT_BACK_REF],
|
|
8724
8914
|
value.$state$,
|
|
8725
8915
|
];
|
|
8726
|
-
while (out[out.length - 1]
|
|
8916
|
+
while (out[out.length - 1] === undefined) {
|
|
8727
8917
|
out.pop();
|
|
8728
8918
|
}
|
|
8729
8919
|
output(21 /* TypeIds.Task */, out);
|
|
@@ -8850,7 +9040,7 @@ class PromiseResult {
|
|
|
8850
9040
|
$value$;
|
|
8851
9041
|
$effects$;
|
|
8852
9042
|
$qrl$;
|
|
8853
|
-
constructor($type$, $resolved$, $value$, $effects$ =
|
|
9043
|
+
constructor($type$, $resolved$, $value$, $effects$ = undefined, $qrl$ = undefined) {
|
|
8854
9044
|
this.$type$ = $type$;
|
|
8855
9045
|
this.$resolved$ = $resolved$;
|
|
8856
9046
|
this.$value$ = $value$;
|
|
@@ -8859,20 +9049,24 @@ class PromiseResult {
|
|
|
8859
9049
|
}
|
|
8860
9050
|
}
|
|
8861
9051
|
function getCustomSerializerPromise(signal, value) {
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
}
|
|
9052
|
+
if (value === NEEDS_COMPUTATION) {
|
|
9053
|
+
return value;
|
|
9054
|
+
}
|
|
9055
|
+
return maybeThen((signal.$computeQrl$.resolved || signal.$computeQrl$.resolve()), (arg) => {
|
|
9056
|
+
let data;
|
|
9057
|
+
if (typeof arg === 'function') {
|
|
9058
|
+
arg = arg();
|
|
9059
|
+
}
|
|
9060
|
+
if (arg.serialize) {
|
|
9061
|
+
data = arg.serialize(value);
|
|
9062
|
+
}
|
|
9063
|
+
else if (typeof value === 'object' && SerializerSymbol in value) {
|
|
9064
|
+
data = value[SerializerSymbol](value);
|
|
9065
|
+
}
|
|
9066
|
+
if (data === undefined) {
|
|
9067
|
+
data = NEEDS_COMPUTATION;
|
|
9068
|
+
}
|
|
9069
|
+
return data;
|
|
8876
9070
|
});
|
|
8877
9071
|
}
|
|
8878
9072
|
const discoverValuesForVNodeData = (vnodeData, callback) => {
|
|
@@ -8923,7 +9117,7 @@ function serializeWrappingFn(serializationContext, value) {
|
|
|
8923
9117
|
return [syncFnId, value.$args$];
|
|
8924
9118
|
}
|
|
8925
9119
|
function filterEffectBackRefs(effectBackRef) {
|
|
8926
|
-
let effectBackRefToSerialize =
|
|
9120
|
+
let effectBackRefToSerialize = undefined;
|
|
8927
9121
|
if (effectBackRef) {
|
|
8928
9122
|
for (const [effectProp, effect] of effectBackRef) {
|
|
8929
9123
|
if (effect[2 /* EffectSubscriptionProp.BACK_REF */]) {
|
|
@@ -9103,7 +9297,7 @@ class _SharedContainer {
|
|
|
9103
9297
|
throw Error('Not implemented');
|
|
9104
9298
|
};
|
|
9105
9299
|
const choreQueue = new ChoreArray();
|
|
9106
|
-
const blockedChores = new
|
|
9300
|
+
const blockedChores = new ChoreArray();
|
|
9107
9301
|
const runningChores = new Set();
|
|
9108
9302
|
this.$scheduler$ = createScheduler(this, journalFlush, choreQueue, blockedChores, runningChores);
|
|
9109
9303
|
}
|
|
@@ -9188,7 +9382,7 @@ async function _walkJSX(ssr, value, options) {
|
|
|
9188
9382
|
}
|
|
9189
9383
|
function processJSXNode(ssr, enqueue, value, options) {
|
|
9190
9384
|
// console.log('processJSXNode', value);
|
|
9191
|
-
if (value
|
|
9385
|
+
if (value == null) {
|
|
9192
9386
|
ssr.textNode('');
|
|
9193
9387
|
}
|
|
9194
9388
|
else if (typeof value === 'boolean') {
|
|
@@ -9245,12 +9439,12 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
9245
9439
|
appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue);
|
|
9246
9440
|
}
|
|
9247
9441
|
}
|
|
9248
|
-
const innerHTML = ssr.openElement(type,
|
|
9442
|
+
const innerHTML = ssr.openElement(type, toSsrAttrs(jsx.varProps, {
|
|
9249
9443
|
serializationCtx: ssr.serializationCtx,
|
|
9250
9444
|
styleScopedId: options.styleScoped,
|
|
9251
9445
|
key: jsx.key,
|
|
9252
9446
|
toSort: jsx.toSort,
|
|
9253
|
-
}),
|
|
9447
|
+
}), toSsrAttrs(jsx.constProps, {
|
|
9254
9448
|
serializationCtx: ssr.serializationCtx,
|
|
9255
9449
|
styleScopedId: options.styleScoped,
|
|
9256
9450
|
}), qwikInspectorAttrValue);
|
|
@@ -9347,12 +9541,22 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
9347
9541
|
const componentFrame = ssr.getParentComponentFrame();
|
|
9348
9542
|
componentFrame.distributeChildrenIntoSlots(jsx.children, options.styleScoped, options.parentComponentFrame);
|
|
9349
9543
|
const jsxOutput = applyQwikComponentBody(ssr, jsx, type);
|
|
9350
|
-
const compStyleComponentId = addComponentStylePrefix(host.getProp(QScopedStyle));
|
|
9351
9544
|
enqueue(new ParentComponentData(options.styleScoped, options.parentComponentFrame));
|
|
9352
9545
|
enqueue(ssr.closeComponent);
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9546
|
+
if (isPromise(jsxOutput)) {
|
|
9547
|
+
// Defer reading QScopedStyle until after the promise resolves
|
|
9548
|
+
enqueue(async () => {
|
|
9549
|
+
const resolvedOutput = await jsxOutput;
|
|
9550
|
+
const compStyleComponentId = addComponentStylePrefix(host.getProp(QScopedStyle));
|
|
9551
|
+
enqueue(resolvedOutput);
|
|
9552
|
+
enqueue(new ParentComponentData(compStyleComponentId, componentFrame));
|
|
9553
|
+
});
|
|
9554
|
+
}
|
|
9555
|
+
else {
|
|
9556
|
+
enqueue(jsxOutput);
|
|
9557
|
+
const compStyleComponentId = addComponentStylePrefix(host.getProp(QScopedStyle));
|
|
9558
|
+
enqueue(new ParentComponentData(compStyleComponentId, componentFrame));
|
|
9559
|
+
}
|
|
9356
9560
|
}
|
|
9357
9561
|
else {
|
|
9358
9562
|
const inlineComponentProps = [ELEMENT_KEY, jsx.key];
|
|
@@ -9369,12 +9573,6 @@ function processJSXNode(ssr, enqueue, value, options) {
|
|
|
9369
9573
|
}
|
|
9370
9574
|
}
|
|
9371
9575
|
}
|
|
9372
|
-
function varPropsToSsrAttrs(varProps, constProps, options) {
|
|
9373
|
-
return toSsrAttrs(varProps, options);
|
|
9374
|
-
}
|
|
9375
|
-
function constPropsToSsrAttrs(constProps, varProps, options) {
|
|
9376
|
-
return toSsrAttrs(constProps, options);
|
|
9377
|
-
}
|
|
9378
9576
|
function toSsrAttrs(record, options) {
|
|
9379
9577
|
if (record == null) {
|
|
9380
9578
|
return null;
|
|
@@ -9468,14 +9666,16 @@ function addQwikEventToSerializationContext(serializationCtx, key, qrl) {
|
|
|
9468
9666
|
// TODO extract window/document too so qwikloader can precisely listen
|
|
9469
9667
|
const data = getEventDataFromHtmlAttribute(key);
|
|
9470
9668
|
if (data) {
|
|
9471
|
-
const eventName = data
|
|
9472
|
-
|
|
9669
|
+
const [scope, eventName] = data;
|
|
9670
|
+
const scopedEvent = getScopedEventName(scope, eventName);
|
|
9671
|
+
const loaderScopedEvent = getLoaderScopedEventName(scope, scopedEvent);
|
|
9672
|
+
serializationCtx.$eventNames$.add(loaderScopedEvent);
|
|
9473
9673
|
serializationCtx.$eventQrls$.add(qrl);
|
|
9474
9674
|
}
|
|
9475
9675
|
}
|
|
9476
9676
|
function addPreventDefaultEventToSerializationContext(serializationCtx, key) {
|
|
9477
|
-
// skip first 15 chars, this is length of the `preventdefault
|
|
9478
|
-
const eventName = key.substring(
|
|
9677
|
+
// skip first 15 chars, this is length of the `preventdefault`, leave the ":"
|
|
9678
|
+
const eventName = key.substring(14);
|
|
9479
9679
|
if (eventName) {
|
|
9480
9680
|
serializationCtx.$eventNames$.add(eventName);
|
|
9481
9681
|
}
|
|
@@ -9613,7 +9813,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
9613
9813
|
asyncComputed.$loadingEffects$ = new Set(d[2]);
|
|
9614
9814
|
asyncComputed.$errorEffects$ = new Set(d[3]);
|
|
9615
9815
|
asyncComputed.$untrackedLoading$ = d[4];
|
|
9616
|
-
asyncComputed.$untrackedError$ = d[5]
|
|
9816
|
+
asyncComputed.$untrackedError$ = d[5];
|
|
9617
9817
|
const hasValue = d.length > 6;
|
|
9618
9818
|
if (hasValue) {
|
|
9619
9819
|
asyncComputed.$untrackedValue$ = d[6];
|
|
@@ -9628,7 +9828,9 @@ const inflate = (container, target, typeId, data) => {
|
|
|
9628
9828
|
const computed = target;
|
|
9629
9829
|
const d = data;
|
|
9630
9830
|
computed.$computeQrl$ = d[0];
|
|
9631
|
-
|
|
9831
|
+
if (d[1]) {
|
|
9832
|
+
computed.$effects$ = new Set(d[1]);
|
|
9833
|
+
}
|
|
9632
9834
|
const hasValue = d.length > 2;
|
|
9633
9835
|
if (hasValue) {
|
|
9634
9836
|
computed.$untrackedValue$ = d[2];
|
|
@@ -9723,6 +9925,7 @@ const inflate = (container, target, typeId, data) => {
|
|
|
9723
9925
|
owner._proxy = propsProxy;
|
|
9724
9926
|
}
|
|
9725
9927
|
propsProxy[_OWNER] = owner;
|
|
9928
|
+
propsProxy[_PROPS_HANDLER].$effects$ = d[3];
|
|
9726
9929
|
break;
|
|
9727
9930
|
case 33 /* TypeIds.SubscriptionData */: {
|
|
9728
9931
|
const effectData = target;
|
|
@@ -10272,9 +10475,6 @@ class DomContainer extends _SharedContainer {
|
|
|
10272
10475
|
this.$setServerData$();
|
|
10273
10476
|
element.setAttribute(QContainerAttr, "resumed" /* QContainerValue.RESUMED */);
|
|
10274
10477
|
element.qContainer = this;
|
|
10275
|
-
if (!qTest && element.isConnected) {
|
|
10276
|
-
element.dispatchEvent(new CustomEvent('qresume', { bubbles: true }));
|
|
10277
|
-
}
|
|
10278
10478
|
const qwikStates = element.querySelectorAll('script[type="qwik/state"]');
|
|
10279
10479
|
if (qwikStates.length !== 0) {
|
|
10280
10480
|
const lastState = qwikStates[qwikStates.length - 1];
|
|
@@ -10282,6 +10482,9 @@ class DomContainer extends _SharedContainer {
|
|
|
10282
10482
|
preprocessState(this.$rawStateData$, this);
|
|
10283
10483
|
this.$stateData$ = wrapDeserializerProxy(this, this.$rawStateData$);
|
|
10284
10484
|
}
|
|
10485
|
+
if (!qTest && element.isConnected) {
|
|
10486
|
+
element.dispatchEvent(new CustomEvent('qresume', { bubbles: true }));
|
|
10487
|
+
}
|
|
10285
10488
|
}
|
|
10286
10489
|
$setRawState$(id, vParent) {
|
|
10287
10490
|
this.$stateData$[id] = vParent;
|
|
@@ -10717,7 +10920,7 @@ const getOrCreateStore = (obj, flags, container) => {
|
|
|
10717
10920
|
class StoreHandler {
|
|
10718
10921
|
$flags$;
|
|
10719
10922
|
$container$;
|
|
10720
|
-
$effects$ =
|
|
10923
|
+
$effects$ = undefined;
|
|
10721
10924
|
constructor($flags$, $container$) {
|
|
10722
10925
|
this.$flags$ = $flags$;
|
|
10723
10926
|
this.$container$ = $container$;
|
|
@@ -10727,7 +10930,7 @@ class StoreHandler {
|
|
|
10727
10930
|
}
|
|
10728
10931
|
force(prop) {
|
|
10729
10932
|
const target = getStoreTarget(this);
|
|
10730
|
-
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
10933
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, this, getEffects(target, prop, this.$effects$));
|
|
10731
10934
|
}
|
|
10732
10935
|
get(target, prop) {
|
|
10733
10936
|
// TODO(perf): handle better `slice` calls
|
|
@@ -10796,7 +10999,7 @@ class StoreHandler {
|
|
|
10796
10999
|
if (!Array.isArray(target)) {
|
|
10797
11000
|
// If the target is an array, we don't need to trigger effects.
|
|
10798
11001
|
// Changing the length property will trigger effects.
|
|
10799
|
-
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
11002
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, this, getEffects(target, prop, this.$effects$));
|
|
10800
11003
|
}
|
|
10801
11004
|
return true;
|
|
10802
11005
|
}
|
|
@@ -10852,13 +11055,14 @@ function addStoreEffect(target, prop, store, effectSubscription) {
|
|
|
10852
11055
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
10853
11056
|
// to this signal.
|
|
10854
11057
|
ensureContainsBackRef(effectSubscription, target);
|
|
11058
|
+
// TODO is this needed with the preloader?
|
|
10855
11059
|
addQrlToSerializationCtx(effectSubscription, store.$container$);
|
|
10856
11060
|
}
|
|
10857
11061
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
10858
11062
|
target[prop] = value;
|
|
10859
11063
|
const effects = getEffects(target, prop, currentStore.$effects$);
|
|
10860
11064
|
if (effects) {
|
|
10861
|
-
currentStore.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */,
|
|
11065
|
+
currentStore.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, undefined, currentStore, effects);
|
|
10862
11066
|
}
|
|
10863
11067
|
}
|
|
10864
11068
|
function getEffects(target, prop, storeEffects) {
|
|
@@ -10883,7 +11087,7 @@ function getEffects(target, prop, storeEffects) {
|
|
|
10883
11087
|
effectsToTrigger.add(effect);
|
|
10884
11088
|
}
|
|
10885
11089
|
}
|
|
10886
|
-
return effectsToTrigger
|
|
11090
|
+
return effectsToTrigger;
|
|
10887
11091
|
}
|
|
10888
11092
|
|
|
10889
11093
|
const canSerialize = (value, seen = new WeakSet()) => {
|
|
@@ -12673,21 +12877,22 @@ const useVisibleTaskQrl = (qrl, opts) => {
|
|
|
12673
12877
|
const { val, set, i, iCtx } = useSequentialScope();
|
|
12674
12878
|
const eagerness = opts?.strategy ?? 'intersection-observer';
|
|
12675
12879
|
if (val) {
|
|
12676
|
-
if (isServerPlatform()) {
|
|
12677
|
-
|
|
12880
|
+
if (!(val.$flags$ & 32 /* TaskFlags.EVENTS_REGISTERED */) && !isServerPlatform()) {
|
|
12881
|
+
val.$flags$ |= 32 /* TaskFlags.EVENTS_REGISTERED */;
|
|
12882
|
+
useRegisterTaskEvents(val, eagerness);
|
|
12678
12883
|
}
|
|
12679
12884
|
return;
|
|
12680
12885
|
}
|
|
12681
12886
|
assertQrl(qrl);
|
|
12682
12887
|
const task = new Task(1 /* TaskFlags.VISIBLE_TASK */, i, iCtx.$hostElement$, qrl, undefined, null);
|
|
12683
12888
|
set(task);
|
|
12684
|
-
|
|
12889
|
+
useRegisterTaskEvents(task, eagerness);
|
|
12685
12890
|
if (!isServerPlatform()) {
|
|
12686
12891
|
qrl.resolve(iCtx.$element$);
|
|
12687
12892
|
iCtx.$container$.$scheduler$(16 /* ChoreType.VISIBLE */, task);
|
|
12688
12893
|
}
|
|
12689
12894
|
};
|
|
12690
|
-
const
|
|
12895
|
+
const useRegisterTaskEvents = (task, eagerness) => {
|
|
12691
12896
|
if (eagerness === 'intersection-observer') {
|
|
12692
12897
|
useOn('qvisible', getTaskHandlerQrl(task));
|
|
12693
12898
|
}
|