@lynx-js/react 0.121.0 → 0.121.1

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 (167) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +2 -2
  3. package/runtime/lib/core/commit-context.d.ts +8 -0
  4. package/runtime/lib/core/commit-context.js +18 -0
  5. package/runtime/lib/core/commit-context.js.map +1 -0
  6. package/runtime/lib/core/forceRootRender.d.ts +7 -0
  7. package/runtime/lib/core/forceRootRender.js +40 -0
  8. package/runtime/lib/core/forceRootRender.js.map +1 -0
  9. package/runtime/lib/core/globalProps.d.ts +31 -0
  10. package/runtime/lib/core/globalProps.js +55 -0
  11. package/runtime/lib/core/globalProps.js.map +1 -0
  12. package/runtime/lib/core/hooks/useLynxGlobalEventListener.js +1 -1
  13. package/runtime/lib/core/hooks/useLynxGlobalEventListener.js.map +1 -1
  14. package/runtime/lib/{snapshot/compat → core}/initData.d.ts +1 -1
  15. package/runtime/lib/{snapshot/compat → core}/initData.js +4 -5
  16. package/runtime/lib/core/initData.js.map +1 -0
  17. package/runtime/lib/core/lynx-data-processors.d.ts +2 -0
  18. package/runtime/lib/core/lynx-data-processors.js +53 -0
  19. package/runtime/lib/core/lynx-data-processors.js.map +1 -0
  20. package/runtime/lib/core/lynx-page-data.d.ts +1 -0
  21. package/runtime/lib/core/lynx-page-data.js +14 -0
  22. package/runtime/lib/core/lynx-page-data.js.map +1 -0
  23. package/runtime/lib/core/lynx-update-data.d.ts +11 -0
  24. package/runtime/lib/core/lynx-update-data.js +21 -0
  25. package/runtime/lib/core/lynx-update-data.js.map +1 -0
  26. package/runtime/lib/core/ref.d.ts +37 -0
  27. package/runtime/lib/core/ref.js +108 -0
  28. package/runtime/lib/core/ref.js.map +1 -0
  29. package/runtime/lib/core/reload-version.d.ts +2 -0
  30. package/runtime/lib/{snapshot/lifecycle/pass.js → core/reload-version.js} +4 -5
  31. package/runtime/lib/core/reload-version.js.map +1 -0
  32. package/runtime/lib/element-template/background/attr-slots.d.ts +6 -1
  33. package/runtime/lib/element-template/background/attr-slots.js +35 -2
  34. package/runtime/lib/element-template/background/attr-slots.js.map +1 -1
  35. package/runtime/lib/element-template/background/commit-context.d.ts +3 -3
  36. package/runtime/lib/element-template/background/commit-context.js +15 -18
  37. package/runtime/lib/element-template/background/commit-context.js.map +1 -1
  38. package/runtime/lib/element-template/background/commit-hook.d.ts +1 -1
  39. package/runtime/lib/element-template/background/commit-hook.js +66 -41
  40. package/runtime/lib/element-template/background/commit-hook.js.map +1 -1
  41. package/runtime/lib/element-template/background/destroy.js +9 -6
  42. package/runtime/lib/element-template/background/destroy.js.map +1 -1
  43. package/runtime/lib/element-template/background/document.js +1 -7
  44. package/runtime/lib/element-template/background/document.js.map +1 -1
  45. package/runtime/lib/element-template/background/hydrate.d.ts +1 -1
  46. package/runtime/lib/element-template/background/hydrate.js +53 -36
  47. package/runtime/lib/element-template/background/hydrate.js.map +1 -1
  48. package/runtime/lib/element-template/background/hydration-listener.js +55 -9
  49. package/runtime/lib/element-template/background/hydration-listener.js.map +1 -1
  50. package/runtime/lib/element-template/background/instance.d.ts +12 -10
  51. package/runtime/lib/element-template/background/instance.js +113 -115
  52. package/runtime/lib/element-template/background/instance.js.map +1 -1
  53. package/runtime/lib/element-template/client/root.d.ts +7 -0
  54. package/runtime/lib/element-template/client/root.js +3 -6
  55. package/runtime/lib/element-template/client/root.js.map +1 -1
  56. package/runtime/lib/element-template/debug/alog.d.ts +7 -0
  57. package/runtime/lib/element-template/debug/alog.js +10 -0
  58. package/runtime/lib/element-template/debug/alog.js.map +1 -1
  59. package/runtime/lib/element-template/debug/elementPAPICall.js +4 -0
  60. package/runtime/lib/element-template/debug/elementPAPICall.js.map +1 -1
  61. package/runtime/lib/element-template/hydration-map.d.ts +5 -0
  62. package/runtime/lib/element-template/hydration-map.js +12 -0
  63. package/runtime/lib/element-template/hydration-map.js.map +1 -0
  64. package/runtime/lib/element-template/index.d.ts +22 -1
  65. package/runtime/lib/element-template/index.js +32 -2
  66. package/runtime/lib/element-template/index.js.map +1 -1
  67. package/runtime/lib/element-template/internal.d.ts +1 -1
  68. package/runtime/lib/element-template/internal.js +2 -3
  69. package/runtime/lib/element-template/internal.js.map +1 -1
  70. package/runtime/lib/element-template/lynx/env.js +5 -48
  71. package/runtime/lib/element-template/lynx/env.js.map +1 -1
  72. package/runtime/lib/element-template/native/index.d.ts +1 -1
  73. package/runtime/lib/element-template/native/index.js +28 -2
  74. package/runtime/lib/element-template/native/index.js.map +1 -1
  75. package/runtime/lib/element-template/native/main-thread-api.js +27 -5
  76. package/runtime/lib/element-template/native/main-thread-api.js.map +1 -1
  77. package/runtime/lib/element-template/native/patch-listener.js +5 -1
  78. package/runtime/lib/element-template/native/patch-listener.js.map +1 -1
  79. package/runtime/lib/element-template/native/reload.d.ts +2 -0
  80. package/runtime/lib/element-template/native/reload.js +64 -0
  81. package/runtime/lib/element-template/native/reload.js.map +1 -0
  82. package/runtime/lib/element-template/prop-adapters/event.d.ts +1 -0
  83. package/runtime/lib/element-template/prop-adapters/event.js +4 -1
  84. package/runtime/lib/element-template/prop-adapters/event.js.map +1 -1
  85. package/runtime/lib/element-template/prop-adapters/ref.d.ts +26 -0
  86. package/runtime/lib/element-template/prop-adapters/ref.js +107 -0
  87. package/runtime/lib/element-template/prop-adapters/ref.js.map +1 -0
  88. package/runtime/lib/element-template/prop-adapters/spread.js +8 -1
  89. package/runtime/lib/element-template/prop-adapters/spread.js.map +1 -1
  90. package/runtime/lib/element-template/protocol/opcodes.d.ts +1 -0
  91. package/runtime/lib/element-template/protocol/opcodes.js +1 -0
  92. package/runtime/lib/element-template/protocol/opcodes.js.map +1 -1
  93. package/runtime/lib/element-template/protocol/types.d.ts +50 -2
  94. package/runtime/lib/element-template/runtime/page/page.d.ts +5 -2
  95. package/runtime/lib/element-template/runtime/page/page.js +12 -0
  96. package/runtime/lib/element-template/runtime/page/page.js.map +1 -1
  97. package/runtime/lib/element-template/runtime/patch.js +70 -1
  98. package/runtime/lib/element-template/runtime/patch.js.map +1 -1
  99. package/runtime/lib/element-template/runtime/render/render-main-thread.d.ts +3 -1
  100. package/runtime/lib/element-template/runtime/render/render-main-thread.js +25 -7
  101. package/runtime/lib/element-template/runtime/render/render-main-thread.js.map +1 -1
  102. package/runtime/lib/element-template/runtime/render/render-to-opcodes.js +9 -3
  103. package/runtime/lib/element-template/runtime/render/render-to-opcodes.js.map +1 -1
  104. package/runtime/lib/element-template/runtime/template/attr-slot-plan.d.ts +1 -0
  105. package/runtime/lib/element-template/runtime/template/attr-slot-plan.js +4 -0
  106. package/runtime/lib/element-template/runtime/template/attr-slot-plan.js.map +1 -1
  107. package/runtime/lib/element-template/runtime/template/handle.js +0 -1
  108. package/runtime/lib/element-template/runtime/template/handle.js.map +1 -1
  109. package/runtime/lib/element-template/runtime/template/registry.js +1 -1
  110. package/runtime/lib/element-template/runtime/template/registry.js.map +1 -1
  111. package/runtime/lib/internal.d.ts +1 -1
  112. package/runtime/lib/internal.js +1 -1
  113. package/runtime/lib/internal.js.map +1 -1
  114. package/runtime/lib/lynx-api.d.ts +3 -8
  115. package/runtime/lib/lynx-api.js +8 -45
  116. package/runtime/lib/lynx-api.js.map +1 -1
  117. package/runtime/lib/snapshot/debug/vnodeSource.js +1 -1
  118. package/runtime/lib/snapshot/debug/vnodeSource.js.map +1 -1
  119. package/runtime/lib/snapshot/lifecycle/patch/commit.d.ts +0 -1
  120. package/runtime/lib/snapshot/lifecycle/patch/commit.js +3 -8
  121. package/runtime/lib/snapshot/lifecycle/patch/commit.js.map +1 -1
  122. package/runtime/lib/snapshot/lifecycle/patch/updateMainThread.js +1 -1
  123. package/runtime/lib/snapshot/lifecycle/patch/updateMainThread.js.map +1 -1
  124. package/runtime/lib/snapshot/lifecycle/ref/delay.d.ts +6 -13
  125. package/runtime/lib/snapshot/lifecycle/ref/delay.js +9 -30
  126. package/runtime/lib/snapshot/lifecycle/ref/delay.js.map +1 -1
  127. package/runtime/lib/snapshot/lifecycle/reload.js +2 -2
  128. package/runtime/lib/snapshot/lifecycle/reload.js.map +1 -1
  129. package/runtime/lib/snapshot/list/list.js +1 -1
  130. package/runtime/lib/snapshot/list/list.js.map +1 -1
  131. package/runtime/lib/snapshot/list/listUpdateInfo.js +3 -2
  132. package/runtime/lib/snapshot/list/listUpdateInfo.js.map +1 -1
  133. package/runtime/lib/snapshot/lynx/calledByNative.js +2 -8
  134. package/runtime/lib/snapshot/lynx/calledByNative.js.map +1 -1
  135. package/runtime/lib/snapshot/lynx/component.js +2 -2
  136. package/runtime/lib/snapshot/lynx/component.js.map +1 -1
  137. package/runtime/lib/snapshot/lynx/env.js +5 -51
  138. package/runtime/lib/snapshot/lynx/env.js.map +1 -1
  139. package/runtime/lib/snapshot/lynx/runWithForce.js +9 -39
  140. package/runtime/lib/snapshot/lynx/runWithForce.js.map +1 -1
  141. package/runtime/lib/snapshot/lynx/tt.js +9 -29
  142. package/runtime/lib/snapshot/lynx/tt.js.map +1 -1
  143. package/runtime/lib/snapshot/snapshot/backgroundSnapshot.js +3 -3
  144. package/runtime/lib/snapshot/snapshot/backgroundSnapshot.js.map +1 -1
  145. package/runtime/lib/snapshot/snapshot/list.js +1 -1
  146. package/runtime/lib/snapshot/snapshot/list.js.map +1 -1
  147. package/runtime/lib/snapshot/snapshot/ref.d.ts +3 -5
  148. package/runtime/lib/snapshot/snapshot/ref.js +16 -59
  149. package/runtime/lib/snapshot/snapshot/ref.js.map +1 -1
  150. package/runtime/lib/snapshot/snapshot/snapshotInstanceHydrationMap.js +1 -1
  151. package/runtime/lib/snapshot/snapshot/snapshotInstanceHydrationMap.js.map +1 -1
  152. package/runtime/lib/tsconfig.tsbuildinfo +1 -1
  153. package/runtime/lib/worklet-runtime/workletRuntime.js +1 -1
  154. package/runtime/lib/worklet-runtime/workletRuntime.js.map +1 -1
  155. package/runtime/worklet-runtime/dev.js +2 -2
  156. package/testing-library/dist/env/index.js +2 -8
  157. package/testing-library/dist/plugins/index.js +12 -1
  158. package/transform/dist/wasm.cjs +1 -1
  159. package/runtime/lib/element-template/hooks/react.d.ts +0 -14
  160. package/runtime/lib/element-template/hooks/react.js +0 -24
  161. package/runtime/lib/element-template/hooks/react.js.map +0 -1
  162. package/runtime/lib/element-template/runtime/components/slot.d.ts +0 -1
  163. package/runtime/lib/element-template/runtime/components/slot.js +0 -11
  164. package/runtime/lib/element-template/runtime/components/slot.js.map +0 -1
  165. package/runtime/lib/snapshot/compat/initData.js.map +0 -1
  166. package/runtime/lib/snapshot/lifecycle/pass.d.ts +0 -3
  167. package/runtime/lib/snapshot/lifecycle/pass.js.map +0 -1
