@lynx-js/react 0.121.0 → 0.121.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/package.json +5 -5
  3. package/runtime/lazy/element-template-import.js +73 -0
  4. package/runtime/lazy/import.js +4 -0
  5. package/runtime/lazy/target.js +23 -0
  6. package/runtime/lib/core/commit-context.d.ts +8 -0
  7. package/runtime/lib/core/commit-context.js +18 -0
  8. package/runtime/lib/core/commit-context.js.map +1 -0
  9. package/runtime/lib/{snapshot/legacy-react-runtime/index.d.ts → core/compat/legacy-react-runtime.d.ts} +4 -4
  10. package/runtime/lib/{snapshot/legacy-react-runtime/index.js → core/compat/legacy-react-runtime.js} +6 -6
  11. package/runtime/lib/core/compat/legacy-react-runtime.js.map +1 -0
  12. package/runtime/lib/{snapshot → core}/compat/lynxComponent.d.ts +2 -1
  13. package/runtime/lib/{snapshot → core}/compat/lynxComponent.js +11 -5
  14. package/runtime/lib/core/compat/lynxComponent.js.map +1 -0
  15. package/runtime/lib/core/component.d.ts +2 -0
  16. package/runtime/lib/core/component.js +79 -0
  17. package/runtime/lib/core/component.js.map +1 -0
  18. package/runtime/lib/core/forceRootRender.d.ts +7 -0
  19. package/runtime/lib/core/forceRootRender.js +40 -0
  20. package/runtime/lib/core/forceRootRender.js.map +1 -0
  21. package/runtime/lib/core/globalProps.d.ts +31 -0
  22. package/runtime/lib/core/globalProps.js +55 -0
  23. package/runtime/lib/core/globalProps.js.map +1 -0
  24. package/runtime/lib/core/hooks/useLynxGlobalEventListener.js +1 -1
  25. package/runtime/lib/core/hooks/useLynxGlobalEventListener.js.map +1 -1
  26. package/runtime/lib/{snapshot/compat → core}/initData.d.ts +1 -1
  27. package/runtime/lib/{snapshot/compat → core}/initData.js +4 -5
  28. package/runtime/lib/core/initData.js.map +1 -0
  29. package/runtime/lib/{snapshot/lynx/dynamic-js.js → core/lynx/dynamic-import.js} +1 -1
  30. package/runtime/lib/core/lynx/dynamic-import.js.map +1 -0
  31. package/runtime/lib/core/lynx/lazy-bundle.js.map +1 -0
  32. package/runtime/lib/core/lynx/runtime-backend.d.ts +5 -0
  33. package/runtime/lib/core/lynx/runtime-backend.js +20 -0
  34. package/runtime/lib/core/lynx/runtime-backend.js.map +1 -0
  35. package/runtime/lib/core/lynx-data-processors.d.ts +2 -0
  36. package/runtime/lib/core/lynx-data-processors.js +53 -0
  37. package/runtime/lib/core/lynx-data-processors.js.map +1 -0
  38. package/runtime/lib/core/lynx-page-data.d.ts +1 -0
  39. package/runtime/lib/core/lynx-page-data.js +14 -0
  40. package/runtime/lib/core/lynx-page-data.js.map +1 -0
  41. package/runtime/lib/core/lynx-update-data.d.ts +11 -0
  42. package/runtime/lib/core/lynx-update-data.js +21 -0
  43. package/runtime/lib/core/lynx-update-data.js.map +1 -0
  44. package/runtime/lib/core/performance.d.ts +30 -0
  45. package/runtime/lib/core/performance.js +145 -0
  46. package/runtime/lib/core/performance.js.map +1 -0
  47. package/runtime/lib/core/ref.d.ts +37 -0
  48. package/runtime/lib/core/ref.js +108 -0
  49. package/runtime/lib/core/ref.js.map +1 -0
  50. package/runtime/lib/core/reload-version.d.ts +2 -0
  51. package/runtime/lib/{snapshot/lifecycle/pass.js → core/reload-version.js} +4 -5
  52. package/runtime/lib/core/reload-version.js.map +1 -0
  53. package/runtime/lib/element-template/background/attr-slots.d.ts +6 -1
  54. package/runtime/lib/element-template/background/attr-slots.js +35 -2
  55. package/runtime/lib/element-template/background/attr-slots.js.map +1 -1
  56. package/runtime/lib/element-template/background/commit-context.d.ts +3 -3
  57. package/runtime/lib/element-template/background/commit-context.js +15 -18
  58. package/runtime/lib/element-template/background/commit-context.js.map +1 -1
  59. package/runtime/lib/element-template/background/commit-hook.d.ts +1 -1
  60. package/runtime/lib/element-template/background/commit-hook.js +68 -43
  61. package/runtime/lib/element-template/background/commit-hook.js.map +1 -1
  62. package/runtime/lib/element-template/background/destroy.js +9 -6
  63. package/runtime/lib/element-template/background/destroy.js.map +1 -1
  64. package/runtime/lib/element-template/background/document.js +5 -5
  65. package/runtime/lib/element-template/background/document.js.map +1 -1
  66. package/runtime/lib/element-template/background/hydrate.d.ts +2 -3
  67. package/runtime/lib/element-template/background/hydrate.js +247 -74
  68. package/runtime/lib/element-template/background/hydrate.js.map +1 -1
  69. package/runtime/lib/element-template/background/hydration-listener.js +49 -22
  70. package/runtime/lib/element-template/background/hydration-listener.js.map +1 -1
  71. package/runtime/lib/element-template/background/instance.d.ts +38 -9
  72. package/runtime/lib/element-template/background/instance.js +292 -113
  73. package/runtime/lib/element-template/background/instance.js.map +1 -1
  74. package/runtime/lib/element-template/client/root.d.ts +7 -0
  75. package/runtime/lib/element-template/client/root.js +3 -6
  76. package/runtime/lib/element-template/client/root.js.map +1 -1
  77. package/runtime/lib/element-template/debug/alog.d.ts +21 -0
  78. package/runtime/lib/element-template/debug/alog.js +33 -0
  79. package/runtime/lib/element-template/debug/alog.js.map +1 -1
  80. package/runtime/lib/element-template/debug/elementPAPICall.js +5 -0
  81. package/runtime/lib/element-template/debug/elementPAPICall.js.map +1 -1
  82. package/runtime/lib/element-template/hydration-map.d.ts +5 -0
  83. package/runtime/lib/element-template/hydration-map.js +12 -0
  84. package/runtime/lib/element-template/hydration-map.js.map +1 -0
  85. package/runtime/lib/element-template/index.d.ts +25 -3
  86. package/runtime/lib/element-template/index.js +38 -9
  87. package/runtime/lib/element-template/index.js.map +1 -1
  88. package/runtime/lib/element-template/internal.d.ts +5 -1
  89. package/runtime/lib/element-template/internal.js +6 -7
  90. package/runtime/lib/element-template/internal.js.map +1 -1
  91. package/runtime/lib/element-template/lynx/env.js +5 -48
  92. package/runtime/lib/element-template/lynx/env.js.map +1 -1
  93. package/runtime/lib/element-template/lynx/performance.d.ts +0 -21
  94. package/runtime/lib/element-template/lynx/performance.js +4 -121
  95. package/runtime/lib/element-template/lynx/performance.js.map +1 -1
  96. package/runtime/lib/element-template/native/index.d.ts +1 -1
  97. package/runtime/lib/element-template/native/index.js +28 -2
  98. package/runtime/lib/element-template/native/index.js.map +1 -1
  99. package/runtime/lib/element-template/native/main-thread-api.js +27 -5
  100. package/runtime/lib/element-template/native/main-thread-api.js.map +1 -1
  101. package/runtime/lib/element-template/native/mts-destroy.js +2 -0
  102. package/runtime/lib/element-template/native/mts-destroy.js.map +1 -1
  103. package/runtime/lib/element-template/native/patch-listener.js +6 -2
  104. package/runtime/lib/element-template/native/patch-listener.js.map +1 -1
  105. package/runtime/lib/element-template/native/reload-background.d.ts +1 -0
  106. package/runtime/lib/element-template/native/reload-background.js +39 -0
  107. package/runtime/lib/element-template/native/reload-background.js.map +1 -0
  108. package/runtime/lib/element-template/native/reload-main-thread.d.ts +1 -0
  109. package/runtime/lib/element-template/native/reload-main-thread.js +35 -0
  110. package/runtime/lib/element-template/native/reload-main-thread.js.map +1 -0
  111. package/runtime/lib/element-template/prop-adapters/event.d.ts +1 -0
  112. package/runtime/lib/element-template/prop-adapters/event.js +4 -1
  113. package/runtime/lib/element-template/prop-adapters/event.js.map +1 -1
  114. package/runtime/lib/element-template/prop-adapters/ref.d.ts +26 -0
  115. package/runtime/lib/element-template/prop-adapters/ref.js +107 -0
  116. package/runtime/lib/element-template/prop-adapters/ref.js.map +1 -0
  117. package/runtime/lib/element-template/prop-adapters/spread.js +8 -1
  118. package/runtime/lib/element-template/prop-adapters/spread.js.map +1 -1
  119. package/runtime/lib/element-template/protocol/opcodes.d.ts +4 -0
  120. package/runtime/lib/element-template/protocol/opcodes.js +4 -0
  121. package/runtime/lib/element-template/protocol/opcodes.js.map +1 -1
  122. package/runtime/lib/element-template/protocol/template-type.d.ts +6 -0
  123. package/runtime/lib/element-template/protocol/template-type.js +20 -0
  124. package/runtime/lib/element-template/protocol/template-type.js.map +1 -0
  125. package/runtime/lib/element-template/protocol/types.d.ts +74 -6
  126. package/runtime/lib/element-template/runtime/list/list.d.ts +65 -0
  127. package/runtime/lib/element-template/runtime/list/list.js +587 -0
  128. package/runtime/lib/element-template/runtime/list/list.js.map +1 -0
  129. package/runtime/lib/element-template/runtime/page/page.d.ts +5 -2
  130. package/runtime/lib/element-template/runtime/page/page.js +12 -0
  131. package/runtime/lib/element-template/runtime/page/page.js.map +1 -1
  132. package/runtime/lib/element-template/runtime/patch.js +210 -38
  133. package/runtime/lib/element-template/runtime/patch.js.map +1 -1
  134. package/runtime/lib/element-template/runtime/render/render-main-thread.d.ts +3 -1
  135. package/runtime/lib/element-template/runtime/render/render-main-thread.js +38 -7
  136. package/runtime/lib/element-template/runtime/render/render-main-thread.js.map +1 -1
  137. package/runtime/lib/element-template/runtime/render/render-opcodes.js +80 -43
  138. package/runtime/lib/element-template/runtime/render/render-opcodes.js.map +1 -1
  139. package/runtime/lib/element-template/runtime/render/render-to-opcodes.js +41 -4
  140. package/runtime/lib/element-template/runtime/render/render-to-opcodes.js.map +1 -1
  141. package/runtime/lib/element-template/runtime/template/attr-slot-plan.d.ts +1 -0
  142. package/runtime/lib/element-template/runtime/template/attr-slot-plan.js +4 -0
  143. package/runtime/lib/element-template/runtime/template/attr-slot-plan.js.map +1 -1
  144. package/runtime/lib/element-template/runtime/template/handle.d.ts +3 -2
  145. package/runtime/lib/element-template/runtime/template/handle.js +5 -1
  146. package/runtime/lib/element-template/runtime/template/handle.js.map +1 -1
  147. package/runtime/lib/element-template/runtime/template/registry.d.ts +2 -0
  148. package/runtime/lib/element-template/runtime/template/registry.js +6 -1
  149. package/runtime/lib/element-template/runtime/template/registry.js.map +1 -1
  150. package/runtime/lib/element-template/runtime-backend-marker.js +6 -0
  151. package/runtime/lib/element-template/runtime-backend-marker.js.map +1 -0
  152. package/runtime/lib/index.d.ts +1 -1
  153. package/runtime/lib/index.js +3 -1
  154. package/runtime/lib/index.js.map +1 -1
  155. package/runtime/lib/internal.d.ts +5 -4
  156. package/runtime/lib/internal.js +6 -5
  157. package/runtime/lib/internal.js.map +1 -1
  158. package/runtime/lib/lynx-api.d.ts +3 -8
  159. package/runtime/lib/lynx-api.js +8 -45
  160. package/runtime/lib/lynx-api.js.map +1 -1
  161. package/runtime/lib/runtime-backend-marker.js +6 -0
  162. package/runtime/lib/runtime-backend-marker.js.map +1 -0
  163. package/runtime/lib/snapshot/debug/vnodeSource.js +1 -1
  164. package/runtime/lib/snapshot/debug/vnodeSource.js.map +1 -1
  165. package/runtime/lib/snapshot/lifecycle/patch/commit.d.ts +0 -1
  166. package/runtime/lib/snapshot/lifecycle/patch/commit.js +4 -9
  167. package/runtime/lib/snapshot/lifecycle/patch/commit.js.map +1 -1
  168. package/runtime/lib/snapshot/lifecycle/patch/updateMainThread.js +2 -2
  169. package/runtime/lib/snapshot/lifecycle/patch/updateMainThread.js.map +1 -1
  170. package/runtime/lib/snapshot/lifecycle/ref/delay.d.ts +6 -13
  171. package/runtime/lib/snapshot/lifecycle/ref/delay.js +9 -30
  172. package/runtime/lib/snapshot/lifecycle/ref/delay.js.map +1 -1
  173. package/runtime/lib/snapshot/lifecycle/reload.js +2 -2
  174. package/runtime/lib/snapshot/lifecycle/reload.js.map +1 -1
  175. package/runtime/lib/snapshot/list/list.js +1 -1
  176. package/runtime/lib/snapshot/list/list.js.map +1 -1
  177. package/runtime/lib/snapshot/list/listUpdateInfo.js +3 -2
  178. package/runtime/lib/snapshot/list/listUpdateInfo.js.map +1 -1
  179. package/runtime/lib/snapshot/lynx/calledByNative.js +3 -9
  180. package/runtime/lib/snapshot/lynx/calledByNative.js.map +1 -1
  181. package/runtime/lib/snapshot/lynx/env.js +5 -51
  182. package/runtime/lib/snapshot/lynx/env.js.map +1 -1
  183. package/runtime/lib/snapshot/lynx/performance.d.ts +0 -21
  184. package/runtime/lib/snapshot/lynx/performance.js +7 -121
  185. package/runtime/lib/snapshot/lynx/performance.js.map +1 -1
  186. package/runtime/lib/snapshot/lynx/runWithForce.js +9 -39
  187. package/runtime/lib/snapshot/lynx/runWithForce.js.map +1 -1
  188. package/runtime/lib/snapshot/lynx/tt.js +10 -30
  189. package/runtime/lib/snapshot/lynx/tt.js.map +1 -1
  190. package/runtime/lib/snapshot/snapshot/backgroundSnapshot.js +4 -4
  191. package/runtime/lib/snapshot/snapshot/backgroundSnapshot.js.map +1 -1
  192. package/runtime/lib/snapshot/snapshot/list.js +1 -1
  193. package/runtime/lib/snapshot/snapshot/list.js.map +1 -1
  194. package/runtime/lib/snapshot/snapshot/ref.d.ts +3 -5
  195. package/runtime/lib/snapshot/snapshot/ref.js +16 -59
  196. package/runtime/lib/snapshot/snapshot/ref.js.map +1 -1
  197. package/runtime/lib/snapshot/snapshot/snapshot.js +1 -1
  198. package/runtime/lib/snapshot/snapshot/snapshot.js.map +1 -1
  199. package/runtime/lib/snapshot/snapshot/snapshotInstanceHydrationMap.js +1 -1
  200. package/runtime/lib/snapshot/snapshot/snapshotInstanceHydrationMap.js.map +1 -1
  201. package/runtime/lib/tsconfig.tsbuildinfo +1 -1
  202. package/runtime/lib/worklet-runtime/workletRuntime.js +1 -1
  203. package/runtime/lib/worklet-runtime/workletRuntime.js.map +1 -1
  204. package/runtime/worklet-runtime/dev.js +2 -3
  205. package/runtime/worklet-runtime/main.js +1 -1
  206. package/testing-library/dist/{rslib-runtime.js → 0~rslib-runtime.js} +14 -13
  207. package/testing-library/dist/env/index.js +2 -8
  208. package/testing-library/dist/env/vitest.js +1 -1
  209. package/testing-library/dist/plugins/index.js +13 -2
  210. package/testing-library/dist/pure.js +18 -18
  211. package/testing-library/dist/rstest-config.js +2 -4
  212. package/testing-library/dist/setupFiles/common/bootstrap.js +1 -0
  213. package/testing-library/dist/setupFiles/common/runtime-setup.js +1 -1
  214. package/testing-library/dist/setupFiles/inner/rstest.js +2 -1
  215. package/testing-library/dist/setupFiles/inner/vitest.js +2 -1
  216. package/testing-library/dist/type-entry/index.js +1 -0
  217. package/transform/dist/wasm.cjs +113 -40
  218. package/runtime/lib/element-template/hooks/react.d.ts +0 -14
  219. package/runtime/lib/element-template/hooks/react.js +0 -24
  220. package/runtime/lib/element-template/hooks/react.js.map +0 -1
  221. package/runtime/lib/element-template/runtime/components/slot.js +0 -11
  222. package/runtime/lib/element-template/runtime/components/slot.js.map +0 -1
  223. package/runtime/lib/snapshot/compat/initData.js.map +0 -1
  224. package/runtime/lib/snapshot/compat/lynxComponent.js.map +0 -1
  225. package/runtime/lib/snapshot/legacy-react-runtime/index.js.map +0 -1
  226. package/runtime/lib/snapshot/lifecycle/pass.d.ts +0 -3
  227. package/runtime/lib/snapshot/lifecycle/pass.js.map +0 -1
  228. package/runtime/lib/snapshot/lynx/component.js +0 -73
  229. package/runtime/lib/snapshot/lynx/component.js.map +0 -1
  230. package/runtime/lib/snapshot/lynx/dynamic-js.js.map +0 -1
  231. package/runtime/lib/snapshot/lynx/lazy-bundle.js.map +0 -1
  232. package/testing-library/dist/881.js +0 -1
  233. /package/runtime/lib/{snapshot/lynx/dynamic-js.d.ts → core/lynx/dynamic-import.d.ts} +0 -0
  234. /package/runtime/lib/{snapshot → core}/lynx/lazy-bundle.d.ts +0 -0
  235. /package/runtime/lib/{snapshot → core}/lynx/lazy-bundle.js +0 -0
  236. /package/runtime/lib/element-template/{runtime/components/slot.d.ts → runtime-backend-marker.d.ts} +0 -0
  237. /package/runtime/lib/{snapshot/lynx/component.d.ts → runtime-backend-marker.d.ts} +0 -0
  238. /package/testing-library/dist/{0~123.js → 0~@rstest/adapter-rsbuild.js} +0 -0
