octane 0.10.0 → 0.10.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 CHANGED
@@ -17,6 +17,15 @@ wrapper is narrower: the wrapper must be locally declared in a fully compiled
17
17
  parameter to a supported hook. This package ships both the runtime and compiler,
18
18
  with the compiler exposed at `octane/compiler`.
19
19
 
20
+ To use the compiler in Node, including through the Vite, Rspack, or Rsbuild
21
+ integrations, install its optional parser peer in your project:
22
+
23
+ ```bash
24
+ pnpm add @tsrx/oxc@0.16.0
25
+ ```
26
+
27
+ Applications that use only the Octane runtime do not need this peer.
28
+
20
29
  [Signals](https://octanejs.dev/docs/signals) are stable. Import `createScope` and
21
30
  `query` from `octane/signals`, or `useSignal$` from `octane/signals/client`, for
22
31
  scoped state, derived values, async resources, and native component reads.
@@ -1069,6 +1069,11 @@ function formatClientError(code, ...args) {
1069
1069
  "A descriptor carried a function form action, but no element factory installed form actions. This is a bug in the Octane compiler.",
1070
1070
  args
1071
1071
  );
1072
+ case 343:
1073
+ return (0, import_error_message.formatDevErrorMessage)(
1074
+ "A keyed list rollback record restored a different shape than it recorded. This is a bug in Octane.",
1075
+ args
1076
+ );
1072
1077
  default:
1073
1078
  return (0, import_error_message.formatUnknownDevErrorMessage)(code);
1074
1079
  }
@@ -2256,6 +2256,7 @@ const TRANSITION_JOURNAL_BAG_WINDOWS = [];
2256
2256
  let TRANSITION_JOURNAL_DEPTH = 0;
2257
2257
  let TRANSITION_JOURNAL_REPLAYING = false;
2258
2258
  let ROOT_RENDER_TRANSACTION = null;
2259
+ let ROOT_DISCARD_STAMP = -1;
2259
2260
  let ROOT_RENDER_TRANSACTIONS = [];
2260
2261
  let ROOT_RENDER_ROLLBACK = false;
2261
2262
  let NEXT_ROOT_RENDER_CREATED_STAMP = 0;
@@ -2301,10 +2302,12 @@ function beginRootRender(owner) {
2301
2302
  bagWindow: TRANSITION_JOURNAL_BAG_WINDOW,
2302
2303
  depth: TRANSITION_JOURNAL_DEPTH,
2303
2304
  parked: PARKED_ITEMS,
2304
- capture: WIP_CAPTURE
2305
+ capture: WIP_CAPTURE,
2306
+ discardStamp: ROOT_DISCARD_STAMP
2305
2307
  };
2306
2308
  DEFERRED_LAYOUT_DRIVER?.recordRootTransaction(transaction);
2307
2309
  ROOT_RENDER_TRANSACTION = transaction;
2310
+ ROOT_DISCARD_STAMP = transaction.hydrating === true || transaction.retainedCreated !== null ? -1 : transaction.createdStamp;
2308
2311
  TRANSITION_JOURNAL = transaction.log;
2309
2312
  TRANSITION_JOURNAL_BAGS = transaction.bags;
2310
2313
  TRANSITION_JOURNAL_CHECKPOINT = 0;
