octane 0.2.11 → 0.2.13

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.
Files changed (264) hide show
  1. package/README.md +5 -0
  2. package/dist/behavior-root.d.ts +13 -3
  3. package/dist/behavior-root.js +28 -5
  4. package/dist/cjs/behavior-root.cjs +32 -6
  5. package/dist/cjs/class-names.cjs +49 -0
  6. package/dist/cjs/constants.cjs +9 -0
  7. package/dist/cjs/context-epoch.cjs +38 -0
  8. package/dist/cjs/css.cjs +6 -27
  9. package/dist/cjs/data-encoding.cjs +160 -0
  10. package/dist/cjs/dom-binding-handoff.cjs +93 -0
  11. package/dist/cjs/dom-binding-protocol.cjs +115 -0
  12. package/dist/cjs/dom-binding-styles.cjs +292 -0
  13. package/dist/cjs/dom-bindings.cjs +700 -0
  14. package/dist/cjs/dom-focused-move.cjs +66 -0
  15. package/dist/cjs/dom-stage.cjs +896 -0
  16. package/dist/cjs/dom-tables.cjs +4 -94
  17. package/dist/cjs/error-codes.client.generated.cjs +33 -0
  18. package/dist/cjs/error-codes.server.generated.cjs +24 -0
  19. package/dist/cjs/hydration/control-capture.cjs +244 -0
  20. package/dist/cjs/hydration/event-capture.cjs +125 -43
  21. package/dist/cjs/hydration/interaction-config.cjs +50 -2
  22. package/dist/cjs/hydration-markers.cjs +37 -0
  23. package/dist/cjs/independent-hydration-protocol.cjs +106 -0
  24. package/dist/cjs/index.cjs +9 -0
  25. package/dist/cjs/runtime.cjs +6397 -1683
  26. package/dist/cjs/runtime.server.cjs +1465 -213
  27. package/dist/cjs/server/early-signals.cjs +45 -0
  28. package/dist/cjs/server/index.cjs +47 -0
  29. package/dist/cjs/server/rpc-batch.cjs +149 -0
  30. package/dist/cjs/server/rpc-stream.cjs +146 -0
  31. package/dist/cjs/server/rpc.cjs +34 -15
  32. package/dist/cjs/server/signal-query-observation.cjs +158 -0
  33. package/dist/cjs/server/streamed-region.cjs +52 -0
  34. package/dist/cjs/server/streamed-signals.cjs +512 -0
  35. package/dist/cjs/server-call.cjs +103 -0
  36. package/dist/cjs/server-rpc-batch-client.cjs +141 -0
  37. package/dist/cjs/server-rpc-client.cjs +94 -27
  38. package/dist/cjs/server-rpc-protocol.cjs +141 -0
  39. package/dist/cjs/server-rpc-stream-client.cjs +118 -0
  40. package/dist/cjs/signals/actions.cjs +474 -0
  41. package/dist/cjs/signals/client.cjs +4 -1
  42. package/dist/cjs/signals/computations.cjs +460 -0
  43. package/dist/cjs/signals/control-binding.cjs +368 -0
  44. package/dist/cjs/signals/derived-facade.cjs +50 -0
  45. package/dist/cjs/signals/document-owner.cjs +71 -0
  46. package/dist/cjs/signals/early-values.cjs +155 -0
  47. package/dist/cjs/signals/encoding.cjs +6 -95
  48. package/dist/cjs/signals/engine.cjs +276 -12
  49. package/dist/cjs/signals/errors.cjs +18 -0
  50. package/dist/cjs/signals/facade.cjs +477 -0
  51. package/dist/cjs/signals/graph.cjs +166 -20
  52. package/dist/cjs/signals/handle-protocol.cjs +36 -0
  53. package/dist/cjs/signals/index.cjs +81 -2
  54. package/dist/cjs/signals/native-read-client.cjs +10 -0
  55. package/dist/cjs/signals/owner-context.cjs +112 -0
  56. package/dist/cjs/signals/query-attempt-observer.cjs +68 -0
  57. package/dist/cjs/signals/query-facade.cjs +72 -0
  58. package/dist/cjs/signals/read-protocol.cjs +54 -0
  59. package/dist/cjs/signals/requests.cjs +287 -14
  60. package/dist/cjs/signals/scalar-computations.cjs +76 -0
  61. package/dist/cjs/signals/server.cjs +4 -1
  62. package/dist/cjs/signals/transition-candidate.cjs +567 -0
  63. package/dist/cjs/signals/transition-state.cjs +106 -0
  64. package/dist/cjs/signals/types.cjs +50 -0
  65. package/dist/cjs/stream-protocol.cjs +3 -0
  66. package/dist/cjs/streamed-signals-protocol.cjs +159 -0
  67. package/dist/cjs/style-values.cjs +122 -0
  68. package/dist/cjs/trusted-html.cjs +30 -0
  69. package/dist/cjs/version.cjs +1 -1
  70. package/dist/class-names.d.ts +5 -0
  71. package/dist/class-names.js +25 -0
  72. package/dist/compiler/bundler.js +51 -22
  73. package/dist/compiler/compile.js +2534 -581
  74. package/dist/compiler/dom-binding-program.js +935 -0
  75. package/dist/compiler/dom-binding-request.js +57 -0
  76. package/dist/compiler/dom-bindings.js +2245 -0
  77. package/dist/compiler/hook-deps.js +759 -10
  78. package/dist/compiler/hydrate-boundaries.js +358 -15
  79. package/dist/compiler/index.d.ts +39 -2
  80. package/dist/compiler/index.js +1 -0
  81. package/dist/compiler/native-attribute-reads.js +127 -0
  82. package/dist/compiler/native-change-diagnostics.js +32 -38
  83. package/dist/compiler/native-read-diagnostics.js +69 -8
  84. package/dist/compiler/native-read-types.js +80 -34
  85. package/dist/compiler/parser.node.js +1 -1
  86. package/dist/compiler/renderer-boundaries.js +40 -0
  87. package/dist/compiler/server-context.js +118 -0
  88. package/dist/compiler/signal-attempt-reads.js +479 -0
  89. package/dist/compiler/signal-declarations.js +557 -0
  90. package/dist/compiler/signal-start-reads.js +413 -0
  91. package/dist/compiler/slot-hooks.d.ts +3 -1
  92. package/dist/compiler/slot-hooks.js +168 -34
  93. package/dist/compiler/strong-auto-memo.js +90 -0
  94. package/dist/compiler/strong-html.js +143 -0
  95. package/dist/compiler/strong-mode.js +764 -66
  96. package/dist/compiler/strong-template-policy.js +307 -0
  97. package/dist/compiler/template-ir.js +200 -0
  98. package/dist/compiler/typescript.d.ts +2 -0
  99. package/dist/compiler/typescript.js +2 -0
  100. package/dist/compiler/vite.d.ts +3 -1
  101. package/dist/compiler/vite.js +122 -4
  102. package/dist/compiler/volar.LICENSES.txt +1 -1
  103. package/dist/compiler/volar.d.ts +6 -1
  104. package/dist/compiler/volar.js +750 -1433
  105. package/dist/constants.d.ts +1 -0
  106. package/dist/constants.js +10 -0
  107. package/dist/context-epoch.d.ts +2 -0
  108. package/dist/context-epoch.js +13 -0
  109. package/dist/css.d.ts +2 -5
  110. package/dist/css.js +2 -23
  111. package/dist/data-encoding.d.ts +9 -0
  112. package/dist/data-encoding.js +134 -0
  113. package/dist/dom-binding-classes.d.ts +15 -0
  114. package/dist/dom-binding-classes.js +129 -0
  115. package/dist/dom-binding-controls.d.ts +2 -0
  116. package/dist/dom-binding-controls.js +6 -0
  117. package/dist/dom-binding-handoff.d.ts +55 -0
  118. package/dist/dom-binding-handoff.js +62 -0
  119. package/dist/dom-binding-program.d.ts +300 -0
  120. package/dist/dom-binding-program.js +1625 -0
  121. package/dist/dom-binding-projections.d.ts +15 -0
  122. package/dist/dom-binding-projections.js +187 -0
  123. package/dist/dom-binding-protocol.d.ts +13 -0
  124. package/dist/dom-binding-protocol.js +88 -0
  125. package/dist/dom-binding-signals.d.ts +21 -0
  126. package/dist/dom-binding-signals.js +109 -0
  127. package/dist/dom-binding-styles.d.ts +17 -0
  128. package/dist/dom-binding-styles.js +272 -0
  129. package/dist/dom-bindings.d.ts +89 -0
  130. package/dist/dom-bindings.js +670 -0
  131. package/dist/dom-focused-move.d.ts +6 -0
  132. package/dist/dom-focused-move.js +42 -0
  133. package/dist/dom-stage.d.ts +52 -0
  134. package/dist/dom-stage.js +872 -0
  135. package/dist/dom-tables.d.ts +1 -3
  136. package/dist/dom-tables.js +1 -91
  137. package/dist/error-codes.client.generated.d.ts +9 -0
  138. package/dist/error-codes.client.generated.js +33 -0
  139. package/dist/error-codes.server.generated.d.ts +6 -0
  140. package/dist/error-codes.server.generated.js +24 -0
  141. package/dist/hydration/control-capture.d.ts +62 -0
  142. package/dist/hydration/control-capture.js +223 -0
  143. package/dist/hydration/document-lifecycle.d.ts +23 -0
  144. package/dist/hydration/document-lifecycle.js +80 -0
  145. package/dist/hydration/event-capture.d.ts +20 -1
  146. package/dist/hydration/event-capture.js +128 -42
  147. package/dist/hydration/independent-island.d.ts +45 -0
  148. package/dist/hydration/independent-island.js +233 -0
  149. package/dist/hydration/index.d.ts +8 -1
  150. package/dist/hydration/index.js +55 -1
  151. package/dist/hydration/interaction-config.d.ts +5 -0
  152. package/dist/hydration/interaction-config.js +44 -1
  153. package/dist/hydration/stream-delivery.d.ts +32 -0
  154. package/dist/hydration/stream-delivery.js +333 -0
  155. package/dist/hydration/stream-receiver.d.ts +26 -0
  156. package/dist/hydration/stream-receiver.js +204 -0
  157. package/dist/hydration/stream-result-receiver.d.ts +70 -0
  158. package/dist/hydration/stream-result-receiver.js +246 -0
  159. package/dist/hydration/streamed-signals.d.ts +44 -0
  160. package/dist/hydration/streamed-signals.js +186 -0
  161. package/dist/hydration/types.d.ts +6 -0
  162. package/dist/hydration-markers.d.ts +7 -0
  163. package/dist/hydration-markers.js +10 -0
  164. package/dist/independent-hydration-protocol.d.ts +31 -0
  165. package/dist/independent-hydration-protocol.js +80 -0
  166. package/dist/index.d.ts +3 -0
  167. package/dist/index.js +6 -0
  168. package/dist/internal/signal-read.d.ts +1 -0
  169. package/dist/internal/signal-read.js +4 -0
  170. package/dist/jsx-runtime-strong.d.ts +33 -0
  171. package/dist/jsx-runtime.d.ts +58 -2
  172. package/dist/public-types.d.ts +15 -1
  173. package/dist/runtime.d.ts +297 -23
  174. package/dist/runtime.js +6405 -1679
  175. package/dist/runtime.server.d.ts +110 -27
  176. package/dist/runtime.server.js +1458 -213
  177. package/dist/server/early-signals.d.ts +14 -0
  178. package/dist/server/early-signals.js +34 -0
  179. package/dist/server/index.d.ts +11 -2
  180. package/dist/server/index.js +50 -1
  181. package/dist/server/rpc-batch.d.ts +17 -0
  182. package/dist/server/rpc-batch.js +129 -0
  183. package/dist/server/rpc-stream.d.ts +9 -0
  184. package/dist/server/rpc-stream.js +125 -0
  185. package/dist/server/rpc.d.ts +5 -1
  186. package/dist/server/rpc.js +37 -13
  187. package/dist/server/signal-query-observation.d.ts +3 -0
  188. package/dist/server/signal-query-observation.js +134 -0
  189. package/dist/server/streamed-region.d.ts +15 -0
  190. package/dist/server/streamed-region.js +30 -0
  191. package/dist/server/streamed-signals.d.ts +45 -0
  192. package/dist/server/streamed-signals.js +488 -0
  193. package/dist/server-call.d.ts +41 -0
  194. package/dist/server-call.js +75 -0
  195. package/dist/server-rpc-batch-client.d.ts +7 -0
  196. package/dist/server-rpc-batch-client.js +119 -0
  197. package/dist/server-rpc-client.d.ts +3 -1
  198. package/dist/server-rpc-client.js +99 -27
  199. package/dist/server-rpc-protocol.d.ts +47 -0
  200. package/dist/server-rpc-protocol.js +109 -0
  201. package/dist/server-rpc-stream-client.d.ts +5 -0
  202. package/dist/server-rpc-stream-client.js +98 -0
  203. package/dist/signals/actions.d.ts +12 -0
  204. package/dist/signals/actions.js +466 -0
  205. package/dist/signals/client.d.ts +2 -0
  206. package/dist/signals/client.js +1 -0
  207. package/dist/signals/computations.d.ts +37 -0
  208. package/dist/signals/computations.js +455 -0
  209. package/dist/signals/control-binding.d.ts +31 -0
  210. package/dist/signals/control-binding.js +353 -0
  211. package/dist/signals/derived-facade.d.ts +3 -0
  212. package/dist/signals/derived-facade.js +25 -0
  213. package/dist/signals/document-owner.d.ts +10 -0
  214. package/dist/signals/document-owner.js +43 -0
  215. package/dist/signals/early-values.d.ts +24 -0
  216. package/dist/signals/early-values.js +124 -0
  217. package/dist/signals/encoding.d.ts +1 -3
  218. package/dist/signals/encoding.js +3 -93
  219. package/dist/signals/engine.d.ts +53 -4
  220. package/dist/signals/engine.js +275 -16
  221. package/dist/signals/errors.d.ts +7 -0
  222. package/dist/signals/errors.js +16 -0
  223. package/dist/signals/facade.d.ts +74 -0
  224. package/dist/signals/facade.js +452 -0
  225. package/dist/signals/graph.d.ts +52 -6
  226. package/dist/signals/graph.js +174 -19
  227. package/dist/signals/handle-protocol.d.ts +4 -0
  228. package/dist/signals/handle-protocol.js +11 -0
  229. package/dist/signals/index.d.ts +12 -3
  230. package/dist/signals/index.js +71 -2
  231. package/dist/signals/native-read-client.d.ts +3 -0
  232. package/dist/signals/native-read-client.js +10 -0
  233. package/dist/signals/owner-context.d.ts +22 -0
  234. package/dist/signals/owner-context.js +77 -0
  235. package/dist/signals/query-attempt-observer.d.ts +49 -0
  236. package/dist/signals/query-attempt-observer.js +41 -0
  237. package/dist/signals/query-facade.d.ts +3 -0
  238. package/dist/signals/query-facade.js +49 -0
  239. package/dist/signals/read-protocol.d.ts +37 -2
  240. package/dist/signals/read-protocol.js +44 -0
  241. package/dist/signals/requests.d.ts +38 -5
  242. package/dist/signals/requests.js +298 -15
  243. package/dist/signals/scalar-computations.d.ts +2 -0
  244. package/dist/signals/scalar-computations.js +60 -0
  245. package/dist/signals/server.d.ts +2 -0
  246. package/dist/signals/server.js +1 -0
  247. package/dist/signals/transition-candidate.d.ts +71 -0
  248. package/dist/signals/transition-candidate.js +557 -0
  249. package/dist/signals/transition-state.d.ts +51 -0
  250. package/dist/signals/transition-state.js +70 -0
  251. package/dist/signals/types.d.ts +95 -5
  252. package/dist/signals/types.js +20 -0
  253. package/dist/stream-protocol.d.ts +0 -5
  254. package/dist/stream-protocol.js +3 -0
  255. package/dist/streamed-signals-protocol.d.ts +60 -0
  256. package/dist/streamed-signals-protocol.js +130 -0
  257. package/dist/style-values.d.ts +3 -0
  258. package/dist/style-values.js +96 -0
  259. package/dist/trusted-html.d.ts +17 -0
  260. package/dist/trusted-html.js +6 -0
  261. package/dist/universal-core.d.ts +6 -0
  262. package/dist/universal-core.js +214 -202
  263. package/dist/version.js +1 -1
  264. package/package.json +48 -5