@@ -1,4 +1,4 @@
1
- import type { SerializableValue } from '../protocol/types.js';
1
+ import type { ElementTemplateHandleSlotsCommand, RuntimeOptionsCommand, SerializableValue, TypedElementAttributesCommand, UpdateTypedListItemCommand } from '../protocol/types.js';
2
2
  export declare const BUILTIN_RAW_TEXT_TEMPLATE_KEY = "_et_builtin_raw_text";
3
3
  export declare class BackgroundElementTemplateInstance {
4
4
  instanceId: number;
@@ -8,32 +8,61 @@ export declare class BackgroundElementTemplateInstance {
8
8
  lastChild: BackgroundElementTemplateInstance | null;
9
9
  nextSibling: BackgroundElementTemplateInstance | null;
10
10
  previousSibling: BackgroundElementTemplateInstance | null;
11
+ __slotIndex: number;
11
12
  attributeSlots: SerializableValue[];
12
- elementSlots: BackgroundElementTemplateInstance[][];
13
13
  private rawAttributeSlots;
14
- private hasEmittedCreate;
14
+ protected isMaterializedOnMainThread: boolean;
15
+ private listItemPlatformInfo;
15
16
  get parentNode(): BackgroundElementTemplateInstance | null;
16
17
  get childNodes(): BackgroundElementTemplateInstance[];
18
+ get elementSlots(): BackgroundElementTemplateInstance[][];
17
19
  nodeType: number;
18
20
  constructor(type: string, initialAttributeSlots?: SerializableValue[]);
19
21
  emitCreate(): void;
20
- private isPendingCreate;
21
- private canEmitPatch;
22
+ private needsMainThreadCreate;
23
+ private markSubtreeDetachedFromMainThread;
24
+ releaseDetachedSubtreeFromManager(): void;
25
+ private restoreManagerRegistration;
26
+ private releaseSubtreeFromManager;
27
+ emitMainThreadCreateIfNeeded(): void;
28
+ protected canEmitUpdatePatch(): boolean;
29
+ protected cleanupDetachedChildForLifetimeRemoval(child: BackgroundElementTemplateInstance, canEmitUpdatePatch: boolean): void;
22
30
  appendChild(child: BackgroundElementTemplateInstance): void;
23
31
  insertBefore(child: BackgroundElementTemplateInstance, beforeChild: BackgroundElementTemplateInstance | null, silent?: boolean): void;
24
32
  removeChild(child: BackgroundElementTemplateInstance, silent?: boolean): void;
25
33
  tearDown(): void;
34
+ queueRefCleanupForSubtree(): void;
26
35
  getRawAttributeSlot(attrSlotIndex: number): unknown;
27
- markCreateEmittedForHydration(): void;
28
- prepareAttributeSlotsForNative(): void;
36
+ markMaterializedByHydration(): void;
37
+ prepareAttributeSlotsForNative(options?: {
38
+ queueRefEffects?: boolean;
39
+ }): void;
40
+ prepareAttributeSlotsForHydration(): void;
29
41
  setAttribute(key: string, value: unknown): void;
30
42
  get text(): string;
31
43
  set text(value: string);
32
44
  get data(): string;
33
45
  set data(value: string);
46
+ getListItemPlatformInfo(): Record<string, SerializableValue>;
47
+ private notifyParentListOfLogicalChildUpdate;
34
48
  }
35
- export declare class BackgroundElementTemplateSlot extends BackgroundElementTemplateInstance {
36
- partId: number;
49
+ export declare class BackgroundTypedElementTemplateInstance extends BackgroundElementTemplateInstance {
50
+ constructor(type: string);
51
+ emitCreate(): void;
52
+ setAttribute(key: string, value: unknown): void;
53
+ protected getTypedAttributesForCreate(): TypedElementAttributesCommand | null;
54
+ protected getElementSlotsForCreate(): ElementTemplateHandleSlotsCommand | null;
55
+ protected getRuntimeOptionsForCreate(): RuntimeOptionsCommand | null;
56
+ }
57
+ export declare class BackgroundListElementTemplateInstance extends BackgroundTypedElementTemplateInstance {
37
58
  constructor();
59
+ protected getRuntimeOptionsForCreate(): RuntimeOptionsCommand;
60
+ insertBefore(child: BackgroundElementTemplateInstance, beforeChild: BackgroundElementTemplateInstance | null, silent?: boolean): void;
61
+ removeChild(child: BackgroundElementTemplateInstance, silent?: boolean): void;
62
+ notifyLogicalChildUpdated(child: BackgroundElementTemplateInstance): void;
63
+ private emitTypedListItemInsert;
64
+ private emitTypedListItemRemove;
65
+ private emitTypedListItemUpdate;
38
66
  }
67
+ export declare function toUpdateTypedListItemCommand(child: BackgroundElementTemplateInstance): UpdateTypedListItemCommand;
39
68
  export declare function collectElementTemplateSubtreeHandleIds(root: BackgroundElementTemplateInstance): number[];
@@ -1,12 +1,13 @@
1
1
  // Copyright 2024 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 { prepareAttributeSlots as prepareRawAttributeSlots } from './attr-slots.js';
5
- import { globalCommitContext, markRemovedSubtreeForCurrentCommit } from './commit-context.js';
4
+ import { prepareAttributeSlots as prepareRawAttributeSlots, queueRefAttributeSlotUpdates } from './attr-slots.js';
5
+ import { globalCommitContext, markRemovedSubtreeForPostDispatchTeardown } from './commit-context.js';
6
6
  import { isElementTemplateHydrated } from './commit-hook.js';
7
7
  import { backgroundElementTemplateInstanceManager } from './manager.js';
8
8
  import { isDirectOrDeepEqual } from '../../utils.js';
9
9
  import { ElementTemplateUpdateOps } from '../protocol/opcodes.js';
10
+ import { parseElementTemplateType } from '../protocol/template-type.js';
10
11
  function pushOp(...items) {
11
12
  globalCommitContext.ops.push(...items);
12
13
  }
@@ -23,12 +24,8 @@ function stringifyRawTextValue(value) {
23
24
  }
24
25
  return '';
25
26
  }
26
- function syncElementSlotChildren(parent, slotId, children) {
27
- if (!parent || slotId < 0) {
28
- return;
29
- }
30
- parent.elementSlots[slotId] = [...children];
31
- }
27
+ const EMPTY_LIST_ITEM_PLATFORM_INFO = {};
28
+ const EMPTY_REMOVED_SUBTREE_HANDLE_IDS = [];
32
29
  export class BackgroundElementTemplateInstance {
33
30
  instanceId = 0; // Assigned by manager
34
31
  type;
@@ -37,11 +34,12 @@ export class BackgroundElementTemplateInstance {
37
34
  lastChild = null;
38
35
  nextSibling = null;
39
36
  previousSibling = null;
37
+ __slotIndex = 0;
40
38
  // Shadow State for Hydration
41
39
  attributeSlots;
42
- elementSlots = [];
43
40
  rawAttributeSlots;
44
- hasEmittedCreate = false;
41
+ isMaterializedOnMainThread = false;
42
+ listItemPlatformInfo;
45
43
  get parentNode() {
46
44
  return this.parent;
47
45
  }
@@ -54,6 +52,15 @@ export class BackgroundElementTemplateInstance {
54
52
  }
55
53
  return nodes;
56
54
  }
55
+ get elementSlots() {
56
+ const elementSlots = [];
57
+ let child = this.firstChild;
58
+ while (child) {
59
+ (elementSlots[child.__slotIndex] ??= []).push(child);
60
+ child = child.nextSibling;
61
+ }
62
+ return elementSlots;
63
+ }
57
64
  nodeType;
58
65
  constructor(type, initialAttributeSlots) {
59
66
  this.type = type;
@@ -71,23 +78,111 @@ export class BackgroundElementTemplateInstance {
71
78
  }
72
79
  }
73
80
  emitCreate() {
74
- if (this.hasEmittedCreate) {
81
+ if (this.isMaterializedOnMainThread) {
75
82
  return;
76
83
  }
77
- if (this.instanceId === 0 && __DEV__) {
84
+ if (__DEV__ && this.instanceId === 0) {
78
85
  lynx.reportError(new Error('ElementTemplate patch has illegal handleId 0.'));
79
86
  return;
80
87
  }
81
- pushOp(ElementTemplateUpdateOps.createTemplate, this.instanceId, this.type, null, this.attributeSlots, this.elementSlots.map((children) => children.map((child) => child.instanceId)));
82
- this.hasEmittedCreate = true;
88
+ this.restoreManagerRegistration();
89
+ // Walk the linked-list children once to build the slot-indexed handle list
90
+ // for the createTemplate op. Going via `this.elementSlots` would allocate
91
+ // the full `Instance[][]` intermediate just to throw it away here.
92
+ const serializedSlots = [];
93
+ let child = this.firstChild;
94
+ while (child) {
95
+ (serializedSlots[child.__slotIndex] ??= []).push(child.instanceId);
96
+ child = child.nextSibling;
97
+ }
98
+ const nativeTemplate = parseElementTemplateType(this.type);
99
+ pushOp(ElementTemplateUpdateOps.createTemplate, this.instanceId, nativeTemplate.templateKey, nativeTemplate.bundleUrl, this.attributeSlots, serializedSlots);
100
+ this.isMaterializedOnMainThread = true;
101
+ }
102
+ needsMainThreadCreate() {
103
+ return this.instanceId !== 0 && !this.isMaterializedOnMainThread;
104
+ }
105
+ markSubtreeDetachedFromMainThread() {
106
+ if (this.instanceId !== 0) {
107
+ this.isMaterializedOnMainThread = false;
108
+ }
109
+ let child = this.firstChild;
110
+ while (child) {
111
+ child.markSubtreeDetachedFromMainThread();
112
+ child = child.nextSibling;
113
+ }
114
+ }
115
+ releaseDetachedSubtreeFromManager() {
116
+ if (this.parent !== null || this.isMaterializedOnMainThread) {
117
+ return;
118
+ }
119
+ this.releaseSubtreeFromManager();
120
+ }
121
+ restoreManagerRegistration() {
122
+ if (this.instanceId === 0) {
123
+ return;
124
+ }
125
+ const instances = backgroundElementTemplateInstanceManager.values;
126
+ const existing = instances.get(this.instanceId);
127
+ if (existing === this) {
128
+ return;
129
+ }
130
+ if (existing) {
131
+ throw new Error(`ElementTemplate handleId ${this.instanceId} is already bound.`);
132
+ }
133
+ instances.set(this.instanceId, this);
134
+ }
135
+ releaseSubtreeFromManager() {
136
+ const instances = backgroundElementTemplateInstanceManager.values;
137
+ if (instances.get(this.instanceId) === this) {
138
+ instances.delete(this.instanceId);
139
+ }
140
+ let child = this.firstChild;
141
+ while (child) {
142
+ child.releaseSubtreeFromManager();
143
+ child = child.nextSibling;
144
+ }
83
145
  }
84
- isPendingCreate() {
85
- return this.instanceId > 0 && !this.hasEmittedCreate;
146
+ emitMainThreadCreateIfNeeded() {
147
+ if (!this.needsMainThreadCreate()) {
148
+ return;
149
+ }
150
+ // An unmaterialized subtree may receive attr updates before it is inserted;
151
+ // prepare here so ref attach happens once, at the create boundary.
152
+ this.prepareAttributeSlotsForNative();
153
+ this.emitCreate();
86
154
  }
87
- canEmitPatch() {
155
+ canEmitUpdatePatch() {
88
156
  // Background tree construction is local until hydrate binds it to main-thread
89
- // instances. Only hydrated and already-created owners can emit update ops.
90
- return isElementTemplateHydrated() && !this.isPendingCreate();
157
+ // instances. Only hydrated and materialized owners can emit update ops.
158
+ return isElementTemplateHydrated() && !this.needsMainThreadCreate();
159
+ }
160
+ cleanupDetachedChildForLifetimeRemoval(child, canEmitUpdatePatch) {
161
+ if (canEmitUpdatePatch) {
162
+ child.markSubtreeDetachedFromMainThread();
163
+ // The removed JS object graph may outlive the detach until GC, so keep
164
+ // it pending and tear it down on the Snapshot-aligned delayed boundary.
165
+ markRemovedSubtreeForPostDispatchTeardown(child);
166
+ child.queueRefCleanupForSubtree();
167
+ return;
168
+ }
169
+ // Mirrors `shouldQueueRefEffects` in `setAttribute`: pre-hydration
170
+ // commits and post-hydration materialized children publish their refs
171
+ // to user effects. Post-hydration unmaterialized children defer attach
172
+ // to `emitCreate`, which never fires for a subtree torn down before
173
+ // insert — so cleaning up there would emit a spurious detach.
174
+ const refAttachWasPublished = !isElementTemplateHydrated()
175
+ || !child.needsMainThreadCreate();
176
+ if (refAttachWasPublished) {
177
+ // Run before any tearDown below: `tearDown` clears `rawAttributeSlots`,
178
+ // which `queueRefCleanupForSubtree` walks to enqueue the detach.
179
+ child.queueRefCleanupForSubtree();
180
+ }
181
+ if (child.needsMainThreadCreate()) {
182
+ // An unmaterialized subtree has no main-thread registry entry, so it
183
+ // can be released from the background manager without delayed cleanup.
184
+ child.tearDown();
185
+ }
91
186
  }
92
187
  // DOM API for Preact
93
188
  appendChild(child) {
@@ -126,31 +221,12 @@ export class BackgroundElementTemplateInstance {
126
221
  this.lastChild = child;
127
222
  child.nextSibling = null;
128
223
  }
129
- if (child instanceof BackgroundElementTemplateSlot) {
130
- syncElementSlotChildren(this, child.partId, collectChildren(child));
131
- }
132
- if (this instanceof BackgroundElementTemplateSlot) {
133
- const slotId = this.partId;
134
- const parent = this.parent;
135
- if (parent) {
136
- syncElementSlotChildren(parent, slotId, collectChildren(this));
137
- }
138
- if (silent) {
139
- return;
140
- }
141
- if (slotId !== -1 && parent) {
142
- if (!parent.canEmitPatch()) {
143
- return;
144
- }
145
- const beforeId = beforeChild ? beforeChild.instanceId : 0;
146
- emitCreateRecursive(child);
147
- pushOp(ElementTemplateUpdateOps.insertNode, parent.instanceId, slotId, child.instanceId, beforeId);
148
- }
149
- return;
150
- }
151
- if (silent) {
224
+ if (silent || !this.canEmitUpdatePatch()) {
152
225
  return;
153
226
  }
227
+ const beforeId = (beforeChild && beforeChild.__slotIndex === child.__slotIndex) ? beforeChild.instanceId : 0;
228
+ emitMainThreadCreateRecursive(child);
229
+ pushOp(ElementTemplateUpdateOps.insertNode, this.instanceId, child.__slotIndex, child.instanceId, beforeId);
154
230
  }
155
231
  removeChild(child, silent) {
156
232
  if (child.parent !== this) {
@@ -171,37 +247,15 @@ export class BackgroundElementTemplateInstance {
171
247
  child.parent = null;
172
248
  child.nextSibling = null;
173
249
  child.previousSibling = null;
174
- if (child instanceof BackgroundElementTemplateSlot && child.partId >= 0) {
175
- this.elementSlots[child.partId] = [];
176
- }
177
- if (this instanceof BackgroundElementTemplateSlot) {
178
- const slotId = this.partId;
179
- const parent = this.parent;
180
- if (parent) {
181
- syncElementSlotChildren(parent, slotId, collectChildren(this));
182
- }
183
- if (silent) {
184
- return;
185
- }
186
- if (slotId !== -1 && parent) {
187
- if (!parent.canEmitPatch()) {
188
- if (child.isPendingCreate()) {
189
- // A never-created subtree has no main-thread registry entry, so it
190
- // can be released from the background manager without delayed cleanup.
191
- child.tearDown();
192
- }
193
- return;
194
- }
195
- pushOp(ElementTemplateUpdateOps.removeNode, parent.instanceId, slotId, child.instanceId, collectElementTemplateSubtreeHandleIds(child));
196
- // The removed JS object graph may outlive the detach until GC, so keep
197
- // it pending and tear it down on the Snapshot-aligned delayed boundary.
198
- markRemovedSubtreeForCurrentCommit(child);
199
- }
200
- return;
201
- }
250
+ const slotId = child.__slotIndex;
202
251
  if (silent) {
203
252
  return;
204
253
  }
254
+ const canEmitUpdatePatch = this.canEmitUpdatePatch();
255
+ if (canEmitUpdatePatch) {
256
+ pushOp(ElementTemplateUpdateOps.removeNode, this.instanceId, slotId, child.instanceId, collectElementTemplateSubtreeHandleIds(child));
257
+ }
258
+ this.cleanupDetachedChildForLifetimeRemoval(child, canEmitUpdatePatch);
205
259
  }
206
260
  tearDown() {
207
261
  // Recursively tear down children first
@@ -219,35 +273,69 @@ export class BackgroundElementTemplateInstance {
219
273
  this.nextSibling = null;
220
274
  this.attributeSlots = [];
221
275
  this.rawAttributeSlots = undefined;
222
- this.elementSlots = [];
223
276
  // Remove from manager
224
277
  if (this.instanceId) {
225
278
  backgroundElementTemplateInstanceManager.values.delete(this.instanceId);
226
279
  }
227
280
  }
281
+ queueRefCleanupForSubtree() {
282
+ if (this.rawAttributeSlots) {
283
+ queueRefAttributeSlotUpdates(this.type, this.instanceId, this.rawAttributeSlots);
284
+ }
285
+ let child = this.firstChild;
286
+ while (child) {
287
+ child.queueRefCleanupForSubtree();
288
+ child = child.nextSibling;
289
+ }
290
+ }
228
291
  getRawAttributeSlot(attrSlotIndex) {
229
292
  return this.rawAttributeSlots?.[attrSlotIndex] ?? this.attributeSlots[attrSlotIndex];
230
293
  }
231
- markCreateEmittedForHydration() {
294
+ markMaterializedByHydration() {
232
295
  // Hydration binds this object to a template that already exists on the main
233
- // thread; future updates must treat it as created without emitting create.
234
- this.hasEmittedCreate = true;
296
+ // thread; future updates must treat it as materialized without emitting create.
297
+ this.isMaterializedOnMainThread = true;
298
+ this.restoreManagerRegistration();
235
299
  }
236
- prepareAttributeSlotsForNative() {
300
+ prepareAttributeSlotsForNative(options) {
237
301
  if (!this.rawAttributeSlots) {
238
302
  return;
239
303
  }
240
- this.attributeSlots = prepareRawAttributeSlots(this.type, this.instanceId, this.rawAttributeSlots);
304
+ this.attributeSlots = prepareRawAttributeSlots(this.type, this.instanceId, this.rawAttributeSlots, {
305
+ queueRefEffects: options?.queueRefEffects ?? true,
306
+ });
307
+ }
308
+ prepareAttributeSlotsForHydration() {
309
+ // Hydrate only rebinds the selector marker to the stable handle. The ref was
310
+ // already made visible to user effects on the pre-hydration commit path.
311
+ this.prepareAttributeSlotsForNative({
312
+ queueRefEffects: false,
313
+ });
241
314
  }
242
315
  setAttribute(key, value) {
243
316
  if (isBuiltinRawTextTemplateKey(this.type) && (key === '0' || key === 'data')) {
244
317
  this.text = String(value);
245
318
  }
319
+ else if (key === '__listItemPlatformInfo') {
320
+ const previous = this.getListItemPlatformInfo();
321
+ const next = value;
322
+ this.listItemPlatformInfo = next;
323
+ if (!isDirectOrDeepEqual(previous, next)) {
324
+ this.notifyParentListOfLogicalChildUpdate();
325
+ }
326
+ }
246
327
  else if (key === 'attributeSlots' && Array.isArray(value)) {
247
328
  const previousSlots = this.attributeSlots;
329
+ const previousRawSlots = this.rawAttributeSlots ?? previousSlots;
248
330
  const isHydrated = isElementTemplateHydrated();
249
- const canEmitPatch = isHydrated && !this.isPendingCreate();
250
- const nextSlots = prepareRawAttributeSlots(this.type, this.instanceId, value);
331
+ const canEmitUpdatePatch = isHydrated && !this.needsMainThreadCreate();
332
+ // Pre-hydration commits must expose refs to effects, while post-hydration
333
+ // unmaterialized nodes defer ref attach to create emission to avoid dupes.
334
+ const shouldQueueRefEffects = !isHydrated || canEmitUpdatePatch;
335
+ const nextSlots = prepareRawAttributeSlots(this.type, this.instanceId, value, {
336
+ previousRawSlots,
337
+ queueRefEffects: shouldQueueRefEffects,
338
+ });
251
339
  this.rawAttributeSlots = nextSlots === value ? undefined : value;
252
340
  const maxLength = Math.max(previousSlots.length, nextSlots.length);
253
341
  this.attributeSlots = nextSlots;
@@ -257,23 +345,12 @@ export class BackgroundElementTemplateInstance {
257
345
  if (isDirectOrDeepEqual(previousValue, nextValue)) {
258
346
  continue;
259
347
  }
260
- if (!canEmitPatch) {
348
+ if (!canEmitUpdatePatch) {
261
349
  continue;
262
350
  }
263
351
  pushOp(ElementTemplateUpdateOps.setAttribute, this.instanceId, slotIndex, nextValue ?? null);
264
352
  }
265
353
  }
266
- else if (key === 'id' && this instanceof BackgroundElementTemplateSlot) {
267
- const previousPartId = this.partId;
268
- this.partId = Number(value);
269
- if (this.parent && previousPartId >= 0 && previousPartId !== this.partId) {
270
- this.parent.elementSlots[previousPartId] = [];
271
- }
272
- syncElementSlotChildren(this.parent, this.partId, collectChildren(this));
273
- }
274
- else {
275
- return;
276
- }
277
354
  }
278
355
  get text() {
279
356
  return stringifyRawTextValue(this.attributeSlots[0]);
@@ -288,7 +365,7 @@ export class BackgroundElementTemplateInstance {
288
365
  }
289
366
  this.rawAttributeSlots = undefined;
290
367
  this.attributeSlots = [text];
291
- if (!this.canEmitPatch()) {
368
+ if (!this.canEmitUpdatePatch()) {
292
369
  return;
293
370
  }
294
371
  pushOp(ElementTemplateUpdateOps.setAttribute, this.instanceId, 0, text);
@@ -299,12 +376,125 @@ export class BackgroundElementTemplateInstance {
299
376
  set data(value) {
300
377
  this.text = value;
301
378
  }
379
+ getListItemPlatformInfo() {
380
+ return this.listItemPlatformInfo ?? EMPTY_LIST_ITEM_PLATFORM_INFO;
381
+ }
382
+ notifyParentListOfLogicalChildUpdate() {
383
+ if (this.parent instanceof BackgroundListElementTemplateInstance) {
384
+ this.parent.notifyLogicalChildUpdated(this);
385
+ }
386
+ }
387
+ }
388
+ function toTypedAttributesCommand(value) {
389
+ if (value == null || typeof value !== 'object' || Array.isArray(value)) {
390
+ return null;
391
+ }
392
+ return value;
393
+ }
394
+ export class BackgroundTypedElementTemplateInstance extends BackgroundElementTemplateInstance {
395
+ constructor(type) {
396
+ super(type);
397
+ }
398
+ emitCreate() {
399
+ if (this.isMaterializedOnMainThread) {
400
+ return;
401
+ }
402
+ if (__DEV__ && this.instanceId === 0) {
403
+ lynx.reportError(new Error('ElementTemplate patch has illegal handleId 0.'));
404
+ return;
405
+ }
406
+ pushOp(ElementTemplateUpdateOps.createTypedElement, this.instanceId, this.type, this.getTypedAttributesForCreate(), this.getElementSlotsForCreate(), this.getRuntimeOptionsForCreate());
407
+ this.isMaterializedOnMainThread = true;
408
+ }
409
+ setAttribute(key, value) {
410
+ if (key !== 'attributes') {
411
+ super.setAttribute(key, value);
412
+ return;
413
+ }
414
+ const previousValue = this.attributeSlots[0];
415
+ const nextValue = toTypedAttributesCommand(value);
416
+ this.attributeSlots = [nextValue];
417
+ if (isElementTemplateHydrated()
418
+ && this.isMaterializedOnMainThread
419
+ && !isDirectOrDeepEqual(previousValue, nextValue)) {
420
+ pushOp(ElementTemplateUpdateOps.setAttribute, this.instanceId, 0, nextValue);
421
+ }
422
+ }
423
+ getTypedAttributesForCreate() {
424
+ return toTypedAttributesCommand(this.attributeSlots[0]);
425
+ }
426
+ getElementSlotsForCreate() {
427
+ return null;
428
+ }
429
+ getRuntimeOptionsForCreate() {
430
+ return null;
431
+ }
302
432
  }
303
- export class BackgroundElementTemplateSlot extends BackgroundElementTemplateInstance {
304
- partId = -1;
433
+ export class BackgroundListElementTemplateInstance extends BackgroundTypedElementTemplateInstance {
305
434
  constructor() {
306
- super('slot');
435
+ super('list');
436
+ }
437
+ getRuntimeOptionsForCreate() {
438
+ const listChildren = [];
439
+ let child = this.firstChild;
440
+ while (child) {
441
+ listChildren.push(toUpdateTypedListItemCommand(child));
442
+ child = child.nextSibling;
443
+ }
444
+ return {
445
+ listChildren,
446
+ };
447
+ }
448
+ insertBefore(child, beforeChild, silent) {
449
+ const previousParent = child.parent;
450
+ super.insertBefore(child, beforeChild, true);
451
+ if (!silent) {
452
+ if (previousParent instanceof BackgroundListElementTemplateInstance) {
453
+ previousParent.emitTypedListItemRemove(child, EMPTY_REMOVED_SUBTREE_HANDLE_IDS);
454
+ }
455
+ this.emitTypedListItemInsert(child, beforeChild);
456
+ }
457
+ }
458
+ removeChild(child, silent) {
459
+ super.removeChild(child, true);
460
+ if (!silent) {
461
+ const canEmitUpdatePatch = this.canEmitUpdatePatch();
462
+ const removedSubtreeHandleIds = canEmitUpdatePatch
463
+ ? collectElementTemplateSubtreeHandleIds(child)
464
+ : EMPTY_REMOVED_SUBTREE_HANDLE_IDS;
465
+ this.cleanupDetachedChildForLifetimeRemoval(child, canEmitUpdatePatch);
466
+ this.emitTypedListItemRemove(child, removedSubtreeHandleIds);
467
+ }
468
+ }
469
+ notifyLogicalChildUpdated(child) {
470
+ this.emitTypedListItemUpdate(child);
307
471
  }
472
+ emitTypedListItemInsert(child, beforeChild) {
473
+ if (!isElementTemplateHydrated() || !this.isMaterializedOnMainThread) {
474
+ return;
475
+ }
476
+ emitMainThreadCreateRecursive(child);
477
+ pushOp(ElementTemplateUpdateOps.insertTypedListItem, this.instanceId, toUpdateTypedListItemCommand(child), beforeChild?.instanceId ?? 0);
478
+ }
479
+ emitTypedListItemRemove(child, removedSubtreeHandleIds) {
480
+ if (!isElementTemplateHydrated() || !this.isMaterializedOnMainThread) {
481
+ return;
482
+ }
483
+ pushOp(ElementTemplateUpdateOps.removeTypedListItem, this.instanceId, child.instanceId, removedSubtreeHandleIds);
484
+ }
485
+ emitTypedListItemUpdate(child) {
486
+ if (!isElementTemplateHydrated() || !this.isMaterializedOnMainThread) {
487
+ return;
488
+ }
489
+ pushOp(ElementTemplateUpdateOps.updateTypedListItem, this.instanceId, toUpdateTypedListItemCommand(child));
490
+ }
491
+ }
492
+ export function toUpdateTypedListItemCommand(child) {
493
+ return {
494
+ __etHandleRef: child.instanceId,
495
+ type: child.type,
496
+ platformInfo: child.getListItemPlatformInfo(),
497
+ };
308
498
  }
309
499
  export function collectElementTemplateSubtreeHandleIds(root) {
310
500
  const handles = [];
@@ -312,7 +502,7 @@ export function collectElementTemplateSubtreeHandleIds(root) {
312
502
  return handles;
313
503
  }
314
504
  function collectElementTemplateSubtreeHandleIdsImpl(instance, handles) {
315
- if (!(instance instanceof BackgroundElementTemplateSlot) && instance.instanceId !== 0) {
505
+ if (instance.instanceId !== 0) {
316
506
  handles.push(instance.instanceId);
317
507
  }
318
508
  let child = instance.firstChild;
@@ -321,29 +511,18 @@ function collectElementTemplateSubtreeHandleIdsImpl(instance, handles) {
321
511
  child = child.nextSibling;
322
512
  }
323
513
  }
324
- function emitCreateRecursive(instance) {
514
+ function emitMainThreadCreateRecursive(instance) {
325
515
  if (!isElementTemplateHydrated()
326
- || instance.instanceId < 0
327
- || instance instanceof BackgroundElementTemplateSlot) {
516
+ || instance.instanceId === 0) {
328
517
  return;
329
518
  }
330
- for (const slotChildren of instance.elementSlots) {
331
- if (!slotChildren) {
332
- continue;
333
- }
334
- for (const child of slotChildren) {
335
- emitCreateRecursive(child);
336
- }
337
- }
338
- instance.emitCreate();
339
- }
340
- function collectChildren(slot) {
341
- const res = [];
342
- let child = slot.firstChild;
519
+ // Walk children in linked-list order; the slot-grouped view would just be
520
+ // discarded here since we recurse into every child regardless of slot.
521
+ let child = instance.firstChild;
343
522
  while (child) {
344
- res.push(child);
523
+ emitMainThreadCreateRecursive(child);
345
524
  child = child.nextSibling;
346
525
  }
347
- return res;
526
+ instance.emitMainThreadCreateIfNeeded();
348
527
  }
349
528
  //# sourceMappingURL=instance.js.map