@qwik.dev/core 2.0.0-beta.8 → 2.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bindings/qwik.darwin-arm64.node +0 -0
- package/bindings/qwik.darwin-x64.node +0 -0
- package/bindings/qwik.linux-x64-gnu.node +0 -0
- package/bindings/qwik.win32-x64-msvc.node +0 -0
- package/bindings/qwik_wasm_bg.wasm +0 -0
- package/dist/backpatch/index.cjs +6 -0
- package/dist/backpatch/index.d.ts +2 -0
- package/dist/backpatch/index.mjs +5 -0
- package/dist/backpatch/package.json +8 -0
- package/dist/backpatch-executor.debug.js +34 -0
- package/dist/backpatch-executor.js +1 -0
- package/dist/build/package.json +1 -1
- package/dist/cli.cjs +2 -2
- package/dist/core-internal.d.ts +105 -55
- package/dist/core.cjs +976 -456
- package/dist/core.cjs.map +1 -1
- package/dist/core.min.mjs +1 -1
- package/dist/core.mjs +974 -456
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.cjs +638 -351
- package/dist/core.prod.mjs +709 -362
- package/dist/loader/package.json +1 -1
- package/dist/optimizer.cjs +75 -73
- package/dist/optimizer.mjs +75 -75
- package/dist/server.cjs +143 -42
- package/dist/server.d.ts +9 -0
- package/dist/server.mjs +140 -42
- package/dist/testing/index.cjs +3749 -927
- package/dist/testing/index.d.ts +972 -1
- package/dist/testing/index.mjs +3735 -921
- package/dist/testing/package.json +1 -1
- package/package.json +4 -2
package/dist/core.cjs
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.9-dev+6b582c7
|
|
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
|
|
@@ -11,6 +11,13 @@
|
|
|
11
11
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.qwikCore = {}, global.qwikBuild, global.qwikPreloader));
|
|
12
12
|
})(this, (function (exports, build, preloader) { 'use strict';
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* QWIK_VERSION
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
const version = "2.0.0-beta.9-dev+6b582c7";
|
|
20
|
+
|
|
14
21
|
// same as isDev but separate so we can test
|
|
15
22
|
const qDev = globalThis.qDev !== false;
|
|
16
23
|
const qInspector = globalThis.qInspector === true;
|
|
@@ -88,6 +95,9 @@
|
|
|
88
95
|
const isString = (v) => {
|
|
89
96
|
return typeof v === 'string';
|
|
90
97
|
};
|
|
98
|
+
const isNumber$1 = (v) => {
|
|
99
|
+
return typeof v === 'number';
|
|
100
|
+
};
|
|
91
101
|
const isFunction = (v) => {
|
|
92
102
|
return typeof v === 'function';
|
|
93
103
|
};
|
|
@@ -290,13 +300,6 @@
|
|
|
290
300
|
});
|
|
291
301
|
});
|
|
292
302
|
},
|
|
293
|
-
nextTick: (fn) => {
|
|
294
|
-
return new Promise((resolve) => {
|
|
295
|
-
setTimeout(() => {
|
|
296
|
-
resolve(fn());
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
},
|
|
300
303
|
chunkForSymbol(symbolName, chunk) {
|
|
301
304
|
return [symbolName, chunk ?? '_'];
|
|
302
305
|
},
|
|
@@ -554,6 +557,13 @@
|
|
|
554
557
|
this.$container$ = container;
|
|
555
558
|
this.$untrackedValue$ = value;
|
|
556
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* Use this to force running subscribers, for example when the calculated value has mutated but
|
|
562
|
+
* remained the same object
|
|
563
|
+
*/
|
|
564
|
+
force() {
|
|
565
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
|
|
566
|
+
}
|
|
557
567
|
get untrackedValue() {
|
|
558
568
|
return this.$untrackedValue$;
|
|
559
569
|
}
|
|
@@ -567,14 +577,7 @@
|
|
|
567
577
|
set value(value) {
|
|
568
578
|
if (value !== this.$untrackedValue$) {
|
|
569
579
|
this.$untrackedValue$ = value;
|
|
570
|
-
|
|
571
|
-
triggerEffects(this.$container$, this, this.$effects$);
|
|
572
|
-
// this.$container$?.$scheduler$(
|
|
573
|
-
// ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
|
|
574
|
-
// null,
|
|
575
|
-
// this,
|
|
576
|
-
// this.$effects$
|
|
577
|
-
// );
|
|
580
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
|
|
578
581
|
}
|
|
579
582
|
}
|
|
580
583
|
// prevent accidental use as value
|
|
@@ -636,12 +639,11 @@
|
|
|
636
639
|
$funcStr$;
|
|
637
640
|
$flags$;
|
|
638
641
|
$hostElement$ = null;
|
|
639
|
-
$forceRunEffects$ = false;
|
|
640
642
|
[_EFFECT_BACK_REF] = null;
|
|
641
643
|
constructor(container, fn, args, fnStr,
|
|
642
644
|
// We need a separate flag to know when the computation needs running because
|
|
643
645
|
// we need the old value to know if effects need running after computation
|
|
644
|
-
flags = 1 /* SignalFlags.INVALID */ |
|
|
646
|
+
flags = 1 /* SignalFlags.INVALID */ | 4 /* WrappedSignalFlags.UNWRAP */) {
|
|
645
647
|
super(container, NEEDS_COMPUTATION);
|
|
646
648
|
this.$args$ = args;
|
|
647
649
|
this.$func$ = fn;
|
|
@@ -650,7 +652,6 @@
|
|
|
650
652
|
}
|
|
651
653
|
invalidate() {
|
|
652
654
|
this.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
653
|
-
this.$forceRunEffects$ = false;
|
|
654
655
|
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
|
|
655
656
|
}
|
|
656
657
|
/**
|
|
@@ -658,29 +659,26 @@
|
|
|
658
659
|
* remained the same object.
|
|
659
660
|
*/
|
|
660
661
|
force() {
|
|
661
|
-
this.$
|
|
662
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
662
663
|
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
|
|
663
664
|
}
|
|
664
665
|
get untrackedValue() {
|
|
665
|
-
|
|
666
|
-
if (didChange) {
|
|
667
|
-
this.$forceRunEffects$ = didChange;
|
|
668
|
-
}
|
|
666
|
+
this.$computeIfNeeded$();
|
|
669
667
|
assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
|
|
670
668
|
return this.$untrackedValue$;
|
|
671
669
|
}
|
|
672
670
|
$computeIfNeeded$() {
|
|
673
671
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
674
|
-
return
|
|
672
|
+
return;
|
|
675
673
|
}
|
|
676
674
|
const untrackedValue = trackSignal(() => this.$func$(...this.$args$), this, "." /* EffectProperty.VNODE */, this.$container$);
|
|
677
|
-
// TODO: we should remove invalid flag here
|
|
675
|
+
// TODO: we should remove invalid flag here, but some tests are failing
|
|
678
676
|
// this.$flags$ &= ~SignalFlags.INVALID;
|
|
679
677
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
680
678
|
if (didChange) {
|
|
679
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
681
680
|
this.$untrackedValue$ = untrackedValue;
|
|
682
681
|
}
|
|
683
|
-
return didChange;
|
|
684
682
|
}
|
|
685
683
|
// Make this signal read-only
|
|
686
684
|
set value(_) {
|
|
@@ -875,12 +873,26 @@
|
|
|
875
873
|
};
|
|
876
874
|
/** @internal */
|
|
877
875
|
const _waitUntilRendered = (elm) => {
|
|
878
|
-
const
|
|
879
|
-
if (!
|
|
876
|
+
const container = _getQContainerElement(elm)?.qContainer;
|
|
877
|
+
if (!container) {
|
|
880
878
|
return Promise.resolve();
|
|
881
879
|
}
|
|
882
|
-
|
|
883
|
-
|
|
880
|
+
// Multi-cycle idle: loop WAIT_FOR_QUEUE until the flush epoch stays stable
|
|
881
|
+
// across an extra microtask, which signals that no new work re-scheduled.
|
|
882
|
+
return (async () => {
|
|
883
|
+
for (;;) {
|
|
884
|
+
await container.$scheduler$(255 /* ChoreType.WAIT_FOR_QUEUE */).$returnValue$;
|
|
885
|
+
const firstEpoch = container.$flushEpoch$ || 0;
|
|
886
|
+
// Give a microtask for any immediate follow-up scheduling to enqueue
|
|
887
|
+
await Promise.resolve();
|
|
888
|
+
const secondEpoch = container.$flushEpoch$ || 0;
|
|
889
|
+
// If no epoch change occurred during and after WAIT_FOR_QUEUE, we are idle.
|
|
890
|
+
if (firstEpoch === secondEpoch) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
// Continue loop if epoch advanced, meaning more work flushed.
|
|
894
|
+
}
|
|
895
|
+
})();
|
|
884
896
|
};
|
|
885
897
|
|
|
886
898
|
/**
|
|
@@ -958,7 +970,7 @@
|
|
|
958
970
|
}
|
|
959
971
|
return null; // Return null if not matching expected format
|
|
960
972
|
}
|
|
961
|
-
function eventNameToJsxEvent(eventName, prefix
|
|
973
|
+
function eventNameToJsxEvent(eventName, prefix) {
|
|
962
974
|
eventName = eventName.charAt(0).toUpperCase() + eventName.substring(1);
|
|
963
975
|
return prefix + eventName + EVENT_SUFFIX;
|
|
964
976
|
}
|
|
@@ -1247,13 +1259,6 @@
|
|
|
1247
1259
|
return true;
|
|
1248
1260
|
};
|
|
1249
1261
|
|
|
1250
|
-
/**
|
|
1251
|
-
* QWIK_VERSION
|
|
1252
|
-
*
|
|
1253
|
-
* @public
|
|
1254
|
-
*/
|
|
1255
|
-
const version = "2.0.0-beta.8-dev+434cd18";
|
|
1256
|
-
|
|
1257
1262
|
/** @internal */
|
|
1258
1263
|
const EMPTY_ARRAY = [];
|
|
1259
1264
|
const EMPTY_OBJ = {};
|
|
@@ -1394,7 +1399,7 @@
|
|
|
1394
1399
|
*
|
|
1395
1400
|
* @internal
|
|
1396
1401
|
*/
|
|
1397
|
-
const
|
|
1402
|
+
const _run = (...args) => {
|
|
1398
1403
|
// This will already check container
|
|
1399
1404
|
const [runQrl] = useLexicalScope();
|
|
1400
1405
|
const context = getInvokeContext();
|
|
@@ -1408,7 +1413,9 @@
|
|
|
1408
1413
|
if (!scheduler) {
|
|
1409
1414
|
throw qError(1 /* QError.schedulerNotFound */);
|
|
1410
1415
|
}
|
|
1411
|
-
return
|
|
1416
|
+
// We don't return anything, the scheduler is in charge now
|
|
1417
|
+
const chore = scheduler(2 /* ChoreType.RUN_QRL */, hostElement, runQrl, args);
|
|
1418
|
+
return getChorePromise(chore);
|
|
1412
1419
|
};
|
|
1413
1420
|
|
|
1414
1421
|
/** @internal */
|
|
@@ -1532,13 +1539,12 @@
|
|
|
1532
1539
|
*/
|
|
1533
1540
|
$computeQrl$;
|
|
1534
1541
|
$flags$;
|
|
1535
|
-
$forceRunEffects$ = false;
|
|
1536
1542
|
[_EFFECT_BACK_REF] = null;
|
|
1537
1543
|
constructor(container, fn,
|
|
1538
1544
|
// We need a separate flag to know when the computation needs running because
|
|
1539
1545
|
// we need the old value to know if effects need running after computation
|
|
1540
1546
|
flags = 1 /* SignalFlags.INVALID */ |
|
|
1541
|
-
|
|
1547
|
+
32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */) {
|
|
1542
1548
|
// The value is used for comparison when signals trigger, which can only happen
|
|
1543
1549
|
// when it was calculated before. Therefore we can pass whatever we like.
|
|
1544
1550
|
super(container, NEEDS_COMPUTATION);
|
|
@@ -1547,7 +1553,6 @@
|
|
|
1547
1553
|
}
|
|
1548
1554
|
invalidate() {
|
|
1549
1555
|
this.$flags$ |= 1 /* SignalFlags.INVALID */;
|
|
1550
|
-
this.$forceRunEffects$ = false;
|
|
1551
1556
|
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
|
|
1552
1557
|
}
|
|
1553
1558
|
/**
|
|
@@ -1555,20 +1560,17 @@
|
|
|
1555
1560
|
* remained the same object
|
|
1556
1561
|
*/
|
|
1557
1562
|
force() {
|
|
1558
|
-
this.$
|
|
1559
|
-
|
|
1563
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1564
|
+
super.force();
|
|
1560
1565
|
}
|
|
1561
1566
|
get untrackedValue() {
|
|
1562
|
-
|
|
1563
|
-
if (didChange) {
|
|
1564
|
-
this.$forceRunEffects$ = didChange;
|
|
1565
|
-
}
|
|
1567
|
+
this.$computeIfNeeded$();
|
|
1566
1568
|
assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
|
|
1567
1569
|
return this.$untrackedValue$;
|
|
1568
1570
|
}
|
|
1569
1571
|
$computeIfNeeded$() {
|
|
1570
1572
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
1571
|
-
return
|
|
1573
|
+
return;
|
|
1572
1574
|
}
|
|
1573
1575
|
const computeQrl = this.$computeQrl$;
|
|
1574
1576
|
throwIfQRLNotResolved(computeQrl);
|
|
@@ -1587,9 +1589,12 @@
|
|
|
1587
1589
|
this.$flags$ &= ~1 /* SignalFlags.INVALID */;
|
|
1588
1590
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
1589
1591
|
if (didChange) {
|
|
1592
|
+
// skip first computation when value is not changed
|
|
1593
|
+
if (this.$untrackedValue$ !== NEEDS_COMPUTATION) {
|
|
1594
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1595
|
+
}
|
|
1590
1596
|
this.$untrackedValue$ = untrackedValue;
|
|
1591
1597
|
}
|
|
1592
|
-
return didChange;
|
|
1593
1598
|
}
|
|
1594
1599
|
finally {
|
|
1595
1600
|
if (ctx) {
|
|
@@ -1615,12 +1620,12 @@
|
|
|
1615
1620
|
*/
|
|
1616
1621
|
class SerializerSignalImpl extends ComputedSignalImpl {
|
|
1617
1622
|
constructor(container, argQrl) {
|
|
1618
|
-
super(container, argQrl, 1 /* SignalFlags.INVALID */ |
|
|
1623
|
+
super(container, argQrl, 1 /* SignalFlags.INVALID */ | 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */);
|
|
1619
1624
|
}
|
|
1620
1625
|
$didInitialize$ = false;
|
|
1621
1626
|
$computeIfNeeded$() {
|
|
1622
1627
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
1623
|
-
return
|
|
1628
|
+
return;
|
|
1624
1629
|
}
|
|
1625
1630
|
throwIfQRLNotResolved(this.$computeQrl$);
|
|
1626
1631
|
let arg = this.$computeQrl$.resolved;
|
|
@@ -1638,9 +1643,9 @@
|
|
|
1638
1643
|
this.$flags$ &= -2 /* SignalFlags.INVALID */;
|
|
1639
1644
|
this.$didInitialize$ = true;
|
|
1640
1645
|
if (didChange) {
|
|
1646
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1641
1647
|
this.$untrackedValue$ = untrackedValue;
|
|
1642
1648
|
}
|
|
1643
|
-
return didChange;
|
|
1644
1649
|
}
|
|
1645
1650
|
}
|
|
1646
1651
|
|
|
@@ -1650,6 +1655,28 @@
|
|
|
1650
1655
|
const getStoreTarget = (value) => {
|
|
1651
1656
|
return value?.[STORE_TARGET] || null;
|
|
1652
1657
|
};
|
|
1658
|
+
/**
|
|
1659
|
+
* Force a store to recompute and schedule effects.
|
|
1660
|
+
*
|
|
1661
|
+
* @public
|
|
1662
|
+
*/
|
|
1663
|
+
const forceStoreEffects = (value, prop) => {
|
|
1664
|
+
const handler = getStoreHandler(value);
|
|
1665
|
+
if (handler) {
|
|
1666
|
+
handler.force(prop);
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
/**
|
|
1670
|
+
* @returns True if the store has effects for the given prop
|
|
1671
|
+
* @internal
|
|
1672
|
+
*/
|
|
1673
|
+
const _hasStoreEffects = (value, prop) => {
|
|
1674
|
+
const handler = getStoreHandler(value);
|
|
1675
|
+
if (handler) {
|
|
1676
|
+
return (handler.$effects$?.get(prop)?.size ?? 0) > 0;
|
|
1677
|
+
}
|
|
1678
|
+
return false;
|
|
1679
|
+
};
|
|
1653
1680
|
/**
|
|
1654
1681
|
* Get the original object that was wrapped by the store. Useful if you want to clone a store
|
|
1655
1682
|
* (structuredClone, IndexedDB,...)
|
|
@@ -1688,7 +1715,12 @@
|
|
|
1688
1715
|
toString() {
|
|
1689
1716
|
return '[Store]';
|
|
1690
1717
|
}
|
|
1718
|
+
force(prop) {
|
|
1719
|
+
const target = getStoreTarget(this);
|
|
1720
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, getEffects(target, prop, this.$effects$));
|
|
1721
|
+
}
|
|
1691
1722
|
get(target, prop) {
|
|
1723
|
+
// TODO(perf): handle better `slice` calls
|
|
1692
1724
|
if (typeof prop === 'symbol') {
|
|
1693
1725
|
if (prop === STORE_TARGET) {
|
|
1694
1726
|
return target;
|
|
@@ -1751,7 +1783,11 @@
|
|
|
1751
1783
|
if (typeof prop != 'string' || !delete target[prop]) {
|
|
1752
1784
|
return false;
|
|
1753
1785
|
}
|
|
1754
|
-
|
|
1786
|
+
if (!Array.isArray(target)) {
|
|
1787
|
+
// If the target is an array, we don't need to trigger effects.
|
|
1788
|
+
// Changing the length property will trigger effects.
|
|
1789
|
+
this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, getEffects(target, prop, this.$effects$));
|
|
1790
|
+
}
|
|
1755
1791
|
return true;
|
|
1756
1792
|
}
|
|
1757
1793
|
has(target, prop) {
|
|
@@ -1810,8 +1846,10 @@
|
|
|
1810
1846
|
}
|
|
1811
1847
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
1812
1848
|
target[prop] = value;
|
|
1813
|
-
|
|
1814
|
-
|
|
1849
|
+
const effects = getEffects(target, prop, currentStore.$effects$);
|
|
1850
|
+
if (effects) {
|
|
1851
|
+
currentStore.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, currentStore, effects);
|
|
1852
|
+
}
|
|
1815
1853
|
}
|
|
1816
1854
|
function getEffects(target, prop, storeEffects) {
|
|
1817
1855
|
let effectsToTrigger;
|
|
@@ -1939,7 +1977,7 @@
|
|
|
1939
1977
|
}
|
|
1940
1978
|
$computeIfNeeded$() {
|
|
1941
1979
|
if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
|
|
1942
|
-
return
|
|
1980
|
+
return;
|
|
1943
1981
|
}
|
|
1944
1982
|
const computeQrl = this.$computeQrl$;
|
|
1945
1983
|
throwIfQRLNotResolved(computeQrl);
|
|
@@ -1969,6 +2007,7 @@
|
|
|
1969
2007
|
this.$flags$ &= -2 /* SignalFlags.INVALID */;
|
|
1970
2008
|
const didChange = untrackedValue !== this.$untrackedValue$;
|
|
1971
2009
|
if (didChange) {
|
|
2010
|
+
this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
|
|
1972
2011
|
this.$untrackedValue$ = untrackedValue;
|
|
1973
2012
|
}
|
|
1974
2013
|
return didChange;
|
|
@@ -2056,7 +2095,7 @@
|
|
|
2056
2095
|
if (!(obj instanceof AsyncComputedSignalImpl)) {
|
|
2057
2096
|
assertEqual(prop, 'value', 'Left side is a signal, prop must be value');
|
|
2058
2097
|
}
|
|
2059
|
-
if (obj instanceof WrappedSignalImpl && obj.flags &
|
|
2098
|
+
if (obj instanceof WrappedSignalImpl && obj.flags & 4 /* WrappedSignalFlags.UNWRAP */) {
|
|
2060
2099
|
return obj;
|
|
2061
2100
|
}
|
|
2062
2101
|
return getWrapped(args);
|
|
@@ -2117,7 +2156,7 @@
|
|
|
2117
2156
|
return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
|
|
2118
2157
|
}
|
|
2119
2158
|
/** @internal */
|
|
2120
|
-
const _restProps = (props, omit, target = {}) => {
|
|
2159
|
+
const _restProps = (props, omit = [], target = {}) => {
|
|
2121
2160
|
let constPropsTarget = null;
|
|
2122
2161
|
const constProps = props[_CONST_PROPS];
|
|
2123
2162
|
if (constProps) {
|
|
@@ -2572,12 +2611,12 @@
|
|
|
2572
2611
|
}
|
|
2573
2612
|
if (targetElement) {
|
|
2574
2613
|
if (targetElement.type === 'script' && key === qVisibleEvent) {
|
|
2575
|
-
eventKey = 'document:
|
|
2614
|
+
eventKey = 'document:onQInit$';
|
|
2576
2615
|
logWarn('You are trying to add an event "' +
|
|
2577
2616
|
key +
|
|
2578
2617
|
'" using `useVisibleTask$` hook, ' +
|
|
2579
2618
|
'but a node to which you can add an event is not found. ' +
|
|
2580
|
-
'Using document:
|
|
2619
|
+
'Using document:onQInit$ instead.');
|
|
2581
2620
|
}
|
|
2582
2621
|
addUseOnEvent(targetElement, eventKey, useOnEvents[key]);
|
|
2583
2622
|
}
|
|
@@ -2700,13 +2739,13 @@
|
|
|
2700
2739
|
if (srcProps && srcProps.children) {
|
|
2701
2740
|
delete srcProps.children;
|
|
2702
2741
|
}
|
|
2703
|
-
const scheduler = ssr.$scheduler$;
|
|
2704
2742
|
host.setProp(OnRenderProp, componentQrl);
|
|
2705
2743
|
host.setProp(ELEMENT_PROPS, srcProps);
|
|
2706
2744
|
if (jsx.key !== null) {
|
|
2707
2745
|
host.setProp(ELEMENT_KEY, jsx.key);
|
|
2708
2746
|
}
|
|
2709
|
-
|
|
2747
|
+
const componentChore = ssr.$scheduler$(6 /* ChoreType.COMPONENT */, host, componentQrl, srcProps);
|
|
2748
|
+
return getChorePromise(componentChore);
|
|
2710
2749
|
};
|
|
2711
2750
|
|
|
2712
2751
|
class ParentComponentData {
|
|
@@ -2814,7 +2853,14 @@
|
|
|
2814
2853
|
appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue);
|
|
2815
2854
|
}
|
|
2816
2855
|
}
|
|
2817
|
-
const innerHTML = ssr.openElement(type, varPropsToSsrAttrs(jsx.varProps, jsx.constProps,
|
|
2856
|
+
const innerHTML = ssr.openElement(type, varPropsToSsrAttrs(jsx.varProps, jsx.constProps, {
|
|
2857
|
+
serializationCtx: ssr.serializationCtx,
|
|
2858
|
+
styleScopedId: options.styleScoped,
|
|
2859
|
+
key: jsx.key,
|
|
2860
|
+
}), constPropsToSsrAttrs(jsx.constProps, jsx.varProps, {
|
|
2861
|
+
serializationCtx: ssr.serializationCtx,
|
|
2862
|
+
styleScopedId: options.styleScoped,
|
|
2863
|
+
}), qwikInspectorAttrValue);
|
|
2818
2864
|
if (innerHTML) {
|
|
2819
2865
|
ssr.htmlNode(innerHTML);
|
|
2820
2866
|
}
|
|
@@ -2930,16 +2976,17 @@
|
|
|
2930
2976
|
}
|
|
2931
2977
|
}
|
|
2932
2978
|
}
|
|
2933
|
-
function varPropsToSsrAttrs(varProps, constProps,
|
|
2934
|
-
return toSsrAttrs(varProps, constProps,
|
|
2979
|
+
function varPropsToSsrAttrs(varProps, constProps, options) {
|
|
2980
|
+
return toSsrAttrs(varProps, constProps, false, options);
|
|
2935
2981
|
}
|
|
2936
|
-
function constPropsToSsrAttrs(constProps, varProps,
|
|
2937
|
-
return toSsrAttrs(constProps, varProps,
|
|
2982
|
+
function constPropsToSsrAttrs(constProps, varProps, options) {
|
|
2983
|
+
return toSsrAttrs(constProps, varProps, true, options);
|
|
2938
2984
|
}
|
|
2939
|
-
function toSsrAttrs(record, anotherRecord,
|
|
2985
|
+
function toSsrAttrs(record, anotherRecord, isConst, options) {
|
|
2940
2986
|
if (record == null) {
|
|
2941
2987
|
return null;
|
|
2942
2988
|
}
|
|
2989
|
+
const pushMergedEventProps = !isConst;
|
|
2943
2990
|
const ssrAttrs = [];
|
|
2944
2991
|
for (const key in record) {
|
|
2945
2992
|
let value = record[key];
|
|
@@ -2976,7 +3023,7 @@
|
|
|
2976
3023
|
}
|
|
2977
3024
|
}
|
|
2978
3025
|
}
|
|
2979
|
-
const eventValue = setEvent(serializationCtx, key, value);
|
|
3026
|
+
const eventValue = setEvent(options.serializationCtx, key, value);
|
|
2980
3027
|
if (eventValue) {
|
|
2981
3028
|
ssrAttrs.push(jsxEventToHtmlAttribute(key), eventValue);
|
|
2982
3029
|
}
|
|
@@ -2986,7 +3033,7 @@
|
|
|
2986
3033
|
// write signal as is. We will track this signal inside `writeAttrs`
|
|
2987
3034
|
if (isClassAttr(key)) {
|
|
2988
3035
|
// additionally append styleScopedId for class attr
|
|
2989
|
-
ssrAttrs.push(key, [value, styleScopedId]);
|
|
3036
|
+
ssrAttrs.push(key, [value, options.styleScopedId]);
|
|
2990
3037
|
}
|
|
2991
3038
|
else {
|
|
2992
3039
|
ssrAttrs.push(key, value);
|
|
@@ -2994,13 +3041,13 @@
|
|
|
2994
3041
|
continue;
|
|
2995
3042
|
}
|
|
2996
3043
|
if (isPreventDefault(key)) {
|
|
2997
|
-
addPreventDefaultEventToSerializationContext(serializationCtx, key);
|
|
3044
|
+
addPreventDefaultEventToSerializationContext(options.serializationCtx, key);
|
|
2998
3045
|
}
|
|
2999
|
-
value = serializeAttribute(key, value, styleScopedId);
|
|
3046
|
+
value = serializeAttribute(key, value, options.styleScopedId);
|
|
3000
3047
|
ssrAttrs.push(key, value);
|
|
3001
3048
|
}
|
|
3002
|
-
if (key != null) {
|
|
3003
|
-
ssrAttrs.push(ELEMENT_KEY, key);
|
|
3049
|
+
if (options.key != null) {
|
|
3050
|
+
ssrAttrs.push(ELEMENT_KEY, options.key);
|
|
3004
3051
|
}
|
|
3005
3052
|
return ssrAttrs;
|
|
3006
3053
|
}
|
|
@@ -3049,7 +3096,7 @@
|
|
|
3049
3096
|
* For internal qrls (starting with `_`) we assume that they do the right thing.
|
|
3050
3097
|
*/
|
|
3051
3098
|
if (!qrl.$symbol$.startsWith('_') && (qrl.$captureRef$ || qrl.$capture$)) {
|
|
3052
|
-
qrl = createQRL(null, '_run',
|
|
3099
|
+
qrl = createQRL(null, '_run', _run, null, null, [qrl]);
|
|
3053
3100
|
}
|
|
3054
3101
|
return qrlToString(serializationCtx, qrl);
|
|
3055
3102
|
};
|
|
@@ -3129,10 +3176,9 @@
|
|
|
3129
3176
|
// deleted and we need to be able to release the task subscriptions.
|
|
3130
3177
|
set(task);
|
|
3131
3178
|
const container = iCtx.$container$;
|
|
3132
|
-
const
|
|
3133
|
-
if (isPromise(
|
|
3134
|
-
|
|
3135
|
-
promise.catch(() => { });
|
|
3179
|
+
const result = runTask(task, container, iCtx.$hostElement$);
|
|
3180
|
+
if (isPromise(result)) {
|
|
3181
|
+
throw result;
|
|
3136
3182
|
}
|
|
3137
3183
|
};
|
|
3138
3184
|
const runTask = (task, container, host) => {
|
|
@@ -3144,7 +3190,7 @@
|
|
|
3144
3190
|
const track = trackFn(task, container);
|
|
3145
3191
|
const [cleanup] = cleanupFn(task, (reason) => container.handleError(reason, host));
|
|
3146
3192
|
const taskApi = { track, cleanup };
|
|
3147
|
-
|
|
3193
|
+
return safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
3148
3194
|
// If a Promise is thrown, that means we need to re-run the task.
|
|
3149
3195
|
if (isPromise(err)) {
|
|
3150
3196
|
return err.then(() => runTask(task, container, host));
|
|
@@ -3153,7 +3199,6 @@
|
|
|
3153
3199
|
throw err;
|
|
3154
3200
|
}
|
|
3155
3201
|
});
|
|
3156
|
-
return result;
|
|
3157
3202
|
};
|
|
3158
3203
|
const cleanupTask = (task) => {
|
|
3159
3204
|
const destroy = task.$destroy$;
|
|
@@ -3195,7 +3240,7 @@
|
|
|
3195
3240
|
*/
|
|
3196
3241
|
const scheduleTask = (_event, element) => {
|
|
3197
3242
|
const [task] = useLexicalScope();
|
|
3198
|
-
const type = task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */ ?
|
|
3243
|
+
const type = task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */ ? 16 /* ChoreType.VISIBLE */ : 3 /* ChoreType.TASK */;
|
|
3199
3244
|
const container = getDomContainer(element);
|
|
3200
3245
|
container.$scheduler$(type, task);
|
|
3201
3246
|
};
|
|
@@ -3447,7 +3492,7 @@
|
|
|
3447
3492
|
? this.$constProps$[prop]
|
|
3448
3493
|
: this.$varProps$[prop];
|
|
3449
3494
|
// a proxied value that the optimizer made
|
|
3450
|
-
return value instanceof WrappedSignalImpl && value.$flags$ &
|
|
3495
|
+
return value instanceof WrappedSignalImpl && value.$flags$ & 4 /* WrappedSignalFlags.UNWRAP */
|
|
3451
3496
|
? value.value
|
|
3452
3497
|
: value;
|
|
3453
3498
|
}
|
|
@@ -3861,6 +3906,10 @@
|
|
|
3861
3906
|
vNewNode = null;
|
|
3862
3907
|
vCurrent = vnode_getFirstChild(vStartNode);
|
|
3863
3908
|
stackPush(jsxNode, true);
|
|
3909
|
+
if (vParent[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */) {
|
|
3910
|
+
// Ignore diff if the parent is deleted.
|
|
3911
|
+
return;
|
|
3912
|
+
}
|
|
3864
3913
|
while (stack.length) {
|
|
3865
3914
|
while (jsxIdx < jsxCount) {
|
|
3866
3915
|
assertFalse(vParent === vCurrent, "Parent and current can't be the same");
|
|
@@ -4393,8 +4442,13 @@
|
|
|
4393
4442
|
let returnValue = false;
|
|
4394
4443
|
qrls.flat(2).forEach((qrl) => {
|
|
4395
4444
|
if (qrl) {
|
|
4396
|
-
|
|
4397
|
-
|
|
4445
|
+
if (isSyncQrl(qrl)) {
|
|
4446
|
+
qrl(event, element);
|
|
4447
|
+
}
|
|
4448
|
+
else {
|
|
4449
|
+
const value = container.$scheduler$(2 /* ChoreType.RUN_QRL */, vNode, qrl, [event, element]);
|
|
4450
|
+
returnValue = returnValue || value === true;
|
|
4451
|
+
}
|
|
4398
4452
|
}
|
|
4399
4453
|
});
|
|
4400
4454
|
return returnValue;
|
|
@@ -4896,7 +4950,7 @@
|
|
|
4896
4950
|
const task = obj;
|
|
4897
4951
|
clearAllEffects(container, task);
|
|
4898
4952
|
if (task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
|
|
4899
|
-
container.$scheduler$(
|
|
4953
|
+
container.$scheduler$(32 /* ChoreType.CLEANUP_VISIBLE */, task);
|
|
4900
4954
|
}
|
|
4901
4955
|
else {
|
|
4902
4956
|
cleanupTask(task);
|
|
@@ -4947,7 +5001,16 @@
|
|
|
4947
5001
|
*/
|
|
4948
5002
|
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
4949
5003
|
if (vFirstChild) {
|
|
4950
|
-
vnode_walkVNode(vFirstChild)
|
|
5004
|
+
vnode_walkVNode(vFirstChild, (vNode) => {
|
|
5005
|
+
/**
|
|
5006
|
+
* Instead of an ID, we store a direct reference to the VNode. This is necessary to
|
|
5007
|
+
* locate the slot's parent in a detached subtree, as the ID would become invalid.
|
|
5008
|
+
*/
|
|
5009
|
+
if (vNode[0 /* VNodeProps.flags */] & 2 /* VNodeFlags.Virtual */) {
|
|
5010
|
+
// The QSlotParent is used to find the slot parent during scheduling
|
|
5011
|
+
vnode_getProp(vNode, QSlotParent, (id) => vnode_locate(container.rootVNode, id));
|
|
5012
|
+
}
|
|
5013
|
+
});
|
|
4951
5014
|
return;
|
|
4952
5015
|
}
|
|
4953
5016
|
}
|
|
@@ -5024,8 +5087,8 @@
|
|
|
5024
5087
|
const resource = createResourceReturn(container, opts);
|
|
5025
5088
|
const el = iCtx.$hostElement$;
|
|
5026
5089
|
const task = new Task(8 /* TaskFlags.DIRTY */ | 4 /* TaskFlags.RESOURCE */, i, el, qrl, resource, null);
|
|
5027
|
-
container.$scheduler$(3 /* ChoreType.TASK */, task);
|
|
5028
5090
|
set(resource);
|
|
5091
|
+
runResource(task, container, el);
|
|
5029
5092
|
return resource;
|
|
5030
5093
|
};
|
|
5031
5094
|
// <docs markdown="../readme.md#useResource">
|
|
@@ -5093,10 +5156,10 @@
|
|
|
5093
5156
|
function getResourceValueAsPromise(props) {
|
|
5094
5157
|
const resource = props.value;
|
|
5095
5158
|
if (isResourceReturn(resource)) {
|
|
5159
|
+
// create a subscription for the resource._state changes
|
|
5160
|
+
const state = resource._state;
|
|
5096
5161
|
const isBrowser = !isServerPlatform();
|
|
5097
5162
|
if (isBrowser) {
|
|
5098
|
-
// create a subscription for the resource._state changes
|
|
5099
|
-
const state = resource._state;
|
|
5100
5163
|
if (state === 'pending' && props.onPending) {
|
|
5101
5164
|
return Promise.resolve().then(useBindInvokeContext(props.onPending));
|
|
5102
5165
|
}
|
|
@@ -5111,14 +5174,7 @@
|
|
|
5111
5174
|
}
|
|
5112
5175
|
}
|
|
5113
5176
|
}
|
|
5114
|
-
|
|
5115
|
-
if (value) {
|
|
5116
|
-
return value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
5117
|
-
}
|
|
5118
|
-
else {
|
|
5119
|
-
// this is temporary value until the `runResource` is executed and promise is assigned to the value
|
|
5120
|
-
return Promise.resolve(undefined);
|
|
5121
|
-
}
|
|
5177
|
+
return untrack(() => resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
5122
5178
|
}
|
|
5123
5179
|
else if (isPromise(resource)) {
|
|
5124
5180
|
return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
@@ -5136,7 +5192,7 @@
|
|
|
5136
5192
|
const resource = {
|
|
5137
5193
|
__brand: 'resource',
|
|
5138
5194
|
value: undefined,
|
|
5139
|
-
loading: isServerPlatform()
|
|
5195
|
+
loading: !isServerPlatform(),
|
|
5140
5196
|
_resolved: undefined,
|
|
5141
5197
|
_error: undefined,
|
|
5142
5198
|
_state: 'pending',
|
|
@@ -5187,19 +5243,22 @@
|
|
|
5187
5243
|
done = true;
|
|
5188
5244
|
if (resolved) {
|
|
5189
5245
|
done = true;
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5246
|
+
resourceTarget.loading = false;
|
|
5247
|
+
resourceTarget._state = 'resolved';
|
|
5248
|
+
resourceTarget._resolved = value;
|
|
5249
|
+
resourceTarget._error = undefined;
|
|
5194
5250
|
resolve(value);
|
|
5195
5251
|
}
|
|
5196
5252
|
else {
|
|
5197
5253
|
done = true;
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5254
|
+
resourceTarget.loading = false;
|
|
5255
|
+
resourceTarget._state = 'rejected';
|
|
5256
|
+
resourceTarget._error = value;
|
|
5201
5257
|
reject(value);
|
|
5202
5258
|
}
|
|
5259
|
+
if (!isServerPlatform()) {
|
|
5260
|
+
forceStoreEffects(resource, '_state');
|
|
5261
|
+
}
|
|
5203
5262
|
return true;
|
|
5204
5263
|
}
|
|
5205
5264
|
return false;
|
|
@@ -5215,17 +5274,17 @@
|
|
|
5215
5274
|
}
|
|
5216
5275
|
});
|
|
5217
5276
|
// Execute mutation inside empty invocation
|
|
5277
|
+
// TODO: is it right? why we need to invoke inside context and trigger effects?
|
|
5218
5278
|
invoke(iCtx, () => {
|
|
5219
5279
|
// console.log('RESOURCE.pending: ');
|
|
5220
5280
|
resource._state = 'pending';
|
|
5221
5281
|
resource.loading = !isServerPlatform();
|
|
5222
|
-
|
|
5282
|
+
resource.value = new Promise((r, re) => {
|
|
5223
5283
|
resolve = r;
|
|
5224
5284
|
reject = re;
|
|
5225
|
-
})
|
|
5226
|
-
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
5285
|
+
});
|
|
5227
5286
|
});
|
|
5228
|
-
const promise = safeCall(() =>
|
|
5287
|
+
const promise = safeCall(() => taskFn(opts), (value) => {
|
|
5229
5288
|
setState(true, value);
|
|
5230
5289
|
}, (err) => {
|
|
5231
5290
|
if (isPromise(err)) {
|
|
@@ -5248,10 +5307,6 @@
|
|
|
5248
5307
|
}
|
|
5249
5308
|
return promise;
|
|
5250
5309
|
};
|
|
5251
|
-
const ignoreErrorToPreventNodeFromCrashing = (err) => {
|
|
5252
|
-
// ignore error to prevent node from crashing
|
|
5253
|
-
// node will crash in promise is rejected and no one is listening to the rejection.
|
|
5254
|
-
};
|
|
5255
5310
|
|
|
5256
5311
|
/// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
|
|
5257
5312
|
const aVNodePath = [];
|
|
@@ -5334,11 +5389,11 @@
|
|
|
5334
5389
|
let bDepth = -1;
|
|
5335
5390
|
while (a) {
|
|
5336
5391
|
const ssrNode = (aSsrNodePath[++aDepth] = a);
|
|
5337
|
-
a = ssrNode.
|
|
5392
|
+
a = ssrNode.parentComponent;
|
|
5338
5393
|
}
|
|
5339
5394
|
while (b) {
|
|
5340
5395
|
const ssrNode = (bSsrNodePath[++bDepth] = b);
|
|
5341
|
-
b = ssrNode.
|
|
5396
|
+
b = ssrNode.parentComponent;
|
|
5342
5397
|
}
|
|
5343
5398
|
while (aDepth >= 0 && bDepth >= 0) {
|
|
5344
5399
|
a = aSsrNodePath[aDepth];
|
|
@@ -5355,6 +5410,210 @@
|
|
|
5355
5410
|
return aDepth < bDepth ? -1 : 1;
|
|
5356
5411
|
};
|
|
5357
5412
|
|
|
5413
|
+
/**
|
|
5414
|
+
* Rules for determining if a chore is blocked by another chore. Some chores can block other chores.
|
|
5415
|
+
* They cannot run until the blocking chore has completed.
|
|
5416
|
+
*
|
|
5417
|
+
* The match function is used to determine if the blocked chore is blocked by the blocking chore.
|
|
5418
|
+
* The match function is called with the blocked chore, the blocking chore, and the container.
|
|
5419
|
+
*/
|
|
5420
|
+
const VISIBLE_BLOCKING_RULES = [
|
|
5421
|
+
// NODE_DIFF blocks VISIBLE on same host,
|
|
5422
|
+
// if the blocked chore is a child of the blocking chore
|
|
5423
|
+
// or the blocked chore is a sibling of the blocking chore
|
|
5424
|
+
{
|
|
5425
|
+
blockedType: 16 /* ChoreType.VISIBLE */,
|
|
5426
|
+
blockingType: 4 /* ChoreType.NODE_DIFF */,
|
|
5427
|
+
match: (blocked, blocking, container) => isDescendant(blocked, blocking, container) || isDescendant(blocking, blocked, container),
|
|
5428
|
+
},
|
|
5429
|
+
// COMPONENT blocks VISIBLE on same host
|
|
5430
|
+
// if the blocked chore is a child of the blocking chore
|
|
5431
|
+
// or the blocked chore is a sibling of the blocking chore
|
|
5432
|
+
{
|
|
5433
|
+
blockedType: 16 /* ChoreType.VISIBLE */,
|
|
5434
|
+
blockingType: 6 /* ChoreType.COMPONENT */,
|
|
5435
|
+
match: (blocked, blocking, container) => isDescendant(blocked, blocking, container) || isDescendant(blocking, blocked, container),
|
|
5436
|
+
},
|
|
5437
|
+
];
|
|
5438
|
+
const BLOCKING_RULES = [
|
|
5439
|
+
// QRL_RESOLVE blocks RUN_QRL, TASK, VISIBLE on same host
|
|
5440
|
+
{
|
|
5441
|
+
blockedType: 2 /* ChoreType.RUN_QRL */,
|
|
5442
|
+
blockingType: 1 /* ChoreType.QRL_RESOLVE */,
|
|
5443
|
+
match: (blocked, blocking) => {
|
|
5444
|
+
const blockedQrl = blocked.$target$;
|
|
5445
|
+
const blockingQrl = blocking.$target$;
|
|
5446
|
+
return isSameHost(blocked, blocking) && isSameQrl(blockedQrl, blockingQrl);
|
|
5447
|
+
},
|
|
5448
|
+
},
|
|
5449
|
+
{
|
|
5450
|
+
blockedType: 3 /* ChoreType.TASK */,
|
|
5451
|
+
blockingType: 1 /* ChoreType.QRL_RESOLVE */,
|
|
5452
|
+
match: (blocked, blocking) => {
|
|
5453
|
+
const blockedTask = blocked.$payload$;
|
|
5454
|
+
const blockingQrl = blocking.$target$;
|
|
5455
|
+
return isSameHost(blocked, blocking) && isSameQrl(blockedTask.$qrl$, blockingQrl);
|
|
5456
|
+
},
|
|
5457
|
+
},
|
|
5458
|
+
{
|
|
5459
|
+
blockedType: 16 /* ChoreType.VISIBLE */,
|
|
5460
|
+
blockingType: 1 /* ChoreType.QRL_RESOLVE */,
|
|
5461
|
+
match: (blocked, blocking) => {
|
|
5462
|
+
const blockedTask = blocked.$payload$;
|
|
5463
|
+
const blockingQrl = blocking.$target$;
|
|
5464
|
+
return isSameHost(blocked, blocking) && isSameQrl(blockedTask.$qrl$, blockingQrl);
|
|
5465
|
+
},
|
|
5466
|
+
},
|
|
5467
|
+
// COMPONENT blocks NODE_DIFF, NODE_PROP on same host
|
|
5468
|
+
{
|
|
5469
|
+
blockedType: 4 /* ChoreType.NODE_DIFF */,
|
|
5470
|
+
blockingType: 6 /* ChoreType.COMPONENT */,
|
|
5471
|
+
match: (blocked, blocking) => blocked.$host$ === blocking.$host$,
|
|
5472
|
+
},
|
|
5473
|
+
{
|
|
5474
|
+
blockedType: 5 /* ChoreType.NODE_PROP */,
|
|
5475
|
+
blockingType: 6 /* ChoreType.COMPONENT */,
|
|
5476
|
+
match: (blocked, blocking) => blocked.$host$ === blocking.$host$,
|
|
5477
|
+
},
|
|
5478
|
+
...VISIBLE_BLOCKING_RULES,
|
|
5479
|
+
// TASK blocks subsequent TASKs in the same component
|
|
5480
|
+
{
|
|
5481
|
+
blockedType: 3 /* ChoreType.TASK */,
|
|
5482
|
+
blockingType: 3 /* ChoreType.TASK */,
|
|
5483
|
+
match: (blocked, blocking, container) => {
|
|
5484
|
+
if (blocked.$host$ !== blocking.$host$) {
|
|
5485
|
+
return false;
|
|
5486
|
+
}
|
|
5487
|
+
const blockedIdx = blocked.$idx$;
|
|
5488
|
+
if (!isNumber$1(blockedIdx) || blockedIdx <= 0) {
|
|
5489
|
+
return false;
|
|
5490
|
+
}
|
|
5491
|
+
const previousTask = findPreviousTaskInComponent(blocked.$host$, blockedIdx, container);
|
|
5492
|
+
return previousTask === blocking.$payload$;
|
|
5493
|
+
},
|
|
5494
|
+
},
|
|
5495
|
+
];
|
|
5496
|
+
function isDescendant(descendantChore, ancestorChore, container) {
|
|
5497
|
+
const descendantHost = descendantChore.$host$;
|
|
5498
|
+
const ancestorHost = ancestorChore.$host$;
|
|
5499
|
+
if (!vnode_isVNode(descendantHost) || !vnode_isVNode(ancestorHost)) {
|
|
5500
|
+
return false;
|
|
5501
|
+
}
|
|
5502
|
+
return vnode_isDescendantOf(descendantHost, ancestorHost, container.rootVNode);
|
|
5503
|
+
}
|
|
5504
|
+
function isSameHost(a, b) {
|
|
5505
|
+
return a.$host$ === b.$host$;
|
|
5506
|
+
}
|
|
5507
|
+
function isSameQrl(a, b) {
|
|
5508
|
+
return a.$symbol$ === b.$symbol$;
|
|
5509
|
+
}
|
|
5510
|
+
function findBlockingChoreInQueue(chore, choreQueue, container) {
|
|
5511
|
+
for (const candidate of choreQueue) {
|
|
5512
|
+
// everything after VISIBLE is not blocking. Visible task, task and resource should not block anything in this rule.
|
|
5513
|
+
if (candidate.$type$ >= 16 /* ChoreType.VISIBLE */ || candidate.$type$ === 3 /* ChoreType.TASK */) {
|
|
5514
|
+
continue;
|
|
5515
|
+
}
|
|
5516
|
+
if (isDescendant(chore, candidate, container)) {
|
|
5517
|
+
return candidate;
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
return null;
|
|
5521
|
+
}
|
|
5522
|
+
function findBlockingChore(chore, choreQueue, blockedChores, runningChores, container) {
|
|
5523
|
+
const blockingChoreInChoreQueue = findBlockingChoreInQueue(chore, choreQueue, container);
|
|
5524
|
+
if (blockingChoreInChoreQueue) {
|
|
5525
|
+
return blockingChoreInChoreQueue;
|
|
5526
|
+
}
|
|
5527
|
+
const blockingChoreInBlockedChores = findBlockingChoreInQueue(chore, Array.from(blockedChores), container);
|
|
5528
|
+
if (blockingChoreInBlockedChores) {
|
|
5529
|
+
return blockingChoreInBlockedChores;
|
|
5530
|
+
}
|
|
5531
|
+
const blockingChoreInRunningChores = findBlockingChoreInQueue(chore, Array.from(runningChores), container);
|
|
5532
|
+
if (blockingChoreInRunningChores) {
|
|
5533
|
+
return blockingChoreInRunningChores;
|
|
5534
|
+
}
|
|
5535
|
+
for (const rule of BLOCKING_RULES) {
|
|
5536
|
+
if (chore.$type$ !== rule.blockedType) {
|
|
5537
|
+
continue;
|
|
5538
|
+
}
|
|
5539
|
+
// Check in choreQueue
|
|
5540
|
+
// TODO(perf): better to iterate in reverse order?
|
|
5541
|
+
for (const candidate of choreQueue) {
|
|
5542
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5543
|
+
return candidate;
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
// Check in blockedChores
|
|
5547
|
+
for (const candidate of blockedChores) {
|
|
5548
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5549
|
+
return candidate;
|
|
5550
|
+
}
|
|
5551
|
+
}
|
|
5552
|
+
// Check in runningChores
|
|
5553
|
+
for (const candidate of runningChores) {
|
|
5554
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5555
|
+
return candidate;
|
|
5556
|
+
}
|
|
5557
|
+
}
|
|
5558
|
+
}
|
|
5559
|
+
return null;
|
|
5560
|
+
}
|
|
5561
|
+
function findPreviousTaskInComponent(host, currentTaskIdx, container) {
|
|
5562
|
+
const elementSeq = container.getHostProp(host, ELEMENT_SEQ);
|
|
5563
|
+
if (!elementSeq || elementSeq.length <= currentTaskIdx) {
|
|
5564
|
+
return null;
|
|
5565
|
+
}
|
|
5566
|
+
for (let i = currentTaskIdx - 1; i >= 0; i--) {
|
|
5567
|
+
const candidate = elementSeq[i];
|
|
5568
|
+
if (candidate instanceof Task && candidate.$flags$ & 2 /* TaskFlags.TASK */) {
|
|
5569
|
+
return candidate;
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5572
|
+
return null;
|
|
5573
|
+
}
|
|
5574
|
+
function findBlockingChoreForVisible(chore, runningChores, container) {
|
|
5575
|
+
for (const rule of VISIBLE_BLOCKING_RULES) {
|
|
5576
|
+
if (chore.$type$ !== rule.blockedType) {
|
|
5577
|
+
continue;
|
|
5578
|
+
}
|
|
5579
|
+
for (const candidate of runningChores) {
|
|
5580
|
+
if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
|
|
5581
|
+
return candidate;
|
|
5582
|
+
}
|
|
5583
|
+
}
|
|
5584
|
+
}
|
|
5585
|
+
return null;
|
|
5586
|
+
}
|
|
5587
|
+
|
|
5588
|
+
// This can't be in platform.ts because it uses MessageChannel which cannot post messages with functions
|
|
5589
|
+
// TODO: move this to platform.ts somehow
|
|
5590
|
+
const createNextTick = (fn) => {
|
|
5591
|
+
let nextTick;
|
|
5592
|
+
// according to the https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate#notes
|
|
5593
|
+
if (typeof setImmediate === 'function') {
|
|
5594
|
+
// setImmediate is the fastest way to schedule a task, but works only in node.js
|
|
5595
|
+
nextTick = () => {
|
|
5596
|
+
setImmediate(fn);
|
|
5597
|
+
};
|
|
5598
|
+
}
|
|
5599
|
+
else if (typeof MessageChannel !== 'undefined') {
|
|
5600
|
+
const channel = new MessageChannel();
|
|
5601
|
+
channel.port1.onmessage = () => {
|
|
5602
|
+
fn();
|
|
5603
|
+
};
|
|
5604
|
+
nextTick = () => {
|
|
5605
|
+
channel.port2.postMessage(null);
|
|
5606
|
+
};
|
|
5607
|
+
}
|
|
5608
|
+
else {
|
|
5609
|
+
// setTimeout is a fallback, creates 4ms delay
|
|
5610
|
+
nextTick = () => {
|
|
5611
|
+
setTimeout(fn);
|
|
5612
|
+
};
|
|
5613
|
+
}
|
|
5614
|
+
return nextTick;
|
|
5615
|
+
};
|
|
5616
|
+
|
|
5358
5617
|
/**
|
|
5359
5618
|
* Scheduler is responsible for running application code in predictable order.
|
|
5360
5619
|
*
|
|
@@ -5438,29 +5697,43 @@
|
|
|
5438
5697
|
*/
|
|
5439
5698
|
// Turn this on to get debug output of what the scheduler is doing.
|
|
5440
5699
|
const DEBUG = false;
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5700
|
+
var ChoreState;
|
|
5701
|
+
(function (ChoreState) {
|
|
5702
|
+
ChoreState[ChoreState["NONE"] = 0] = "NONE";
|
|
5703
|
+
ChoreState[ChoreState["RUNNING"] = 1] = "RUNNING";
|
|
5704
|
+
ChoreState[ChoreState["FAILED"] = 2] = "FAILED";
|
|
5705
|
+
ChoreState[ChoreState["DONE"] = 3] = "DONE";
|
|
5706
|
+
})(ChoreState || (ChoreState = {}));
|
|
5707
|
+
const getChorePromise = (chore) => chore.$state$ === ChoreState.NONE
|
|
5708
|
+
? (chore.$returnValue$ ||= new Promise((resolve, reject) => {
|
|
5709
|
+
chore.$resolve$ = resolve;
|
|
5710
|
+
chore.$reject$ = reject;
|
|
5711
|
+
}))
|
|
5712
|
+
: chore.$returnValue$;
|
|
5713
|
+
const createScheduler = (container, journalFlush, choreQueue = [], blockedChores = new Set(), runningChores = new Set()) => {
|
|
5714
|
+
let drainChore = null;
|
|
5448
5715
|
let drainScheduled = false;
|
|
5716
|
+
let isDraining = false;
|
|
5717
|
+
let isJournalFlushRunning = false;
|
|
5718
|
+
let flushBudgetStart = 0;
|
|
5719
|
+
let currentTime = performance.now();
|
|
5720
|
+
const nextTick = createNextTick(drainChoreQueue);
|
|
5721
|
+
function drainInNextTick() {
|
|
5722
|
+
if (!drainScheduled) {
|
|
5723
|
+
drainScheduled = true;
|
|
5724
|
+
nextTick();
|
|
5725
|
+
}
|
|
5726
|
+
}
|
|
5727
|
+
// Drain for ~16.67ms, then apply journal flush for ~16.67ms, then repeat
|
|
5728
|
+
// We divide by 60 because we want to run at 60fps
|
|
5729
|
+
const FREQUENCY_MS = Math.floor(1000 / 60);
|
|
5449
5730
|
return schedule;
|
|
5450
5731
|
///// IMPLEMENTATION /////
|
|
5451
5732
|
function schedule(type, hostOrTask = null, targetOrQrl = null, payload = null) {
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
const runLater = type !== 255 /* ChoreType.WAIT_FOR_ALL */ && !isComponentSsr && type !== 2 /* ChoreType.RUN_QRL */;
|
|
5455
|
-
const isTask = type === 3 /* ChoreType.TASK */ || type === 32 /* ChoreType.VISIBLE */ || type === 48 /* ChoreType.CLEANUP_VISIBLE */;
|
|
5456
|
-
const isClientOnly = type === 16 /* ChoreType.JOURNAL_FLUSH */ ||
|
|
5457
|
-
type === 4 /* ChoreType.NODE_DIFF */ ||
|
|
5458
|
-
type === 5 /* ChoreType.NODE_PROP */ ||
|
|
5459
|
-
type === 1 /* ChoreType.QRL_RESOLVE */ ||
|
|
5460
|
-
type === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */;
|
|
5461
|
-
if (isServer && isClientOnly) {
|
|
5462
|
-
return;
|
|
5733
|
+
if (type === 255 /* ChoreType.WAIT_FOR_QUEUE */ && drainChore) {
|
|
5734
|
+
return drainChore;
|
|
5463
5735
|
}
|
|
5736
|
+
const isTask = type === 3 /* ChoreType.TASK */ || type === 16 /* ChoreType.VISIBLE */ || type === 32 /* ChoreType.CLEANUP_VISIBLE */;
|
|
5464
5737
|
if (isTask) {
|
|
5465
5738
|
hostOrTask.$flags$ |= 8 /* TaskFlags.DIRTY */;
|
|
5466
5739
|
}
|
|
@@ -5474,167 +5747,310 @@
|
|
|
5474
5747
|
$host$: isTask ? hostOrTask.$el$ : hostOrTask,
|
|
5475
5748
|
$target$: targetOrQrl,
|
|
5476
5749
|
$payload$: isTask ? hostOrTask : payload,
|
|
5477
|
-
$
|
|
5478
|
-
$
|
|
5750
|
+
$state$: ChoreState.NONE,
|
|
5751
|
+
$blockedChores$: null,
|
|
5752
|
+
$startTime$: undefined,
|
|
5753
|
+
$endTime$: undefined,
|
|
5754
|
+
$resolve$: undefined,
|
|
5755
|
+
$reject$: undefined,
|
|
5479
5756
|
$returnValue$: null,
|
|
5480
|
-
$executed$: false,
|
|
5481
5757
|
};
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5758
|
+
if (type === 255 /* ChoreType.WAIT_FOR_QUEUE */) {
|
|
5759
|
+
getChorePromise(chore);
|
|
5760
|
+
drainChore = chore;
|
|
5761
|
+
drainInNextTick();
|
|
5762
|
+
return chore;
|
|
5763
|
+
}
|
|
5764
|
+
const isServer = isServerPlatform();
|
|
5765
|
+
const isClientOnly = type === 4 /* ChoreType.NODE_DIFF */ || type === 1 /* ChoreType.QRL_RESOLVE */;
|
|
5766
|
+
if (isServer && isClientOnly) {
|
|
5767
|
+
// Mark skipped client-only chores as completed on the server
|
|
5768
|
+
finishChore(chore, undefined);
|
|
5769
|
+
return chore;
|
|
5770
|
+
}
|
|
5771
|
+
if (isServer && chore.$host$ && isSsrNode(chore.$host$)) {
|
|
5772
|
+
const isUpdatable = !!(chore.$host$.flags & 1 /* SsrNodeFlags.Updatable */);
|
|
5773
|
+
if (!isUpdatable) {
|
|
5774
|
+
if (
|
|
5775
|
+
// backpatching exceptions:
|
|
5776
|
+
// - node prop is allowed because it is used to update the node property
|
|
5777
|
+
// - recompute and schedule effects because it triggers effects (so node prop too)
|
|
5778
|
+
chore.$type$ !== 5 /* ChoreType.NODE_PROP */ &&
|
|
5779
|
+
chore.$type$ !== 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */) {
|
|
5780
|
+
// We are running on the server.
|
|
5781
|
+
// On server we can't schedule task for a different host!
|
|
5782
|
+
// Server is SSR, and therefore scheduling for anything but the current host
|
|
5783
|
+
// implies that things need to be re-run and that is not supported because of streaming.
|
|
5784
|
+
const warningMessage = `A '${choreTypeToName(chore.$type$)}' chore was scheduled on a host element that has already been streamed to the client.
|
|
5785
|
+
This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
|
|
5786
|
+
|
|
5787
|
+
Problematic chore:
|
|
5788
|
+
- Type: ${choreTypeToName(chore.$type$)}
|
|
5789
|
+
- Host: ${chore.$host$.toString()}
|
|
5790
|
+
- Nearest element location: ${chore.$host$.currentFile}
|
|
5791
|
+
|
|
5792
|
+
This is often caused by modifying a signal in an already rendered component during SSR.`;
|
|
5793
|
+
logWarn(warningMessage);
|
|
5794
|
+
return chore;
|
|
5795
|
+
}
|
|
5796
|
+
}
|
|
5797
|
+
}
|
|
5798
|
+
const blockingChore = findBlockingChore(chore, choreQueue, blockedChores, runningChores, container);
|
|
5799
|
+
if (blockingChore) {
|
|
5800
|
+
addBlockedChore(chore, blockingChore, blockedChores);
|
|
5801
|
+
return chore;
|
|
5489
5802
|
}
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5803
|
+
chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
|
|
5804
|
+
const runImmediately = (isServer && type === 6 /* ChoreType.COMPONENT */) || type === 2 /* ChoreType.RUN_QRL */;
|
|
5805
|
+
if (runImmediately && !isDraining) {
|
|
5806
|
+
immediateDrain();
|
|
5493
5807
|
}
|
|
5494
5808
|
else {
|
|
5495
|
-
|
|
5496
|
-
}
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
function
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5809
|
+
drainInNextTick();
|
|
5810
|
+
}
|
|
5811
|
+
return chore;
|
|
5812
|
+
}
|
|
5813
|
+
function immediateDrain() {
|
|
5814
|
+
drainScheduled = true;
|
|
5815
|
+
drainChoreQueue();
|
|
5816
|
+
}
|
|
5817
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
5818
|
+
// Drain queue helpers
|
|
5819
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
5820
|
+
function applyJournalFlush() {
|
|
5821
|
+
if (!isJournalFlushRunning) {
|
|
5822
|
+
// prevent multiple journal flushes from running at the same time
|
|
5823
|
+
isJournalFlushRunning = true;
|
|
5824
|
+
journalFlush();
|
|
5825
|
+
isJournalFlushRunning = false;
|
|
5826
|
+
flushBudgetStart = performance.now();
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
function shouldApplyJournalFlush(isServer) {
|
|
5830
|
+
return !isServer && currentTime - flushBudgetStart >= FREQUENCY_MS;
|
|
5831
|
+
}
|
|
5832
|
+
function drainChoreQueue() {
|
|
5833
|
+
const isServer = isServerPlatform();
|
|
5834
|
+
drainScheduled = false;
|
|
5835
|
+
if (isDraining) {
|
|
5836
|
+
return;
|
|
5837
|
+
}
|
|
5838
|
+
// early return if the queue is empty
|
|
5839
|
+
if (!choreQueue.length) {
|
|
5840
|
+
applyJournalFlush();
|
|
5841
|
+
if (drainChore && !runningChores.size) {
|
|
5842
|
+
// resolve drainChore only if there are no running chores, because
|
|
5843
|
+
// we are sure that we are done
|
|
5844
|
+
drainChore.$resolve$(null);
|
|
5845
|
+
drainChore = null;
|
|
5512
5846
|
}
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5847
|
+
return;
|
|
5848
|
+
}
|
|
5849
|
+
isDraining = true;
|
|
5850
|
+
flushBudgetStart = performance.now();
|
|
5851
|
+
const maybeFinishDrain = () => {
|
|
5852
|
+
if (choreQueue.length) {
|
|
5853
|
+
drainInNextTick();
|
|
5854
|
+
return false;
|
|
5855
|
+
}
|
|
5856
|
+
if (drainChore && runningChores.size) {
|
|
5857
|
+
if (shouldApplyJournalFlush(isServer)) {
|
|
5858
|
+
// apply journal flush even if we are not finished draining the queue
|
|
5859
|
+
applyJournalFlush();
|
|
5518
5860
|
}
|
|
5519
|
-
|
|
5861
|
+
return false;
|
|
5520
5862
|
}
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5863
|
+
currentChore = null;
|
|
5864
|
+
applyJournalFlush();
|
|
5865
|
+
drainChore?.$resolve$(null);
|
|
5866
|
+
drainChore = null;
|
|
5867
|
+
return true;
|
|
5868
|
+
};
|
|
5869
|
+
const scheduleBlockedChoresAndDrainIfNeeded = (chore) => {
|
|
5870
|
+
let blockedChoresScheduled = false;
|
|
5871
|
+
if (chore.$blockedChores$) {
|
|
5872
|
+
for (const blockedChore of chore.$blockedChores$) {
|
|
5873
|
+
const blockingChore = findBlockingChore(blockedChore, choreQueue, blockedChores, runningChores, container);
|
|
5874
|
+
if (blockingChore) {
|
|
5875
|
+
addBlockedChore(blockedChore, blockingChore, blockedChores);
|
|
5876
|
+
}
|
|
5877
|
+
else {
|
|
5878
|
+
blockedChores.delete(blockedChore);
|
|
5879
|
+
sortedInsert(choreQueue, blockedChore, container.rootVNode || null);
|
|
5880
|
+
blockedChoresScheduled = true;
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
chore.$blockedChores$ = null;
|
|
5526
5884
|
}
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
const host = chore.$host$;
|
|
5533
|
-
assertEqual(currentChore, null, 'Chore already running.');
|
|
5534
|
-
currentChore = chore;
|
|
5535
|
-
let returnValue = null;
|
|
5885
|
+
if (blockedChoresScheduled && !isDraining) {
|
|
5886
|
+
drainInNextTick();
|
|
5887
|
+
}
|
|
5888
|
+
};
|
|
5889
|
+
let currentChore = null;
|
|
5536
5890
|
try {
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5891
|
+
while (choreQueue.length) {
|
|
5892
|
+
currentTime = performance.now();
|
|
5893
|
+
const chore = (currentChore = choreQueue.shift());
|
|
5894
|
+
if (chore.$state$ !== ChoreState.NONE) {
|
|
5895
|
+
continue;
|
|
5896
|
+
}
|
|
5897
|
+
if (vNodeAlreadyDeleted(chore) &&
|
|
5898
|
+
// we need to process cleanup tasks for deleted nodes
|
|
5899
|
+
chore.$type$ !== 32 /* ChoreType.CLEANUP_VISIBLE */) {
|
|
5900
|
+
// skip deleted chore
|
|
5901
|
+
DEBUG && debugTrace('skip chore', chore, choreQueue, blockedChores);
|
|
5902
|
+
continue;
|
|
5903
|
+
}
|
|
5904
|
+
if (chore.$type$ === 16 /* ChoreType.VISIBLE */) {
|
|
5905
|
+
// ensure that the journal flush is applied before the visible chore is executed
|
|
5906
|
+
// so that the visible chore can see the latest DOM changes
|
|
5907
|
+
applyJournalFlush();
|
|
5908
|
+
const blockingChore = findBlockingChoreForVisible(chore, runningChores, container);
|
|
5909
|
+
if (blockingChore && blockingChore.$state$ === ChoreState.RUNNING) {
|
|
5910
|
+
addBlockedChore(chore, blockingChore, blockedChores);
|
|
5911
|
+
continue;
|
|
5549
5912
|
}
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5913
|
+
}
|
|
5914
|
+
// Note that this never throws
|
|
5915
|
+
chore.$startTime$ = performance.now();
|
|
5916
|
+
const result = executeChore(chore, isServer);
|
|
5917
|
+
chore.$returnValue$ = result;
|
|
5918
|
+
if (isPromise(result)) {
|
|
5919
|
+
runningChores.add(chore);
|
|
5920
|
+
chore.$state$ = ChoreState.RUNNING;
|
|
5921
|
+
result
|
|
5922
|
+
.then((value) => {
|
|
5923
|
+
finishChore(chore, value);
|
|
5924
|
+
})
|
|
5925
|
+
.catch((e) => {
|
|
5926
|
+
if (chore.$state$ !== ChoreState.RUNNING) {
|
|
5927
|
+
// we already handled the error
|
|
5928
|
+
return;
|
|
5929
|
+
}
|
|
5930
|
+
handleError(chore, e);
|
|
5931
|
+
})
|
|
5932
|
+
.finally(() => {
|
|
5933
|
+
runningChores.delete(chore);
|
|
5934
|
+
// Note that we ignore failed chores so the app keeps working
|
|
5935
|
+
// TODO decide if this is ok and document it
|
|
5936
|
+
scheduleBlockedChoresAndDrainIfNeeded(chore);
|
|
5937
|
+
// If drainChore is not null, we are waiting for it to finish.
|
|
5938
|
+
// If there are no running chores, we can finish the drain.
|
|
5939
|
+
if (!runningChores.size) {
|
|
5940
|
+
let finished = false;
|
|
5941
|
+
if (drainChore) {
|
|
5942
|
+
finished = maybeFinishDrain();
|
|
5556
5943
|
}
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5944
|
+
if (!finished && !isDraining) {
|
|
5945
|
+
// if finished, then journal flush is already applied
|
|
5946
|
+
applyJournalFlush();
|
|
5560
5947
|
}
|
|
5561
|
-
}, (err) => container.handleError(err, host));
|
|
5562
|
-
}
|
|
5563
|
-
break;
|
|
5564
|
-
case 2 /* ChoreType.RUN_QRL */:
|
|
5565
|
-
{
|
|
5566
|
-
const fn = chore.$target$.getFn();
|
|
5567
|
-
const result = retryOnPromise(() => fn(...chore.$payload$));
|
|
5568
|
-
if (isPromise(result)) {
|
|
5569
|
-
const handled = result
|
|
5570
|
-
.finally(() => {
|
|
5571
|
-
qrlRuns.splice(qrlRuns.indexOf(handled), 1);
|
|
5572
|
-
})
|
|
5573
|
-
.catch((error) => {
|
|
5574
|
-
container.handleError(error, chore.$host$);
|
|
5575
|
-
});
|
|
5576
|
-
// Don't wait for the promise to resolve
|
|
5577
|
-
// TODO come up with a better solution, we also want concurrent signal handling with tasks but serial tasks
|
|
5578
|
-
qrlRuns.push(handled);
|
|
5579
|
-
DEBUG &&
|
|
5580
|
-
debugTrace('execute.DONE (but still running)', chore, currentChore, choreQueue);
|
|
5581
|
-
chore.$returnValue$ = handled;
|
|
5582
|
-
chore.$resolve$?.(handled);
|
|
5583
|
-
currentChore = null;
|
|
5584
|
-
chore.$executed$ = true;
|
|
5585
|
-
// early out so we don't call after()
|
|
5586
|
-
return;
|
|
5587
5948
|
}
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5949
|
+
});
|
|
5950
|
+
}
|
|
5951
|
+
else {
|
|
5952
|
+
finishChore(chore, result);
|
|
5953
|
+
scheduleBlockedChoresAndDrainIfNeeded(chore);
|
|
5954
|
+
}
|
|
5955
|
+
if (shouldApplyJournalFlush(isServer)) {
|
|
5956
|
+
applyJournalFlush();
|
|
5957
|
+
drainInNextTick();
|
|
5958
|
+
return;
|
|
5959
|
+
}
|
|
5960
|
+
}
|
|
5961
|
+
}
|
|
5962
|
+
catch (e) {
|
|
5963
|
+
handleError(currentChore, e);
|
|
5964
|
+
scheduleBlockedChoresAndDrainIfNeeded(currentChore);
|
|
5965
|
+
}
|
|
5966
|
+
finally {
|
|
5967
|
+
isDraining = false;
|
|
5968
|
+
maybeFinishDrain();
|
|
5969
|
+
}
|
|
5970
|
+
}
|
|
5971
|
+
function finishChore(chore, value) {
|
|
5972
|
+
chore.$endTime$ = performance.now();
|
|
5973
|
+
chore.$state$ = ChoreState.DONE;
|
|
5974
|
+
chore.$returnValue$ = value;
|
|
5975
|
+
chore.$resolve$?.(value);
|
|
5976
|
+
}
|
|
5977
|
+
function handleError(chore, e) {
|
|
5978
|
+
chore.$endTime$ = performance.now();
|
|
5979
|
+
chore.$state$ = ChoreState.FAILED;
|
|
5980
|
+
// If we used the result as promise, this won't exist
|
|
5981
|
+
chore.$reject$?.(e);
|
|
5982
|
+
container.handleError(e, chore.$host$);
|
|
5983
|
+
}
|
|
5984
|
+
function executeChore(chore, isServer) {
|
|
5985
|
+
const host = chore.$host$;
|
|
5986
|
+
let returnValue;
|
|
5987
|
+
switch (chore.$type$) {
|
|
5988
|
+
case 6 /* ChoreType.COMPONENT */:
|
|
5989
|
+
{
|
|
5990
|
+
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
5991
|
+
if (isServer) {
|
|
5992
|
+
return jsx;
|
|
5604
5993
|
}
|
|
5605
5994
|
else {
|
|
5606
|
-
|
|
5995
|
+
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
5996
|
+
return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
|
|
5607
5997
|
}
|
|
5998
|
+
}, (err) => {
|
|
5999
|
+
handleError(chore, err);
|
|
6000
|
+
});
|
|
6001
|
+
}
|
|
6002
|
+
break;
|
|
6003
|
+
case 2 /* ChoreType.RUN_QRL */:
|
|
6004
|
+
{
|
|
6005
|
+
const fn = chore.$target$.getFn();
|
|
6006
|
+
returnValue = retryOnPromise(() => fn(...chore.$payload$));
|
|
6007
|
+
}
|
|
6008
|
+
break;
|
|
6009
|
+
case 3 /* ChoreType.TASK */:
|
|
6010
|
+
case 16 /* ChoreType.VISIBLE */:
|
|
6011
|
+
{
|
|
6012
|
+
const payload = chore.$payload$;
|
|
6013
|
+
if (payload.$flags$ & 4 /* TaskFlags.RESOURCE */) {
|
|
6014
|
+
returnValue = runResource(payload, container, host);
|
|
5608
6015
|
}
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
{
|
|
5612
|
-
const task = chore.$payload$;
|
|
5613
|
-
cleanupTask(task);
|
|
6016
|
+
else {
|
|
6017
|
+
returnValue = runTask(payload, container, host);
|
|
5614
6018
|
}
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
6019
|
+
}
|
|
6020
|
+
break;
|
|
6021
|
+
case 32 /* ChoreType.CLEANUP_VISIBLE */:
|
|
6022
|
+
{
|
|
6023
|
+
const task = chore.$payload$;
|
|
6024
|
+
cleanupTask(task);
|
|
6025
|
+
}
|
|
6026
|
+
break;
|
|
6027
|
+
case 4 /* ChoreType.NODE_DIFF */:
|
|
6028
|
+
{
|
|
6029
|
+
const parentVirtualNode = chore.$target$;
|
|
6030
|
+
let jsx = chore.$payload$;
|
|
6031
|
+
if (isSignal(jsx)) {
|
|
6032
|
+
jsx = jsx.value;
|
|
5624
6033
|
}
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
6034
|
+
returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
|
|
6035
|
+
}
|
|
6036
|
+
break;
|
|
6037
|
+
case 5 /* ChoreType.NODE_PROP */:
|
|
6038
|
+
{
|
|
6039
|
+
const virtualNode = chore.$host$;
|
|
6040
|
+
const payload = chore.$payload$;
|
|
6041
|
+
let value = payload.$value$;
|
|
6042
|
+
if (isSignal(value)) {
|
|
6043
|
+
value = value.value;
|
|
6044
|
+
}
|
|
6045
|
+
const isConst = payload.$isConst$;
|
|
6046
|
+
const journal = container.$journal$;
|
|
6047
|
+
const property = chore.$idx$;
|
|
6048
|
+
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
6049
|
+
if (isServer) {
|
|
6050
|
+
container.addBackpatchEntry(chore.$host$.id, property, serializedValue);
|
|
6051
|
+
returnValue = null;
|
|
6052
|
+
}
|
|
6053
|
+
else {
|
|
5638
6054
|
if (isConst) {
|
|
5639
6055
|
const element = virtualNode[6 /* ElementVNodeProps.element */];
|
|
5640
6056
|
journal.push(2 /* VNodeJournalOpCode.SetAttribute */, element, property, serializedValue);
|
|
@@ -5642,64 +6058,49 @@
|
|
|
5642
6058
|
else {
|
|
5643
6059
|
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
5644
6060
|
}
|
|
6061
|
+
returnValue = undefined;
|
|
5645
6062
|
}
|
|
5646
|
-
break;
|
|
5647
|
-
case 1 /* ChoreType.QRL_RESOLVE */: {
|
|
5648
|
-
{
|
|
5649
|
-
const target = chore.$target$;
|
|
5650
|
-
returnValue = !target.resolved ? target.resolve() : null;
|
|
5651
|
-
}
|
|
5652
|
-
break;
|
|
5653
6063
|
}
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
6064
|
+
break;
|
|
6065
|
+
case 1 /* ChoreType.QRL_RESOLVE */: {
|
|
6066
|
+
{
|
|
6067
|
+
const target = chore.$target$;
|
|
6068
|
+
returnValue = (!target.resolved ? target.resolve() : null);
|
|
6069
|
+
}
|
|
6070
|
+
break;
|
|
6071
|
+
}
|
|
6072
|
+
case 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */: {
|
|
6073
|
+
{
|
|
6074
|
+
const target = chore.$target$;
|
|
6075
|
+
const effects = chore.$payload$;
|
|
6076
|
+
if (!effects?.size) {
|
|
6077
|
+
break;
|
|
6078
|
+
}
|
|
6079
|
+
let shouldCompute = target instanceof ComputedSignalImpl || target instanceof WrappedSignalImpl;
|
|
6080
|
+
if (target instanceof AsyncComputedSignalImpl && effects !== target.$effects$) {
|
|
6081
|
+
shouldCompute = false;
|
|
6082
|
+
}
|
|
6083
|
+
if (shouldCompute) {
|
|
5658
6084
|
const ctx = newInvokeContext();
|
|
5659
6085
|
ctx.$container$ = container;
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
target.$
|
|
5663
|
-
|
|
5664
|
-
|
|
6086
|
+
// needed for computed signals and throwing QRLs
|
|
6087
|
+
returnValue = maybeThen(retryOnPromise(() => invoke.call(target, ctx, target.$computeIfNeeded$)), () => {
|
|
6088
|
+
if (target.$flags$ & 2 /* SignalFlags.RUN_EFFECTS */) {
|
|
6089
|
+
target.$flags$ &= -3 /* SignalFlags.RUN_EFFECTS */;
|
|
6090
|
+
return retryOnPromise(() => triggerEffects(container, target, effects));
|
|
5665
6091
|
}
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
}
|
|
5673
|
-
else {
|
|
5674
|
-
returnValue = retryOnPromise(() => triggerEffects(container, target, effects));
|
|
5675
|
-
}
|
|
6092
|
+
});
|
|
6093
|
+
}
|
|
6094
|
+
else {
|
|
6095
|
+
returnValue = retryOnPromise(() => {
|
|
6096
|
+
triggerEffects(container, target, effects);
|
|
6097
|
+
});
|
|
5676
6098
|
}
|
|
5677
|
-
break;
|
|
5678
6099
|
}
|
|
6100
|
+
break;
|
|
5679
6101
|
}
|
|
5680
6102
|
}
|
|
5681
|
-
|
|
5682
|
-
returnValue = Promise.reject(e);
|
|
5683
|
-
}
|
|
5684
|
-
const after = (value, error) => {
|
|
5685
|
-
currentChore = null;
|
|
5686
|
-
chore.$executed$ = true;
|
|
5687
|
-
if (error) {
|
|
5688
|
-
container.handleError(error, host);
|
|
5689
|
-
}
|
|
5690
|
-
else {
|
|
5691
|
-
chore.$returnValue$ = value;
|
|
5692
|
-
chore.$resolve$?.(value);
|
|
5693
|
-
}
|
|
5694
|
-
};
|
|
5695
|
-
if (isPromise(returnValue)) {
|
|
5696
|
-
chore.$promise$ = returnValue.then(after, (error) => after(undefined, error));
|
|
5697
|
-
chore.$resolve$?.(chore.$promise$);
|
|
5698
|
-
chore.$resolve$ = undefined;
|
|
5699
|
-
}
|
|
5700
|
-
else {
|
|
5701
|
-
after(returnValue);
|
|
5702
|
-
}
|
|
6103
|
+
return returnValue;
|
|
5703
6104
|
}
|
|
5704
6105
|
/**
|
|
5705
6106
|
* Compares two chores to determine their execution order in the scheduler's queue.
|
|
@@ -5728,15 +6129,6 @@
|
|
|
5728
6129
|
else {
|
|
5729
6130
|
assertFalse(vnode_isVNode(aHost), 'expected aHost to be SSRNode but it is a VNode');
|
|
5730
6131
|
assertFalse(vnode_isVNode(bHost), 'expected bHost to be SSRNode but it is a VNode');
|
|
5731
|
-
// we are running on the server.
|
|
5732
|
-
// On server we can't schedule task for a different host!
|
|
5733
|
-
// Server is SSR, and therefore scheduling for anything but the current host
|
|
5734
|
-
// implies that things need to be re-run nad that is not supported because of streaming.
|
|
5735
|
-
const errorMessage = `SERVER: during HTML streaming, re-running tasks on a different host is not allowed.
|
|
5736
|
-
You are attempting to change a state that has already been streamed to the client.
|
|
5737
|
-
This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
|
|
5738
|
-
Problematic Node: ${aHost.toString()}`;
|
|
5739
|
-
logWarn(errorMessage);
|
|
5740
6132
|
const hostDiff = ssrNodeDocumentPosition(aHost, bHost);
|
|
5741
6133
|
if (hostDiff !== 0) {
|
|
5742
6134
|
return hostDiff;
|
|
@@ -5760,8 +6152,14 @@
|
|
|
5760
6152
|
// 1 means that we are going to process chores as FIFO
|
|
5761
6153
|
return 1;
|
|
5762
6154
|
}
|
|
5763
|
-
//
|
|
5764
|
-
|
|
6155
|
+
// ensure that the effect chores are scheduled for the same target
|
|
6156
|
+
// TODO: can we do this better?
|
|
6157
|
+
if (a.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
|
|
6158
|
+
b.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
|
|
6159
|
+
((a.$target$ instanceof StoreHandler && b.$target$ instanceof StoreHandler) ||
|
|
6160
|
+
(a.$target$ instanceof AsyncComputedSignalImpl &&
|
|
6161
|
+
b.$target$ instanceof AsyncComputedSignalImpl)) &&
|
|
6162
|
+
a.$payload$ !== b.$payload$) {
|
|
5765
6163
|
return 1;
|
|
5766
6164
|
}
|
|
5767
6165
|
// The chores are the same and will run only once
|
|
@@ -5793,6 +6191,15 @@
|
|
|
5793
6191
|
/// We need to ensure that the `queue` is sorted by priority.
|
|
5794
6192
|
/// 1. Find a place where to insert into.
|
|
5795
6193
|
const idx = sortedFindIndex(sortedArray, value, rootVNode);
|
|
6194
|
+
if (idx < 0 && runningChores.size) {
|
|
6195
|
+
// 1.1. Check if the chore is already running.
|
|
6196
|
+
for (const chore of runningChores) {
|
|
6197
|
+
const comp = choreComparator(value, chore, rootVNode);
|
|
6198
|
+
if (comp === 0) {
|
|
6199
|
+
return chore;
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
5796
6203
|
if (idx < 0) {
|
|
5797
6204
|
/// 2. Insert the chore into the queue.
|
|
5798
6205
|
sortedArray.splice(~idx, 0, value);
|
|
@@ -5807,9 +6214,6 @@
|
|
|
5807
6214
|
if (existing.$payload$ !== value.$payload$) {
|
|
5808
6215
|
existing.$payload$ = value.$payload$;
|
|
5809
6216
|
}
|
|
5810
|
-
if (existing.$executed$) {
|
|
5811
|
-
existing.$executed$ = false;
|
|
5812
|
-
}
|
|
5813
6217
|
return existing;
|
|
5814
6218
|
}
|
|
5815
6219
|
};
|
|
@@ -5821,6 +6225,25 @@
|
|
|
5821
6225
|
vnode_isVNode(chore.$host$) &&
|
|
5822
6226
|
chore.$host$[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */);
|
|
5823
6227
|
}
|
|
6228
|
+
function addBlockedChore(blockedChore, blockingChore, blockedChores) {
|
|
6229
|
+
blockingChore.$blockedChores$ ||= [];
|
|
6230
|
+
blockingChore.$blockedChores$.push(blockedChore);
|
|
6231
|
+
blockedChores.add(blockedChore);
|
|
6232
|
+
}
|
|
6233
|
+
function choreTypeToName(type) {
|
|
6234
|
+
return ({
|
|
6235
|
+
[1 /* ChoreType.QRL_RESOLVE */]: 'Resolve QRL',
|
|
6236
|
+
[2 /* ChoreType.RUN_QRL */]: 'Run QRL',
|
|
6237
|
+
[3 /* ChoreType.TASK */]: 'Task',
|
|
6238
|
+
[4 /* ChoreType.NODE_DIFF */]: 'Changes diffing',
|
|
6239
|
+
[5 /* ChoreType.NODE_PROP */]: 'Updating node property',
|
|
6240
|
+
[6 /* ChoreType.COMPONENT */]: 'Component',
|
|
6241
|
+
[7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */]: 'Signal recompute',
|
|
6242
|
+
[16 /* ChoreType.VISIBLE */]: 'Visible',
|
|
6243
|
+
[32 /* ChoreType.CLEANUP_VISIBLE */]: 'Cleanup visible',
|
|
6244
|
+
[255 /* ChoreType.WAIT_FOR_QUEUE */]: 'Wait for queue',
|
|
6245
|
+
}[type] || 'Unknown: ' + type);
|
|
6246
|
+
}
|
|
5824
6247
|
function debugChoreTypeToString(type) {
|
|
5825
6248
|
return ({
|
|
5826
6249
|
[1 /* ChoreType.QRL_RESOLVE */]: 'QRL_RESOLVE',
|
|
@@ -5830,31 +6253,87 @@
|
|
|
5830
6253
|
[5 /* ChoreType.NODE_PROP */]: 'NODE_PROP',
|
|
5831
6254
|
[6 /* ChoreType.COMPONENT */]: 'COMPONENT',
|
|
5832
6255
|
[7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */]: 'RECOMPUTE_SIGNAL',
|
|
5833
|
-
[16 /* ChoreType.
|
|
5834
|
-
[32 /* ChoreType.
|
|
5835
|
-
[
|
|
5836
|
-
[255 /* ChoreType.WAIT_FOR_ALL */]: 'WAIT_FOR_ALL',
|
|
6256
|
+
[16 /* ChoreType.VISIBLE */]: 'VISIBLE',
|
|
6257
|
+
[32 /* ChoreType.CLEANUP_VISIBLE */]: 'CLEANUP_VISIBLE',
|
|
6258
|
+
[255 /* ChoreType.WAIT_FOR_QUEUE */]: 'WAIT_FOR_QUEUE',
|
|
5837
6259
|
}[type] || 'UNKNOWN: ' + type);
|
|
5838
6260
|
}
|
|
5839
|
-
function
|
|
5840
|
-
const
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
6261
|
+
function debugTrace(action, arg, queue, blockedChores) {
|
|
6262
|
+
const lines = [];
|
|
6263
|
+
// Header
|
|
6264
|
+
lines.push(`Scheduler: ${action}`);
|
|
6265
|
+
// Argument section
|
|
6266
|
+
if (arg) {
|
|
6267
|
+
lines.push('');
|
|
6268
|
+
if (arg && '$type$' in arg) {
|
|
6269
|
+
const chore = arg;
|
|
6270
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
6271
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
6272
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
6273
|
+
const targetOrHost = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
|
|
6274
|
+
? qrlTarget
|
|
6275
|
+
: host;
|
|
6276
|
+
lines.push(`🎯 Current Chore:`);
|
|
6277
|
+
lines.push(` Type: ${type}`);
|
|
6278
|
+
lines.push(` Host: ${targetOrHost}`);
|
|
6279
|
+
// Show execution time if available
|
|
6280
|
+
if (chore.$startTime$ && chore.$endTime$) {
|
|
6281
|
+
const executionTime = chore.$endTime$ - chore.$startTime$;
|
|
6282
|
+
lines.push(` Time: ${executionTime.toFixed(2)}ms`);
|
|
6283
|
+
}
|
|
6284
|
+
else if (chore.$startTime$) {
|
|
6285
|
+
const elapsedTime = performance.now() - chore.$startTime$;
|
|
6286
|
+
lines.push(` Time: ${elapsedTime.toFixed(2)}ms (running)`);
|
|
6287
|
+
}
|
|
6288
|
+
// Show blocked chores for this chore
|
|
6289
|
+
if (chore.$blockedChores$ && chore.$blockedChores$.length > 0) {
|
|
6290
|
+
lines.push(` ⛔ Blocked Chores:`);
|
|
6291
|
+
chore.$blockedChores$.forEach((blockedChore, index) => {
|
|
6292
|
+
const blockedType = debugChoreTypeToString(blockedChore.$type$);
|
|
6293
|
+
const blockedTarget = String(blockedChore.$host$).replaceAll(/\n.*/gim, '');
|
|
6294
|
+
lines.push(` ${index + 1}. ${blockedType} ${blockedTarget} ${blockedChore.$idx$}`);
|
|
6295
|
+
});
|
|
6296
|
+
}
|
|
6297
|
+
}
|
|
6298
|
+
else {
|
|
6299
|
+
lines.push(`📝 Argument: ${String(arg).replaceAll(/\n.*/gim, '')}`);
|
|
6300
|
+
}
|
|
6301
|
+
}
|
|
6302
|
+
// Queue section
|
|
6303
|
+
if (queue && queue.length > 0) {
|
|
6304
|
+
lines.push('');
|
|
6305
|
+
lines.push(`📋 Queue (${queue.length} items):`);
|
|
6306
|
+
queue.forEach((chore, index) => {
|
|
6307
|
+
const isActive = chore === arg;
|
|
6308
|
+
const activeMarker = isActive ? `▶ ` : ' ';
|
|
6309
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
6310
|
+
const state = chore.$state$ ? `[${ChoreState[chore.$state$]}]` : '';
|
|
6311
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
6312
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
6313
|
+
const target = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
|
|
6314
|
+
? qrlTarget
|
|
6315
|
+
: host;
|
|
6316
|
+
const line = `${activeMarker}${state} ${type} ${target} ${chore.$idx$}`;
|
|
6317
|
+
lines.push(line);
|
|
6318
|
+
});
|
|
6319
|
+
}
|
|
6320
|
+
// Blocked chores section
|
|
6321
|
+
if (blockedChores && blockedChores.size > 0) {
|
|
6322
|
+
lines.push('');
|
|
6323
|
+
lines.push(`🚫 Blocked Chores (${blockedChores.size} items):`);
|
|
6324
|
+
Array.from(blockedChores).forEach((chore, index) => {
|
|
6325
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
6326
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
6327
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
6328
|
+
const target = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
|
|
6329
|
+
? qrlTarget
|
|
6330
|
+
: host;
|
|
6331
|
+
lines.push(` ${index + 1}. ${type} ${target} ${chore.$idx$}`);
|
|
5856
6332
|
});
|
|
5857
6333
|
}
|
|
6334
|
+
// Footer
|
|
6335
|
+
lines.push('');
|
|
6336
|
+
lines.push('─'.repeat(60));
|
|
5858
6337
|
// eslint-disable-next-line no-console
|
|
5859
6338
|
console.log(lines.join('\n') + '\n');
|
|
5860
6339
|
}
|
|
@@ -5872,7 +6351,8 @@
|
|
|
5872
6351
|
$currentUniqueId$ = 0;
|
|
5873
6352
|
$instanceHash$ = null;
|
|
5874
6353
|
$buildBase$ = null;
|
|
5875
|
-
|
|
6354
|
+
$flushEpoch$ = 0;
|
|
6355
|
+
constructor(journalFlush, serverData, locale) {
|
|
5876
6356
|
this.$serverData$ = serverData;
|
|
5877
6357
|
this.$locale$ = locale;
|
|
5878
6358
|
this.$version$ = version;
|
|
@@ -5880,7 +6360,7 @@
|
|
|
5880
6360
|
this.$getObjectById$ = (_id) => {
|
|
5881
6361
|
throw Error('Not implemented');
|
|
5882
6362
|
};
|
|
5883
|
-
this.$scheduler$ = createScheduler(this,
|
|
6363
|
+
this.$scheduler$ = createScheduler(this, journalFlush);
|
|
5884
6364
|
}
|
|
5885
6365
|
trackSignalValue(signal, subscriber, property, data) {
|
|
5886
6366
|
return trackSignalAndAssignHost(signal, subscriber, property, this, data);
|
|
@@ -6189,9 +6669,10 @@
|
|
|
6189
6669
|
const shadowRootContainer = node;
|
|
6190
6670
|
const shadowRoot = shadowRootContainer?.shadowRoot;
|
|
6191
6671
|
if (shadowRoot) {
|
|
6672
|
+
const firstShadowRootChild = firstChild(shadowRoot);
|
|
6192
6673
|
walkContainer(
|
|
6193
6674
|
// we need to create a new walker for the shadow root
|
|
6194
|
-
document.createTreeWalker(
|
|
6675
|
+
document.createTreeWalker(firstShadowRootChild, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */), null, firstShadowRootChild, null, '', null);
|
|
6195
6676
|
}
|
|
6196
6677
|
}
|
|
6197
6678
|
if ((nodeType & 2 /* NodeType.ELEMENT */) === 2 /* NodeType.ELEMENT */) {
|
|
@@ -6267,7 +6748,7 @@
|
|
|
6267
6748
|
/** @internal */
|
|
6268
6749
|
function _getQContainerElement(element) {
|
|
6269
6750
|
const qContainerElement = Array.isArray(element)
|
|
6270
|
-
? vnode_getDomParent(element)
|
|
6751
|
+
? vnode_getDomParent(element, true)
|
|
6271
6752
|
: element;
|
|
6272
6753
|
return qContainerElement.closest(QContainerSelector);
|
|
6273
6754
|
}
|
|
@@ -6282,7 +6763,6 @@
|
|
|
6282
6763
|
rootVNode;
|
|
6283
6764
|
document;
|
|
6284
6765
|
$journal$;
|
|
6285
|
-
renderDone = null;
|
|
6286
6766
|
$rawStateData$;
|
|
6287
6767
|
$storeProxyMap$ = new WeakMap();
|
|
6288
6768
|
$qFuncs$;
|
|
@@ -6292,9 +6772,11 @@
|
|
|
6292
6772
|
vNodeLocate = (id) => vnode_locate(this.rootVNode, id);
|
|
6293
6773
|
$stateData$;
|
|
6294
6774
|
$styleIds$ = null;
|
|
6295
|
-
$renderCount$ = 0;
|
|
6296
6775
|
constructor(element) {
|
|
6297
|
-
super(() =>
|
|
6776
|
+
super(() => {
|
|
6777
|
+
this.$flushEpoch$++;
|
|
6778
|
+
vnode_applyJournal(this.$journal$);
|
|
6779
|
+
}, {}, element.getAttribute(QLocaleAttr));
|
|
6298
6780
|
this.qContainer = element.getAttribute(QContainerAttr);
|
|
6299
6781
|
if (!this.qContainer) {
|
|
6300
6782
|
throw qError(25 /* QError.elementWithoutContainer */);
|
|
@@ -6336,20 +6818,17 @@
|
|
|
6336
6818
|
}
|
|
6337
6819
|
handleError(err, host) {
|
|
6338
6820
|
if (qDev && host) {
|
|
6339
|
-
// Clean vdom
|
|
6340
6821
|
if (typeof document !== 'undefined') {
|
|
6341
6822
|
const vHost = host;
|
|
6342
|
-
const errorDiv = document.createElement('errored-host');
|
|
6343
|
-
if (err && err instanceof Error) {
|
|
6344
|
-
errorDiv.props = { error: err };
|
|
6345
|
-
}
|
|
6346
|
-
errorDiv.setAttribute('q:key', '_error_');
|
|
6347
6823
|
const journal = [];
|
|
6348
|
-
const
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6824
|
+
const vHostParent = vnode_getParent(vHost);
|
|
6825
|
+
const vHostNextSibling = vnode_getNextSibling(vHost);
|
|
6826
|
+
const vErrorDiv = vnode_createErrorDiv(document, vHost, err, journal);
|
|
6827
|
+
// If the host is an element node, we need to insert the error div into its parent.
|
|
6828
|
+
const insertHost = vnode_isElementVNode(vHost) ? vHostParent || vHost : vHost;
|
|
6829
|
+
// If the host is different then we need to insert errored-host in the same position as the host.
|
|
6830
|
+
const insertBefore = insertHost === vHost ? null : vHostNextSibling;
|
|
6831
|
+
vnode_insertBefore(journal, insertHost, vErrorDiv, insertBefore);
|
|
6353
6832
|
vnode_applyJournal(journal);
|
|
6354
6833
|
}
|
|
6355
6834
|
if (err && err instanceof Error) {
|
|
@@ -6424,29 +6903,6 @@
|
|
|
6424
6903
|
}
|
|
6425
6904
|
return vnode_getProp(vNode, name, getObjectById);
|
|
6426
6905
|
}
|
|
6427
|
-
scheduleRender() {
|
|
6428
|
-
this.$renderCount$++;
|
|
6429
|
-
this.renderDone ||= getPlatform().nextTick(() => this.processChores());
|
|
6430
|
-
return this.renderDone.finally(() => emitEvent('qrender', { instanceHash: this.$instanceHash$, renderCount: this.$renderCount$ }));
|
|
6431
|
-
}
|
|
6432
|
-
processChores() {
|
|
6433
|
-
let renderCount = this.$renderCount$;
|
|
6434
|
-
const result = this.$scheduler$(255 /* ChoreType.WAIT_FOR_ALL */);
|
|
6435
|
-
if (isPromise(result)) {
|
|
6436
|
-
return result.then(async () => {
|
|
6437
|
-
while (renderCount !== this.$renderCount$) {
|
|
6438
|
-
renderCount = this.$renderCount$;
|
|
6439
|
-
await this.$scheduler$(255 /* ChoreType.WAIT_FOR_ALL */);
|
|
6440
|
-
}
|
|
6441
|
-
this.renderDone = null;
|
|
6442
|
-
});
|
|
6443
|
-
}
|
|
6444
|
-
if (renderCount !== this.$renderCount$) {
|
|
6445
|
-
this.processChores();
|
|
6446
|
-
return;
|
|
6447
|
-
}
|
|
6448
|
-
this.renderDone = null;
|
|
6449
|
-
}
|
|
6450
6906
|
ensureProjectionResolved(vNode) {
|
|
6451
6907
|
if ((vNode[0 /* VNodeProps.flags */] & 16 /* VNodeFlags.Resolved */) === 0) {
|
|
6452
6908
|
vNode[0 /* VNodeProps.flags */] |= 16 /* VNodeFlags.Resolved */;
|
|
@@ -6456,7 +6912,9 @@
|
|
|
6456
6912
|
if (isSlotProp(prop)) {
|
|
6457
6913
|
const value = props[i + 1];
|
|
6458
6914
|
if (typeof value == 'string') {
|
|
6459
|
-
|
|
6915
|
+
const projection = this.vNodeLocate(value);
|
|
6916
|
+
props[i + 1] = projection;
|
|
6917
|
+
vnode_getProp(projection, QSlotParent, (id) => this.vNodeLocate(id));
|
|
6460
6918
|
}
|
|
6461
6919
|
}
|
|
6462
6920
|
}
|
|
@@ -6577,7 +7035,7 @@
|
|
|
6577
7035
|
}
|
|
6578
7036
|
};
|
|
6579
7037
|
const triggerEffects = (container, signal, effects) => {
|
|
6580
|
-
const isBrowser =
|
|
7038
|
+
const isBrowser = !isServerPlatform();
|
|
6581
7039
|
if (effects) {
|
|
6582
7040
|
const scheduleEffect = (effectSubscription) => {
|
|
6583
7041
|
const consumer = effectSubscription[0 /* EffectSubscriptionProp.CONSUMER */];
|
|
@@ -6587,7 +7045,7 @@
|
|
|
6587
7045
|
consumer.$flags$ |= 8 /* TaskFlags.DIRTY */;
|
|
6588
7046
|
let choreType = 3 /* ChoreType.TASK */;
|
|
6589
7047
|
if (consumer.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
|
|
6590
|
-
choreType =
|
|
7048
|
+
choreType = 16 /* ChoreType.VISIBLE */;
|
|
6591
7049
|
}
|
|
6592
7050
|
container.$scheduler$(choreType, consumer);
|
|
6593
7051
|
}
|
|
@@ -6610,22 +7068,22 @@
|
|
|
6610
7068
|
const props = container.getHostProp(host, ELEMENT_PROPS);
|
|
6611
7069
|
container.$scheduler$(6 /* ChoreType.COMPONENT */, host, qrl, props);
|
|
6612
7070
|
}
|
|
6613
|
-
else if (
|
|
6614
|
-
if (
|
|
7071
|
+
else if (property === "." /* EffectProperty.VNODE */) {
|
|
7072
|
+
if (isBrowser) {
|
|
6615
7073
|
const host = consumer;
|
|
6616
7074
|
container.$scheduler$(4 /* ChoreType.NODE_DIFF */, host, host, signal);
|
|
6617
7075
|
}
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
7076
|
+
}
|
|
7077
|
+
else {
|
|
7078
|
+
const host = consumer;
|
|
7079
|
+
const effectData = effectSubscription[3 /* EffectSubscriptionProp.DATA */];
|
|
7080
|
+
if (effectData instanceof SubscriptionData) {
|
|
7081
|
+
const data = effectData.data;
|
|
7082
|
+
const payload = {
|
|
7083
|
+
...data,
|
|
7084
|
+
$value$: signal,
|
|
7085
|
+
};
|
|
7086
|
+
container.$scheduler$(5 /* ChoreType.NODE_PROP */, host, property, payload);
|
|
6629
7087
|
}
|
|
6630
7088
|
}
|
|
6631
7089
|
};
|
|
@@ -6646,10 +7104,10 @@
|
|
|
6646
7104
|
// flags |= ComputedSignalFlags.SERIALIZATION_STRATEGY_AUTO;
|
|
6647
7105
|
// break;
|
|
6648
7106
|
case 'never':
|
|
6649
|
-
flags |=
|
|
7107
|
+
flags |= 16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
|
|
6650
7108
|
break;
|
|
6651
7109
|
case 'always':
|
|
6652
|
-
flags |=
|
|
7110
|
+
flags |= 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
|
|
6653
7111
|
break;
|
|
6654
7112
|
}
|
|
6655
7113
|
return flags;
|
|
@@ -7041,6 +7499,9 @@
|
|
|
7041
7499
|
}
|
|
7042
7500
|
let vParent = null;
|
|
7043
7501
|
do {
|
|
7502
|
+
if (callback?.(vCursor, vParent)) {
|
|
7503
|
+
return;
|
|
7504
|
+
}
|
|
7044
7505
|
const vFirstChild = vnode_getFirstChild(vCursor);
|
|
7045
7506
|
if (vFirstChild) {
|
|
7046
7507
|
vCursor = vFirstChild;
|
|
@@ -7209,6 +7670,7 @@
|
|
|
7209
7670
|
const flags = textVNode[0 /* VNodeProps.flags */];
|
|
7210
7671
|
if ((flags & 8 /* VNodeFlags.Inflated */) === 0) {
|
|
7211
7672
|
const parentNode = vnode_getDomParent(vnode);
|
|
7673
|
+
assertDefined(parentNode, 'Missing parent node.');
|
|
7212
7674
|
const sharedTextNode = textVNode[4 /* TextVNodeProps.node */];
|
|
7213
7675
|
const doc = parentNode.ownerDocument;
|
|
7214
7676
|
// Walk the previous siblings and inflate them.
|
|
@@ -7367,6 +7829,18 @@
|
|
|
7367
7829
|
}
|
|
7368
7830
|
return length;
|
|
7369
7831
|
};
|
|
7832
|
+
const vnode_createErrorDiv = (document, host, err, journal) => {
|
|
7833
|
+
const errorDiv = document.createElement('errored-host');
|
|
7834
|
+
if (err && err instanceof Error) {
|
|
7835
|
+
errorDiv.props = { error: err };
|
|
7836
|
+
}
|
|
7837
|
+
errorDiv.setAttribute('q:key', '_error_');
|
|
7838
|
+
const vErrorDiv = vnode_newElement(errorDiv, 'errored-host');
|
|
7839
|
+
vnode_getDOMChildNodes(journal, host, true).forEach((child) => {
|
|
7840
|
+
vnode_insertBefore(journal, vErrorDiv, child, null);
|
|
7841
|
+
});
|
|
7842
|
+
return vErrorDiv;
|
|
7843
|
+
};
|
|
7370
7844
|
const parseBoolean = (value) => {
|
|
7371
7845
|
if (value === 'false') {
|
|
7372
7846
|
return false;
|
|
@@ -7505,7 +7979,7 @@
|
|
|
7505
7979
|
* unlink the previous or next sibling, we don't know that after "a" node is "b". So we need to
|
|
7506
7980
|
* find children first (and inflate them).
|
|
7507
7981
|
*/
|
|
7508
|
-
const domParentVNode = vnode_getDomParentVNode(parent);
|
|
7982
|
+
const domParentVNode = vnode_getDomParentVNode(parent, false);
|
|
7509
7983
|
const parentNode = domParentVNode && domParentVNode[6 /* ElementVNodeProps.element */];
|
|
7510
7984
|
let domChildren = null;
|
|
7511
7985
|
if (domParentVNode) {
|
|
@@ -7554,27 +8028,31 @@
|
|
|
7554
8028
|
newChildCurrentParent !== parent)) {
|
|
7555
8029
|
vnode_remove(journal, newChildCurrentParent, newChild, false);
|
|
7556
8030
|
}
|
|
7557
|
-
|
|
7558
|
-
if
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
8031
|
+
const parentIsDeleted = parent[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */;
|
|
8032
|
+
// if the parent is deleted, then we don't need to insert the new child
|
|
8033
|
+
if (!parentIsDeleted) {
|
|
8034
|
+
let adjustedInsertBefore = null;
|
|
8035
|
+
if (insertBefore == null) {
|
|
8036
|
+
if (vnode_isVirtualVNode(parent)) {
|
|
8037
|
+
// If `insertBefore` is null, than we need to insert at the end of the list.
|
|
8038
|
+
// Well, not quite. If the parent is a virtual node, our "last node" is not the same
|
|
8039
|
+
// as the DOM "last node". So in that case we need to look for the "next node" from
|
|
8040
|
+
// our parent.
|
|
8041
|
+
adjustedInsertBefore = vnode_getDomSibling(parent, true, false);
|
|
8042
|
+
}
|
|
8043
|
+
}
|
|
8044
|
+
else if (vnode_isVirtualVNode(insertBefore)) {
|
|
8045
|
+
// If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
|
|
8046
|
+
adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
|
|
8047
|
+
}
|
|
8048
|
+
else {
|
|
8049
|
+
adjustedInsertBefore = insertBefore;
|
|
8050
|
+
}
|
|
8051
|
+
adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
|
|
8052
|
+
// Here we know the insertBefore node
|
|
8053
|
+
if (domChildren && domChildren.length) {
|
|
8054
|
+
journal.push(5 /* VNodeJournalOpCode.Insert */, parentNode, vnode_getNode(adjustedInsertBefore), ...domChildren);
|
|
7565
8055
|
}
|
|
7566
|
-
}
|
|
7567
|
-
else if (vnode_isVirtualVNode(insertBefore)) {
|
|
7568
|
-
// If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
|
|
7569
|
-
adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
|
|
7570
|
-
}
|
|
7571
|
-
else {
|
|
7572
|
-
adjustedInsertBefore = insertBefore;
|
|
7573
|
-
}
|
|
7574
|
-
adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
|
|
7575
|
-
// Here we know the insertBefore node
|
|
7576
|
-
if (domChildren && domChildren.length) {
|
|
7577
|
-
journal.push(5 /* VNodeJournalOpCode.Insert */, parentNode, vnode_getNode(adjustedInsertBefore), ...domChildren);
|
|
7578
8056
|
}
|
|
7579
8057
|
// link newChild into the previous/next list
|
|
7580
8058
|
const vNext = insertBefore;
|
|
@@ -7596,14 +8074,22 @@
|
|
|
7596
8074
|
newChild[2 /* VNodeProps.previousSibling */] = vPrevious;
|
|
7597
8075
|
newChild[3 /* VNodeProps.nextSibling */] = vNext;
|
|
7598
8076
|
newChild[1 /* VNodeProps.parent */] = parent;
|
|
8077
|
+
if (parentIsDeleted) {
|
|
8078
|
+
// if the parent is deleted, then the new child is also deleted
|
|
8079
|
+
newChild[0 /* VNodeProps.flags */] |= 32 /* VNodeFlags.Deleted */;
|
|
8080
|
+
}
|
|
7599
8081
|
};
|
|
7600
|
-
const vnode_getDomParent = (vnode) => {
|
|
7601
|
-
vnode = vnode_getDomParentVNode(vnode);
|
|
8082
|
+
const vnode_getDomParent = (vnode, includeProjection = true) => {
|
|
8083
|
+
vnode = vnode_getDomParentVNode(vnode, includeProjection);
|
|
7602
8084
|
return (vnode && vnode[6 /* ElementVNodeProps.element */]);
|
|
7603
8085
|
};
|
|
7604
|
-
const vnode_getDomParentVNode = (vnode) => {
|
|
8086
|
+
const vnode_getDomParentVNode = (vnode, includeProjection = true) => {
|
|
7605
8087
|
while (vnode && !vnode_isElementVNode(vnode)) {
|
|
7606
|
-
vnode =
|
|
8088
|
+
vnode =
|
|
8089
|
+
vnode[1 /* VNodeProps.parent */] ||
|
|
8090
|
+
(includeProjection
|
|
8091
|
+
? vnode_getProp(vnode, QSlotParent, (id) => (vnode_isVNode(id) ? id : null))
|
|
8092
|
+
: null);
|
|
7607
8093
|
}
|
|
7608
8094
|
return vnode;
|
|
7609
8095
|
};
|
|
@@ -7613,7 +8099,7 @@
|
|
|
7613
8099
|
vnode_ensureTextInflated(journal, vToRemove);
|
|
7614
8100
|
}
|
|
7615
8101
|
if (removeDOM) {
|
|
7616
|
-
const domParent = vnode_getDomParent(vParent);
|
|
8102
|
+
const domParent = vnode_getDomParent(vParent, false);
|
|
7617
8103
|
const isInnerHTMLParent = vnode_getAttr(vParent, dangerouslySetInnerHTML);
|
|
7618
8104
|
if (isInnerHTMLParent) {
|
|
7619
8105
|
// ignore children, as they are inserted via innerHTML
|
|
@@ -8094,6 +8580,26 @@
|
|
|
8094
8580
|
const vnode_getParent = (vnode) => {
|
|
8095
8581
|
return vnode[1 /* VNodeProps.parent */] || null;
|
|
8096
8582
|
};
|
|
8583
|
+
const vnode_isDescendantOf = (vnode, ancestor, rootVNode) => {
|
|
8584
|
+
let parent = vnode_getParentOrProjectionParent(vnode, rootVNode);
|
|
8585
|
+
while (parent) {
|
|
8586
|
+
if (parent === ancestor) {
|
|
8587
|
+
return true;
|
|
8588
|
+
}
|
|
8589
|
+
parent = vnode_getParentOrProjectionParent(parent, rootVNode);
|
|
8590
|
+
}
|
|
8591
|
+
return false;
|
|
8592
|
+
};
|
|
8593
|
+
const vnode_getParentOrProjectionParent = (vnode, rootVNode) => {
|
|
8594
|
+
if (rootVNode) {
|
|
8595
|
+
const parentProjection = vnode_getProp(vnode, QSlotParent, (id) => vnode_locate(rootVNode, id));
|
|
8596
|
+
if (parentProjection) {
|
|
8597
|
+
// This is a projection, so we need to check the parent of the projection
|
|
8598
|
+
return parentProjection;
|
|
8599
|
+
}
|
|
8600
|
+
}
|
|
8601
|
+
return vnode_getParent(vnode);
|
|
8602
|
+
};
|
|
8097
8603
|
const vnode_getNode = (vnode) => {
|
|
8098
8604
|
if (vnode === null || vnode_isVirtualVNode(vnode)) {
|
|
8099
8605
|
return null;
|
|
@@ -8453,13 +8959,15 @@
|
|
|
8453
8959
|
}
|
|
8454
8960
|
const container = this.$container$;
|
|
8455
8961
|
let propValue = allocate(container, typeId, value);
|
|
8962
|
+
Reflect.set(target, property, propValue);
|
|
8963
|
+
this.$data$[idx] = undefined;
|
|
8964
|
+
this.$data$[idx + 1] = propValue;
|
|
8456
8965
|
/** We stored the reference, so now we can inflate, allowing cycles. */
|
|
8457
8966
|
if (typeId >= 14 /* TypeIds.Error */) {
|
|
8458
8967
|
propValue = inflate(container, propValue, typeId, value);
|
|
8968
|
+
Reflect.set(target, property, propValue);
|
|
8969
|
+
this.$data$[idx + 1] = propValue;
|
|
8459
8970
|
}
|
|
8460
|
-
Reflect.set(target, property, propValue);
|
|
8461
|
-
this.$data$[idx] = undefined;
|
|
8462
|
-
this.$data$[idx + 1] = propValue;
|
|
8463
8971
|
return propValue;
|
|
8464
8972
|
}
|
|
8465
8973
|
has(target, property) {
|
|
@@ -8638,7 +9146,7 @@
|
|
|
8638
9146
|
*/
|
|
8639
9147
|
// try to download qrl in this tick
|
|
8640
9148
|
computed.$computeQrl$.resolve();
|
|
8641
|
-
container.$scheduler
|
|
9149
|
+
container.$scheduler$(1 /* ChoreType.QRL_RESOLVE */, null, computed.$computeQrl$);
|
|
8642
9150
|
}
|
|
8643
9151
|
break;
|
|
8644
9152
|
}
|
|
@@ -9426,8 +9934,8 @@
|
|
|
9426
9934
|
}
|
|
9427
9935
|
else if (value instanceof ComputedSignalImpl) {
|
|
9428
9936
|
let v = value.$untrackedValue$;
|
|
9429
|
-
const shouldAlwaysSerialize = value.$flags$ &
|
|
9430
|
-
const shouldNeverSerialize = value.$flags$ &
|
|
9937
|
+
const shouldAlwaysSerialize = value.$flags$ & 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
|
|
9938
|
+
const shouldNeverSerialize = value.$flags$ & 16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
|
|
9431
9939
|
const isInvalid = value.$flags$ & 1 /* SignalFlags.INVALID */;
|
|
9432
9940
|
const isSkippable = fastSkipSerialize(value.$untrackedValue$);
|
|
9433
9941
|
if (shouldAlwaysSerialize) {
|
|
@@ -10769,7 +11277,7 @@
|
|
|
10769
11277
|
container.$serverData$ = opts.serverData || {};
|
|
10770
11278
|
const host = container.rootVNode;
|
|
10771
11279
|
container.$scheduler$(4 /* ChoreType.NODE_DIFF */, host, host, jsxNode);
|
|
10772
|
-
await container.$scheduler$(255 /* ChoreType.
|
|
11280
|
+
await container.$scheduler$(255 /* ChoreType.WAIT_FOR_QUEUE */).$returnValue$;
|
|
10773
11281
|
return {
|
|
10774
11282
|
cleanup: () => {
|
|
10775
11283
|
cleanup(container, container.rootVNode);
|
|
@@ -11607,7 +12115,7 @@
|
|
|
11607
12115
|
useRunTask(task, eagerness);
|
|
11608
12116
|
if (!isServerPlatform()) {
|
|
11609
12117
|
qrl.resolve(iCtx.$element$);
|
|
11610
|
-
iCtx.$container$.$scheduler$(
|
|
12118
|
+
iCtx.$container$.$scheduler$(16 /* ChoreType.VISIBLE */, task);
|
|
11611
12119
|
}
|
|
11612
12120
|
};
|
|
11613
12121
|
const useRunTask = (task, eagerness) => {
|
|
@@ -11885,6 +12393,16 @@
|
|
|
11885
12393
|
*/
|
|
11886
12394
|
const PrefetchGraph = (_opts = {}) => null;
|
|
11887
12395
|
|
|
12396
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
|
12397
|
+
// Protect against duplicate imports
|
|
12398
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
|
12399
|
+
if (globalThis.__qwik) {
|
|
12400
|
+
console.error(`==============================================\n` +
|
|
12401
|
+
`Qwik version ${globalThis.__qwik} already imported while importing ${version}. Verify external vs bundled imports etc. This can lead to issues due to duplicated shared structures.\n` +
|
|
12402
|
+
`==============================================\n`);
|
|
12403
|
+
}
|
|
12404
|
+
globalThis.__qwik = version;
|
|
12405
|
+
|
|
11888
12406
|
Object.defineProperty(exports, "isBrowser", {
|
|
11889
12407
|
enumerable: true,
|
|
11890
12408
|
get: function () { return build.isBrowser; }
|
|
@@ -11930,6 +12448,7 @@
|
|
|
11930
12448
|
exports._getDomContainer = getDomContainer;
|
|
11931
12449
|
exports._getQContainerElement = _getQContainerElement;
|
|
11932
12450
|
exports._getVarProps = _getVarProps;
|
|
12451
|
+
exports._hasStoreEffects = _hasStoreEffects;
|
|
11933
12452
|
exports._isJSXNode = isJSXNode;
|
|
11934
12453
|
exports._isStore = isStore;
|
|
11935
12454
|
exports._isStringifiable = isStringifiable;
|
|
@@ -11950,7 +12469,7 @@
|
|
|
11950
12469
|
exports._regSymbol = _regSymbol;
|
|
11951
12470
|
exports._resolveContextWithoutSequentialScope = _resolveContextWithoutSequentialScope;
|
|
11952
12471
|
exports._restProps = _restProps;
|
|
11953
|
-
exports._run =
|
|
12472
|
+
exports._run = _run;
|
|
11954
12473
|
exports._serializationWeakRef = _serializationWeakRef;
|
|
11955
12474
|
exports._serialize = _serialize;
|
|
11956
12475
|
exports._task = scheduleTask;
|
|
@@ -11983,6 +12502,7 @@
|
|
|
11983
12502
|
exports.createSignal = createSignal;
|
|
11984
12503
|
exports.event$ = event$;
|
|
11985
12504
|
exports.eventQrl = eventQrl;
|
|
12505
|
+
exports.forceStoreEffects = forceStoreEffects;
|
|
11986
12506
|
exports.getDomContainer = getDomContainer;
|
|
11987
12507
|
exports.getLocale = getLocale;
|
|
11988
12508
|
exports.getPlatform = getPlatform;
|