@@ -1,3 +1,4 @@
1
+ import { bumpContextEpoch } from "./context-epoch.js";
1
2
  import { hasOwnProp } from "./has-own.js";
2
3
  import { resolveHookPath } from "./hook-slot-cache.js";
3
4
  import {
@@ -394,35 +395,48 @@ function universalProps(entries, children = NO_CHILDREN, canonicalizeHostClass =
394
395
  hasChildren: false
395
396
  };
396
397
  }
397
- const props = {};
398
+ let props = {};
399
+ let key = null;
400
+ let hasKey = false;
398
401
  if (!canonicalizeHostClass) {
399
402
  for (const entry of entries) {
400
403
  if (entry[0] === "set") {
401
- if (entry[1] === "__proto__") defineUniversalProtoProp(props, entry[2]);
404
+ if (entry[1] === "key") {
405
+ key = entry[2];
406
+ hasKey = true;
407
+ } else if (entry[1] === "__proto__") defineUniversalProtoProp(props, entry[2]);
402
408
  else props[entry[1]] = entry[2];
403
409
  continue;
404
410
  }
405
411
  const spread = entry[1];
406
412
  if (spread == null) continue;
407
413
  assignUniversalPropSpread(props, spread, false);
414
+ if (hasOwnProp.call(props, "key")) {
415
+ ({ key, ...props } = props);
416
+ hasKey = true;
417
+ }
408
418
  }
409
419
  } else {
410
420
  for (const entry of entries) {
411
421
  if (entry[0] === "set") {
412
422
  const name = entry[1];
413
- if (name === "__proto__") defineUniversalProtoProp(props, entry[2]);
423
+ if (name === "key") {
424
+ key = entry[2];
425
+ hasKey = true;
426
+ } else if (name === "__proto__") defineUniversalProtoProp(props, entry[2]);
414
427
  else props[name === "className" ? "class" : name] = entry[2];
415
428
  continue;
416
429
  }
417
430
  const spread = entry[1];
418
431
  if (spread == null) continue;
419
432
  assignUniversalPropSpread(props, spread, true);
433
+ if (hasOwnProp.call(props, "key")) {
434
+ ({ key, ...props } = props);
435
+ hasKey = true;
436
+ }
420
437
  }
421
438
  }