@@ -1,7 +1,8 @@
1
1
  // Copyright 2026 The Lynx Authors. All rights reserved.
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
- import { __etAttrPlanMap } from '../runtime/template/attr-slot-plan.js';
4
+ import { getSpreadRefFromValue, queueRefAttrUpdate } from '../prop-adapters/ref.js';
5
+ import { __etAttrPlanMap, adaptRefAttrSlot, adaptSpreadAttrSlot } from '../runtime/template/attr-slot-plan.js';
5
6
  function normalizeAttributeSlots(rawSlots) {
6
7
  let normalizedSlots;
7
8
  for (let slotIndex = 0; slotIndex < rawSlots.length; slotIndex += 1) {
@@ -14,7 +15,25 @@ function normalizeAttributeSlots(rawSlots) {
14
15
  }
15
16
  return normalizedSlots ?? rawSlots;
16
17
  }
17
- export function prepareAttributeSlots(templateKey, handleId, rawSlots) {
18
+ function queuePlannedRefAttributeSlotUpdates(handleId, attrPlan, previousRawSlots, nextRawSlots) {
19
+ for (let planIndex = 0; planIndex < attrPlan.length; planIndex += 2) {
20
+ const attrSlotIndex = attrPlan[planIndex];
21
+ const adapter = attrPlan[planIndex + 1];
22
+ if (adapter === adaptRefAttrSlot) {
23
+ queueRefAttrUpdate(previousRawSlots?.[attrSlotIndex], nextRawSlots?.[attrSlotIndex], handleId, attrSlotIndex);
24
+ continue;
25
+ }
26
+ if (adapter === adaptSpreadAttrSlot) {
27
+ const previousSpreadRef = getSpreadRefFromValue(previousRawSlots?.[attrSlotIndex]);
28
+ const nextSpreadRef = getSpreadRefFromValue(nextRawSlots?.[attrSlotIndex]);
29
+ if (previousSpreadRef === undefined && nextSpreadRef === undefined) {
30
+ continue;
31
+ }
32
+ queueRefAttrUpdate(previousSpreadRef, nextSpreadRef ?? null, handleId, attrSlotIndex);
33
+ }
34
+ }
35
+ }
36
+ export function prepareAttributeSlots(templateKey, handleId, rawSlots, options) {
18
37
  const attrPlan = __etAttrPlanMap[templateKey];
19
38
  if (!attrPlan || attrPlan.length === 0) {
20
39
  return normalizeAttributeSlots(rawSlots);
@@ -23,12 +42,26 @@ export function prepareAttributeSlots(templateKey, handleId, rawSlots) {
23
42
  const preparedSlots = normalizedSlots === rawSlots
24
43
  ? rawSlots.slice()
25
44
  : normalizedSlots;
45
+ const shouldQueueRefEffects = options?.queueRefEffects === true;
46
+ const previousRawSlots = options?.previousRawSlots;
26
47
  for (let planIndex = 0; planIndex < attrPlan.length; planIndex += 2) {
27
48
  const attrSlotIndex = attrPlan[planIndex];
28
49
  const adapter = attrPlan[planIndex + 1];
29
50
  const rawValue = rawSlots[attrSlotIndex];
30
51
  preparedSlots[attrSlotIndex] = adapter(handleId, attrSlotIndex, rawValue);
31
52
  }
53
+ if (shouldQueueRefEffects) {
54
+ // Ref effects compare raw user refs, not prepared marker strings or the
55
+ // spread wrapper object.
56
+ queuePlannedRefAttributeSlotUpdates(handleId, attrPlan, previousRawSlots, rawSlots);
57
+ }
32
58
  return preparedSlots;
33
59
  }
60
+ export function queueRefAttributeSlotUpdates(templateKey, handleId, previousRawSlots, nextRawSlots) {
61
+ const attrPlan = __etAttrPlanMap[templateKey];
62
+ if (!attrPlan || attrPlan.length === 0) {
63
+ return;
64
+ }
65
+ queuePlannedRefAttributeSlotUpdates(handleId, attrPlan, previousRawSlots, nextRawSlots);
66
+ }
34
67
  //# sourceMappingURL=attr-slots.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"attr-slots.js","sourceRoot":"","sources":["../../../src/element-template/background/attr-slots.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAG1D,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,SAAS,uBAAuB,CAAC,QAA4B;IAC3D,IAAI,eAAgD,CAAC;IACrD,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,IAAI,CAAC,EAAE,CAAC;QACpE,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,eAAe,KAAK,QAAQ,CAAC,KAAK,EAAyB,CAAC;QAC5D,eAAe,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IACpC,CAAC;IACD,OAAO,eAAe,IAAI,QAA+B,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,QAAgB,EAChB,QAA4B;IAE5B,MAAM,QAAQ,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,eAAe,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,eAAe,KAAK,QAAQ;QAChD,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAyB;QACzC,CAAC,CAAC,eAAe,CAAC;IACpB,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,IAAI,CAAC,EAAE,CAAC;QACpE,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAW,CAAC;QACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,GAAG,CAAC,CAAkB,CAAC;QACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;QACzC,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"attr-slots.js","sourceRoot":"","sources":["../../../src/element-template/background/attr-slots.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  import type { BackgroundElementTemplateInstance } from './instance.js';
2
2
  import type { ElementTemplateUpdateCommitContext } from '../protocol/types.js';
3
3
  interface ElementTemplateCommitNonPayloadState {
4
- removedSubtrees: BackgroundElementTemplateInstance[];
4
+ removedSubtreesAwaitingTeardown: BackgroundElementTemplateInstance[];
5
5
  }
6
6
  type ElementTemplateGlobalCommitContext = ElementTemplateUpdateCommitContext & {
7
7
  nonPayload: ElementTemplateCommitNonPayloadState;
8
8
  };
9
9
  export declare const globalCommitContext: ElementTemplateGlobalCommitContext;
10
10
  export declare function resetGlobalCommitContext(): void;
11
- export declare function markRemovedSubtreeForCurrentCommit(root: BackgroundElementTemplateInstance): void;
12
- export declare function takeRemovedSubtreesForCurrentCommit(): BackgroundElementTemplateInstance[];
11
+ export declare function markRemovedSubtreeForPostDispatchTeardown(root: BackgroundElementTemplateInstance): void;
12
+ export declare function takeRemovedSubtreesForPostDispatchTeardown(): BackgroundElementTemplateInstance[];
13
13
  export {};
@@ -1,25 +1,22 @@
1
- export const globalCommitContext = {
2
- ops: [],
3
- flushOptions: {},
4
- nonPayload: {
5
- removedSubtrees: [],
6
- },
1
+ import { globalCommitContext as coreGlobalCommitContext, resetGlobalCommitContext as resetCoreGlobalCommitContext, } from '../../core/commit-context.js';
2
+ const nonPayload = {
3
+ removedSubtreesAwaitingTeardown: [],
7
4
  };
5
+ export const globalCommitContext = coreGlobalCommitContext;
6
+ globalCommitContext.nonPayload = nonPayload;
8
7
  export function resetGlobalCommitContext() {
9
- globalCommitContext.ops = [];
10
- globalCommitContext.flushOptions = {};
11
- delete globalCommitContext.flowIds;
12
- globalCommitContext.nonPayload.removedSubtrees = [];
8
+ resetCoreGlobalCommitContext();
9
+ nonPayload.removedSubtreesAwaitingTeardown = [];
13
10
  }
14
- export function markRemovedSubtreeForCurrentCommit(root) {
15
- const { removedSubtrees } = globalCommitContext.nonPayload;
16
- if (!removedSubtrees.includes(root)) {
17
- removedSubtrees.push(root);
11
+ export function markRemovedSubtreeForPostDispatchTeardown(root) {
12
+ const { removedSubtreesAwaitingTeardown } = globalCommitContext.nonPayload;
13
+ if (!removedSubtreesAwaitingTeardown.includes(root)) {
14
+ removedSubtreesAwaitingTeardown.push(root);
18
15
  }
19
16
  }
20
- export function takeRemovedSubtreesForCurrentCommit() {
21
- const removedSubtrees = globalCommitContext.nonPayload.removedSubtrees;
22
- globalCommitContext.nonPayload.removedSubtrees = [];
23
- return removedSubtrees;
17
+ export function takeRemovedSubtreesForPostDispatchTeardown() {
18
+ const removedSubtreesAwaitingTeardown = globalCommitContext.nonPayload.removedSubtreesAwaitingTeardown;
19
+ globalCommitContext.nonPayload.removedSubtreesAwaitingTeardown = [];
20
+ return removedSubtreesAwaitingTeardown;
24
21
  }
25
22
  //# sourceMappingURL=commit-context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commit-context.js","sourceRoot":"","sources":["../../../src/element-template/background/commit-context.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,mBAAmB,GAAuC;IACrE,GAAG,EAAE,EAAE;IACP,YAAY,EAAE,EAAE;IAChB,UAAU,EAAE;QACV,eAAe,EAAE,EAAE;KACpB;CACF,CAAC;AAEF,MAAM,UAAU,wBAAwB;IACtC,mBAAmB,CAAC,GAAG,GAAG,EAAE,CAAC;IAC7B,mBAAmB,CAAC,YAAY,GAAG,EAAE,CAAC;IACtC,OAAO,mBAAmB,CAAC,OAAO,CAAC;IACnC,mBAAmB,CAAC,UAAU,CAAC,eAAe,GAAG,EAAE,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,IAAuC;IAEvC,MAAM,EAAE,eAAe,EAAE,GAAG,mBAAmB,CAAC,UAAU,CAAC;IAC3D,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mCAAmC;IACjD,MAAM,eAAe,GAAG,mBAAmB,CAAC,UAAU,CAAC,eAAe,CAAC;IACvE,mBAAmB,CAAC,UAAU,CAAC,eAAe,GAAG,EAAE,CAAC;IACpD,OAAO,eAAe,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"commit-context.js","sourceRoot":"","sources":["../../../src/element-template/background/commit-context.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,mBAAmB,IAAI,uBAAuB,EAC9C,wBAAwB,IAAI,4BAA4B,GACzD,MAAM,8BAA8B,CAAC;AActC,MAAM,UAAU,GAAyC;IACvD,+BAA+B,EAAE,EAAE;CACpC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,uBAAwE,CAAC;AAE5G,mBAAmB,CAAC,UAAU,GAAG,UAAU,CAAC;AAE5C,MAAM,UAAU,wBAAwB;IACtC,4BAA4B,EAAE,CAAC;IAC/B,UAAU,CAAC,+BAA+B,GAAG,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,yCAAyC,CACvD,IAAuC;IAEvC,MAAM,EAAE,+BAA+B,EAAE,GAAG,mBAAmB,CAAC,UAAU,CAAC;IAC3E,IAAI,CAAC,+BAA+B,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,0CAA0C;IACxD,MAAM,+BAA+B,GAAG,mBAAmB,CAAC,UAAU,CAAC,+BAA+B,CAAC;IACvG,mBAAmB,CAAC,UAAU,CAAC,+BAA+B,GAAG,EAAE,CAAC;IACpE,OAAO,+BAA+B,CAAC;AACzC,CAAC"}
@@ -2,6 +2,6 @@ import type { BackgroundElementTemplateInstance } from './instance.js';
2
2
  export declare function markElementTemplateHydrated(): void;
3
3
  export declare function isElementTemplateHydrated(): boolean;
4
4
  export declare function resetElementTemplateCommitState(): void;
5
- export declare function scheduleElementTemplateRemovedSubtreeCleanup(removedSubtrees: BackgroundElementTemplateInstance[]): void;
5
+ export declare function scheduleElementTemplateRemovedSubtreeCleanup(removedSubtreesAwaitingTeardown: BackgroundElementTemplateInstance[]): void;
6
6
  export declare function cancelElementTemplateRemovedSubtreeCleanup(): void;
7
7
  export declare function installElementTemplateCommitHook(): void;
@@ -2,16 +2,18 @@
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
4
  import { options } from 'preact';
5
- import { globalCommitContext, resetGlobalCommitContext, takeRemovedSubtreesForCurrentCommit, } from './commit-context.js';
5
+ import { globalCommitContext, resetGlobalCommitContext, takeRemovedSubtreesForPostDispatchTeardown, } from './commit-context.js';
6
+ import { getReloadVersion } from '../../core/reload-version.js';
6
7
  import { COMMIT } from '../../shared/render-constants.js';
7
- import { hook } from '../../utils.js';
8
+ import { hook, isEmptyObject } from '../../utils.js';
8
9
  import { formatElementTemplateUpdateCommands } from '../debug/alog.js';
9
10
  import { profileEnd, profileStart } from '../debug/profile.js';
10
11
  import { globalPipelineOptions, markTiming, markTimingLegacy, setPipeline } from '../lynx/performance.js';
12
+ import { clearPendingRefs, flushPendingRefs, hasPendingRefs } from '../prop-adapters/ref.js';
11
13
  import { ElementTemplateLifecycleConstant } from '../protocol/lifecycle-constant.js';
12
14
  let installed = false;
13
15
  let hasHydrated = false;
14
- const scheduledRemovedSubtreeCleanupTimers = new Set();
16
+ const scheduledRemovedSubtreeCleanupTimers = /*#__PURE__*/ new Set();
15
17
  export function markElementTemplateHydrated() {
16
18
  hasHydrated = true;
17
19
  }
@@ -22,13 +24,13 @@ export function resetElementTemplateCommitState() {
22
24
  hasHydrated = false;
23
25
  resetGlobalCommitContext();
24
26
  }
25
- export function scheduleElementTemplateRemovedSubtreeCleanup(removedSubtrees) {
26
- if (removedSubtrees.length === 0) {
27
+ export function scheduleElementTemplateRemovedSubtreeCleanup(removedSubtreesAwaitingTeardown) {
28
+ if (removedSubtreesAwaitingTeardown.length === 0) {
27
29
  return;
28
30
  }
29
31
  const timer = setTimeout(() => {
30
32
  scheduledRemovedSubtreeCleanupTimers.delete(timer);
31
- for (const root of removedSubtrees) {
33
+ for (const root of removedSubtreesAwaitingTeardown) {
32
34
  root.tearDown();
33
35
  }
34
36
  }, 10000);
@@ -46,48 +48,71 @@ export function installElementTemplateCommitHook() {
46
48
  }
47
49
  installed = true;
48
50
  hook(options, COMMIT, (originalCommit, vnode, commitQueue) => {
49
- if (__BACKGROUND__ && hasHydrated && globalCommitContext.ops.length > 0) {
50
- markTimingLegacy('updateDiffVdomEnd');
51
- markTiming('diffVdomEnd');
52
- if (__PROFILE__) {
53
- profileStart('ReactLynx::commitChanges');
54
- }
55
- markTiming('packChangesStart');
56
- if (globalPipelineOptions) {
57
- globalCommitContext.flushOptions.pipelineOptions = globalPipelineOptions;
58
- }
59
- markTiming('packChangesEnd');
60
- if (globalPipelineOptions) {
61
- setPipeline(undefined);
62
- }
63
- if (__PROFILE__) {
64
- profileEnd();
65
- }
66
- if (typeof __ALOG__ !== 'undefined' && __ALOG__) {
67
- console.alog?.('[ReactLynxDebug] ElementTemplate BTS -> MTS update:\n'
68
- + JSON.stringify({
69
- ops: formatElementTemplateUpdateCommands(globalCommitContext.ops),
70
- flushOptions: globalCommitContext.flushOptions,
71
- flowIds: globalCommitContext.flowIds,
72
- }, null, 2));
73
- }
74
- const removedSubtrees = takeRemovedSubtreesForCurrentCommit();
51
+ if (__BACKGROUND__ && !hasHydrated && hasPendingRefs()) {
52
+ // User effects can run before ET hydrate arrives, so ordinary refs must be
53
+ // attached on the background commit even though native UI ops are delayed.
54
+ flushPendingRefs();
55
+ }
56
+ else if (__BACKGROUND__ && hasHydrated
57
+ && (globalCommitContext.ops.length > 0
58
+ || !isEmptyObject(globalCommitContext.flushOptions)
59
+ || hasPendingRefs())) {
60
+ const hasNativeOps = globalCommitContext.ops.length > 0;
61
+ const hasUpdatePayload = hasNativeOps || !isEmptyObject(globalCommitContext.flushOptions);
62
+ const removedSubtreesAwaitingTeardown = hasNativeOps ? takeRemovedSubtreesForPostDispatchTeardown() : [];
63
+ let didFlushRefs = false;
75
64
  try {
76
- lynx.getCoreContext().dispatchEvent({
77
- type: ElementTemplateLifecycleConstant.update,
78
- data: {
79
- ops: globalCommitContext.ops,
80
- flushOptions: globalCommitContext.flushOptions,
81
- flowIds: globalCommitContext.flowIds,
82
- },
83
- });
65
+ if (hasUpdatePayload) {
66
+ markTimingLegacy('updateDiffVdomEnd');
67
+ markTiming('diffVdomEnd');
68
+ if (__PROFILE__) {
69
+ profileStart('ReactLynx::commitChanges');
70
+ }
71
+ markTiming('packChangesStart');
72
+ if (globalPipelineOptions) {
73
+ globalCommitContext.flushOptions.pipelineOptions = globalPipelineOptions;
74
+ }
75
+ markTiming('packChangesEnd');
76
+ if (globalPipelineOptions) {
77
+ setPipeline(undefined);
78
+ }
79
+ if (__PROFILE__) {
80
+ profileEnd();
81
+ }
82
+ if (typeof __ALOG__ !== 'undefined' && __ALOG__) {
83
+ console.alog?.('[ReactLynxDebug] ElementTemplate BTS -> MTS update:\n'
84
+ + JSON.stringify({
85
+ ops: formatElementTemplateUpdateCommands(globalCommitContext.ops),
86
+ flushOptions: globalCommitContext.flushOptions,
87
+ flowIds: globalCommitContext.flowIds,
88
+ }, null, 2));
89
+ }
90
+ }
91
+ if (hasUpdatePayload) {
92
+ lynx.getCoreContext().dispatchEvent({
93
+ type: ElementTemplateLifecycleConstant.update,
94
+ data: {
95
+ ops: globalCommitContext.ops,
96
+ flushOptions: globalCommitContext.flushOptions,
97
+ flowIds: globalCommitContext.flowIds,
98
+ reloadVersion: getReloadVersion(),
99
+ },
100
+ });
101
+ }
102
+ // When native ops exist, patch first so a newly attached ref observes the
103
+ // committed native state. Ref-only commits still flush through this path.
104
+ flushPendingRefs();
105
+ didFlushRefs = true;
84
106
  }
85
107
  finally {
108
+ if (!didFlushRefs) {
109
+ clearPendingRefs();
110
+ }
86
111
  resetGlobalCommitContext();
87
112
  // Match Snapshot's cleanup boundary: start the delayed teardown only
88
113
  // after the bridge dispatch attempt, so background JS objects are not
89
114
  // torn down before main-thread detach observes the same commit.
90
- scheduleElementTemplateRemovedSubtreeCleanup(removedSubtrees);
115
+ scheduleElementTemplateRemovedSubtreeCleanup(removedSubtreesAwaitingTeardown);
91
116
  }
92
117
  }
93
118
  originalCommit?.(vnode, commitQueue);
@@ -1 +1 @@
1
- {"version":3,"file":"commit-hook.js","sourceRoot":"","sources":["../../../src/element-template/background/commit-hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commit-hook.js","sourceRoot":"","sources":["../../../src/element-template/background/commit-hook.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,20 @@
1
- // Copyright 2026 The Lynx Authors. All rights reserved.
2
- // Licensed under the Apache License Version 2.0 that can be found in the
3
- // LICENSE file in the root directory of this source tree.
1
+ import { render } from 'preact';
4
2
  import { cancelElementTemplateRemovedSubtreeCleanup, resetElementTemplateCommitState } from './commit-hook.js';
5
3
  import { resetElementTemplateHydrationListener } from './hydration-listener.js';
6
4
  import { backgroundElementTemplateInstanceManager } from './manager.js';
7
5
  import { clearEventState } from '../prop-adapters/event.js';
6
+ import { clearRefState, flushPendingRefs } from '../prop-adapters/ref.js';
7
+ import { __root } from '../runtime/page/root-instance.js';
8
8
  export function destroyElementTemplateBackgroundRuntime() {
9
9
  resetElementTemplateHydrationListener();
10
- resetElementTemplateCommitState();
11
- // Destroy is the only place that may discard delayed removed subtrees instead
12
- // of letting the Snapshot-aligned timer tear them down later.
13
10
  cancelElementTemplateRemovedSubtreeCleanup();
11
+ render(null, __root);
12
+ // Run user cleanup before dropping the backend side tables; after clearRefState
13
+ // the raw ref ownership needed to detach callbacks is gone.
14
+ flushPendingRefs();
15
+ resetElementTemplateCommitState();
14
16
  clearEventState();
17
+ clearRefState();
15
18
  backgroundElementTemplateInstanceManager.clear();
16
19
  }
17
20
  //# sourceMappingURL=destroy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"destroy.js","sourceRoot":"","sources":["../../../src/element-template/background/destroy.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAE1D,OAAO,EAAE,0CAA0C,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,wCAAwC,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,UAAU,uCAAuC;IACrD,qCAAqC,EAAE,CAAC;IACxC,+BAA+B,EAAE,CAAC;IAClC,8EAA8E;IAC9E,8DAA8D;IAC9D,0CAA0C,EAAE,CAAC;IAC7C,eAAe,EAAE,CAAC;IAClB,wCAAwC,CAAC,KAAK,EAAE,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"destroy.js","sourceRoot":"","sources":["../../../src/element-template/background/destroy.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,0CAA0C,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,wCAAwC,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAC;AAE1D,MAAM,UAAU,uCAAuC;IACrD,qCAAqC,EAAE,CAAC;IACxC,0CAA0C,EAAE,CAAC;IAE7C,MAAM,CAAC,IAAI,EAAE,MAAkC,CAAC,CAAC;IACjD,gFAAgF;IAChF,4DAA4D;IAC5D,gBAAgB,EAAE,CAAC;IAEnB,+BAA+B,EAAE,CAAC;IAClC,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC;IAChB,wCAAwC,CAAC,KAAK,EAAE,CAAC;AACnD,CAAC"}
@@ -2,19 +2,13 @@
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
4
  import { options } from 'preact';
5
- import { BUILTIN_RAW_TEXT_TEMPLATE_KEY, BackgroundElementTemplateInstance, BackgroundElementTemplateSlot, } from './instance.js';
5
+ import { BUILTIN_RAW_TEXT_TEMPLATE_KEY, BackgroundElementTemplateInstance } from './instance.js';
6
6
  export function setupBackgroundElementTemplateDocument() {
7
7
  const doc = {
8
8
  createElement(type) {
9
- if (type === 'slot') {
10
- return new BackgroundElementTemplateSlot();
11
- }
12
9
  return new BackgroundElementTemplateInstance(type);
13
10
  },
14
11
  createElementNS(_ns, type) {
15
- if (type === 'slot') {
16
- return new BackgroundElementTemplateSlot();
17
- }
18
12
  return new BackgroundElementTemplateInstance(type);
19
13
  },
20
14
  createTextNode(text) {
@@ -1 +1 @@
1
- {"version":3,"file":"document.js","sourceRoot":"","sources":["../../../src/element-template/background/document.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,OAAO,EACL,6BAA6B,EAC7B,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,eAAe,CAAC;AAQvB,MAAM,UAAU,sCAAsC;IACpD,MAAM,GAAG,GAAG;QACV,aAAa,CAAC,IAAY;YACxB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpB,OAAO,IAAI,6BAA6B,EAAE,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,iCAAiC,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,eAAe,CAAC,GAAW,EAAE,IAAY;YACvC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpB,OAAO,IAAI,6BAA6B,EAAE,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,iCAAiC,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,cAAc,CAAC,IAAY;YACzB,OAAO,IAAI,iCAAiC,CAAC,6BAA6B,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACtF,CAAC;KACF,CAAC;IAEF,OAAO,CAAC,QAAQ,GAAG,GAA0B,CAAC;IAE9C,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../../src/element-template/background/document.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,OAAO,EAAE,6BAA6B,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAQjG,MAAM,UAAU,sCAAsC;IACpD,MAAM,GAAG,GAAG;QACV,aAAa,CAAC,IAAY;YACxB,OAAO,IAAI,iCAAiC,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,eAAe,CAAC,GAAW,EAAE,IAAY;YACvC,OAAO,IAAI,iCAAiC,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,cAAc,CAAC,IAAY;YACzB,OAAO,IAAI,iCAAiC,CAAC,6BAA6B,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACtF,CAAC;KACF,CAAC;IAEF,OAAO,CAAC,QAAQ,GAAG,GAA0B,CAAC;IAE9C,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1,4 +1,4 @@
1
1
  import type { BackgroundElementTemplateInstance } from './instance.js';
2
2
  import type { ElementTemplateUpdateCommandStream, SerializedElementTemplate } from '../protocol/types.js';
3
3
  export declare function hydrate(serialized: SerializedElementTemplate, instance: BackgroundElementTemplateInstance): ElementTemplateUpdateCommandStream;
4
- export declare function hydrateIntoContext(serialized: SerializedElementTemplate, instance: BackgroundElementTemplateInstance): void;
4
+ export declare function hydrateIntoContext(serialized: SerializedElementTemplate, instance: BackgroundElementTemplateInstance): boolean;
@@ -1,18 +1,24 @@
1
1
  // Copyright 2025 The Lynx Authors. All rights reserved.
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
- import { globalCommitContext, markRemovedSubtreeForCurrentCommit, resetGlobalCommitContext } from './commit-context.js';
4
+ import { globalCommitContext, markRemovedSubtreeForPostDispatchTeardown, resetGlobalCommitContext, } from './commit-context.js';
5
5
  import { BUILTIN_RAW_TEXT_TEMPLATE_KEY } from './instance.js';
6
6
  import { backgroundElementTemplateInstanceManager } from './manager.js';
7
7
  import { isDirectOrDeepEqual } from '../../utils.js';
8
+ import { hydrationMap } from '../hydration-map.js';
8
9
  import { ElementTemplateUpdateOps } from '../protocol/opcodes.js';
9
10
  export function hydrate(serialized, instance) {
10
11
  resetGlobalCommitContext();
11
- hydrateIntoContext(serialized, instance);
12
+ if (!hydrateIntoContext(serialized, instance)) {
13
+ // Hydration protocol errors are not transactional: earlier matched nodes
14
+ // may already be rebound while discovering a later mismatch. Discard the
15
+ // native output for this failed pass and let the listener keep refs/events gated.
16
+ resetGlobalCommitContext();
17
+ }
12
18
  return globalCommitContext.ops;
13
19
  }
14
20
  export function hydrateIntoContext(serialized, instance) {
15
- hydrateInstance(serialized, instance);
21
+ return hydrateInstance(serialized, instance);
16
22
  }
17
23
  function hydrateMatchingChildrenAndDiffSlot(serializedChildren, backgroundChildren) {
18
24
  let lastPlacedIndex = 0;
@@ -37,7 +43,9 @@ function hydrateMatchingChildrenAndDiffSlot(serializedChildren, backgroundChildr
37
43
  if (matchedSerialized) {
38
44
  serializedCursorByTemplateKey[backgroundChild.type] = candidateCursor + 1;
39
45
  const oldIndex = matchedSerialized[1];
40
- hydrateInstance(matchedSerialized[0], backgroundChild);
46
+ if (!hydrateInstance(matchedSerialized[0], backgroundChild)) {
47
+ return null;
48
+ }
41
49
  if (oldIndex < lastPlacedIndex) {
42
50
  result.moves[oldIndex] = { toIndex: i, instance: backgroundChild };
43
51
  result.hasChanges = true;
@@ -67,48 +75,54 @@ function hydrateInstance(serialized, instance) {
67
75
  if (__DEV__) {
68
76
  lynx.reportError(new Error(`ElementTemplate hydrate key mismatch: main='${serialized.templateKey}' background='${instance.type}'.`));
69
77
  }
70
- return;
78
+ return false;
71
79
  }
72
80
  const handleId = serialized.uid;
73
81
  if (!bindHydrationHandleId(instance, handleId, serialized.templateKey)) {
74
- return;
82
+ return false;
75
83
  }
76
- instance.prepareAttributeSlotsForNative();
84
+ instance.prepareAttributeSlotsForHydration();
77
85
  hydrateAttributeSlots(handleId, serialized.attributeSlots ?? [], instance.attributeSlots);
78
86
  if (serialized.templateKey === BUILTIN_RAW_TEXT_TEMPLATE_KEY) {
79
- return;
87
+ return true;
80
88
  }
81
89
  const serializedElementSlots = serialized.elementSlots ?? [];
90
+ const backgroundElementSlots = instance.elementSlots;
82
91
  // Snapshot hydrates dynamic children through slot-filtered lists. Keeping ET
83
92
  // scoped the same way means a cross-slot candidate is a source remove plus a
84
93
  // target create/insert, while same-slot reorder can still stay move-like.
85
- const slotCount = Math.max(serializedElementSlots.length, instance.elementSlots.length);
94
+ const slotCount = Math.max(serializedElementSlots.length, backgroundElementSlots.length);
86
95
  for (let slotId = 0; slotId < slotCount; slotId += 1) {
87
96
  const serializedSlot = serializedElementSlots[slotId];
88
- const backgroundSlot = instance.elementSlots[slotId];
97
+ const backgroundSlot = backgroundElementSlots[slotId];
89
98
  if (!serializedSlot && !backgroundSlot) {
90
99
  continue;
91
100
  }
92
- hydrateElementSlot(instance, slotId, serializedSlot ?? []);
101
+ if (!hydrateElementSlot(instance, slotId, serializedSlot ?? [], backgroundSlot ?? [])) {
102
+ return false;
103
+ }
93
104
  }
105
+ return true;
94
106
  }
95
- function hydrateElementSlot(parent, slotId, serializedChildren) {
96
- const backgroundChildren = parent.elementSlots[slotId] ?? [];
107
+ function hydrateElementSlot(parent, slotId, serializedChildren, backgroundChildren) {
97
108
  if (backgroundChildren.length === 0) {
98
109
  for (const serialized of serializedChildren) {
99
110
  emitSerializedSubtreeRemove(parent, slotId, serialized);
100
111
  }
101
- return;
112
+ return true;
102
113
  }
103
114
  const listDiff = hydrateMatchingChildrenAndDiffSlot(serializedChildren, backgroundChildren);
115
+ if (listDiff === null) {
116
+ return false;
117
+ }
104
118
  if (!listDiff.hasChanges) {
105
- return;
119
+ return true;
106
120
  }
107
121
  // Hydrate emits patches directly here. Replaying against serialized order
108
122
  // keeps insert targets in the main-thread slot without reshaping background.
109
123
  const removalIndexes = new Set(listDiff.removals);
110
124
  const { insertions, moves } = listDiff;
111
- const pendingMoves = new Map();
125
+ const movesWaitingForInsertionPoint = new Map();
112
126
  let serializedCursor = 0;
113
127
  let currentSerializedChild = serializedChildren[serializedCursor];
114
128
  let newIndex = 0;
@@ -116,31 +130,31 @@ function hydrateElementSlot(parent, slotId, serializedChildren) {
116
130
  // Insertions are known before replay starts. Moves are counted only when their
117
131
  // old serialized position is reached, so the cursor can keep emitting patches
118
132
  // even after all serialized children have been consumed.
119
- let pendingInsertOrMovePatchCount = listDiff.insertionCount;
120
- while (currentSerializedChild || pendingInsertOrMovePatchCount > 0) {
133
+ let insertOrMovePatchesWaitingForInsertionPoint = listDiff.insertionCount;
134
+ while (currentSerializedChild || insertOrMovePatchesWaitingForInsertionPoint > 0) {
121
135
  let keepCurrentSerializedChild = false;
122
136
  if (currentSerializedChild && removalIndexes.has(oldIndex)) {
123
137
  emitSerializedSubtreeRemove(parent, slotId, currentSerializedChild);
124
138
  }
125
139
  else if (currentSerializedChild && moves[oldIndex] !== undefined) {
126
140
  const move = moves[oldIndex];
127
- pendingMoves.set(move.toIndex, move.instance);
128
- pendingInsertOrMovePatchCount += 1;
141
+ movesWaitingForInsertionPoint.set(move.toIndex, move.instance);
142
+ insertOrMovePatchesWaitingForInsertionPoint += 1;
129
143
  }
130
144
  else {
131
145
  const beforeChildId = currentSerializedChild ? currentSerializedChild.uid : 0;
132
- const movedChild = pendingMoves.get(newIndex);
146
+ const movedChild = movesWaitingForInsertionPoint.get(newIndex);
133
147
  if (movedChild) {
134
148
  keepCurrentSerializedChild = true;
135
149
  globalCommitContext.ops.push(ElementTemplateUpdateOps.insertNode, parent.instanceId, slotId, movedChild.instanceId, beforeChildId);
136
- pendingInsertOrMovePatchCount -= 1;
150
+ insertOrMovePatchesWaitingForInsertionPoint -= 1;
137
151
  }
138
152
  else if (insertions[newIndex] !== undefined) {
139
153
  const insertedChild = insertions[newIndex];
140
154
  keepCurrentSerializedChild = true;
141
155
  emitCreateSubtree(insertedChild);
142
156
  globalCommitContext.ops.push(ElementTemplateUpdateOps.insertNode, parent.instanceId, slotId, insertedChild.instanceId, beforeChildId);
143
- pendingInsertOrMovePatchCount -= 1;
157
+ insertOrMovePatchesWaitingForInsertionPoint -= 1;
144
158
  }
145
159
  newIndex += 1;
146
160
  }
@@ -149,6 +163,7 @@ function hydrateElementSlot(parent, slotId, serializedChildren) {
149
163
  oldIndex += 1;
150
164
  }
151
165
  }
166
+ return true;
152
167
  }
153
168
  function emitSerializedSubtreeRemove(parent, slotId, serialized) {
154
169
  const childId = serialized.uid;
@@ -159,7 +174,7 @@ function emitSerializedSubtreeRemove(parent, slotId, serialized) {
159
174
  collectSerializedSubtreeHandleIdsInto(serialized, removedSubtreeHandleIds);
160
175
  globalCommitContext.ops.push(ElementTemplateUpdateOps.removeNode, parent.instanceId, slotId, childId, removedSubtreeHandleIds);
161
176
  if (existing && !existing.parent) {
162
- markRemovedSubtreeForCurrentCommit(existing);
177
+ markRemovedSubtreeForPostDispatchTeardown(existing);
163
178
  }
164
179
  }
165
180
  function collectSerializedSubtreeHandleIdsInto(serialized, handles) {
@@ -174,23 +189,25 @@ function collectSerializedSubtreeHandleIdsInto(serialized, handles) {
174
189
  }
175
190
  }
176
191
  function emitCreateSubtree(node) {
177
- for (const slotChildren of node.elementSlots) {
178
- /* v8 ignore start */
179
- if (!slotChildren) {
180
- continue;
181
- }
182
- /* v8 ignore stop */
183
- for (const child of slotChildren) {
184
- emitCreateSubtree(child);
185
- }
186
- }
187
- node.prepareAttributeSlotsForNative();
192
+ // Linked-list walk: slot grouping would be discarded since we recurse into
193
+ // every child regardless of slot. `emitCreate` does its own single-walk
194
+ // serialization of `instanceId`s grouped by slot.
195
+ let child = node.firstChild;
196
+ while (child) {
197
+ emitCreateSubtree(child);
198
+ child = child.nextSibling;
199
+ }
200
+ node.prepareAttributeSlotsForHydration();
188
201
  node.emitCreate();
189
202
  }
190
203
  function bindHydrationHandleId(instance, handleId, templateKey) {
204
+ const oldHandleId = instance.instanceId;
191
205
  try {
192
206
  backgroundElementTemplateInstanceManager.updateId(instance.instanceId, handleId);
193
- instance.markCreateEmittedForHydration();
207
+ // Ref proxies created before hydrate keep the old background id; resolve it
208
+ // lazily so user-held proxies continue selecting the hydrated native node.
209
+ hydrationMap.set(oldHandleId, handleId);
210
+ instance.markMaterializedByHydration();
194
211
  return true;
195
212
  }
196
213
  catch (error) {