octane 0.1.26 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime.js +138 -52
- package/dist/universal-core.js +266 -66
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -1184,12 +1184,18 @@ function drainQueue() {
|
|
|
1184
1184
|
}
|
|
1185
1185
|
const crossRenderUpdate = block.crossRenderUpdate;
|
|
1186
1186
|
block.crossRenderUpdate = false;
|
|
1187
|
+
const hiddenOwner = findHiddenRenderOwner(block, true);
|
|
1188
|
+
let hiddenActivity = null;
|
|
1189
|
+
let hiddenTry = null;
|
|
1190
|
+
if (hiddenOwner !== null) {
|
|
1191
|
+
if (hiddenOwner.__kind === "trySlotSlot") hiddenTry = hiddenOwner;
|
|
1192
|
+
else hiddenActivity = hiddenOwner;
|
|
1193
|
+
}
|
|
1187
1194
|
try {
|
|
1188
1195
|
if (block.nestedUpdateError) {
|
|
1189
1196
|
block.nestedUpdateError = false;
|
|
1190
1197
|
throw maximumUpdateDepthError();
|
|
1191
1198
|
}
|
|
1192
|
-
const hiddenTry = findSuspenseHiddenTry(block);
|
|
1193
1199
|
if (hiddenTry !== null) {
|
|
1194
1200
|
attemptHiddenReveal(hiddenTry, block.pendingMode ?? "urgent");
|
|
1195
1201
|
continue;
|
|
@@ -1221,6 +1227,8 @@ function drainQueue() {
|
|
|
1221
1227
|
while (root.parentBlock !== null) root = root.parentBlock;
|
|
1222
1228
|
if (root.kind === "root" && !root.disposed) unmountBlock(root);
|
|
1223
1229
|
}
|
|
1230
|
+
} finally {
|
|
1231
|
+
if (hiddenActivity !== null) rehideActivityAfterDescendantRender(hiddenActivity);
|
|
1224
1232
|
}
|
|
1225
1233
|
}
|
|
1226
1234
|
QUEUE.length = 0;
|
|
@@ -10700,8 +10708,63 @@ function setTransitionFallbackTimeout(ms) {
|
|
|
10700
10708
|
function getTransitionFallbackTimeout() {
|
|
10701
10709
|
return TRANSITION_FALLBACK_TIMEOUT_MS;
|
|
10702
10710
|
}
|
|
10703
|
-
const
|
|
10704
|
-
const
|
|
10711
|
+
const HIDDEN_DISPLAYS = /* @__PURE__ */ new WeakMap();
|
|
10712
|
+
const HIDDEN_TEXTS = /* @__PURE__ */ new WeakMap();
|
|
10713
|
+
function enforceHiddenDisplay(el) {
|
|
10714
|
+
const hidden = HIDDEN_DISPLAYS.get(el);
|
|
10715
|
+
el.style.setProperty(
|
|
10716
|
+
"display",
|
|
10717
|
+
"none",
|
|
10718
|
+
hidden !== void 0 && hidden.importantOwners > 0 ? "important" : ""
|
|
10719
|
+
);
|
|
10720
|
+
}
|
|
10721
|
+
function retainHiddenDisplay(el, important) {
|
|
10722
|
+
const existing = HIDDEN_DISPLAYS.get(el);
|
|
10723
|
+
if (existing === void 0) {
|
|
10724
|
+
HIDDEN_DISPLAYS.set(el, {
|
|
10725
|
+
owners: 1,
|
|
10726
|
+
importantOwners: important ? 1 : 0,
|
|
10727
|
+
value: el.style.getPropertyValue("display"),
|
|
10728
|
+
priority: el.style.getPropertyPriority("display"),
|
|
10729
|
+
hadStyle: el.hasAttribute("style")
|
|
10730
|
+
});
|
|
10731
|
+
} else {
|
|
10732
|
+
existing.owners++;
|
|
10733
|
+
if (important) existing.importantOwners++;
|
|
10734
|
+
}
|
|
10735
|
+
enforceHiddenDisplay(el);
|
|
10736
|
+
}
|
|
10737
|
+
function releaseHiddenDisplay(el, important) {
|
|
10738
|
+
const display = HIDDEN_DISPLAYS.get(el);
|
|
10739
|
+
if (display === void 0) return;
|
|
10740
|
+
if (important) display.importantOwners--;
|
|
10741
|
+
if (--display.owners === 0) {
|
|
10742
|
+
HIDDEN_DISPLAYS.delete(el);
|
|
10743
|
+
if (display.value === "") el.style.removeProperty("display");
|
|
10744
|
+
else el.style.setProperty("display", display.value, display.priority);
|
|
10745
|
+
if (!display.hadStyle && el.getAttribute("style") === "") el.removeAttribute("style");
|
|
10746
|
+
} else {
|
|
10747
|
+
enforceHiddenDisplay(el);
|
|
10748
|
+
}
|
|
10749
|
+
}
|
|
10750
|
+
function enforceHiddenText(text) {
|
|
10751
|
+
if (text.data !== "") text.data = "";
|
|
10752
|
+
}
|
|
10753
|
+
function retainHiddenText(text) {
|
|
10754
|
+
const existing = HIDDEN_TEXTS.get(text);
|
|
10755
|
+
if (existing === void 0) HIDDEN_TEXTS.set(text, { owners: 1, data: text.data });
|
|
10756
|
+
else existing.owners++;
|
|
10757
|
+
}
|
|
10758
|
+
function releaseHiddenText(text) {
|
|
10759
|
+
const saved = HIDDEN_TEXTS.get(text);
|
|
10760
|
+
if (saved === void 0) return;
|
|
10761
|
+
if (--saved.owners === 0) {
|
|
10762
|
+
HIDDEN_TEXTS.delete(text);
|
|
10763
|
+
text.data = saved.data;
|
|
10764
|
+
} else {
|
|
10765
|
+
enforceHiddenText(text);
|
|
10766
|
+
}
|
|
10767
|
+
}
|
|
10705
10768
|
function setTryBranch(slot, next) {
|
|
10706
10769
|
slot.branch = next;
|
|
10707
10770
|
if (typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__) {
|
|
@@ -11063,31 +11126,17 @@ function hideBlockHostRange(block, hidden) {
|
|
|
11063
11126
|
const el = node;
|
|
11064
11127
|
if (!hidden.displays.has(el)) {
|
|
11065
11128
|
hidden.displays.add(el);
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
owners: 1,
|
|
11070
|
-
value: el.style.getPropertyValue("display"),
|
|
11071
|
-
priority: el.style.getPropertyPriority("display"),
|
|
11072
|
-
hadStyle: el.hasAttribute("style")
|
|
11073
|
-
});
|
|
11074
|
-
} else {
|
|
11075
|
-
existing.owners++;
|
|
11076
|
-
}
|
|
11129
|
+
retainHiddenDisplay(el, true);
|
|
11130
|
+
} else {
|
|
11131
|
+
enforceHiddenDisplay(el);
|
|
11077
11132
|
}
|
|
11078
|
-
el.style.setProperty("display", "none", "important");
|
|
11079
11133
|
} else if (node.nodeType === 3) {
|
|
11080
11134
|
const text = node;
|
|
11081
11135
|
if (!hidden.texts.has(text)) {
|
|
11082
11136
|
hidden.texts.add(text);
|
|
11083
|
-
|
|
11084
|
-
if (existing === void 0) {
|
|
11085
|
-
SUSPENSE_HIDDEN_TEXTS.set(text, { owners: 1, data: text.data });
|
|
11086
|
-
} else {
|
|
11087
|
-
existing.owners++;
|
|
11088
|
-
}
|
|
11137
|
+
retainHiddenText(text);
|
|
11089
11138
|
}
|
|
11090
|
-
|
|
11139
|
+
enforceHiddenText(text);
|
|
11091
11140
|
}
|
|
11092
11141
|
node = node.nextSibling;
|
|
11093
11142
|
}
|
|
@@ -11115,26 +11164,10 @@ function showTryBlock(state) {
|
|
|
11115
11164
|
if (hidden === null) return;
|
|
11116
11165
|
state.hiddenDom = null;
|
|
11117
11166
|
for (const el of hidden.displays) {
|
|
11118
|
-
|
|
11119
|
-
if (display === void 0) continue;
|
|
11120
|
-
if (--display.owners === 0) {
|
|
11121
|
-
SUSPENSE_HIDDEN_DISPLAYS.delete(el);
|
|
11122
|
-
if (display.value === "") el.style.removeProperty("display");
|
|
11123
|
-
else el.style.setProperty("display", display.value, display.priority);
|
|
11124
|
-
if (!display.hadStyle && el.getAttribute("style") === "") el.removeAttribute("style");
|
|
11125
|
-
} else {
|
|
11126
|
-
el.style.setProperty("display", "none", "important");
|
|
11127
|
-
}
|
|
11167
|
+
releaseHiddenDisplay(el, true);
|
|
11128
11168
|
}
|
|
11129
11169
|
for (const text of hidden.texts) {
|
|
11130
|
-
|
|
11131
|
-
if (saved === void 0) continue;
|
|
11132
|
-
if (--saved.owners === 0) {
|
|
11133
|
-
SUSPENSE_HIDDEN_TEXTS.delete(text);
|
|
11134
|
-
text.data = saved.data;
|
|
11135
|
-
} else if (text.data !== "") {
|
|
11136
|
-
text.data = "";
|
|
11137
|
-
}
|
|
11170
|
+
releaseHiddenText(text);
|
|
11138
11171
|
}
|
|
11139
11172
|
}
|
|
11140
11173
|
function releaseHeldTransition(state) {
|
|
@@ -11286,6 +11319,7 @@ function commitResume(state) {
|
|
|
11286
11319
|
}
|
|
11287
11320
|
function commitResumeInner(state) {
|
|
11288
11321
|
if (state.parentBlock.disposed) return;
|
|
11322
|
+
const hiddenActivity = findHiddenActivity(state.parentBlock);
|
|
11289
11323
|
const wasHeld = state.transitionHeld;
|
|
11290
11324
|
if (wasHeld) state.transitionHeld = false;
|
|
11291
11325
|
HELD_TRANSITIONS.delete(state);
|
|
@@ -11377,14 +11411,33 @@ function commitResumeInner(state) {
|
|
|
11377
11411
|
}
|
|
11378
11412
|
if (!deferringStagedRevealEffects) commitEffects();
|
|
11379
11413
|
} finally {
|
|
11414
|
+
if (hiddenActivity !== null) rehideActivityAfterDescendantRender(hiddenActivity);
|
|
11380
11415
|
if (wasHeld) tickTransitionCount(-1);
|
|
11381
11416
|
}
|
|
11382
11417
|
}
|
|
11383
|
-
function
|
|
11418
|
+
function findHiddenRenderOwner(block, includeActivity) {
|
|
11419
|
+
let activity = null;
|
|
11384
11420
|
for (let p = block; p !== null; p = p.parentBlock) {
|
|
11421
|
+
if (includeActivity && activity === null && p.inactive) {
|
|
11422
|
+
const candidate = p.__activitySlot;
|
|
11423
|
+
if (candidate !== void 0 && candidate.block === p && candidate.hidden) {
|
|
11424
|
+
activity = candidate;
|
|
11425
|
+
}
|
|
11426
|
+
}
|
|
11385
11427
|
const slot = p.__trySlot;
|
|
11386
11428
|
if (slot !== void 0 && slot.tryBlock === p && slot.hiddenDom !== null) return slot;
|
|
11387
11429
|
}
|
|
11430
|
+
return activity;
|
|
11431
|
+
}
|
|
11432
|
+
function findSuspenseHiddenTry(block) {
|
|
11433
|
+
return findHiddenRenderOwner(block, false);
|
|
11434
|
+
}
|
|
11435
|
+
function findHiddenActivity(block) {
|
|
11436
|
+
for (let p = block; p !== null; p = p.parentBlock) {
|
|
11437
|
+
if (!p.inactive) continue;
|
|
11438
|
+
const candidate = p.__activitySlot;
|
|
11439
|
+
if (candidate !== void 0 && candidate.block === p && candidate.hidden) return candidate;
|
|
11440
|
+
}
|
|
11388
11441
|
return null;
|
|
11389
11442
|
}
|
|
11390
11443
|
function snapshotSubtreeEffectDeps(scope) {
|
|
@@ -11500,11 +11553,19 @@ function queueCurrentHiddenRefs(state) {
|
|
|
11500
11553
|
}
|
|
11501
11554
|
}
|
|
11502
11555
|
function attemptHiddenReveal(state, scheduledMode) {
|
|
11556
|
+
const hiddenActivity = findHiddenActivity(state.tryBlock);
|
|
11557
|
+
try {
|
|
11558
|
+
attemptHiddenRevealInner(state, scheduledMode);
|
|
11559
|
+
} finally {
|
|
11560
|
+
if (hiddenActivity !== null) rehideActivityAfterDescendantRender(hiddenActivity);
|
|
11561
|
+
}
|
|
11562
|
+
}
|
|
11563
|
+
function attemptHiddenRevealInner(state, scheduledMode) {
|
|
11503
11564
|
const tryBlock2 = state.tryBlock;
|
|
11504
11565
|
if (tryBlock2 === null || tryBlock2.disposed || state.hiddenDom === null) return;
|
|
11505
11566
|
const hiddenAncestor = findSuspenseHiddenTry(tryBlock2.parentBlock);
|
|
11506
11567
|
if (hiddenAncestor !== null) {
|
|
11507
|
-
|
|
11568
|
+
attemptHiddenRevealInner(hiddenAncestor, scheduledMode);
|
|
11508
11569
|
return;
|
|
11509
11570
|
}
|
|
11510
11571
|
STAGED_REVEALS.delete(state);
|
|
@@ -12492,25 +12553,49 @@ function ifBlock(parentScope, slotKey, domParent, cond, thenBody, elseBody, anch
|
|
|
12492
12553
|
function hideActivityRange(state) {
|
|
12493
12554
|
const b = state.block;
|
|
12494
12555
|
if (!b) return;
|
|
12556
|
+
for (const el of state.hiddenDisplays) {
|
|
12557
|
+
if (el.parentNode !== b.parentNode) {
|
|
12558
|
+
state.hiddenDisplays.delete(el);
|
|
12559
|
+
releaseHiddenDisplay(el, false);
|
|
12560
|
+
}
|
|
12561
|
+
}
|
|
12562
|
+
for (const text of state.hiddenTexts) {
|
|
12563
|
+
if (text.parentNode !== b.parentNode) {
|
|
12564
|
+
state.hiddenTexts.delete(text);
|
|
12565
|
+
releaseHiddenText(text);
|
|
12566
|
+
}
|
|
12567
|
+
}
|
|
12495
12568
|
let node = b.startMarker.nextSibling;
|
|
12496
12569
|
while (node && node !== b.endMarker) {
|
|
12497
12570
|
if (node.nodeType === 1) {
|
|
12498
12571
|
const el = node;
|
|
12499
|
-
if (!state.
|
|
12500
|
-
|
|
12572
|
+
if (!state.hiddenDisplays.has(el)) {
|
|
12573
|
+
state.hiddenDisplays.add(el);
|
|
12574
|
+
retainHiddenDisplay(el, false);
|
|
12575
|
+
} else {
|
|
12576
|
+
enforceHiddenDisplay(el);
|
|
12577
|
+
}
|
|
12501
12578
|
} else if (node.nodeType === 3) {
|
|
12502
12579
|
const t = node;
|
|
12503
|
-
if (!state.
|
|
12504
|
-
|
|
12580
|
+
if (!state.hiddenTexts.has(t)) {
|
|
12581
|
+
state.hiddenTexts.add(t);
|
|
12582
|
+
retainHiddenText(t);
|
|
12583
|
+
}
|
|
12584
|
+
enforceHiddenText(t);
|
|
12505
12585
|
}
|
|
12506
12586
|
node = node.nextSibling;
|
|
12507
12587
|
}
|
|
12508
12588
|
}
|
|
12589
|
+
function rehideActivityAfterDescendantRender(state) {
|
|
12590
|
+
const b = state.block;
|
|
12591
|
+
if (b === null || !state.hidden || state.deactivationPending || blockSubtreeDisposed(b)) return;
|
|
12592
|
+
hideActivityRange(state);
|
|
12593
|
+
}
|
|
12509
12594
|
function showActivityRange(state) {
|
|
12510
|
-
for (const
|
|
12511
|
-
state.
|
|
12512
|
-
for (const
|
|
12513
|
-
state.
|
|
12595
|
+
for (const el of state.hiddenDisplays) releaseHiddenDisplay(el, false);
|
|
12596
|
+
state.hiddenDisplays.clear();
|
|
12597
|
+
for (const text of state.hiddenTexts) releaseHiddenText(text);
|
|
12598
|
+
state.hiddenTexts.clear();
|
|
12514
12599
|
}
|
|
12515
12600
|
function queueActivityDeactivation(state, block, commitVersion) {
|
|
12516
12601
|
enqueueEffectEventCommitAction(() => {
|
|
@@ -12560,9 +12645,10 @@ function activityBlock(parentScope, slotKey, domParent, mode, body, anchor, env)
|
|
|
12560
12645
|
hidden: false,
|
|
12561
12646
|
commitVersion: 0,
|
|
12562
12647
|
deactivationPending: false,
|
|
12563
|
-
|
|
12564
|
-
|
|
12648
|
+
hiddenDisplays: /* @__PURE__ */ new Set(),
|
|
12649
|
+
hiddenTexts: /* @__PURE__ */ new Set()
|
|
12565
12650
|
};
|
|
12651
|
+
b2.__activitySlot = state;
|
|
12566
12652
|
parentScope.slots[slotKey] = state;
|
|
12567
12653
|
registerSlot(parentScope, state);
|
|
12568
12654
|
const adopted = open !== null;
|
package/dist/universal-core.js
CHANGED
|
@@ -617,6 +617,7 @@ function createOwnerRecord(root, component, parent, identityPath, key) {
|
|
|
617
617
|
renderer: root.renderer,
|
|
618
618
|
component,
|
|
619
619
|
componentProps: null,
|
|
620
|
+
componentRevision: 0,
|
|
620
621
|
parent,
|
|
621
622
|
identityPath,
|
|
622
623
|
key,
|
|
@@ -625,6 +626,7 @@ function createOwnerRecord(root, component, parent, identityPath, key) {
|
|
|
625
626
|
hooks: /* @__PURE__ */ new Map(),
|
|
626
627
|
effectOrder: [],
|
|
627
628
|
children: [],
|
|
629
|
+
dirtyEpoch: 0,
|
|
628
630
|
range: null,
|
|
629
631
|
contextValues: null,
|
|
630
632
|
updates: /* @__PURE__ */ new Map(),
|
|
@@ -642,13 +644,16 @@ function draftOwner(record, parent, replayPath) {
|
|
|
642
644
|
return {
|
|
643
645
|
record,
|
|
644
646
|
componentProps: record.componentProps,
|
|
647
|
+
componentRevision: record.componentRevision,
|
|
645
648
|
parent,
|
|
646
649
|
replayPath,
|
|
647
650
|
hooks: new Map(record.hooks),
|
|
648
651
|
clonedHooks: /* @__PURE__ */ new Set(),
|
|
649
652
|
seenEffects: [],
|
|
650
653
|
children: [],
|
|
654
|
+
retainedChildren: null,
|
|
651
655
|
claimedChildren: /* @__PURE__ */ new Set(),
|
|
656
|
+
sequentialClaimCursor: 0,
|
|
652
657
|
childOwnerBuckets: null,
|
|
653
658
|
childClaimCursors: null,
|
|
654
659
|
childReplayOrdinals: null,
|
|
@@ -661,7 +666,8 @@ function draftOwner(record, parent, replayPath) {
|
|
|
661
666
|
boundaryThenable: record.boundaryThenable,
|
|
662
667
|
isBoundary: record.isBoundary,
|
|
663
668
|
canHandleSuspense: record.canHandleSuspense,
|
|
664
|
-
visibility: parent?.visibility ?? record.visibility
|
|
669
|
+
visibility: parent?.visibility ?? record.visibility,
|
|
670
|
+
contextStable: null
|
|
665
671
|
};
|
|
666
672
|
}
|
|
667
673
|
function childReplayPath(parent, component, identityPath, key) {
|
|
@@ -686,30 +692,79 @@ function childOwnerBucket(parent, component, identityPath, key) {
|
|
|
686
692
|
}
|
|
687
693
|
return readOwnerIdentity(buckets, component, identityPath, key);
|
|
688
694
|
}
|
|
689
|
-
function
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
);
|
|
695
|
+
function identityPathsEqual(left, right) {
|
|
696
|
+
if (left === right) return true;
|
|
697
|
+
if (left.length !== right.length) return false;
|
|
698
|
+
for (let index = 0; index < left.length; index++) {
|
|
699
|
+
if (!Object.is(left[index], right[index])) return false;
|
|
700
|
+
}
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
function findClaimableChildRecord(parent, component, identityPath, key) {
|
|
704
|
+
if (parent.childOwnerBuckets === null) {
|
|
705
|
+
const candidate = parent.record.children[parent.sequentialClaimCursor];
|
|
706
|
+
if (candidate !== void 0 && candidate.component === component && Object.is(candidate.key, key) && identityPathsEqual(candidate.identityPath, identityPath) && !parent.claimedChildren.has(candidate)) {
|
|
707
|
+
parent.sequentialClaimCursor++;
|
|
708
|
+
return candidate;
|
|
709
|
+
}
|
|
705
710
|
}
|
|
706
|
-
|
|
711
|
+
const bucket = childOwnerBucket(parent, component, identityPath, key);
|
|
712
|
+
if (bucket === void 0) return void 0;
|
|
713
|
+
const cursors = parent.childClaimCursors ??= createOwnerIdentityIndex();
|
|
714
|
+
let cursor = readOwnerIdentity(cursors, component, identityPath, key) ?? 0;
|
|
715
|
+
while (cursor < bucket.length && parent.claimedChildren.has(bucket[cursor])) cursor++;
|
|
716
|
+
const record = bucket[cursor];
|
|
717
|
+
writeOwnerIdentity(
|
|
718
|
+
cursors,
|
|
719
|
+
component,
|
|
720
|
+
identityPath,
|
|
721
|
+
key,
|
|
722
|
+
cursor + (record === void 0 ? 0 : 1)
|
|
723
|
+
);
|
|
724
|
+
return record;
|
|
725
|
+
}
|
|
726
|
+
function adoptChildOwner(parent, record, component, identityPath, key) {
|
|
727
|
+
const attempt = currentAttempt();
|
|
707
728
|
parent.claimedChildren.add(record);
|
|
708
729
|
const draft = draftOwner(record, parent, childReplayPath(parent, component, identityPath, key));
|
|
709
730
|
parent.children.push(draft);
|
|
710
731
|
attempt.owners.push(draft);
|
|
711
732
|
return draft;
|
|
712
733
|
}
|
|
734
|
+
function claimChildOwner(parent, component, identityPath, key) {
|
|
735
|
+
const record = findClaimableChildRecord(parent, component, identityPath, key) ?? createOwnerRecord(currentAttempt().root, component, parent.record, identityPath, key);
|
|
736
|
+
return adoptChildOwner(parent, record, component, identityPath, key);
|
|
737
|
+
}
|
|
738
|
+
function ancestorContextsStable(owner) {
|
|
739
|
+
if (owner.contextStable !== null) return owner.contextStable;
|
|
740
|
+
let stable = owner.parent === null ? true : ancestorContextsStable(owner.parent);
|
|
741
|
+
if (stable && owner.contextValues !== null) {
|
|
742
|
+
const committed = owner.record.mounted ? owner.record.contextValues : null;
|
|
743
|
+
if (committed === null) {
|
|
744
|
+
stable = owner.contextValues.size === 0;
|
|
745
|
+
} else if (committed.size !== owner.contextValues.size) {
|
|
746
|
+
stable = false;
|
|
747
|
+
} else {
|
|
748
|
+
for (const [context, value] of owner.contextValues) {
|
|
749
|
+
if (!committed.has(context) || !Object.is(committed.get(context), value)) {
|
|
750
|
+
stable = false;
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
owner.contextStable = stable;
|
|
757
|
+
return stable;
|
|
758
|
+
}
|
|
759
|
+
function ownerSubtreeRetainable(owner) {
|
|
760
|
+
if (owner.updates.size !== 0 || owner.visibility !== "visible" || owner.isBoundary && (owner.hasBoundaryError || owner.boundaryThenable !== null) || owner.component?.__warm !== void 0 || owner.component !== null && universalComponentRevision(owner.component) !== owner.componentRevision) {
|
|
761
|
+
return false;
|
|
762
|
+
}
|
|
763
|
+
for (const child of owner.children) {
|
|
764
|
+
if (!ownerSubtreeRetainable(child)) return false;
|
|
765
|
+
}
|
|
766
|
+
return true;
|
|
767
|
+
}
|
|
713
768
|
function activateLazyLeafOwner() {
|
|
714
769
|
const scope = CURRENT_LAZY_LEAF_OWNER;
|
|
715
770
|
const attempt = CURRENT_ATTEMPT;
|
|
@@ -759,9 +814,12 @@ function executeOwner(owner, build, initialRenderCount = 0) {
|
|
|
759
814
|
if (renderCount > 0) resetDraftChildren(owner);
|
|
760
815
|
owner.seenEffects = [];
|
|
761
816
|
owner.children = [];
|
|
817
|
+
owner.retainedChildren = null;
|
|
762
818
|
owner.claimedChildren = /* @__PURE__ */ new Set();
|
|
819
|
+
owner.sequentialClaimCursor = 0;
|
|
763
820
|
owner.childClaimCursors = null;
|
|
764
821
|
owner.childReplayOrdinals = null;
|
|
822
|
+
owner.contextStable = null;
|
|
765
823
|
owner.needsRender = false;
|
|
766
824
|
owner.implicitSlot = 0;
|
|
767
825
|
const previousOwner = CURRENT_OWNER;
|
|
@@ -846,7 +904,35 @@ function materializeComponentValue(value, expectedRenderer, path) {
|
|
|
846
904
|
const parent = CURRENT_OWNER;
|
|
847
905
|
if (parent === null) throw new Error("A nested universal component requires an owner.");
|
|
848
906
|
const normalized = normalizePropsValue(value.props);
|
|
849
|
-
const
|
|
907
|
+
const key = value.hasKey ? value.key : null;
|
|
908
|
+
const attempt = currentAttempt();
|
|
909
|
+
const record = findClaimableChildRecord(parent, value.component, path, key);
|
|
910
|
+
if (attempt.retainEligible && record !== void 0 && record.mounted && !record.disposed && record.dirtyEpoch !== attempt.dirtyEpoch && record.visibility === "visible" && parent.visibility === "visible" && record.componentProps !== null && universalShallowEqual(record.componentProps, normalized.props) && record.range !== null && record.range.owner === record && ancestorContextsStable(parent) && ownerSubtreeRetainable(record)) {
|
|
911
|
+
const features = logicalTreeFeatures(record.range);
|
|
912
|
+
if ((features & (UNIVERSAL_TREE_PORTAL | UNIVERSAL_TREE_REGION)) === 0) {
|
|
913
|
+
parent.claimedChildren.add(record);
|
|
914
|
+
(parent.retainedChildren ??= []).push({ record, position: parent.children.length });
|
|
915
|
+
attempt.treeFeatures |= features;
|
|
916
|
+
attempt.retainedCount++;
|
|
917
|
+
return [
|
|
918
|
+
{
|
|
919
|
+
kind: "range",
|
|
920
|
+
key: record.range.key,
|
|
921
|
+
owner: record,
|
|
922
|
+
retained: record.range,
|
|
923
|
+
children: []
|
|
924
|
+
}
|
|
925
|
+
];
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
const owner = adoptChildOwner(
|
|
929
|
+
parent,
|
|
930
|
+
record ?? createOwnerRecord(attempt.root, value.component, parent.record, path, key),
|
|
931
|
+
value.component,
|
|
932
|
+
path,
|
|
933
|
+
key
|
|
934
|
+
);
|
|
935
|
+
owner.componentRevision = universalComponentRevision(value.component);
|
|
850
936
|
const props = { ...normalized.props };
|
|
851
937
|
owner.componentProps = props;
|
|
852
938
|
const nodes = executeOwner(owner, () => {
|
|
@@ -886,7 +972,9 @@ function disposeUncommittedDraft(owner) {
|
|
|
886
972
|
function resetDraftChildren(owner) {
|
|
887
973
|
for (const child of owner.children) disposeUncommittedDraft(child);
|
|
888
974
|
owner.children = [];
|
|
975
|
+
owner.retainedChildren = null;
|
|
889
976
|
owner.claimedChildren = /* @__PURE__ */ new Set();
|
|
977
|
+
owner.sequentialClaimCursor = 0;
|
|
890
978
|
owner.childClaimCursors = null;
|
|
891
979
|
owner.childReplayOrdinals = null;
|
|
892
980
|
}
|
|
@@ -895,7 +983,9 @@ function retainCommittedOwnerTree(owner) {
|
|
|
895
983
|
owner.seenEffects = [...owner.record.effectOrder];
|
|
896
984
|
owner.contextValues = owner.record.contextValues === null ? null : new Map(owner.record.contextValues);
|
|
897
985
|
owner.children = [];
|
|
986
|
+
owner.retainedChildren = null;
|
|
898
987
|
owner.claimedChildren = new Set(owner.record.children);
|
|
988
|
+
owner.sequentialClaimCursor = 0;
|
|
899
989
|
owner.childClaimCursors = null;
|
|
900
990
|
owner.childReplayOrdinals = null;
|
|
901
991
|
for (const childRecord of owner.record.children) {
|
|
@@ -1773,11 +1863,12 @@ function physicalRecords(records) {
|
|
|
1773
1863
|
}
|
|
1774
1864
|
return output;
|
|
1775
1865
|
}
|
|
1776
|
-
function physicalDrafts(
|
|
1866
|
+
function physicalDrafts(drafts) {
|
|
1777
1867
|
const output = [];
|
|
1778
|
-
for (const
|
|
1779
|
-
if (
|
|
1780
|
-
else if (
|
|
1868
|
+
for (const draft of drafts) {
|
|
1869
|
+
if (draft.record.kind === "host") output.push(draft.record);
|
|
1870
|
+
else if (draft.retained === true) output.push(...physicalRecords(draft.record.children));
|
|
1871
|
+
else if (draft.record.kind === "range") output.push(...physicalDrafts(draft.children));
|
|
1781
1872
|
}
|
|
1782
1873
|
return output;
|
|
1783
1874
|
}
|
|
@@ -1842,6 +1933,10 @@ function stableLogicalChildren(records, blueprints) {
|
|
|
1842
1933
|
for (let index = 0; index < records.length; index++) {
|
|
1843
1934
|
const record = records[index];
|
|
1844
1935
|
const blueprint = blueprints[index];
|
|
1936
|
+
if (blueprint.kind === "range" && blueprint.retained !== void 0) {
|
|
1937
|
+
if (blueprint.retained === record) continue;
|
|
1938
|
+
return false;
|
|
1939
|
+
}
|
|
1845
1940
|
if (blueprint.kind === "range" && blueprint.compactLeafList !== void 0 || !sameRecordShape(record, blueprint) || !stableLogicalChildren(record.children, blueprint.children)) {
|
|
1846
1941
|
return false;
|
|
1847
1942
|
}
|
|
@@ -3469,6 +3564,12 @@ class UniversalRootImpl {
|
|
|
3469
3564
|
scheduledFullRoot = false;
|
|
3470
3565
|
scheduledOwners = /* @__PURE__ */ new Set();
|
|
3471
3566
|
scheduledPreparationDepth = 0;
|
|
3567
|
+
// The current dirty epoch: scheduleOwned() stamps it on the scheduled owner
|
|
3568
|
+
// and its ancestors, and prepare() bumps it as it consumes the batch, so an
|
|
3569
|
+
// attempt recognizes exactly the owners scheduled into it.
|
|
3570
|
+
dirtyEpoch = 1;
|
|
3571
|
+
attemptDirtyEpoch = 0;
|
|
3572
|
+
attemptFullRootScheduled = false;
|
|
3472
3573
|
scheduledTransitionBatches = /* @__PURE__ */ new Set();
|
|
3473
3574
|
unattemptedTransitionBatches = /* @__PURE__ */ new Set();
|
|
3474
3575
|
eventScopeDepth = 0;
|
|
@@ -4125,6 +4226,9 @@ class UniversalRootImpl {
|
|
|
4125
4226
|
scheduleOwned(owner) {
|
|
4126
4227
|
if (owner.root !== this || owner.disposed) return;
|
|
4127
4228
|
this.scheduledOwners.add(owner);
|
|
4229
|
+
for (let current = owner; current !== null && current.dirtyEpoch !== this.dirtyEpoch; current = current.parent) {
|
|
4230
|
+
current.dirtyEpoch = this.dirtyEpoch;
|
|
4231
|
+
}
|
|
4128
4232
|
this.markUrgentScheduled();
|
|
4129
4233
|
}
|
|
4130
4234
|
schedule() {
|
|
@@ -4292,7 +4396,8 @@ class UniversalRootImpl {
|
|
|
4292
4396
|
replay.props,
|
|
4293
4397
|
replay.entries,
|
|
4294
4398
|
replay.transitionBatches,
|
|
4295
|
-
replay.transitionRender
|
|
4399
|
+
replay.transitionRender,
|
|
4400
|
+
false
|
|
4296
4401
|
);
|
|
4297
4402
|
} catch (error) {
|
|
4298
4403
|
const batches = new Set(replay.transitionBatches);
|
|
@@ -4326,7 +4431,8 @@ class UniversalRootImpl {
|
|
|
4326
4431
|
replay.props,
|
|
4327
4432
|
replay.entries,
|
|
4328
4433
|
replay.transitionBatches,
|
|
4329
|
-
replay.transitionRender
|
|
4434
|
+
replay.transitionRender,
|
|
4435
|
+
false
|
|
4330
4436
|
);
|
|
4331
4437
|
} catch (error) {
|
|
4332
4438
|
const batches = new Set(replay.transitionBatches);
|
|
@@ -4538,7 +4644,7 @@ class UniversalRootImpl {
|
|
|
4538
4644
|
}
|
|
4539
4645
|
}
|
|
4540
4646
|
const unsupported = UNIVERSAL_TREE_PORTAL | UNIVERSAL_TREE_REGION;
|
|
4541
|
-
const scopeFeatures = logicalTreeFeatures(range);
|
|
4647
|
+
const scopeFeatures = range === this.rootRecord ? this.treeFeatures : logicalTreeFeatures(range);
|
|
4542
4648
|
if ((scopeFeatures & unsupported) !== 0) return null;
|
|
4543
4649
|
this.flushPassivesBeforeRender();
|
|
4544
4650
|
this.pending?.abort();
|
|
@@ -4550,6 +4656,7 @@ class UniversalRootImpl {
|
|
|
4550
4656
|
ordinal: 0
|
|
4551
4657
|
}
|
|
4552
4658
|
]);
|
|
4659
|
+
owner.componentRevision = universalComponentRevision(target.component);
|
|
4553
4660
|
const previousAttempt = CURRENT_ATTEMPT;
|
|
4554
4661
|
const previousOwner = CURRENT_OWNER;
|
|
4555
4662
|
const previousWarm = CURRENT_UNIVERSAL_WARM;
|
|
@@ -4567,7 +4674,12 @@ class UniversalRootImpl {
|
|
|
4567
4674
|
implicitSlot: 0,
|
|
4568
4675
|
transitionBatches: EMPTY_UNIVERSAL_TRANSITION_BATCHES,
|
|
4569
4676
|
transitionRender: false,
|
|
4570
|
-
bridgeContextReads: null
|
|
4677
|
+
bridgeContextReads: null,
|
|
4678
|
+
// The owned-update guards already require a plain urgent local-driver
|
|
4679
|
+
// attempt, which is exactly the retain-eligible shape.
|
|
4680
|
+
retainEligible: true,
|
|
4681
|
+
retainedCount: 0,
|
|
4682
|
+
dirtyEpoch: this.attemptDirtyEpoch
|
|
4571
4683
|
};
|
|
4572
4684
|
ACTIVE_UNIVERSAL_WARM_PLANS.length = 0;
|
|
4573
4685
|
CURRENT_UNIVERSAL_WARM = null;
|
|
@@ -4608,13 +4720,16 @@ class UniversalRootImpl {
|
|
|
4608
4720
|
}
|
|
4609
4721
|
const blueprint = {
|
|
4610
4722
|
kind: "range",
|
|
4611
|
-
key:
|
|
4723
|
+
// The committed range key: rangeKey for an ownerRange() scope, null for
|
|
4724
|
+
// the root range, so the reapplied key never drifts from what the full
|
|
4725
|
+
// render path would commit.
|
|
4726
|
+
key: range.key,
|
|
4612
4727
|
owner: target,
|
|
4613
4728
|
children: nodes
|
|
4614
4729
|
};
|
|
4615
4730
|
this.expandCompactLeafLists(blueprint);
|
|
4616
4731
|
let scopePlacement = null;
|
|
4617
|
-
if (!stableLogicalChildren(range.children, blueprint.children)) {
|
|
4732
|
+
if (range !== this.rootRecord && !stableLogicalChildren(range.children, blueprint.children)) {
|
|
4618
4733
|
scopePlacement = this.scopePhysicalPlacement(range);
|
|
4619
4734
|
if (scopePlacement === null) {
|
|
4620
4735
|
this.discardDraftOwners(attempt.owners);
|
|
@@ -4698,6 +4813,9 @@ class UniversalRootImpl {
|
|
|
4698
4813
|
prepare(component, props) {
|
|
4699
4814
|
const ownedTarget = this.scheduledPreparationDepth > 0 && this.scheduledUrgent && !this.scheduledFullRoot && this.scheduledOwners.size !== 0 ? this.resolveScopedTarget() : void 0;
|
|
4700
4815
|
const scheduledUrgent = this.scheduledUrgent || this.scheduledPreparationDepth === 0;
|
|
4816
|
+
this.attemptFullRootScheduled = this.scheduledFullRoot;
|
|
4817
|
+
this.attemptDirtyEpoch = this.dirtyEpoch;
|
|
4818
|
+
this.dirtyEpoch++;
|
|
4701
4819
|
this.scheduledUrgent = false;
|
|
4702
4820
|
this.scheduledFullRoot = false;
|
|
4703
4821
|
this.scheduledOwners.clear();
|
|
@@ -4750,7 +4868,7 @@ class UniversalRootImpl {
|
|
|
4750
4868
|
throw error;
|
|
4751
4869
|
}
|
|
4752
4870
|
}
|
|
4753
|
-
prepareWithReplay(component, props, replayEntries, transitionBatches, transitionRender) {
|
|
4871
|
+
prepareWithReplay(component, props, replayEntries, transitionBatches, transitionRender, allowRetain = true) {
|
|
4754
4872
|
if (this.unmounted || this.unmounting) {
|
|
4755
4873
|
throw new Error("Cannot render an unmounted universal root.");
|
|
4756
4874
|
}
|
|
@@ -4769,6 +4887,7 @@ class UniversalRootImpl {
|
|
|
4769
4887
|
];
|
|
4770
4888
|
const owner = draftOwner(ownerRecord, null, rootPath);
|
|
4771
4889
|
owner.componentProps = props;
|
|
4890
|
+
owner.componentRevision = universalComponentRevision(component);
|
|
4772
4891
|
const previousAttempt = CURRENT_ATTEMPT;
|
|
4773
4892
|
const previousOwner = CURRENT_OWNER;
|
|
4774
4893
|
const previousWarm = CURRENT_UNIVERSAL_WARM;
|
|
@@ -4786,7 +4905,14 @@ class UniversalRootImpl {
|
|
|
4786
4905
|
implicitSlot: 0,
|
|
4787
4906
|
transitionBatches,
|
|
4788
4907
|
transitionRender,
|
|
4789
|
-
bridgeContextReads: null
|
|
4908
|
+
bridgeContextReads: null,
|
|
4909
|
+
// Replay, transition, bridge, and transport attempts re-execute every
|
|
4910
|
+
// owner for their own bookkeeping (warm replays, lane rebasing, bridge
|
|
4911
|
+
// context read tracking, remote commit protocols); only a plain urgent
|
|
4912
|
+
// local attempt may adopt committed subtrees without re-rendering them.
|
|
4913
|
+
retainEligible: allowRetain && this.transport === null && this.bridge === null && !this.attemptFullRootScheduled && replayEntries.length === 0 && transitionBatches.size === 0 && !transitionRender,
|
|
4914
|
+
retainedCount: 0,
|
|
4915
|
+
dirtyEpoch: this.attemptDirtyEpoch
|
|
4790
4916
|
};
|
|
4791
4917
|
ACTIVE_UNIVERSAL_WARM_PLANS.length = 0;
|
|
4792
4918
|
CURRENT_UNIVERSAL_WARM = null;
|
|
@@ -4797,10 +4923,13 @@ class UniversalRootImpl {
|
|
|
4797
4923
|
try {
|
|
4798
4924
|
nodes = executeOwner(owner, () => {
|
|
4799
4925
|
const value = component(props, componentContext(this.renderer));
|
|
4800
|
-
return materializeValue(value, this.renderer, null, [
|
|
4926
|
+
return materializeValue(value, this.renderer, null, [
|
|
4927
|
+
...ownerRecord.identityPath,
|
|
4928
|
+
"output"
|
|
4929
|
+
]);
|
|
4801
4930
|
});
|
|
4802
4931
|
} catch (error) {
|
|
4803
|
-
const suspendedMemos = collectSuspendedMemos(attempt);
|
|
4932
|
+
const suspendedMemos = attempt.retainedCount !== 0 ? [] : collectSuspendedMemos(attempt);
|
|
4804
4933
|
this.discardDraftOwners(attempt.owners);
|
|
4805
4934
|
if (error instanceof UniversalSuspense) {
|
|
4806
4935
|
return this.suspend(
|
|
@@ -4823,7 +4952,12 @@ class UniversalRootImpl {
|
|
|
4823
4952
|
CURRENT_OWNER = previousOwner;
|
|
4824
4953
|
}
|
|
4825
4954
|
try {
|
|
4826
|
-
const rootBlueprint = {
|
|
4955
|
+
const rootBlueprint = {
|
|
4956
|
+
kind: "range",
|
|
4957
|
+
key: null,
|
|
4958
|
+
owner: owner.record,
|
|
4959
|
+
children: nodes
|
|
4960
|
+
};
|
|
4827
4961
|
const transaction = this.createTransaction(rootBlueprint, attempt, component, props);
|
|
4828
4962
|
this.pending = transaction;
|
|
4829
4963
|
return transaction;
|
|
@@ -5024,6 +5158,7 @@ class UniversalRootImpl {
|
|
|
5024
5158
|
for (const draft of attempt.owners) {
|
|
5025
5159
|
const record = draft.record;
|
|
5026
5160
|
record.componentProps = draft.componentProps;
|
|
5161
|
+
record.componentRevision = draft.componentRevision;
|
|
5027
5162
|
record.parent = draft.parent?.record ?? null;
|
|
5028
5163
|
record.hooks = draft.hooks;
|
|
5029
5164
|
record.effectOrder = [...draft.seenEffects];
|
|
@@ -5133,6 +5268,7 @@ class UniversalRootImpl {
|
|
|
5133
5268
|
for (const draft of attempt.owners) {
|
|
5134
5269
|
const record = draft.record;
|
|
5135
5270
|
record.componentProps = draft.componentProps;
|
|
5271
|
+
record.componentRevision = draft.componentRevision;
|
|
5136
5272
|
record.parent = draft.parent?.record ?? null;
|
|
5137
5273
|
record.hooks = draft.hooks;
|
|
5138
5274
|
record.effectOrder = [...draft.seenEffects];
|
|
@@ -5229,11 +5365,29 @@ class UniversalRootImpl {
|
|
|
5229
5365
|
const used = /* @__PURE__ */ new Set([scopeRecord]);
|
|
5230
5366
|
const changedRangeOwners = [];
|
|
5231
5367
|
let topologyChanged = false;
|
|
5368
|
+
const retainedScopes = /* @__PURE__ */ new Set();
|
|
5369
|
+
const retainedDraft = (record, blueprint2) => {
|
|
5370
|
+
retainedScopes.add(record);
|
|
5371
|
+
return { record, blueprint: blueprint2, children: [], isNew: false, hostUpdate: null, retained: true };
|
|
5372
|
+
};
|
|
5373
|
+
const expandRetained = (marker) => {
|
|
5374
|
+
const previousAttempt = CURRENT_ATTEMPT;
|
|
5375
|
+
CURRENT_ATTEMPT = attempt;
|
|
5376
|
+
try {
|
|
5377
|
+
return blueprintFromLogical(marker.retained);
|
|
5378
|
+
} finally {
|
|
5379
|
+
CURRENT_ATTEMPT = previousAttempt;
|
|
5380
|
+
}
|
|
5381
|
+
};
|
|
5232
5382
|
const reconcileChildren = (oldChildren, blueprints) => {
|
|
5233
5383
|
if ((treeFeatures & UNIVERSAL_TREE_PORTAL) === 0 && oldChildren.length === blueprints.length && oldChildren.every((record, index) => sameRecordShape(record, blueprints[index]))) {
|
|
5234
5384
|
return oldChildren.map((record, index) => {
|
|
5235
5385
|
used.add(record);
|
|
5236
|
-
|
|
5386
|
+
let blueprint2 = blueprints[index];
|
|
5387
|
+
if (blueprint2.kind === "range" && blueprint2.retained !== void 0) {
|
|
5388
|
+
if (blueprint2.retained === record) return retainedDraft(record, blueprint2);
|
|
5389
|
+
blueprint2 = expandRetained(blueprint2);
|
|
5390
|
+
}
|
|
5237
5391
|
const draft = {
|
|
5238
5392
|
record,
|
|
5239
5393
|
blueprint: blueprint2,
|
|
@@ -5253,7 +5407,7 @@ class UniversalRootImpl {
|
|
|
5253
5407
|
const nextKeys = /* @__PURE__ */ new Set();
|
|
5254
5408
|
const output = [];
|
|
5255
5409
|
for (let childIndex = 0; childIndex < blueprints.length; childIndex++) {
|
|
5256
|
-
|
|
5410
|
+
let child = blueprints[childIndex];
|
|
5257
5411
|
let record;
|
|
5258
5412
|
if (child.key !== null) {
|
|
5259
5413
|
if (nextKeys.has(child.key)) {
|
|
@@ -5270,6 +5424,15 @@ class UniversalRootImpl {
|
|
|
5270
5424
|
record = candidate;
|
|
5271
5425
|
}
|
|
5272
5426
|
}
|
|
5427
|
+
if (child.kind === "range" && child.retained !== void 0) {
|
|
5428
|
+
if (record === child.retained && record !== void 0) {
|
|
5429
|
+
claimed.add(record);
|
|
5430
|
+
used.add(record);
|
|
5431
|
+
output.push(retainedDraft(record, child));
|
|
5432
|
+
continue;
|
|
5433
|
+
}
|
|
5434
|
+
child = expandRetained(child);
|
|
5435
|
+
}
|
|
5273
5436
|
if (record?.kind === "portal" && child.kind === "portal") {
|
|
5274
5437
|
const previousRegistration = record.portalRegistration;
|
|
5275
5438
|
const nextRegistration = child.registration;
|
|
@@ -5309,11 +5472,14 @@ class UniversalRootImpl {
|
|
|
5309
5472
|
isNew: false,
|
|
5310
5473
|
hostUpdate: null
|
|
5311
5474
|
};
|
|
5475
|
+
if (scopeRecord.kind === "range" && scopeRecord.owner !== (blueprint.owner ?? null)) {
|
|
5476
|
+
changedRangeOwners.push(draftRoot);
|
|
5477
|
+
}
|
|
5312
5478
|
const removedRoots = [];
|
|
5313
5479
|
const findRemoved = (parent) => {
|
|
5314
5480
|
for (const child of parent.children) {
|
|
5315
5481
|
if (!used.has(child)) removedRoots.push(child);
|
|
5316
|
-
else findRemoved(child);
|
|
5482
|
+
else if (!retainedScopes.has(child)) findRemoved(child);
|
|
5317
5483
|
}
|
|
5318
5484
|
};
|
|
5319
5485
|
if (topologyChanged) findRemoved(scopeRecord);
|
|
@@ -5456,7 +5622,7 @@ class UniversalRootImpl {
|
|
|
5456
5622
|
const planPlacements = (parentId, oldRecords, newDrafts, sourceParentId = parentId, forceMove = false, endAnchor = null) => {
|
|
5457
5623
|
const oldPhysical = physicalRecords(oldRecords);
|
|
5458
5624
|
const newPhysical = physicalDrafts(newDrafts);
|
|
5459
|
-
const desiredIds = new Set(newPhysical.map((entry) => entry.
|
|
5625
|
+
const desiredIds = new Set(newPhysical.map((entry) => entry.id));
|
|
5460
5626
|
for (const old of oldPhysical) {
|
|
5461
5627
|
if (!desiredIds.has(old.id)) {
|
|
5462
5628
|
removes.push({ op: "remove", parent: sourceParentId, id: old.id });
|
|
@@ -5465,8 +5631,7 @@ class UniversalRootImpl {
|
|
|
5465
5631
|
const previousIds = new Set(oldPhysical.map((entry) => entry.id));
|
|
5466
5632
|
const current = forceMove ? [] : oldPhysical.filter((entry) => desiredIds.has(entry.id)).map((entry) => entry.id);
|
|
5467
5633
|
for (let index = 0; index < newPhysical.length; index++) {
|
|
5468
|
-
const
|
|
5469
|
-
const id = draft.record.id;
|
|
5634
|
+
const id = newPhysical[index].id;
|
|
5470
5635
|
if (current[index] === id) continue;
|
|
5471
5636
|
const currentIndex = current.indexOf(id);
|
|
5472
5637
|
const before = current[index] ?? endAnchor;
|
|
@@ -5662,18 +5827,24 @@ class UniversalRootImpl {
|
|
|
5662
5827
|
const retryMemos = retryThenables.length === 0 ? [] : collectSuspendedMemos(attempt);
|
|
5663
5828
|
const refDetaches = [];
|
|
5664
5829
|
const refAttaches = [];
|
|
5665
|
-
const
|
|
5666
|
-
const lifecycleDrafts = /* @__PURE__ */ new Set();
|
|
5830
|
+
const lifecycleHosts = /* @__PURE__ */ new Set();
|
|
5667
5831
|
if ((treeFeatures & UNIVERSAL_TREE_LIFECYCLE) !== 0) {
|
|
5832
|
+
const hostsById = /* @__PURE__ */ new Map();
|
|
5668
5833
|
walkDraft(draftRoot, (draft) => {
|
|
5834
|
+
if (draft.retained === true) {
|
|
5835
|
+
for (const host of physicalRecords(draft.record.children)) {
|
|
5836
|
+
hostsById.set(host.id, host);
|
|
5837
|
+
}
|
|
5838
|
+
return;
|
|
5839
|
+
}
|
|
5669
5840
|
if (draft.record.kind !== "host") return;
|
|
5670
|
-
|
|
5671
|
-
if (draft.isNew || draft.hostUpdate !== null)
|
|
5841
|
+
hostsById.set(draft.record.id, draft.record);
|
|
5842
|
+
if (draft.isNew || draft.hostUpdate !== null) lifecycleHosts.add(draft.record);
|
|
5672
5843
|
});
|
|
5673
5844
|
for (const placement of placements) {
|
|
5674
5845
|
if (placement.op !== "move") continue;
|
|
5675
|
-
const
|
|
5676
|
-
if (
|
|
5846
|
+
const host = hostsById.get(placement.id);
|
|
5847
|
+
if (host !== void 0) lifecycleHosts.add(host);
|
|
5677
5848
|
}
|
|
5678
5849
|
}
|
|
5679
5850
|
if ((treeFeatures & UNIVERSAL_TREE_REF) !== 0) {
|
|
@@ -5721,11 +5892,18 @@ class UniversalRootImpl {
|
|
|
5721
5892
|
}
|
|
5722
5893
|
}
|
|
5723
5894
|
const draftedRecords = new Set(draftOwnersParentFirst.map((owner) => owner.record));
|
|
5895
|
+
const retainedOwnerRoots = /* @__PURE__ */ new Set();
|
|
5896
|
+
for (const draft of draftOwnersParentFirst) {
|
|
5897
|
+
if (draft.retainedChildren === null) continue;
|
|
5898
|
+
for (const entry of draft.retainedChildren) retainedOwnerRoots.add(entry.record);
|
|
5899
|
+
}
|
|
5724
5900
|
const committedOwnersParentFirst = [];
|
|
5725
5901
|
const walkCommittedOwners = (owner) => {
|
|
5726
5902
|
if (owner === null) return;
|
|
5727
5903
|
committedOwnersParentFirst.push(owner);
|
|
5728
|
-
for (const child of owner.children)
|
|
5904
|
+
for (const child of owner.children) {
|
|
5905
|
+
if (!retainedOwnerRoots.has(child)) walkCommittedOwners(child);
|
|
5906
|
+
}
|
|
5729
5907
|
};
|
|
5730
5908
|
walkCommittedOwners(scoped ? attempt.owner.record : this.owner);
|
|
5731
5909
|
const removedOwners = committedOwnersParentFirst.filter((owner) => !draftedRecords.has(owner));
|
|
@@ -5803,6 +5981,10 @@ class UniversalRootImpl {
|
|
|
5803
5981
|
};
|
|
5804
5982
|
const apply = (draft, parent) => {
|
|
5805
5983
|
const record = draft.record;
|
|
5984
|
+
if (draft.retained === true) {
|
|
5985
|
+
record.parent = parent;
|
|
5986
|
+
return;
|
|
5987
|
+
}
|
|
5806
5988
|
record.parent = parent;
|
|
5807
5989
|
record.key = draft.blueprint.key;
|
|
5808
5990
|
if (record.kind === "host") {
|
|
@@ -5831,24 +6013,32 @@ class UniversalRootImpl {
|
|
|
5831
6013
|
}
|
|
5832
6014
|
};
|
|
5833
6015
|
const lifecycleOrder = [];
|
|
5834
|
-
if (
|
|
6016
|
+
if (lifecycleHosts.size !== 0) {
|
|
5835
6017
|
walkDraftPostOrder(draftRoot, (draft) => {
|
|
5836
|
-
if (
|
|
6018
|
+
if (draft.retained === true) {
|
|
6019
|
+
for (const host of physicalRecords(draft.record.children)) {
|
|
6020
|
+
if (lifecycleHosts.has(host)) lifecycleOrder.push(host);
|
|
6021
|
+
}
|
|
6022
|
+
return;
|
|
6023
|
+
}
|
|
6024
|
+
if (lifecycleHosts.has(draft.record)) lifecycleOrder.push(draft.record);
|
|
5837
6025
|
});
|
|
5838
6026
|
}
|
|
5839
6027
|
const hasPassiveWork = removedEffectEventCells.length !== 0 || orderedEffectCleanups.some((cleanup) => cleanup.phase === "passive") || effectChanges.some(({ next, changed }) => changed && next.phase === "passive");
|
|
5840
|
-
const
|
|
5841
|
-
const
|
|
5842
|
-
if (
|
|
5843
|
-
|
|
6028
|
+
const previousReplacedEventListeners = /* @__PURE__ */ new Set();
|
|
6029
|
+
const previousReplacedLocalCallbacks = /* @__PURE__ */ new Set();
|
|
6030
|
+
if ((treeFeatures & (UNIVERSAL_TREE_EVENT | UNIVERSAL_TREE_LOCAL_CALLBACK)) !== 0) {
|
|
6031
|
+
const collectReplaced = (record) => {
|
|
5844
6032
|
if (record.kind !== "host") return;
|
|
5845
6033
|
for (const event of record.events.values()) {
|
|
5846
|
-
|
|
6034
|
+
previousReplacedEventListeners.add(event.listener);
|
|
5847
6035
|
}
|
|
5848
6036
|
for (const callback of record.localCallbacks.values()) {
|
|
5849
|
-
|
|
6037
|
+
previousReplacedLocalCallbacks.add(callback.listener);
|
|
5850
6038
|
}
|
|
5851
|
-
}
|
|
6039
|
+
};
|
|
6040
|
+
walkDraft(draftRoot, (draft) => collectReplaced(draft.record));
|
|
6041
|
+
for (const removed of removedHosts) collectReplaced(removed);
|
|
5852
6042
|
}
|
|
5853
6043
|
const prepareHost = (value) => this.driver.prepareBatch(this.container, value, {
|
|
5854
6044
|
invokeLocalCallback: (listener, args) => this.invokeLocalCallback(listener, args)
|
|
@@ -5884,9 +6074,8 @@ class UniversalRootImpl {
|
|
|
5884
6074
|
}
|
|
5885
6075
|
}
|
|
5886
6076
|
if ((treeFeatures & UNIVERSAL_TREE_EVENT) !== 0) {
|
|
5887
|
-
const handlers =
|
|
5888
|
-
const
|
|
5889
|
-
for (const listener of replacedListeners) {
|
|
6077
|
+
const handlers = this.handlers;
|
|
6078
|
+
for (const listener of previousReplacedEventListeners) {
|
|
5890
6079
|
EVENT_DISPATCHERS.delete(listener);
|
|
5891
6080
|
this.publishedListeners.delete(listener);
|
|
5892
6081
|
handlers.delete(listener);
|
|
@@ -5902,11 +6091,10 @@ class UniversalRootImpl {
|
|
|
5902
6091
|
);
|
|
5903
6092
|
}
|
|
5904
6093
|
}
|
|
5905
|
-
this.handlers = handlers;
|
|
5906
6094
|
}
|
|
5907
6095
|
if ((treeFeatures & UNIVERSAL_TREE_LOCAL_CALLBACK) !== 0) {
|
|
5908
|
-
const localCallbacks =
|
|
5909
|
-
for (const listener of
|
|
6096
|
+
const localCallbacks = this.localCallbacks;
|
|
6097
|
+
for (const listener of previousReplacedLocalCallbacks) {
|
|
5910
6098
|
localCallbacks.delete(listener);
|
|
5911
6099
|
}
|
|
5912
6100
|
for (const callbacks of localCallbackStage.staged.values()) {
|
|
@@ -5914,7 +6102,6 @@ class UniversalRootImpl {
|
|
|
5914
6102
|
localCallbacks.set(callback.listener, callback);
|
|
5915
6103
|
}
|
|
5916
6104
|
}
|
|
5917
|
-
this.localCallbacks = localCallbacks;
|
|
5918
6105
|
}
|
|
5919
6106
|
for (const owner of removedOwners) {
|
|
5920
6107
|
owner.disposed = true;
|
|
@@ -5926,12 +6113,25 @@ class UniversalRootImpl {
|
|
|
5926
6113
|
for (const draft of draftOwnersParentFirst) {
|
|
5927
6114
|
const record = draft.record;
|
|
5928
6115
|
record.componentProps = draft.componentProps;
|
|
6116
|
+
record.componentRevision = draft.componentRevision;
|
|
5929
6117
|
if (!scoped || draft !== attempt.owner) {
|
|
5930
6118
|
record.parent = draft.parent?.record ?? null;
|
|
5931
6119
|
}
|
|
5932
6120
|
record.hooks = draft.hooks;
|
|
5933
6121
|
record.effectOrder = [...draft.seenEffects];
|
|
5934
|
-
|
|
6122
|
+
if (draft.retainedChildren === null) {
|
|
6123
|
+
record.children = draft.children.map((child) => child.record);
|
|
6124
|
+
} else {
|
|
6125
|
+
const merged = [];
|
|
6126
|
+
let retainedIndex = 0;
|
|
6127
|
+
for (let index = 0; index <= draft.children.length; index++) {
|
|
6128
|
+
while (retainedIndex < draft.retainedChildren.length && draft.retainedChildren[retainedIndex].position === index) {
|
|
6129
|
+
merged.push(draft.retainedChildren[retainedIndex++].record);
|
|
6130
|
+
}
|
|
6131
|
+
if (index < draft.children.length) merged.push(draft.children[index].record);
|
|
6132
|
+
}
|
|
6133
|
+
record.children = merged;
|
|
6134
|
+
}
|
|
5935
6135
|
record.contextValues = draft.contextValues;
|
|
5936
6136
|
record.isBoundary = draft.isBoundary;
|
|
5937
6137
|
record.canHandleSuspense = draft.canHandleSuspense;
|
|
@@ -6036,8 +6236,7 @@ class UniversalRootImpl {
|
|
|
6036
6236
|
},
|
|
6037
6237
|
() => {
|
|
6038
6238
|
const tasks = [];
|
|
6039
|
-
for (const
|
|
6040
|
-
const record = draft.record;
|
|
6239
|
+
for (const record of lifecycleOrder) {
|
|
6041
6240
|
for (const callback of record.lifecycles.values()) {
|
|
6042
6241
|
tasks.push(
|
|
6043
6242
|
() => runOwnedCommit(
|
|
@@ -6381,6 +6580,7 @@ class UniversalRootImpl {
|
|
|
6381
6580
|
}
|
|
6382
6581
|
}
|
|
6383
6582
|
this.rootRecord.children = [];
|
|
6583
|
+
this.rootRecord.owner = null;
|
|
6384
6584
|
let portalReleaseError = NO_PENDING_PASSIVE_ERROR;
|
|
6385
6585
|
for (const registration of portalRegistrations) {
|
|
6386
6586
|
try {
|