@@ -2318,6 +2321,7 @@ function endRootRender(frame) {
2318
2321
  if (frame === null) return;
2319
2322
  frame.transaction.parked = PARKED_ITEMS;
2320
2323
  ROOT_RENDER_TRANSACTION = frame.previous;
2324
+ ROOT_DISCARD_STAMP = frame.discardStamp;
2321
2325
  TRANSITION_JOURNAL = frame.log;
2322
2326
  TRANSITION_JOURNAL_BAGS = frame.bags;
2323
2327
  TRANSITION_JOURNAL_CHECKPOINT = frame.checkpoint;
@@ -2544,8 +2548,10 @@ function createdInRootRender(block) {
2544
2548
  TRANSITION_JOURNAL.push(JOURNAL_CREATED, block, transaction, null);
2545
2549
  }
2546
2550
  function preserveRootCreatedDom(block) {
2547
- if (ROOT_RENDER_TRANSACTION !== null)
2551
+ if (ROOT_RENDER_TRANSACTION !== null) {
2548
2552
  (ROOT_RENDER_TRANSACTION.retainedCreated ??= /* @__PURE__ */ new Set()).add(block);
2553
+ ROOT_DISCARD_STAMP = -1;
2554
+ }
2549
2555
  }
2550
2556
  function rollbackRootRender(transaction) {
2551
2557
  if (transaction.aborted) return;
@@ -2839,9 +2845,7 @@ function cloneBindingBag(bag, arity) {
2839
2845
  function journalBag() {
2840
2846
  const scope = CURRENT_SCOPE;
2841
2847
  if (scope === null) return;
2842
- const transaction = ROOT_RENDER_TRANSACTION;
2843
- if (transaction !== null && !transaction.hydrating && transaction.retainedCreated === null && TRANSITION_JOURNAL_DEPTH === 1 && scope.block.createdStamp === transaction.createdStamp)
2844
- return;
2848
+ if (TRANSITION_JOURNAL_DEPTH === 1 && scope.block.createdStamp === ROOT_DISCARD_STAMP) return;
2845
2849
  const bag = scope.slots[0];
2846
2850
  if (bag === null || typeof bag !== "object") return;
2847
2851
  const arity = bag[BINDING_BAG_ARITY];
@@ -3002,9 +3006,20 @@ function itemRemovalDefers() {
3002
3006
  function forSlotParkable(state) {
3003
3007
  return TRANSITION_JOURNAL !== null && TRANSITION_JOURNAL_BAGS.has(state);
3004
3008
  }
3005
- function journalForSlot(state) {
3009
+ const SLOT_RECORDS = /* @__PURE__ */ new WeakMap();
3010
+ function journalForSlot(state, link) {
3006
3011
  const seen = TRANSITION_JOURNAL_BAGS;
3007
- if ((seen.get(state) ?? -1) >= TRANSITION_JOURNAL_CHECKPOINT) return false;
3012
+ let records = SLOT_RECORDS.get(TRANSITION_JOURNAL);
3013
+ const current = records?.get(state) ?? null;
3014
+ if ((seen.get(state) ?? -1) >= TRANSITION_JOURNAL_CHECKPOINT) {
3015
+ if (link) return current;
3016
+ if (current !== null && current.links !== null) fullForSlotRecord(state, current);
3017
+ return null;
3018
+ }
3019
+ if (current !== null) {
3020
+ if (current.links !== null) fullForSlotRecord(state, current);
3021
+ records.delete(state);
3022
+ }
3008
3023
  seen.set(state, TRANSITION_JOURNAL.length);
3009
3024
  if (ROOT_RENDER_TRANSACTION !== null && (ROOT_RENDER_TRANSACTION.hydrating === true && import_hydration_flag.hydrating && activeHydration() !== null || state.adopt !== null)) {
3010
3025
  journalUndo(() => {
@@ -3013,28 +3028,76 @@ function journalForSlot(state) {
3013
3028
  journalRootRange(domNode(state.start).parentNode, state.start, state.end);
3014
3029
  for (let b = state.head; b !== null; b = b.nextSibling)
3015
3030
  TRANSITION_JOURNAL.push(JOURNAL_PROP, b, "itemIndex", b.itemIndex);
3016
- return false;
3017
- }
3018
- const chain = [];
3019
- for (let b = state.head; b !== null; b = b.nextSibling) {
3020
- chain.push(b);
3031
+ return null;
3021
3032
  }
3022
- const keyOrder = [...state.items.values()];
3023
- let mapOrder = keyOrder.length === chain.length ? null : keyOrder;
3024
- for (let i = 0; mapOrder === null && i < keyOrder.length; i++)
3025
- if (keyOrder[i] !== chain[i]) mapOrder = keyOrder;
3026
- const snapshot = {
3033
+ let chain = null;
3034
+ let mapOrder = null;
3035
+ if (!link) {
3036
+ chain = [];
3037
+ for (let b = state.head; b !== null; b = b.nextSibling) chain.push(b);
3038
+ const keyOrder = [...state.items.values()];
3039
+ if (keyOrder.length !== chain.length) mapOrder = keyOrder;
3040
+ for (let i = 0; mapOrder === null && i < keyOrder.length; i++)
3041
+ if (keyOrder[i] !== chain[i]) mapOrder = keyOrder;
3042
+ }
3043
+ const record = {
3027
3044
  empty: state.emptyBlock,
3028
- mapOrder
3045
+ chain,
3046
+ mapOrder,
3047
+ head: state.head,
3048
+ links: link ? /* @__PURE__ */ new Map() : null,
3049
+ inOrder: state.inOrder,
3050
+ prior: null
3029
3051
  };
3052
+ if (link) {
3053
+ if (__octaneDev) record.check = forSlotShape(state);
3054
+ if (records === void 0) SLOT_RECORDS.set(TRANSITION_JOURNAL, records = /* @__PURE__ */ new Map());
3055
+ records.set(state, record);
3056
+ }
3057
+ const owner = records;
3030
3058
  journalUndo(() => {
3031
- restoreForSlot(state, snapshot, chain);
3032
- TRANSITION_JOURNAL_BAGS.delete(state);
3059
+ if (record.links !== null) fullForSlotRecord(state, record);
3060
+ restoreForSlot(state, record, record.chain);
3061
+ seen.delete(state);
3062
+ if (owner?.get(state) === record) owner.delete(state);
3033
3063
  });
3034
- return false;
3064
+ return link ? record : null;
3065
+ }
3066
+ function forSlotShape(state) {
3067
+ const chain = [];
3068
+ for (let b = state.head; b !== null; b = b.nextSibling) chain.push(b);
3069
+ const keyOrder = [...state.items.values()];
3070
+ return keyOrder.length === chain.length && keyOrder.every((block, i) => block === chain[i]) ? [chain] : [chain, keyOrder];
3071
+ }
3072
+ function fullForSlotRecord(state, record) {
3073
+ const links = record.links;
3074
+ record.links = null;
3075
+ const chain = [];
3076
+ for (let b = record.head; b !== null; b = links.has(b) ? links.get(b) : b.nextSibling)
3077
+ chain.push(b);
3078
+ record.chain = chain;
3079
+ if (!record.inOrder) {
3080
+ const kept = new Set(chain);
3081
+ const mapOrder = [];
3082
+ for (const block of record.prior ?? state.items.values())
3083
+ if (kept.has(block)) mapOrder.push(block);
3084
+ record.mapOrder = mapOrder;
3085
+ }
3086
+ if (__octaneDev) {
3087
+ const [expectedChain, expectedMap = expectedChain] = record.check;
3088
+ const restoredMap = record.mapOrder ?? chain;
3089
+ if (expectedChain.length !== chain.length || expectedChain.some((block, i) => block !== chain[i]) || expectedMap.length !== restoredMap.length || expectedMap.some((block, i) => block !== restoredMap[i]))
3090
+ throw new Error((0, import_error_codes_client_generated.formatClientError)(343));
3091
+ }
3035
3092
  }
3036
3093
  function journalForOwnedListClear(state) {
3037
3094
  const seen = TRANSITION_JOURNAL_BAGS;
3095
+ const records = SLOT_RECORDS.get(TRANSITION_JOURNAL);
3096
+ const current = records?.get(state);
3097
+ if (current !== void 0) {
3098
+ if (current.links !== null) fullForSlotRecord(state, current);
3099
+ records.delete(state);
3100
+ }
3038
3101
  const oldItems = state.items;
3039
3102
  seen.set(state, TRANSITION_JOURNAL.length);
3040
3103
  const snapshot = {
@@ -3049,6 +3112,7 @@ function journalForOwnedListClear(state) {
3049
3112
  seen.delete(state);
3050
3113
  });
3051
3114
  state.items = /* @__PURE__ */ new Map();
3115
+ state.inOrder = true;
3052
3116
  }
3053
3117
  function restoreForSlot(state, snapshot, chain) {
3054
3118
  const preservedMap = chain === null ? snapshot.entries : null;
@@ -3060,8 +3124,10 @@ function restoreForSlot(state, snapshot, chain) {
3060
3124
  state.head = chain === null ? snapshot.head : chain[0] ?? null;
3061
3125
  state.tail = chain === null ? snapshot.tail : chain[chain.length - 1] ?? null;
3062
3126
  state.size = chain === null ? snapshot.size : chain.length;
3063
- if (preservedMap !== null) state.items = preservedMap;
3064
- else {
3127
+ if (preservedMap !== null) {
3128
+ state.items = preservedMap;
3129
+ state.inOrder = false;
3130
+ } else {
3065
3131
  const originalChain = chain;
3066
3132
  state.items.clear();
3067
3133
  for (let i = 0; i < originalChain.length; i++) {
@@ -3075,6 +3141,7 @@ function restoreForSlot(state, snapshot, chain) {
3075
3141
  const block = keyOrder[i];
3076
3142
  state.items.set(block.key, block);
3077
3143
  }
3144
+ state.inOrder = keyOrder === originalChain;
3078
3145
  }
3079
3146
  const nodes = [];
3080
3147
  for (let b = state.head; b !== null; b = b.nextSibling) {
@@ -15356,7 +15423,7 @@ function writeDirectSignalText(target, value, kind, previous) {
15356
15423
  function writeDirectSignalAttribute(target, value, _kind, _previous, name, attributeKind) {
15357
15424
  const element = target;
15358
15425
  if (attributeKind === "class") {
15359
- if (element.namespaceURI === HTML_NS) setClassName(element, value);
15426
+ if (element.namespaceURI === HTML_NS) setClassName(element, value, true);
15360
15427
  else setClassAttr(element, value);
15361
15428
  } else attributeKind(element, name, value);
15362
15429
  return value;
@@ -16898,11 +16965,12 @@ function coerceAttrValue(el, name, value) {
16898
16965
  }
16899
16966
  return v;
16900
16967
  }
16901
- function setClassName(el, value) {
16968
+ function setClassName(el, value, foreign) {
16902
16969
  const cls = (0, import_css.normalizeClass)(value);
16903
16970
  const hydration = import_hydration_flag.hydrating ? activeHydration() : null;
16904
16971
  if (hydration !== null && hydration.keepsClass(el, cls, true)) return;
16905
- if (TRANSITION_JOURNAL !== null) journalAttr(el, "class");
16972
+ if (TRANSITION_JOURNAL !== null && (foreign === true || TRANSITION_JOURNAL_DEPTH !== 1 || CURRENT_SCOPE?.block.createdStamp !== ROOT_DISCARD_STAMP))
16973
+ journalAttr(el, "class");
16906
16974
  if (value == null || value === false) (STAGED_DOM?.view(el) ?? el).removeAttribute("class");
16907
16975
  else (STAGED_DOM?.view(el) ?? el).className = cls;
16908
16976
  }
@@ -16918,7 +16986,7 @@ function setDeoptClass(el, value) {
16918
16986
  if (el.namespaceURI === SVG_NS) {
16919
16987
  setClassAttr(el, value);
16920
16988
  } else {
16921
- setClassName(el, value);
16989
+ setClassName(el, value, true);
16922
16990
  }
16923
16991
  }
16924
16992
  const IMPORTANT_SUFFIX = "!important";
@@ -17081,7 +17149,7 @@ function removeHostProp(el, name, prevValue) {
17081
17149
  return;
17082
17150
  }
17083
17151
  const ev = eventSlot(name, el);
17084
- if (ev) setEventHandler(el, ev.key, null);
17152
+ if (ev) setEventHandler(el, ev.key, null, true);
17085
17153
  else setAttribute(el, name, null);
17086
17154
  }
17087
17155
  }
@@ -17680,7 +17748,8 @@ function setSpread(el, value, prev, mountScope, skipDangerouslySetInnerHTML = fa
17680
17748
  setEventHandler(
17681
17749
  el,
17682
17750
  ev.key,
17683
- __octaneDev ? devEventListener(k, v) : v
17751
+ __octaneDev ? devEventListener(k, v) : v,
17752
+ true
17684
17753
  );
17685
17754
  continue;
17686
17755
  }
@@ -17966,9 +18035,9 @@ function retireHostRange(node, last) {
17966
18035
  if (node === last) return;
17967
18036
  }
17968
18037
  }
17969
- function setEventHandler(el, key, handler) {
18038
+ function setEventHandler(el, key, handler, foreign) {
17970
18039
  if (key !== void 0) {
17971
- if (TRANSITION_JOURNAL !== null) {
18040
+ if (TRANSITION_JOURNAL !== null && (foreign === true || TRANSITION_JOURNAL_DEPTH !== 1 || CURRENT_SCOPE?.block.createdStamp !== ROOT_DISCARD_STAMP)) {
17972
18041
  TRANSITION_JOURNAL.push(
17973
18042
  JOURNAL_PROP,
17974
18043
  el,
@@ -23033,6 +23102,7 @@ function renderPreparedChildList(state, parentBlock, domParent, preparedList, hy
23033
23102
  // Non-null: an anchorless slot was promoted to markers above.
23034
23103
  end: state.end,
23035
23104
  items: /* @__PURE__ */ new Map(),
23105
+ inOrder: true,
23036
23106
  head: null,
23037
23107
  tail: null,
23038
23108
  size: 0,
@@ -28526,6 +28596,7 @@ function forBlock(parentScope, slotKey, domParent, inputItems, getKey, itemBody,
28526
28596
  start,
28527
28597
  end,
28528
28598
  items: /* @__PURE__ */ new Map(),
28599
+ inOrder: true,
28529
28600
  head: null,
28530
28601
  tail: null,
28531
28602
  size: 0,
@@ -29171,6 +29242,7 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29171
29242
  const newLen = items.length;
29172
29243
  const parentNode = domNode(state.end).parentNode;
29173
29244
  let journalShape = TRANSITION_JOURNAL !== null;
29245
+ let record = null;
29174
29246
  if (oldSize === 0) {
29175
29247
  mountItemsLinear(
29176
29248
  parentBlock,
@@ -29198,6 +29270,7 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29198
29270
  state.head = null;
29199
29271
  state.tail = null;
29200
29272
  state.size = 0;
29273
+ state.inOrder = true;
29201
29274
  return;
29202
29275
  }
29203
29276
  let oldFirst = state.head;
@@ -29209,7 +29282,10 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29209
29282
  if (observeKey !== void 0) observeKey(prefixLen, newKey);
29210
29283
  const block = oldFirst;
29211
29284
  if (!pure || block.props !== newItem || block.body !== itemBody || block.itemIndex !== prefixLen) {
29212
- if (journalShape && block.itemIndex !== prefixLen) journalShape = journalForSlot(state);
29285
+ if (journalShape && block.itemIndex !== prefixLen) {
29286
+ record = journalForSlot(state, true);
29287
+ journalShape = false;
29288
+ }
29213
29289
  updateSurvivor(block, newItem, prefixLen, itemBody, pure, lite, indexIndependent, state.env);
29214
29290
  }
29215
29291
  oldFirst = block.nextSibling;
@@ -29226,7 +29302,10 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29226
29302
  if (observeKey !== void 0) observeKey(newEnd, newKey);
29227
29303
  const block = oldLast;
29228
29304
  if (!pure || block.props !== newItem || block.body !== itemBody || block.itemIndex !== newEnd) {
29229
- if (journalShape && block.itemIndex !== newEnd) journalShape = journalForSlot(state);
29305
+ if (journalShape && block.itemIndex !== newEnd) {
29306
+ record = journalForSlot(state, true);
29307
+ journalShape = false;
29308
+ }
29230
29309
  updateSurvivor(block, newItem, newEnd, itemBody, pure, lite, indexIndependent, state.env);
29231
29310
  }
29232
29311
  oldLast = block.prevSibling;
@@ -29243,7 +29322,11 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29243
29322
  afterMiddle = oldLast.nextSibling;
29244
29323
  }
29245
29324
  if (oldRemain === 0) {
29246
- if (journalShape) journalForSlot(state);
29325
+ if (journalShape) record = journalForSlot(state, true);
29326
+ const links = record !== null ? record.links : null;
29327
+ if (links !== null && beforeMiddle !== null && !links.has(beforeMiddle))
29328
+ links.set(beforeMiddle, beforeMiddle.nextSibling);
29329
+ if (afterMiddle !== null) state.inOrder = false;
29247
29330
  const anchor = afterMiddle ? afterMiddle.startMarker : state.end;
29248
29331
  let prev = beforeMiddle;
29249
29332
  for (let i = prefixLen; i <= newEnd; i++) {
@@ -29277,7 +29360,13 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29277
29360
  return;
29278
29361
  }
29279
29362
  if (prefixLen > newEnd) {
29280
- if (journalShape) journalForSlot(state);
29363
+ if (journalShape) record = journalForSlot(state, true);
29364
+ const links = record !== null ? record.links : null;
29365
+ if (links !== null) {
29366
+ if (!record.inOrder) record.prior ??= [...oldItems.values()];
29367
+ if (beforeMiddle !== null && !links.has(beforeMiddle))
29368
+ links.set(beforeMiddle, beforeMiddle.nextSibling);
29369
+ }
29281
29370
  let cur = oldFirst;
29282
29371
  let removed = 0;
29283
29372
  while (cur !== afterMiddle) {
@@ -29315,8 +29404,9 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29315
29404
  cur = cur.nextSibling;
29316
29405
  }
29317
29406
  if (!anySurvivors) {
29318
- if (journalShape) journalForSlot(state);
29407
+ if (journalShape || record !== null && record.links !== null) journalForSlot(state);
29319
29408
  batchClearItems(state, oldItems);
29409
+ state.inOrder = true;
29320
29410
  state.head = null;
29321
29411
  state.tail = null;
29322
29412
  state.size = 0;
@@ -29369,7 +29459,11 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29369
29459
  const next = cur.nextSibling;
29370
29460
  const newRelIdx = newKeysToIdx.get(cur.key);
29371
29461
  if (newRelIdx === void 0) {
29372
- if (journalShape) journalShape = journalForSlot(state);
29462
+ if (journalShape || record !== null && record.links !== null) {
29463
+ journalForSlot(state);
29464
+ journalShape = false;
29465
+ record = null;
29466
+ }
29373
29467
  if (itemRemovalDefers()) parkItemForHold(cur);
29374
29468
  else unmountBlock(cur);
29375
29469
  oldItems.delete(cur.key);
@@ -29382,7 +29476,10 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29382
29476
  const newIdx = prefixLen + newRelIdx;
29383
29477
  const newItem = items[newIdx];
29384
29478
  if (!pure || cur.props !== newItem || cur.body !== itemBody || cur.itemIndex !== newIdx) {
29385
- if (journalShape && cur.itemIndex !== newIdx) journalShape = journalForSlot(state);
29479
+ if (journalShape && cur.itemIndex !== newIdx) {
29480
+ record = journalForSlot(state, true);
29481
+ journalShape = false;
29482
+ }
29386
29483
  updateSurvivor(cur, newItem, newIdx, itemBody, pure, lite, indexIndependent, state.env);
29387
29484
  }
29388
29485
  }
@@ -29405,7 +29502,7 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29405
29502
  }
29406
29503
  return;
29407
29504
  }
29408
- if (journalShape) journalForSlot(state);
29505
+ state.inOrder = false;
29409
29506
  if (moved && patched === newMidLen) {
29410
29507
  let dCount = 0;
29411
29508
  for (let i = 0; i < newMidLen; i++) {
@@ -29418,6 +29515,16 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29418
29515
  }
29419
29516
  }
29420
29517
  if (dCount <= K_DISP) {
29518
+ if (journalShape) record = journalForSlot(state, true);
29519
+ const links = record !== null ? record.links : null;
29520
+ if (links !== null) {
29521
+ const touched = [beforeMiddle, oldItems.get(newKeys[newMidLen - 1])];
29522
+ for (let j = 0; j < dCount; j++) {
29523
+ const i = _disp[j];
29524
+ touched.push(oldItems.get(newKeys[i]), i > 0 ? oldItems.get(newKeys[i - 1]) : null);
29525
+ }
29526
+ for (const b of touched) if (b !== null && !links.has(b)) links.set(b, b.nextSibling);
29527
+ }
29421
29528
  const endAnchor = afterMiddle ? afterMiddle.startMarker : state.end;
29422
29529
  for (let j = dCount - 1; j >= 0; j--) {
29423
29530
  const i = _disp[j];
@@ -29448,6 +29555,7 @@ function reconcileKeyed(parentBlock, state, items, keySource, itemBody, pure, si
29448
29555
  return;
29449
29556
  }
29450
29557
  }
29558
+ if (journalShape || record !== null && record.links !== null) journalForSlot(state);
29451
29559
  const middleEndAnchor = afterMiddle ? afterMiddle.startMarker : state.end;
29452
29560
  if (patched === newMidLen) {
29453
29561
  const seq = lis(sources, newMidLen);
@@ -29564,13 +29672,14 @@ function deferRootOwnedListClear(state, certified = false) {
29564
29672
  if (cancelled) return;
29565
29673
  let wholeParent = state.size === 0 && (STAGED_DOM?.view(start) ?? start).parentNode === parent && (STAGED_DOM?.view(end) ?? end).parentNode === parent && (STAGED_DOM?.view(start) ?? start).previousSibling === null && getNextSibling(end) === null;
29566
29674
  if (wholeParent) {
29675
+ const read = STAGED_DOM === null ? nextSiblingGetter : void 0;
29567
29676
  let node = getNextSibling(start);
29568
29677
  for (let block = oldHead; block !== null; block = block.nextSibling) {
29569
- if (node !== block.startMarker) {
29678
+ if (node === null || node !== block.startMarker) {
29570
29679
  wholeParent = false;
29571
29680
  break;
29572
29681
  }
29573
- node = getNextSibling(node);
29682
+ node = read !== void 0 ? read.call(node) : getNextSibling(node);
29574
29683
  }
29575
29684
  if (node !== end) wholeParent = false;
29576
29685
  }
@@ -31058,6 +31167,7 @@ function hydrateRootWithOutputHandler(container, bodyOrElement, propsOrOptions,
31058
31167
  const frame = beginRootRender(owner);
31059
31168
  owner.transaction.rootRequest = true;
31060
31169
  owner.transaction.hydrating = true;
31170
+ ROOT_DISCARD_STAMP = -1;
31061
31171
  createdInRootRender(rootBlock);
31062
31172
  journalRootProperty(idState, "next", idState.next);
31063
31173
  idState.next = rootOptions?.identifierSeed ?? 0;
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  version: () => version
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const version = "0.10.0";
24
+ const version = "0.10.2";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version