422
439
  if (children !== NO_CHILDREN) props.children = children;
423
- const hasKey = hasOwnProp.call(props, "key");
424
- const key = hasKey ? props.key : null;
425
- if (hasKey) delete props.key;
426
440
  return {
427
441
  $$kind: UNIVERSAL_PROPS,
428
442
  props: Object.freeze(props),
@@ -1086,7 +1100,8 @@ function materializeComponentValue(value, expectedRenderer, path) {
1086
1100
  const normalized = normalizePropsValue(value.props);
1087
1101
  const host = trustedUniversalHostComponent(value.component, expectedRenderer);
1088
1102
  if (host !== null) {
1089
- const nodes2 = materializeNode(host.plan.root, [normalized], expectedRenderer, path);
1103
+ const nodes2 = [];
1104
+ materializeNode(host.plan.root, [normalized], expectedRenderer, path, nodes2);
1090
1105
  if (value.hasKey) nodes2[0].key = normalizeUniversalKey(value.key);
1091
1106
  return nodes2;
1092
1107
  }
@@ -1127,7 +1142,7 @@ function materializeComponentValue(value, expectedRenderer, path) {
1127
1142
  });
1128
1143
  return ownerRange(owner, nodes);
1129
1144
  }
1130
- function materializeScoped(parent, path, key, build, contextValues = null) {
1145
+ function materializeScoped(parent, path, key, build, contextValues = null, outputPath = [...path, "output"]) {
1131
1146
  const attempt = currentAttempt();
1132
1147
  const universalIdCheckpoint = attempt.nextUniversalId;
1133
1148
  const owner = claimChildOwner(parent, null, path, key);
@@ -1135,7 +1150,7 @@ function materializeScoped(parent, path, key, build, contextValues = null) {
1135
1150
  try {
1136
1151
  const nodes = executeOwner(
1137
1152
  owner,
1138
- () => materializeValue(build(), parent.record.renderer, null, [...path, "output"])
1153
+ () => materializeValue(build(), parent.record.renderer, null, outputPath)
1139
1154
  );
1140
1155
  return ownerRange(owner, nodes);
1141
1156
  } catch (error) {
@@ -1298,7 +1313,7 @@ function ownerlessLeafHostPlan(plan) {
1298
1313
  OWNERLESS_LEAF_PLAN_CACHE.set(plan, host);
1299
1314
  return host;
1300
1315
  }
1301
- function materializeOwnerlessLeafValue(value, expectedRenderer, compilerLeafProps, owner = CURRENT_OWNER) {
1316
+ function materializeOwnerlessLeafValue(value, expectedRenderer, owner = CURRENT_OWNER) {
1302
1317
  if (value?.$$kind !== UNIVERSAL_VALUE) return null;
1303
1318
  const planValue = value;
1304
1319
  if (planValue.plan.renderer !== expectedRenderer) {
@@ -1311,9 +1326,6 @@ function materializeOwnerlessLeafValue(value, expectedRenderer, compilerLeafProp
1311
1326
  if (node === null) return null;
1312
1327
  const props = { ...node.props ?? {} };
1313
1328
  for (const [name, slot] of node.bindings ?? []) props[name] = planValue.values[slot];
1314
- let events = null;
1315
- let lifecycles = null;
1316
- let localCallbacks = null;
1317
1329
  let hostBindings = null;
1318
1330
  const attempt = currentAttempt();
1319
1331
  for (const name of Object.keys(props)) {
@@ -1329,76 +1341,9 @@ function materializeOwnerlessLeafValue(value, expectedRenderer, compilerLeafProp
1329
1341
  props[name] = attempt.root.encodeHostProp(node.type, name, handler.getSnapshot());
1330
1342
  continue;
1331
1343
  }
1332
- if (compilerLeafProps) {
1333
- if (isRendererRegion(handler)) markUniversalTreeFeature(UNIVERSAL_TREE_REGION);
1334
- props[name] = attempt.root.encodeHostProp(node.type, name, handler);
1335
- continue;
1336
- }
1337
- const lifecycle = attempt.root.classifyLifecycle(name, handler);
1338
- if (lifecycle !== null) {
1339
- delete props[name];
1340
- if (handler == null) continue;
1341
- if (typeof handler !== "function") {
1342
- throw new TypeError(
1343
- `Universal lifecycle prop ${JSON.stringify(name)} for renderer ${JSON.stringify(expectedRenderer)} must be a function, null, or undefined.`
1344
- );
1345
- }
1346
- (lifecycles ??= /* @__PURE__ */ new Map()).set(lifecycle.type, {
1347
- prop: name,
1348
- type: lifecycle.type,
1349
- handler,
1350
- owner: owner.record
1351
- });
1352
- continue;
1353
- }
1354
- const local = attempt.root.classifyLocalCallback(name, handler);
1355
- if (local !== null) {
1356
- delete props[name];
1357
- if (attempt.root.driverCapabilities().localHostCallbacks !== true) {
1358
- throw new Error(
1359
- `Universal renderer ${JSON.stringify(expectedRenderer)} does not declare the local-host-callback capability.`
1360
- );
1361
- }
1362
- if (handler == null) continue;
1363
- if (typeof handler !== "function") {
1364
- throw new TypeError(
1365
- `Universal local callback prop ${JSON.stringify(name)} for renderer ${JSON.stringify(expectedRenderer)} must be a function, null, or undefined.`
1366
- );
1367
- }
1368
- (localCallbacks ??= /* @__PURE__ */ new Map()).set(local.type, {
1369
- prop: name,
1370
- type: local.type,
1371
- handler,
1372
- owner: owner.record
1373
- });
1374
- continue;
1375
- }
1376
- const definition = attempt.root.classifyEvent(name);
1377
- if (definition !== null) {
1378
- delete props[name];
1379
- if (handler == null) continue;
1380
- if (typeof handler !== "function") {
1381
- throw new TypeError(
1382
- `Universal event prop ${JSON.stringify(name)} for renderer ${JSON.stringify(expectedRenderer)} must be a function, null, or undefined.`
1383
- );
1384
- }
1385
- (events ??= /* @__PURE__ */ new Map()).set(definition.type, {
1386
- prop: name,
1387
- type: definition.type,
1388
- priority: definition.priority ?? "default",
1389
- handler,
1390
- owner: owner.record
1391
- });
1392
- continue;
1393
- }
1394
1344
  if (isRendererRegion(handler)) markUniversalTreeFeature(UNIVERSAL_TREE_REGION);
1395
1345
  props[name] = attempt.root.encodeHostProp(node.type, name, handler);
1396
1346
  }
1397
- if (events !== null && events.size !== 0) markUniversalTreeFeature(UNIVERSAL_TREE_EVENT);
1398
- if (lifecycles !== null && lifecycles.size !== 0)
1399
- markUniversalTreeFeature(UNIVERSAL_TREE_LIFECYCLE);
1400
- if (localCallbacks !== null && localCallbacks.size !== 0)
1401
- markUniversalTreeFeature(UNIVERSAL_TREE_LOCAL_CALLBACK);
1402
1347
  if (owner.visibility !== "visible") markUniversalTreeFeature(UNIVERSAL_TREE_HIDDEN);
1403
1348
  return {
1404
1349
  kind: "host",
@@ -1408,9 +1353,9 @@ function materializeOwnerlessLeafValue(value, expectedRenderer, compilerLeafProp
1408
1353
  ...hostBindings === null ? null : { hostBindings },
1409
1354
  ref: null,
1410
1355
  owner: owner.record,
1411
- events: events ?? EMPTY_BLUEPRINT_EVENTS,
1412
- lifecycles: lifecycles ?? EMPTY_BLUEPRINT_HOST_CALLBACKS,
1413
- localCallbacks: localCallbacks ?? EMPTY_BLUEPRINT_HOST_CALLBACKS,
1356
+ events: EMPTY_BLUEPRINT_EVENTS,
1357
+ lifecycles: EMPTY_BLUEPRINT_HOST_CALLBACKS,
1358
+ localCallbacks: EMPTY_BLUEPRINT_HOST_CALLBACKS,
1414
1359
  visibility: owner.visibility,
1415
1360
  children: []
1416
1361
  };
@@ -1668,6 +1613,7 @@ function materializeValue(value, expectedRenderer, key, path) {
1668
1613
  if (compactIndex !== 0 && owner.visibility !== "visible") {
1669
1614
  markUniversalTreeFeature(UNIVERSAL_TREE_HIDDEN);
1670
1615
  }
1616
+ currentAttempt().hasCompactLists = true;
1671
1617
  return [
1672
1618
  {
1673
1619
  kind: "range",
@@ -1706,6 +1652,8 @@ function materializeValue(value, expectedRenderer, key, path) {
1706
1652
  }
1707
1653
  }
1708
1654
  const componentPath = componentScopeEnabled ? [...lazyOwnerScope.identityPath, "output"] : null;
1655
+ let listOwnerPath = lazyOwnerScope?.identityPath ?? null;
1656
+ let listOutputPath = componentPath;
1709
1657
  let index = 0;
1710
1658
  for (const item of list.items) {
1711
1659
  const itemIndex = index++;
@@ -1817,12 +1765,7 @@ function materializeValue(value, expectedRenderer, key, path) {
1817
1765
  );
1818
1766
  const rendered = materializeRawUniversalListValue(list, rawOutput, expectedRenderer);
1819
1767
  const itemOwner = lazyOwnerScope.owner ?? parent;
1820
- const leaf = materializeOwnerlessLeafValue(
1821
- rendered,
1822
- expectedRenderer,
1823
- compilerLeafProps,
1824
- itemOwner
1825
- );
1768
+ const leaf = materializeOwnerlessLeafValue(rendered, expectedRenderer, itemOwner);
1826
1769
  if (leaf !== null) {
1827
1770
  leaf.key = itemKey;
1828
1771
  output.push(leaf);
@@ -1847,18 +1790,26 @@ function materializeValue(value, expectedRenderer, key, path) {
1847
1790
  nodes[0].key = itemKey;
1848
1791
  output.push(nodes[0]);
1849
1792
  } else {
1793
+ listOwnerPath ??= [...path, "for"];
1794
+ listOutputPath ??= [...listOwnerPath, "output"];
1850
1795
  output.push(
1851
- ...materializeScoped(parent, [...path, "for"], itemKey, () => {
1852
- return materializeRawUniversalListValue(
1796
+ ...materializeScoped(
1797
+ parent,
1798
+ listOwnerPath,
1799
+ itemKey,
1800
+ () => materializeRawUniversalListValue(
1853
1801
  list,
1854
1802
  list.render(item, itemIndex),
1855
1803
  expectedRenderer
1856
- );
1857
- })
1804
+ ),
1805
+ null,
1806
+ listOutputPath
1807
+ )
1858
1808
  );
1859
1809
  }
1860
1810
  }
1861
1811
  if (compactTemplateEnabled && compactTemplateList !== null) {
1812
+ attempt.hasCompactLists = true;
1862
1813
  return [{ kind: "range", key: null, children: [], compactTemplateList }];
1863
1814
  }
1864
1815
  if (index === 0 && list.empty !== null) {
@@ -1959,13 +1910,23 @@ function materializeValue(value, expectedRenderer, key, path) {
1959
1910
  }
1960
1911
  if (Array.isArray(value)) {
1961
1912
  const output = [];
1962
- const keys = /* @__PURE__ */ new Set();
1913
+ let firstKey = null;
1914
+ let keys;
1963
1915
  for (let index = 0; index < value.length; index++) {
1964
1916
  const item = value[index];
1965
1917
  const itemKey = renderableKey(item);
1966
1918
  if (itemKey !== null) {
1967
- if (keys.has(itemKey)) throw new Error(`Duplicate universal child key ${String(itemKey)}.`);
1968
- keys.add(itemKey);
1919
+ if (firstKey === null) {
1920
+ firstKey = itemKey;
1921
+ } else {
1922
+ if (keys === void 0) {
1923
+ keys = /* @__PURE__ */ new Set();
1924
+ keys.add(firstKey);
1925
+ }
1926
+ if (keys.has(itemKey))
1927
+ throw new Error(`Duplicate universal child key ${String(itemKey)}.`);
1928
+ keys.add(itemKey);
1929
+ }
1969
1930
  }
1970
1931
  output.push(
1971
1932
  ...materializeValue(item, expectedRenderer, itemKey, [
@@ -2004,21 +1965,37 @@ function materializeValue(value, expectedRenderer, key, path) {
2004
1965
  `Unsupported universal dynamic child ${Object.prototype.toString.call(value)}.`
2005
1966
  );
2006
1967
  }
2007
- function materializeNode(node, values, renderer, path) {
2008
- if (node.kind === "slot")
2009
- return materializeValue(values[node.slot], renderer, null, [...path, "slot", node.slot]);
1968
+ function copyUniversalHostPropPrefix(source, names, end) {
1969
+ const props = {};
1970
+ for (let index = 0; index < end; index++) {
1971
+ const name = names[index];
1972
+ if (name === "__proto__") defineUniversalProtoProp(props, source[name]);
1973
+ else props[name] = source[name];
1974
+ }
1975
+ for (const symbol of Object.getOwnPropertySymbols(source)) {
1976
+ props[symbol] = source[symbol];
1977
+ }
1978
+ return props;
1979
+ }
1980
+ function materializeNode(node, values, renderer, path, output) {
1981
+ if (node.kind === "slot") {
1982
+ output.push(
1983
+ ...materializeValue(values[node.slot], renderer, null, [...path, "slot", node.slot])
1984
+ );
1985
+ return;
1986
+ }
2010
1987
  if (node.kind === "text") {
2011
1988
  const value = node.slot === void 0 ? node.value ?? "" : values[node.slot];
2012
- return materializeValue(value, renderer, null, [...path, "text"]);
1989
+ output.push(...materializeValue(value, renderer, null, [...path, "text"]));
1990
+ return;
2013
1991
  }
2014
1992
  if (node.kind === "range") {
2015
1993
  const children2 = [];
2016
1994
  for (let index = 0; index < node.children.length; index++) {
2017
- children2.push(
2018
- ...materializeNode(node.children[index], values, renderer, [...path, "range", index])
2019
- );
1995
+ materializeNode(node.children[index], values, renderer, [...path, "range", index], children2);
2020
1996
  }
2021
- return [{ kind: "range", key: null, children: children2 }];
1997
+ output.push({ kind: "range", key: null, children: children2 });
1998
+ return;
2022
1999
  }
2023
2000
  if (node.kind === "component") {
2024
2001
  const component = node.component ?? values[node.componentSlot];
@@ -2031,33 +2008,36 @@ function materializeNode(node, values, renderer, path) {
2031
2008
  const children2 = universalChildren(renderer, () => universalValue(childPlan, values));
2032
2009
  props2 = universalProps([["spread", props2.props]], children2);
2033
2010
  }
2034
- return materializeComponentValue(
2035
- universalComponent(
2036
- node.renderer,
2037
- component,
2038
- props2,
2039
- node.keySlot === void 0 ? NO_KEY : values[node.keySlot]
2040
- ),
2041
- renderer,
2042
- [...path, "component"]
2011
+ output.push(
2012
+ ...materializeComponentValue(
2013
+ universalComponent(
2014
+ node.renderer,
2015
+ component,
2016
+ props2,
2017
+ node.keySlot === void 0 ? NO_KEY : values[node.keySlot]
2018
+ ),
2019
+ renderer,
2020
+ [...path, "component"]
2021
+ )
2043
2022
  );
2023
+ return;
2044
2024
  }
2045
2025
  if (node.kind === "if") {
2046
2026
  const selected = values[node.conditionSlot] ? node.then : node.else;
2047
- if (selected === void 0) return [];
2027
+ if (selected === void 0) return;
2048
2028
  const owner = claimChildOwner(
2049
2029
  CURRENT_OWNER,
2050
2030
  null,
2051
2031
  [...path, "if"],
2052
2032
  values[node.conditionSlot] ? 1 : 0
2053
2033
  );
2054
- return ownerRange(
2055
- owner,
2056
- executeOwner(
2057
- owner,
2058
- () => materializeNode(selected, values, renderer, [...path, "if-output"])
2059
- )
2060
- );
2034
+ const children2 = executeOwner(owner, () => {
2035
+ const nodes = [];
2036
+ materializeNode(selected, values, renderer, [...path, "if-output"], nodes);
2037
+ return nodes;
2038
+ });
2039
+ output.push(...ownerRange(owner, children2));
2040
+ return;
2061
2041
  }
2062
2042
  if (node.kind === "switch") {
2063
2043
  let selected = node.default;
@@ -2069,19 +2049,19 @@ function materializeNode(node, values, renderer, path) {
2069
2049
  break;
2070
2050
  }
2071
2051
  }
2072
- if (selected === void 0) return [];
2052
+ if (selected === void 0) return;
2073
2053
  const owner = claimChildOwner(CURRENT_OWNER, null, [...path, "switch"], selectedKey);
2074
- return ownerRange(
2075
- owner,
2076
- executeOwner(
2077
- owner,
2078
- () => materializeNode(selected, values, renderer, [...path, "switch-output"])
2079
- )
2080
- );
2054
+ const children2 = executeOwner(owner, () => {
2055
+ const nodes = [];
2056
+ materializeNode(selected, values, renderer, [...path, "switch-output"], nodes);
2057
+ return nodes;
2058
+ });
2059
+ output.push(...ownerRange(owner, children2));
2060
+ return;
2081
2061
  }
2082
2062
  if (node.type === "#text") {
2083
2063
  const text = currentAttempt().root.textPolicy();
2084
- if (text === "ignore") return [];
2064
+ if (text === "ignore") return;
2085
2065
  if (text === "reject") {
2086
2066
  throw new Error(
2087
2067
  `Universal renderer ${JSON.stringify(renderer)} rejects primitive text children.`
@@ -2091,35 +2071,37 @@ function materializeNode(node, values, renderer, path) {
2091
2071
  const attempt = currentAttempt();
2092
2072
  const root = attempt.root;
2093
2073
  const staticProps = root.materializeStaticHostProps(node);
2094
- const props = staticProps ?? { ...node.props ?? {} };
2074
+ const sourceProps = staticProps ?? { ...node.props ?? {} };
2095
2075
  if (staticProps === null) {
2096
- for (const [name, slot] of node.bindings ?? []) props[name] = values[slot];
2076
+ for (const [name, slot] of node.bindings ?? []) sourceProps[name] = values[slot];
2097
2077
  }
2098
2078
  let propsValue = null;
2099
2079
  if (node.propsSlot !== void 0) {
2100
2080
  propsValue = normalizePropsValue(values[node.propsSlot]);
2101
- Object.assign(props, propsValue.props);
2081
+ Object.assign(sourceProps, propsValue.props);
2102
2082
  }
2103
- if (isUniversalHostBinding(props.ref) || isUniversalHostBinding(props.key) || isUniversalHostBinding(props.children)) {
2083
+ if (isUniversalHostBinding(sourceProps.ref) || isUniversalHostBinding(sourceProps.key) || isUniversalHostBinding(sourceProps.children)) {
2104
2084
  throw new Error("Experimental host bindings require an ordinary host property.");
2105
2085
  }
2106
- const hasKey = staticProps === null && (propsValue?.hasKey || hasOwnProp.call(props, "key"));
2086
+ const hasKey = staticProps === null && (propsValue?.hasKey || hasOwnProp.call(sourceProps, "key"));
2107
2087
  const hostKey = normalizeUniversalKey(
2108
- propsValue?.hasKey ? propsValue.key : hasKey ? props.key : null
2088
+ propsValue?.hasKey ? propsValue.key : hasKey ? sourceProps.key : null
2109
2089
  );
2110
- const ref = staticProps === null && hasOwnProp.call(props, "ref") ? props.ref : null;
2111
- const dynamicChildren = staticProps === null && hasOwnProp.call(props, "children") ? props.children : void 0;
2112
- if (staticProps === null) {
2113
- delete props.ref;
2114
- delete props.key;
2115
- delete props.children;
2116
- }
2090
+ const ref = staticProps === null && hasOwnProp.call(sourceProps, "ref") ? sourceProps.ref : null;
2091
+ const dynamicChildren = staticProps === null && hasOwnProp.call(sourceProps, "children") ? sourceProps.children : void 0;
2092
+ let props = sourceProps;
2117
2093
  let events = null;
2118
2094
  let lifecycles = null;
2119
2095
  let localCallbacks = null;
2120
2096
  let hostBindings = null;
2121
- for (const name of staticProps === null ? Object.keys(props) : EMPTY_STATIC_PROP_NAMES) {
2122
- const handler = props[name];
2097
+ const names = staticProps === null ? Object.keys(sourceProps) : EMPTY_STATIC_PROP_NAMES;
2098
+ for (let index = 0; index < names.length; index++) {
2099
+ const name = names[index];
2100
+ if (name === "ref" || name === "key" || name === "children") {
2101
+ if (props === sourceProps) props = copyUniversalHostPropPrefix(sourceProps, names, index);
2102
+ continue;
2103
+ }
2104
+ const handler = sourceProps[name];
2123
2105
  if (isUniversalHostBinding(handler)) {
2124
2106
  if (root.hasHostBindingUnsupportedConfiguration() || name.startsWith("on")) {
2125
2107
  throw new Error(
@@ -2128,12 +2110,14 @@ function materializeNode(node, values, renderer, path) {
2128
2110
  }
2129
2111
  markUniversalTreeFeature(UNIVERSAL_TREE_HOST_BINDING);
2130
2112
  (hostBindings ??= /* @__PURE__ */ new Map()).set(name, handler);
2131
- props[name] = root.encodeHostProp(node.type, name, handler.getSnapshot());
2113
+ const encoded2 = root.encodeHostProp(node.type, name, handler.getSnapshot());
2114
+ if (name === "__proto__") defineUniversalProtoProp(props, encoded2);
2115
+ else props[name] = encoded2;
2132
2116
  continue;
2133
2117
  }
2134
2118
  const lifecycle = root.classifyLifecycle(name, handler);
2135
2119
  if (lifecycle !== null) {
2136
- delete props[name];
2120
+ if (props === sourceProps) props = copyUniversalHostPropPrefix(sourceProps, names, index);
2137
2121
  if (handler == null) continue;
2138
2122
  if (typeof handler !== "function") {
2139
2123
  throw new TypeError(
@@ -2150,7 +2134,7 @@ function materializeNode(node, values, renderer, path) {
2150
2134
  }
2151
2135
  const local = root.classifyLocalCallback(name, handler);
2152
2136
  if (local !== null) {
2153
- delete props[name];
2137
+ if (props === sourceProps) props = copyUniversalHostPropPrefix(sourceProps, names, index);
2154
2138
  if (root.driverCapabilities().localHostCallbacks !== true) {
2155
2139
  throw new Error(
2156
2140
  `Universal renderer ${JSON.stringify(renderer)} does not declare the local-host-callback capability.`
@@ -2172,7 +2156,7 @@ function materializeNode(node, values, renderer, path) {
2172
2156
  }
2173
2157
  const definition = root.classifyEvent(name);
2174
2158
  if (definition !== null) {
2175
- delete props[name];
2159
+ if (props === sourceProps) props = copyUniversalHostPropPrefix(sourceProps, names, index);
2176
2160
  if (handler == null) continue;
2177
2161
  if (typeof handler !== "function") {
2178
2162
  throw new TypeError(
@@ -2189,8 +2173,11 @@ function materializeNode(node, values, renderer, path) {
2189
2173
  continue;
2190
2174
  }
2191
2175
  if (isRendererRegion(handler)) markUniversalTreeFeature(UNIVERSAL_TREE_REGION);
2192
- props[name] = root.encodeHostProp(node.type, name, handler);
2176
+ const encoded = root.encodeHostProp(node.type, name, handler);
2177
+ if (name === "__proto__") defineUniversalProtoProp(props, encoded);
2178
+ else props[name] = encoded;
2193
2179
  }
2180
+ if (props !== sourceProps) Object.setPrototypeOf(props, Object.getPrototypeOf(sourceProps));
2194
2181
  if (events !== null && events.size !== 0) markUniversalTreeFeature(UNIVERSAL_TREE_EVENT);
2195
2182
  if (lifecycles !== null && lifecycles.size !== 0)
2196
2183
  markUniversalTreeFeature(UNIVERSAL_TREE_LIFECYCLE);
@@ -2201,29 +2188,25 @@ function materializeNode(node, values, renderer, path) {
2201
2188
  const children = [];
2202
2189
  if ((node.children?.length ?? 0) > 0) {
2203
2190
  for (let index = 0; index < node.children.length; index++) {
2204
- children.push(
2205
- ...materializeNode(node.children[index], values, renderer, [...path, "host", index])
2206
- );
2191
+ materializeNode(node.children[index], values, renderer, [...path, "host", index], children);
2207
2192
  }
2208
2193
  } else if (dynamicChildren !== void 0) {
2209
2194
  children.push(...materializeValue(dynamicChildren, renderer, null, [...path, "host-children"]));
2210
2195
  }
2211
- return [
2212
- {
2213
- kind: "host",
2214
- key: hostKey,
2215
- type: node.type,
2216
- props,
2217
- ...hostBindings === null ? null : { hostBindings },
2218
- ref,
2219
- owner: CURRENT_OWNER.record,
2220
- events: events ?? EMPTY_BLUEPRINT_EVENTS,
2221
- lifecycles: lifecycles ?? EMPTY_BLUEPRINT_HOST_CALLBACKS,
2222
- localCallbacks: localCallbacks ?? EMPTY_BLUEPRINT_HOST_CALLBACKS,
2223
- visibility: CURRENT_OWNER.visibility,
2224
- children
2225
- }
2226
- ];
2196
+ output.push({
2197
+ kind: "host",
2198
+ key: hostKey,
2199
+ type: node.type,
2200
+ props,
2201
+ ...hostBindings === null ? null : { hostBindings },
2202
+ ref,
2203
+ owner: CURRENT_OWNER.record,
2204
+ events: events ?? EMPTY_BLUEPRINT_EVENTS,
2205
+ lifecycles: lifecycles ?? EMPTY_BLUEPRINT_HOST_CALLBACKS,
2206
+ localCallbacks: localCallbacks ?? EMPTY_BLUEPRINT_HOST_CALLBACKS,
2207
+ visibility: CURRENT_OWNER.visibility,
2208
+ children
2209
+ });
2227
2210
  }
2228
2211
  function materializePlanValue(value, expectedRenderer, path = []) {
2229
2212
  if (value.plan.renderer !== expectedRenderer) {
@@ -2236,7 +2219,8 @@ function materializePlanValue(value, expectedRenderer, path = []) {
2236
2219
  if (value.key !== null) collapsed.key = value.key;
2237
2220
  return [collapsed];
2238
2221
  }
2239
- const nodes = materializeNode(value.plan.root, value.values, expectedRenderer, [...path, "plan"]);
2222
+ const nodes = [];
2223
+ materializeNode(value.plan.root, value.values, expectedRenderer, [...path, "plan"], nodes);
2240
2224
  if (currentAttempt().root.driverCapabilities().templateMount === true && value.plan.root.kind === "host" && nodes.length === 1 && nodes[0].kind === "host") {
2241
2225
  nodes[0].templatePlan = value.plan.root;
2242
2226
  }
@@ -2285,17 +2269,21 @@ function materializeCollapsedTemplate(value) {
2285
2269
  nodes[index] = { props: staticProps };
2286
2270
  continue;
2287
2271
  }
2288
- const props = { ...node.props ?? EMPTY_STATIC_HOST_PROPS };
2289
- for (const [name, slot] of node.bindings ?? []) props[name] = value.values[slot];
2272
+ const sourceProps = { ...node.props ?? EMPTY_STATIC_HOST_PROPS };
2273
+ for (const [name, slot] of node.bindings ?? []) sourceProps[name] = value.values[slot];
2274
+ let props = sourceProps;
2290
2275
  let events;
2291
- for (const name of Object.keys(props)) {
2292
- const current = props[name];
2276
+ const names = Object.keys(sourceProps);
2277
+ for (let propIndex = 0; propIndex < names.length; propIndex++) {
2278
+ const name = names[propIndex];
2279
+ const current = sourceProps[name];
2293
2280
  if (isUniversalHostBinding(current) || root.classifyLifecycle(name, current) !== null || root.classifyLocalCallback(name, current) !== null || isRendererRegion(current)) {
2294
2281
  return null;
2295
2282
  }
2296
2283
  const definition = root.classifyEvent(name);
2297
2284
  if (definition !== null) {
2298
- delete props[name];
2285
+ if (props === sourceProps)
2286
+ props = copyUniversalHostPropPrefix(sourceProps, names, propIndex);
2299
2287
  if (current == null) continue;
2300
2288
  if (typeof current !== "function") return null;
2301
2289
  (events ??= []).push({
@@ -2307,8 +2295,11 @@ function materializeCollapsedTemplate(value) {
2307
2295
  });
2308
2296
  continue;
2309
2297
  }
2310
- props[name] = root.encodeHostProp(node.type, name, current);
2298
+ const encoded = root.encodeHostProp(node.type, name, current);
2299
+ if (name === "__proto__") defineUniversalProtoProp(props, encoded);
2300
+ else props[name] = encoded;
2311
2301
  }
2302
+ if (props !== sourceProps) Object.setPrototypeOf(props, Object.getPrototypeOf(sourceProps));
2312
2303
  if (events !== void 0) markUniversalTreeFeature(UNIVERSAL_TREE_EVENT);
2313
2304
  nodes[index] = events === void 0 ? { props } : { props, events };
2314
2305
  }
@@ -2444,7 +2435,8 @@ function createLogicalRecord(id, blueprint) {
2444
2435
  visibility: blueprint.kind === "host" ? blueprint.visibility : "visible",
2445
2436
  portalRegistration: null,
2446
2437
  parent: null,
2447
- children: []
2438
+ children: [],
2439
+ treeFeatures: null
2448
2440
  };
2449
2441
  }
2450
2442
  function hasCrossRealmPlainPrototype(value) {
@@ -2678,27 +2670,34 @@ function walkDraftPostOrder(record, visit) {
2678
2670
  for (const child of record.children) walkDraftPostOrder(child, visit);
2679
2671
  visit(record);
2680
2672
  }
2673
+ function invalidateLogicalTreeFeatures(record) {
2674
+ let current = record;
2675
+ while (current !== null && current.treeFeatures !== null) {
2676
+ current.treeFeatures = null;
2677
+ current = current.parent;
2678
+ }
2679
+ }
2681
2680
  function logicalTreeFeatures(record) {
2681
+ if (record.treeFeatures !== null) return record.treeFeatures;
2682
2682
  let features = 0;
2683
- walkLogical(record, (current) => {
2684
- if (current.kind === "portal") {
2685
- features |= UNIVERSAL_TREE_PORTAL;
2686
- return;
2687
- }
2688
- if (current.kind !== "host") return;
2689
- if (current.events.size !== 0) features |= UNIVERSAL_TREE_EVENT;
2690
- if (current.lifecycles.size !== 0) features |= UNIVERSAL_TREE_LIFECYCLE;
2691
- if (current.localCallbacks.size !== 0) features |= UNIVERSAL_TREE_LOCAL_CALLBACK;
2692
- if (current.ref != null) features |= UNIVERSAL_TREE_REF;
2693
- if (current.visibility !== "visible") features |= UNIVERSAL_TREE_HIDDEN;
2694
- for (const value of Object.values(current.props)) {
2695
- if (isRendererRegion(value)) {
2683
+ if (record.kind === "portal") features |= UNIVERSAL_TREE_PORTAL;
2684
+ else if (record.kind === "host") {
2685
+ if (record.events.size !== 0 || (record.collapsedTemplate?.events.length ?? 0) !== 0) {
2686
+ features |= UNIVERSAL_TREE_EVENT;
2687
+ }
2688
+ if (record.lifecycles.size !== 0) features |= UNIVERSAL_TREE_LIFECYCLE;
2689
+ if (record.localCallbacks.size !== 0) features |= UNIVERSAL_TREE_LOCAL_CALLBACK;
2690
+ if (record.ref != null) features |= UNIVERSAL_TREE_REF;
2691
+ if (record.visibility !== "visible") features |= UNIVERSAL_TREE_HIDDEN;
2692
+ for (const name of Object.keys(record.props)) {
2693
+ if (isRendererRegion(record.props[name])) {
2696
2694
  features |= UNIVERSAL_TREE_REGION;
2697
2695
  break;
2698
2696
  }
2699
2697
  }
2700
- });
2701
- return features;
2698
+ }
2699
+ for (const child of record.children) features |= logicalTreeFeatures(child);
2700
+ return record.treeFeatures = features;
2702
2701
  }
2703
2702
  function ownerTreeHasWarmPlan(owner) {
2704
2703
  if (owner.component?.__warm !== void 0) return true;
@@ -4505,7 +4504,8 @@ class UniversalRootImpl {
4505
4504
  visibility: "visible",
4506
4505
  portalRegistration: null,
4507
4506
  parent: null,
4508
- children: []
4507
+ children: [],
4508
+ treeFeatures: null
4509
4509
  };
4510
4510
  this.initializeHostAttachments();
4511
4511
  }
@@ -5247,6 +5247,7 @@ class UniversalRootImpl {
5247
5247
  if (current === void 0) events.set(entry.index, current = /* @__PURE__ */ new Map());
5248
5248
  current.set(entry.event.type, entry.event);
5249
5249
  }
5250
+ invalidateLogicalTreeFeatures(record);
5250
5251
  const records = [record];
5251
5252
  for (let index = 1; index < state.shape.length; index++) {
5252
5253
  const node = materializeCommittedCollapsedNode(state, index);
@@ -5266,7 +5267,8 @@ class UniversalRootImpl {
5266
5267
  visibility: "visible",
5267
5268
  portalRegistration: null,
5268
5269
  parent: records[state.shape[index].parent],
5269
- children: []
5270
+ children: [],
5271
+ treeFeatures: null
5270
5272
  };
5271
5273
  records.push(child);
5272
5274
  child.parent.children.push(child);
@@ -6132,6 +6134,7 @@ class UniversalRootImpl {
6132
6134
  owners: [owner],
6133
6135
  draftLookup: null,
6134
6136
  treeFeatures: 0,
6137
+ hasCompactLists: false,
6135
6138
  replayEntries: [],
6136
6139
  retryThenables: /* @__PURE__ */ new Set(),
6137
6140
  nextUniversalId: this.nextUniversalId,
@@ -6191,7 +6194,7 @@ class UniversalRootImpl {
6191
6194
  owner: target,
6192
6195
  children: nodes
6193
6196
  };
6194
- this.expandCompactLeafLists(blueprint);
6197
+ if (attempt.hasCompactLists) this.expandCompactLeafLists(blueprint);
6195
6198
  let scopePlacement = null;
6196
6199
  if (range !== this.rootRecord && !stableLogicalChildren(range.children, blueprint.children)) {
6197
6200
  scopePlacement = this.scopePhysicalPlacement(range);
@@ -6364,6 +6367,7 @@ class UniversalRootImpl {
6364
6367
  owners: [owner],
6365
6368
  draftLookup: null,
6366
6369
  treeFeatures: 0,
6370
+ hasCompactLists: false,
6367
6371
  replayEntries,
6368
6372
  retryThenables: /* @__PURE__ */ new Set(),
6369
6373
  nextUniversalId: this.nextUniversalId,
@@ -6963,7 +6967,7 @@ class UniversalRootImpl {
6963
6967
  }
6964
6968
  createTransaction(blueprint, attempt, component, props) {
6965
6969
  const hasHostBindings = (this.boundHosts?.size ?? 0) !== 0 || (attempt.treeFeatures & UNIVERSAL_TREE_HOST_BINDING) !== 0;
6966
- if (!hasHostBindings) {
6970
+ if (attempt.hasCompactLists && !hasHostBindings) {
6967
6971
  const compactTemplateUpdate = this.tryCreateCompactTemplateUpdateTransaction(
6968
6972
  blueprint,
6969
6973
  attempt,
@@ -6979,7 +6983,7 @@ class UniversalRootImpl {
6979
6983
  );
6980
6984
  if (compactLeafUpdate !== null) return compactLeafUpdate;
6981
6985
  }
6982
- this.expandCompactLeafLists(blueprint);
6986
+ if (attempt.hasCompactLists) this.expandCompactLeafLists(blueprint);
6983
6987
  if (!hasHostBindings) {
6984
6988
  const stableLeafUpdate = this.tryCreateStableLeafUpdateTransaction(
6985
6989
  blueprint,
@@ -7090,7 +7094,7 @@ class UniversalRootImpl {
7090
7094
  let keys;
7091
7095
  for (let index = 0; index < blueprints.length; index++) {
7092
7096
  let child = blueprints[index];
7093
- if (child.key !== null) {
7097
+ if (child.key !== null && blueprints.length > 1) {
7094
7098
  keys ??= /* @__PURE__ */ new Set();
7095
7099
  if (keys.has(child.key)) {
7096
7100
  throw new Error(`Duplicate universal child key ${String(child.key)}.`);
@@ -7144,16 +7148,19 @@ class UniversalRootImpl {
7144
7148
  const keyed = /* @__PURE__ */ new Map();
7145
7149
  for (const old of oldChildren) if (old.key !== null) keyed.set(old.key, old);
7146
7150
  const claimed = /* @__PURE__ */ new Set();
7147
- const nextKeys = /* @__PURE__ */ new Set();
7151
+ let nextKeys;
7148
7152
  const output = [];
7149
7153
  for (let childIndex = 0; childIndex < blueprints.length; childIndex++) {
7150
7154
  let child = blueprints[childIndex];
7151
7155
  let record;
7152
7156
  if (child.key !== null) {
7153
- if (nextKeys.has(child.key)) {
7154
- throw new Error(`Duplicate universal child key ${String(child.key)}.`);
7157
+ if (blueprints.length > 1) {
7158
+ nextKeys ??= /* @__PURE__ */ new Set();
7159
+ if (nextKeys.has(child.key)) {
7160
+ throw new Error(`Duplicate universal child key ${String(child.key)}.`);
7161
+ }
7162
+ nextKeys.add(child.key);
7155
7163
  }
7156
- nextKeys.add(child.key);
7157
7164
  const candidate = keyed.get(child.key);
7158
7165
  if (candidate !== void 0 && !claimed.has(candidate) && sameRecordShape(candidate, child)) {
7159
7166
  record = candidate;
@@ -8210,6 +8217,7 @@ class UniversalRootImpl {
8210
8217
  const applyHost = (draft) => {
8211
8218
  const record = draft.record;
8212
8219
  const host = draft.blueprint;
8220
+ invalidateLogicalTreeFeatures(record);
8213
8221
  record.type = host.type;
8214
8222
  record.props = host.props;
8215
8223
  record.ref = host.ref;
@@ -8234,6 +8242,7 @@ class UniversalRootImpl {
8234
8242
  record.parent = parent;
8235
8243
  return;
8236
8244
  }
8245
+ invalidateLogicalTreeFeatures(record);
8237
8246
  record.parent = parent;
8238
8247
  record.key = draft.blueprint.key;
8239
8248
  if (record.kind === "host") {
@@ -8488,6 +8497,7 @@ class UniversalRootImpl {
8488
8497
  this.nextListener = nextListener;
8489
8498
  this.treeFeatures = scoped ? this.treeFeatures | attempt.treeFeatures : attempt.treeFeatures;
8490
8499
  for (const context of changedContexts) context.$$version++;
8500
+ if (changedContexts.size !== 0) bumpContextEpoch();
8491
8501
  const retainedRegionCells = /* @__PURE__ */ new Set();
8492
8502
  for (const { next, previous } of stagedRegionBridges) {
8493
8503
  retainedRegionCells.add(next.activate(previous));
@@ -8903,6 +8913,7 @@ class UniversalRootImpl {
8903
8913
  }
8904
8914
  }
8905
8915
  this.rootRecord.children = [];
8916
+ this.rootRecord.treeFeatures = null;
8906
8917
  this.rootRecord.owner = null;
8907
8918
  let portalReleaseError = NO_PENDING_PASSIVE_ERROR;
8908
8919
  for (const registration of portalRegistrations) {
@@ -9056,6 +9067,7 @@ class UniversalBoundHostTransaction {
9056
9067
  }
9057
9068
  try {
9058
9069
  for (let index = 0; index < this.changedRecords.length; index++) {
9070
+ invalidateLogicalTreeFeatures(this.changedRecords[index]);
9059
9071
  this.changedRecords[index].props = this.batch.commands[index].props;
9060
9072
  }
9061
9073
  } catch (error) {