@b9g/crank 0.7.0 → 0.7.2
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/README.md +646 -138
- package/_css.cjs +80 -0
- package/_css.cjs.map +1 -0
- package/_css.d.ts +21 -0
- package/_css.js +76 -0
- package/_css.js.map +1 -0
- package/_utils.cjs +106 -0
- package/_utils.cjs.map +1 -0
- package/_utils.js +99 -0
- package/_utils.js.map +1 -0
- package/async.cjs +42 -39
- package/async.cjs.map +1 -1
- package/async.d.ts +10 -7
- package/async.js +42 -39
- package/async.js.map +1 -1
- package/crank.cjs +87 -141
- package/crank.cjs.map +1 -1
- package/crank.d.ts +255 -3
- package/crank.js +51 -105
- package/crank.js.map +1 -1
- package/dom.cjs +33 -19
- package/dom.cjs.map +1 -1
- package/dom.js +33 -19
- package/dom.js.map +1 -1
- package/html.cjs +5 -3
- package/html.cjs.map +1 -1
- package/html.js +5 -3
- package/html.js.map +1 -1
- package/jsx-runtime.cjs +0 -1
- package/jsx-runtime.cjs.map +1 -1
- package/jsx-runtime.js +0 -1
- package/jsx-runtime.js.map +1 -1
- package/jsx-tag.cjs +0 -1
- package/jsx-tag.cjs.map +1 -1
- package/jsx-tag.js +0 -1
- package/jsx-tag.js.map +1 -1
- package/package.json +3 -2
- package/standalone.cjs +0 -1
- package/standalone.cjs.map +1 -1
- package/standalone.js +0 -1
- package/standalone.js.map +1 -1
- package/umd.js +160 -28
- package/umd.js.map +1 -1
package/crank.cjs
CHANGED
|
@@ -3,103 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var eventTarget = require('./event-target.cjs');
|
|
6
|
-
|
|
7
|
-
function wrap(value) {
|
|
8
|
-
return value === undefined ? [] : Array.isArray(value) ? value : [value];
|
|
9
|
-
}
|
|
10
|
-
function unwrap(arr) {
|
|
11
|
-
return arr.length === 0 ? undefined : arr.length === 1 ? arr[0] : arr;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Ensures a value is an array.
|
|
15
|
-
*
|
|
16
|
-
* This function does the same thing as wrap() above except it handles nulls
|
|
17
|
-
* and iterables, so it is appropriate for wrapping user-provided element
|
|
18
|
-
* children.
|
|
19
|
-
*/
|
|
20
|
-
function arrayify(value) {
|
|
21
|
-
return value == null
|
|
22
|
-
? []
|
|
23
|
-
: Array.isArray(value)
|
|
24
|
-
? value
|
|
25
|
-
: typeof value === "string" ||
|
|
26
|
-
typeof value[Symbol.iterator] !== "function"
|
|
27
|
-
? [value]
|
|
28
|
-
: [...value];
|
|
29
|
-
}
|
|
30
|
-
function isIteratorLike(value) {
|
|
31
|
-
return value != null && typeof value.next === "function";
|
|
32
|
-
}
|
|
33
|
-
function isPromiseLike(value) {
|
|
34
|
-
return value != null && typeof value.then === "function";
|
|
35
|
-
}
|
|
36
|
-
function createRaceRecord(contender) {
|
|
37
|
-
const deferreds = new Set();
|
|
38
|
-
const record = { deferreds, settled: false };
|
|
39
|
-
// This call to `then` happens once for the lifetime of the value.
|
|
40
|
-
Promise.resolve(contender).then((value) => {
|
|
41
|
-
for (const { resolve } of deferreds) {
|
|
42
|
-
resolve(value);
|
|
43
|
-
}
|
|
44
|
-
deferreds.clear();
|
|
45
|
-
record.settled = true;
|
|
46
|
-
}, (err) => {
|
|
47
|
-
for (const { reject } of deferreds) {
|
|
48
|
-
reject(err);
|
|
49
|
-
}
|
|
50
|
-
deferreds.clear();
|
|
51
|
-
record.settled = true;
|
|
52
|
-
});
|
|
53
|
-
return record;
|
|
54
|
-
}
|
|
55
|
-
// Promise.race is memory unsafe. This is alternative which is. See:
|
|
56
|
-
// https://github.com/nodejs/node/issues/17469#issuecomment-685235106
|
|
57
|
-
// Keys are the values passed to race.
|
|
58
|
-
// Values are a record of data containing a set of deferreds and whether the
|
|
59
|
-
// value has settled.
|
|
60
|
-
const wm = new WeakMap();
|
|
61
|
-
function safeRace(contenders) {
|
|
62
|
-
let deferred;
|
|
63
|
-
const result = new Promise((resolve, reject) => {
|
|
64
|
-
deferred = { resolve, reject };
|
|
65
|
-
for (const contender of contenders) {
|
|
66
|
-
if (!isPromiseLike(contender)) {
|
|
67
|
-
// If the contender is a not a then-able, attempting to use it as a key
|
|
68
|
-
// in the weakmap would throw an error. Luckily, it is safe to call
|
|
69
|
-
// `Promise.resolve(contender).then` on regular values multiple
|
|
70
|
-
// times because the promise fulfills immediately.
|
|
71
|
-
Promise.resolve(contender).then(resolve, reject);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
let record = wm.get(contender);
|
|
75
|
-
if (record === undefined) {
|
|
76
|
-
record = createRaceRecord(contender);
|
|
77
|
-
record.deferreds.add(deferred);
|
|
78
|
-
wm.set(contender, record);
|
|
79
|
-
}
|
|
80
|
-
else if (record.settled) {
|
|
81
|
-
// If the value has settled, it is safe to call
|
|
82
|
-
// `Promise.resolve(contender).then` on it.
|
|
83
|
-
Promise.resolve(contender).then(resolve, reject);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
record.deferreds.add(deferred);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
// The finally callback executes when any value settles, preventing any of
|
|
91
|
-
// the unresolved values from retaining a reference to the resolved value.
|
|
92
|
-
return result.finally(() => {
|
|
93
|
-
for (const contender of contenders) {
|
|
94
|
-
if (isPromiseLike(contender)) {
|
|
95
|
-
const record = wm.get(contender);
|
|
96
|
-
if (record) {
|
|
97
|
-
record.deferreds.delete(deferred);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
6
|
+
var _utils = require('./_utils.cjs');
|
|
103
7
|
|
|
104
8
|
const NOOP = () => { };
|
|
105
9
|
function getTagName(tag) {
|
|
@@ -264,6 +168,7 @@ const IsInForOfLoop = 1 << 13;
|
|
|
264
168
|
const IsInForAwaitOfLoop = 1 << 14;
|
|
265
169
|
const NeedsToYield = 1 << 15;
|
|
266
170
|
const PropsAvailable = 1 << 16;
|
|
171
|
+
const IsSchedulingRefresh = 1 << 17;
|
|
267
172
|
function getFlag(ret, flag) {
|
|
268
173
|
return !!(ret.f & flag);
|
|
269
174
|
}
|
|
@@ -331,7 +236,7 @@ function getValue(ret, isNested = false, index) {
|
|
|
331
236
|
if (index != null && ret.ctx) {
|
|
332
237
|
ret.ctx.index = index;
|
|
333
238
|
}
|
|
334
|
-
return unwrap(getChildValues(ret, index));
|
|
239
|
+
return _utils.unwrap(getChildValues(ret, index));
|
|
335
240
|
}
|
|
336
241
|
return ret.value;
|
|
337
242
|
}
|
|
@@ -346,7 +251,7 @@ function getValue(ret, isNested = false, index) {
|
|
|
346
251
|
function getChildValues(ret, startIndex) {
|
|
347
252
|
const values = [];
|
|
348
253
|
const lingerers = ret.lingerers;
|
|
349
|
-
const children = wrap(ret.children);
|
|
254
|
+
const children = _utils.wrap(ret.children);
|
|
350
255
|
let currentIndex = startIndex;
|
|
351
256
|
for (let i = 0; i < children.length; i++) {
|
|
352
257
|
if (lingerers != null && lingerers[i] != null) {
|
|
@@ -516,7 +421,7 @@ function getRootRetainer(renderer, bridge, { children, root, hydrate, }) {
|
|
|
516
421
|
function renderRoot(adapter, root, ret, children) {
|
|
517
422
|
const diff = diffChildren(adapter, root, ret, ret.ctx, ret.scope, ret, children);
|
|
518
423
|
const schedulePromises = [];
|
|
519
|
-
if (isPromiseLike(diff)) {
|
|
424
|
+
if (_utils.isPromiseLike(diff)) {
|
|
520
425
|
return diff.then(() => {
|
|
521
426
|
commit(adapter, ret, ret, ret.ctx, ret.scope, 0, schedulePromises, undefined);
|
|
522
427
|
if (schedulePromises.length > 0) {
|
|
@@ -524,13 +429,13 @@ function renderRoot(adapter, root, ret, children) {
|
|
|
524
429
|
if (typeof root !== "object" || root === null) {
|
|
525
430
|
unmount(adapter, ret, ret.ctx, ret, false);
|
|
526
431
|
}
|
|
527
|
-
return adapter.read(unwrap(getChildValues(ret)));
|
|
432
|
+
return adapter.read(_utils.unwrap(getChildValues(ret)));
|
|
528
433
|
});
|
|
529
434
|
}
|
|
530
435
|
if (typeof root !== "object" || root === null) {
|
|
531
436
|
unmount(adapter, ret, ret.ctx, ret, false);
|
|
532
437
|
}
|
|
533
|
-
return adapter.read(unwrap(getChildValues(ret)));
|
|
438
|
+
return adapter.read(_utils.unwrap(getChildValues(ret)));
|
|
534
439
|
});
|
|
535
440
|
}
|
|
536
441
|
commit(adapter, ret, ret, ret.ctx, ret.scope, 0, schedulePromises, undefined);
|
|
@@ -539,18 +444,18 @@ function renderRoot(adapter, root, ret, children) {
|
|
|
539
444
|
if (typeof root !== "object" || root === null) {
|
|
540
445
|
unmount(adapter, ret, ret.ctx, ret, false);
|
|
541
446
|
}
|
|
542
|
-
return adapter.read(unwrap(getChildValues(ret)));
|
|
447
|
+
return adapter.read(_utils.unwrap(getChildValues(ret)));
|
|
543
448
|
});
|
|
544
449
|
}
|
|
545
450
|
if (typeof root !== "object" || root === null) {
|
|
546
451
|
unmount(adapter, ret, ret.ctx, ret, false);
|
|
547
452
|
}
|
|
548
|
-
return adapter.read(unwrap(getChildValues(ret)));
|
|
453
|
+
return adapter.read(_utils.unwrap(getChildValues(ret)));
|
|
549
454
|
}
|
|
550
455
|
function diffChildren(adapter, root, host, ctx, scope, parent, newChildren) {
|
|
551
|
-
const oldRetained = wrap(parent.children);
|
|
456
|
+
const oldRetained = _utils.wrap(parent.children);
|
|
552
457
|
const newRetained = [];
|
|
553
|
-
const newChildren1 = arrayify(newChildren);
|
|
458
|
+
const newChildren1 = _utils.arrayify(newChildren);
|
|
554
459
|
const diffs = [];
|
|
555
460
|
let childrenByKey;
|
|
556
461
|
let seenKeys;
|
|
@@ -617,10 +522,10 @@ function diffChildren(adapter, root, host, ctx, scope, parent, newChildren) {
|
|
|
617
522
|
}
|
|
618
523
|
}
|
|
619
524
|
else if (ret) {
|
|
525
|
+
let candidateFound = false;
|
|
620
526
|
// we do not need to add the retainer to the graveyard if it is the
|
|
621
527
|
// fallback of another retainer
|
|
622
528
|
// search for the tag in fallback chain
|
|
623
|
-
let candidateFound = false;
|
|
624
529
|
for (let predecessor = ret, candidate = ret.fallback; candidate; predecessor = candidate, candidate = candidate.fallback) {
|
|
625
530
|
if (candidate.el.tag === child.tag) {
|
|
626
531
|
// If we find a retainer in the fallback chain with the same tag,
|
|
@@ -669,7 +574,7 @@ function diffChildren(adapter, root, host, ctx, scope, parent, newChildren) {
|
|
|
669
574
|
setFlag(ret, IsCopied, false);
|
|
670
575
|
}
|
|
671
576
|
}
|
|
672
|
-
if (isPromiseLike(diff)) {
|
|
577
|
+
if (_utils.isPromiseLike(diff)) {
|
|
673
578
|
isAsync = true;
|
|
674
579
|
}
|
|
675
580
|
}
|
|
@@ -709,7 +614,7 @@ function diffChildren(adapter, root, host, ctx, scope, parent, newChildren) {
|
|
|
709
614
|
graveyard.push(ret);
|
|
710
615
|
}
|
|
711
616
|
}
|
|
712
|
-
parent.children = unwrap(newRetained);
|
|
617
|
+
parent.children = _utils.unwrap(newRetained);
|
|
713
618
|
if (isAsync) {
|
|
714
619
|
const diffs1 = Promise.all(diffs)
|
|
715
620
|
.then(() => undefined)
|
|
@@ -727,7 +632,7 @@ function diffChildren(adapter, root, host, ctx, scope, parent, newChildren) {
|
|
|
727
632
|
}
|
|
728
633
|
});
|
|
729
634
|
let onNextDiffs;
|
|
730
|
-
const diffs2 = (parent.pendingDiff = safeRace([
|
|
635
|
+
const diffs2 = (parent.pendingDiff = _utils.safeRace([
|
|
731
636
|
diffs1,
|
|
732
637
|
new Promise((resolve) => (onNextDiffs = resolve)),
|
|
733
638
|
]));
|
|
@@ -847,7 +752,7 @@ function commit(adapter, host, ret, ctx, scope, index, schedulePromises, hydrati
|
|
|
847
752
|
}
|
|
848
753
|
}
|
|
849
754
|
if (skippedHydrationNodes) {
|
|
850
|
-
skippedHydrationNodes.splice(0, wrap(value).length);
|
|
755
|
+
skippedHydrationNodes.splice(0, _utils.wrap(value).length);
|
|
851
756
|
}
|
|
852
757
|
if (!getFlag(ret, DidCommit)) {
|
|
853
758
|
setFlag(ret, DidCommit);
|
|
@@ -862,7 +767,7 @@ function commit(adapter, host, ret, ctx, scope, index, schedulePromises, hydrati
|
|
|
862
767
|
}
|
|
863
768
|
function commitChildren(adapter, host, ctx, scope, parent, index, schedulePromises, hydrationNodes) {
|
|
864
769
|
let values = [];
|
|
865
|
-
for (let i = 0, children = wrap(parent.children); i < children.length; i++) {
|
|
770
|
+
for (let i = 0, children = _utils.wrap(parent.children); i < children.length; i++) {
|
|
866
771
|
let child = children[i];
|
|
867
772
|
let schedulePromises1;
|
|
868
773
|
let isSchedulingFallback = false;
|
|
@@ -939,7 +844,7 @@ function commitChildren(adapter, host, ctx, scope, parent, index, schedulePromis
|
|
|
939
844
|
}
|
|
940
845
|
}
|
|
941
846
|
if (schedulePromises1 && schedulePromises1.length > 1) {
|
|
942
|
-
schedulePromises.push(safeRace(schedulePromises1));
|
|
847
|
+
schedulePromises.push(_utils.safeRace(schedulePromises1));
|
|
943
848
|
}
|
|
944
849
|
if (child) {
|
|
945
850
|
const value = commit(adapter, host, child, ctx, scope, index, schedulePromises, hydrationNodes);
|
|
@@ -981,7 +886,7 @@ function commitText(adapter, ret, el, scope, hydrationNodes) {
|
|
|
981
886
|
}
|
|
982
887
|
function commitRaw(adapter, host, ret, scope, hydrationNodes) {
|
|
983
888
|
if (!ret.oldProps || ret.oldProps.value !== ret.el.props.value) {
|
|
984
|
-
const oldNodes = wrap(ret.value);
|
|
889
|
+
const oldNodes = _utils.wrap(ret.value);
|
|
985
890
|
for (let i = 0; i < oldNodes.length; i++) {
|
|
986
891
|
const oldNode = oldNodes[i];
|
|
987
892
|
adapter.remove({
|
|
@@ -1293,7 +1198,7 @@ function unmountChildren(adapter, host, ctx, ret, isNested) {
|
|
|
1293
1198
|
}
|
|
1294
1199
|
ret.graveyard = undefined;
|
|
1295
1200
|
}
|
|
1296
|
-
for (let i = 0, children = wrap(ret.children); i < children.length; i++) {
|
|
1201
|
+
for (let i = 0, children = _utils.wrap(ret.children); i < children.length; i++) {
|
|
1297
1202
|
const child = children[i];
|
|
1298
1203
|
if (typeof child === "object") {
|
|
1299
1204
|
unmount(adapter, host, ctx, child, isNested);
|
|
@@ -1446,7 +1351,7 @@ class Context extends eventTarget.CustomEventTarget {
|
|
|
1446
1351
|
}
|
|
1447
1352
|
if (callback) {
|
|
1448
1353
|
const result = callback();
|
|
1449
|
-
if (isPromiseLike(result)) {
|
|
1354
|
+
if (_utils.isPromiseLike(result)) {
|
|
1450
1355
|
return Promise.resolve(result).then(() => {
|
|
1451
1356
|
if (!getFlag(ctx.ret, IsUnmounted)) {
|
|
1452
1357
|
return this.refresh();
|
|
@@ -1455,12 +1360,15 @@ class Context extends eventTarget.CustomEventTarget {
|
|
|
1455
1360
|
});
|
|
1456
1361
|
}
|
|
1457
1362
|
}
|
|
1363
|
+
if (getFlag(ctx.ret, IsScheduling)) {
|
|
1364
|
+
setFlag(ctx.ret, IsSchedulingRefresh);
|
|
1365
|
+
}
|
|
1458
1366
|
let diff;
|
|
1459
1367
|
const schedulePromises = [];
|
|
1460
1368
|
try {
|
|
1461
1369
|
setFlag(ctx.ret, IsRefreshing);
|
|
1462
1370
|
diff = enqueueComponent(ctx);
|
|
1463
|
-
if (isPromiseLike(diff)) {
|
|
1371
|
+
if (_utils.isPromiseLike(diff)) {
|
|
1464
1372
|
return diff
|
|
1465
1373
|
.then(() => ctx.adapter.read(commitComponent(ctx, schedulePromises)))
|
|
1466
1374
|
.then((result) => {
|
|
@@ -1522,7 +1430,7 @@ class Context extends eventTarget.CustomEventTarget {
|
|
|
1522
1430
|
return ctx.adapter.read(getValue(ctx.ret));
|
|
1523
1431
|
}
|
|
1524
1432
|
finally {
|
|
1525
|
-
if (!isPromiseLike(diff)) {
|
|
1433
|
+
if (!_utils.isPromiseLike(diff)) {
|
|
1526
1434
|
setFlag(ctx.ret, IsRefreshing, false);
|
|
1527
1435
|
}
|
|
1528
1436
|
}
|
|
@@ -1736,10 +1644,10 @@ function runComponent(ctx) {
|
|
|
1736
1644
|
finally {
|
|
1737
1645
|
setFlag(ctx.ret, IsExecuting, false);
|
|
1738
1646
|
}
|
|
1739
|
-
if (isIteratorLike(returned)) {
|
|
1647
|
+
if (_utils.isIteratorLike(returned)) {
|
|
1740
1648
|
ctx.iterator = returned;
|
|
1741
1649
|
}
|
|
1742
|
-
else if (!isPromiseLike(returned)) {
|
|
1650
|
+
else if (!_utils.isPromiseLike(returned)) {
|
|
1743
1651
|
// sync function component
|
|
1744
1652
|
return [
|
|
1745
1653
|
undefined,
|
|
@@ -1771,7 +1679,7 @@ function runComponent(ctx) {
|
|
|
1771
1679
|
finally {
|
|
1772
1680
|
setFlag(ctx.ret, IsExecuting, false);
|
|
1773
1681
|
}
|
|
1774
|
-
if (isPromiseLike(iteration)) {
|
|
1682
|
+
if (_utils.isPromiseLike(iteration)) {
|
|
1775
1683
|
setFlag(ctx.ret, IsAsyncGen);
|
|
1776
1684
|
}
|
|
1777
1685
|
else {
|
|
@@ -1794,22 +1702,23 @@ function runComponent(ctx) {
|
|
|
1794
1702
|
setFlag(ctx.ret, IsExecuting, false);
|
|
1795
1703
|
}
|
|
1796
1704
|
}
|
|
1797
|
-
if (isPromiseLike(iteration)) {
|
|
1705
|
+
if (_utils.isPromiseLike(iteration)) {
|
|
1798
1706
|
throw new Error("Mixed generator component");
|
|
1799
1707
|
}
|
|
1800
1708
|
if (getFlag(ctx.ret, IsInForOfLoop) &&
|
|
1801
1709
|
!getFlag(ctx.ret, NeedsToYield) &&
|
|
1802
1710
|
!getFlag(ctx.ret, IsUnmounted) &&
|
|
1803
|
-
!getFlag(ctx.ret,
|
|
1711
|
+
!getFlag(ctx.ret, IsSchedulingRefresh)) {
|
|
1804
1712
|
console.error(`Component <${getTagName(ctx.ret.el.tag)}> yielded/returned more than once in for...of loop`);
|
|
1805
1713
|
}
|
|
1806
1714
|
setFlag(ctx.ret, NeedsToYield, false);
|
|
1715
|
+
setFlag(ctx.ret, IsSchedulingRefresh, false);
|
|
1807
1716
|
if (iteration.done) {
|
|
1808
1717
|
setFlag(ctx.ret, IsSyncGen, false);
|
|
1809
1718
|
ctx.iterator = undefined;
|
|
1810
1719
|
}
|
|
1811
1720
|
const diff = diffComponentChildren(ctx, iteration.value, !iteration.done);
|
|
1812
|
-
const block = isPromiseLike(diff) ? diff.catch(NOOP) : undefined;
|
|
1721
|
+
const block = _utils.isPromiseLike(diff) ? diff.catch(NOOP) : undefined;
|
|
1813
1722
|
return [block, diff];
|
|
1814
1723
|
}
|
|
1815
1724
|
else {
|
|
@@ -1837,7 +1746,7 @@ function runComponent(ctx) {
|
|
|
1837
1746
|
setFlag(ctx.ret, IsExecuting, false);
|
|
1838
1747
|
}
|
|
1839
1748
|
}
|
|
1840
|
-
if (!isPromiseLike(iteration)) {
|
|
1749
|
+
if (!_utils.isPromiseLike(iteration)) {
|
|
1841
1750
|
throw new Error("Mixed generator component");
|
|
1842
1751
|
}
|
|
1843
1752
|
const diff = iteration.then((iteration) => {
|
|
@@ -1849,11 +1758,12 @@ function runComponent(ctx) {
|
|
|
1849
1758
|
if (getFlag(ctx.ret, IsInForOfLoop) &&
|
|
1850
1759
|
!getFlag(ctx.ret, NeedsToYield) &&
|
|
1851
1760
|
!getFlag(ctx.ret, IsUnmounted) &&
|
|
1852
|
-
!getFlag(ctx.ret,
|
|
1761
|
+
!getFlag(ctx.ret, IsSchedulingRefresh)) {
|
|
1853
1762
|
console.error(`Component <${getTagName(ctx.ret.el.tag)}> yielded/returned more than once in for...of loop`);
|
|
1854
1763
|
}
|
|
1855
1764
|
}
|
|
1856
1765
|
setFlag(ctx.ret, NeedsToYield, false);
|
|
1766
|
+
setFlag(ctx.ret, IsSchedulingRefresh, false);
|
|
1857
1767
|
if (iteration.done) {
|
|
1858
1768
|
setFlag(ctx.ret, IsAsyncGen, false);
|
|
1859
1769
|
ctx.iterator = undefined;
|
|
@@ -1907,7 +1817,7 @@ async function pullComponent(ctx, iterationP) {
|
|
|
1907
1817
|
try {
|
|
1908
1818
|
let childError;
|
|
1909
1819
|
while (!done) {
|
|
1910
|
-
if (isPromiseLike(iterationP)) {
|
|
1820
|
+
if (_utils.isPromiseLike(iterationP)) {
|
|
1911
1821
|
ctx.pull.iterationP = iterationP;
|
|
1912
1822
|
}
|
|
1913
1823
|
let onDiff;
|
|
@@ -1994,7 +1904,7 @@ async function pullComponent(ctx, iterationP) {
|
|
|
1994
1904
|
done = !!iteration.done;
|
|
1995
1905
|
let diff;
|
|
1996
1906
|
try {
|
|
1997
|
-
if (!isPromiseLike(iterationP)) {
|
|
1907
|
+
if (!_utils.isPromiseLike(iterationP)) {
|
|
1998
1908
|
// if iterationP is an iteration and not a promise, the component was
|
|
1999
1909
|
// not in a for await...of loop when the iteration started, so we can
|
|
2000
1910
|
// skip the diffing of children as it is handled elsewhere.
|
|
@@ -2085,29 +1995,28 @@ function commitComponent(ctx, schedulePromises, hydrationNodes) {
|
|
|
2085
1995
|
});
|
|
2086
1996
|
return getValue(ctx.ret);
|
|
2087
1997
|
}
|
|
2088
|
-
const wasScheduling = getFlag(ctx.ret, IsScheduling);
|
|
2089
1998
|
const values = commitChildren(ctx.adapter, ctx.host, ctx, ctx.scope, ctx.ret, ctx.index, schedulePromises, hydrationNodes);
|
|
2090
1999
|
if (getFlag(ctx.ret, IsUnmounted)) {
|
|
2091
2000
|
return;
|
|
2092
2001
|
}
|
|
2093
2002
|
eventTarget.addEventTargetDelegates(ctx.ctx, values);
|
|
2094
2003
|
// Execute schedule callbacks early to check for async deferral
|
|
2095
|
-
const
|
|
2004
|
+
const wasScheduling = getFlag(ctx.ret, IsScheduling);
|
|
2096
2005
|
let schedulePromises1;
|
|
2006
|
+
const callbacks = scheduleMap.get(ctx);
|
|
2097
2007
|
if (callbacks) {
|
|
2098
2008
|
scheduleMap.delete(ctx);
|
|
2099
|
-
// TODO: think about error handling for schedule callbacks
|
|
2100
2009
|
setFlag(ctx.ret, IsScheduling);
|
|
2101
|
-
const result = ctx.adapter.read(unwrap(values));
|
|
2010
|
+
const result = ctx.adapter.read(_utils.unwrap(values));
|
|
2102
2011
|
for (const callback of callbacks) {
|
|
2103
2012
|
const scheduleResult = callback(result);
|
|
2104
|
-
if (isPromiseLike(scheduleResult)) {
|
|
2013
|
+
if (_utils.isPromiseLike(scheduleResult)) {
|
|
2105
2014
|
(schedulePromises1 = schedulePromises1 || []).push(scheduleResult);
|
|
2106
2015
|
}
|
|
2107
2016
|
}
|
|
2108
2017
|
if (schedulePromises1 && !getFlag(ctx.ret, DidCommit)) {
|
|
2109
2018
|
const scheduleCallbacksP = Promise.all(schedulePromises1).then(() => {
|
|
2110
|
-
setFlag(ctx.ret, IsScheduling,
|
|
2019
|
+
setFlag(ctx.ret, IsScheduling, wasScheduling);
|
|
2111
2020
|
propagateComponent(ctx);
|
|
2112
2021
|
if (ctx.ret.fallback) {
|
|
2113
2022
|
unmount(ctx.adapter, ctx.host, ctx.parent, ctx.ret.fallback, false);
|
|
@@ -2115,7 +2024,7 @@ function commitComponent(ctx, schedulePromises, hydrationNodes) {
|
|
|
2115
2024
|
ctx.ret.fallback = undefined;
|
|
2116
2025
|
});
|
|
2117
2026
|
let onAbort;
|
|
2118
|
-
const scheduleP = safeRace([
|
|
2027
|
+
const scheduleP = _utils.safeRace([
|
|
2119
2028
|
scheduleCallbacksP,
|
|
2120
2029
|
new Promise((resolve) => (onAbort = resolve)),
|
|
2121
2030
|
]).finally(() => {
|
|
@@ -2147,6 +2056,37 @@ function commitComponent(ctx, schedulePromises, hydrationNodes) {
|
|
|
2147
2056
|
// if schedule callbacks call refresh() or async mounting is happening.
|
|
2148
2057
|
return getValue(ctx.ret, true);
|
|
2149
2058
|
}
|
|
2059
|
+
/**
|
|
2060
|
+
* Checks if a target retainer is active (contributing) in the host's retainer tree.
|
|
2061
|
+
* Performs a downward traversal from host to find if target is in the active path.
|
|
2062
|
+
*/
|
|
2063
|
+
function isRetainerActive(target, host) {
|
|
2064
|
+
const stack = [host];
|
|
2065
|
+
while (stack.length > 0) {
|
|
2066
|
+
const current = stack.pop();
|
|
2067
|
+
if (current === target) {
|
|
2068
|
+
return true;
|
|
2069
|
+
}
|
|
2070
|
+
// Add direct children to stack (skip if this is a host boundary)
|
|
2071
|
+
// Host boundaries are: DOM elements (string tags) or Portal, but NOT Fragment
|
|
2072
|
+
const isHostBoundary = current !== host &&
|
|
2073
|
+
((typeof current.el.tag === "string" && current.el.tag !== Fragment) ||
|
|
2074
|
+
current.el.tag === Portal);
|
|
2075
|
+
if (current.children && !isHostBoundary) {
|
|
2076
|
+
const children = _utils.wrap(current.children);
|
|
2077
|
+
for (const child of children) {
|
|
2078
|
+
if (child) {
|
|
2079
|
+
stack.push(child);
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
// Add fallback chains (only if current retainer is using fallback)
|
|
2084
|
+
if (current.fallback && !getFlag(current, DidDiff)) {
|
|
2085
|
+
stack.push(current.fallback);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
return false;
|
|
2089
|
+
}
|
|
2150
2090
|
/**
|
|
2151
2091
|
* Propagates component changes up to ancestors when rendering starts from a
|
|
2152
2092
|
* component via refresh() or multiple for await...of renders. This handles
|
|
@@ -2157,14 +2097,20 @@ function propagateComponent(ctx) {
|
|
|
2157
2097
|
const values = getChildValues(ctx.ret, ctx.index);
|
|
2158
2098
|
eventTarget.addEventTargetDelegates(ctx.ctx, values, (ctx1) => ctx1[_ContextState].host === ctx.host);
|
|
2159
2099
|
const host = ctx.host;
|
|
2100
|
+
const initiator = ctx.ret;
|
|
2101
|
+
// Check if initiator is active in the host's tree
|
|
2102
|
+
if (!isRetainerActive(initiator, host)) {
|
|
2103
|
+
return;
|
|
2104
|
+
}
|
|
2160
2105
|
const props = stripSpecialProps(host.el.props);
|
|
2106
|
+
const hostChildren = getChildValues(host, 0);
|
|
2161
2107
|
ctx.adapter.arrange({
|
|
2162
2108
|
tag: host.el.tag,
|
|
2163
2109
|
tagName: getTagName(host.el.tag),
|
|
2164
2110
|
node: host.value,
|
|
2165
2111
|
props,
|
|
2166
2112
|
oldProps: props,
|
|
2167
|
-
children:
|
|
2113
|
+
children: hostChildren,
|
|
2168
2114
|
});
|
|
2169
2115
|
flush(ctx.adapter, ctx.root, ctx);
|
|
2170
2116
|
}
|
|
@@ -2180,7 +2126,7 @@ async function unmountComponent(ctx, isNested) {
|
|
|
2180
2126
|
cleanupMap.delete(ctx);
|
|
2181
2127
|
for (const callback of callbacks) {
|
|
2182
2128
|
const cleanup = callback(oldResult);
|
|
2183
|
-
if (isPromiseLike(cleanup)) {
|
|
2129
|
+
if (_utils.isPromiseLike(cleanup)) {
|
|
2184
2130
|
(cleanupPromises = cleanupPromises || []).push(cleanup);
|
|
2185
2131
|
}
|
|
2186
2132
|
}
|
|
@@ -2243,7 +2189,7 @@ async function unmountComponent(ctx, isNested) {
|
|
|
2243
2189
|
setFlag(ctx.ret, IsExecuting);
|
|
2244
2190
|
const oldResult = ctx.adapter.read(getValue(ctx.ret));
|
|
2245
2191
|
const iterationP = ctx.iterator.next(oldResult);
|
|
2246
|
-
if (isPromiseLike(iterationP)) {
|
|
2192
|
+
if (_utils.isPromiseLike(iterationP)) {
|
|
2247
2193
|
if (!getFlag(ctx.ret, IsAsyncGen)) {
|
|
2248
2194
|
throw new Error("Mixed generator component");
|
|
2249
2195
|
}
|
|
@@ -2270,7 +2216,7 @@ async function unmountComponent(ctx, isNested) {
|
|
|
2270
2216
|
try {
|
|
2271
2217
|
setFlag(ctx.ret, IsExecuting);
|
|
2272
2218
|
const iterationP = ctx.iterator.return();
|
|
2273
|
-
if (isPromiseLike(iterationP)) {
|
|
2219
|
+
if (_utils.isPromiseLike(iterationP)) {
|
|
2274
2220
|
if (!getFlag(ctx.ret, IsAsyncGen)) {
|
|
2275
2221
|
throw new Error("Mixed generator component");
|
|
2276
2222
|
}
|
|
@@ -2319,7 +2265,7 @@ function handleChildError(ctx, err) {
|
|
|
2319
2265
|
finally {
|
|
2320
2266
|
setFlag(ctx.ret, IsExecuting, false);
|
|
2321
2267
|
}
|
|
2322
|
-
if (isPromiseLike(iteration)) {
|
|
2268
|
+
if (_utils.isPromiseLike(iteration)) {
|
|
2323
2269
|
return iteration.then((iteration) => {
|
|
2324
2270
|
if (iteration.done) {
|
|
2325
2271
|
setFlag(ctx.ret, IsSyncGen, false);
|
|
@@ -2358,7 +2304,7 @@ function propagateError(ctx, err, schedulePromises) {
|
|
|
2358
2304
|
catch (err) {
|
|
2359
2305
|
return propagateError(parent, err, schedulePromises);
|
|
2360
2306
|
}
|
|
2361
|
-
if (isPromiseLike(diff)) {
|
|
2307
|
+
if (_utils.isPromiseLike(diff)) {
|
|
2362
2308
|
return diff.then(() => void commitComponent(parent, schedulePromises), (err) => propagateError(parent, err, schedulePromises));
|
|
2363
2309
|
}
|
|
2364
2310
|
commitComponent(parent, schedulePromises);
|