@lynx-js/react 0.111.1 → 0.112.0

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 (171) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/components/lib/DeferredListItem.d.ts +3 -1
  3. package/components/lib/DeferredListItem.jsx +4 -2
  4. package/components/lib/DeferredListItem.jsx.map +1 -1
  5. package/components/lib/Page.js.map +1 -1
  6. package/components/src/DeferredListItem.tsx +5 -3
  7. package/components/src/Page.ts +2 -2
  8. package/package.json +15 -2
  9. package/refresh/.turbo/turbo-build.log +2 -2
  10. package/runtime/compat/index.d.ts +40 -0
  11. package/runtime/compat/index.js +15 -0
  12. package/runtime/debug/index.cjs +8 -0
  13. package/runtime/debug/index.d.ts +4 -0
  14. package/runtime/debug/index.js +5 -0
  15. package/runtime/lazy/compat.js +51 -0
  16. package/runtime/lazy/import.js +9 -0
  17. package/runtime/lazy/target.js +1 -0
  18. package/runtime/lib/alog/index.d.ts +1 -0
  19. package/runtime/lib/alog/index.js +8 -0
  20. package/runtime/lib/alog/index.js.map +1 -0
  21. package/runtime/lib/alog/render.d.ts +1 -0
  22. package/runtime/lib/alog/render.js +19 -0
  23. package/runtime/lib/alog/render.js.map +1 -0
  24. package/runtime/lib/backgroundSnapshot.d.ts +1 -0
  25. package/runtime/lib/backgroundSnapshot.js +31 -17
  26. package/runtime/lib/backgroundSnapshot.js.map +1 -1
  27. package/runtime/lib/debug/component-stack.d.ts +33 -0
  28. package/runtime/lib/debug/component-stack.js +145 -0
  29. package/runtime/lib/debug/component-stack.js.map +1 -0
  30. package/runtime/lib/debug/formatPatch.d.ts +2 -0
  31. package/runtime/lib/debug/formatPatch.js +27 -0
  32. package/runtime/lib/debug/formatPatch.js.map +1 -0
  33. package/runtime/lib/debug/printSnapshot.d.ts +1 -1
  34. package/runtime/lib/debug/printSnapshot.js +0 -4
  35. package/runtime/lib/debug/printSnapshot.js.map +1 -1
  36. package/runtime/lib/debug/profile.js +3 -5
  37. package/runtime/lib/debug/profile.js.map +1 -1
  38. package/runtime/lib/hydrate.js +11 -7
  39. package/runtime/lib/hydrate.js.map +1 -1
  40. package/runtime/lib/index.js +3 -5
  41. package/runtime/lib/index.js.map +1 -1
  42. package/runtime/lib/lifecycle/patch/commit.js +3 -3
  43. package/runtime/lib/lifecycle/patch/commit.js.map +1 -1
  44. package/runtime/lib/lifecycle/patch/isMainThreadHydrating.d.ts +2 -0
  45. package/runtime/lib/lifecycle/patch/{isMainThreadHydrationFinished.js → isMainThreadHydrating.js} +5 -5
  46. package/runtime/lib/lifecycle/patch/isMainThreadHydrating.js.map +1 -0
  47. package/runtime/lib/lifecycle/patch/snapshotPatch.d.ts +4 -0
  48. package/runtime/lib/lifecycle/patch/snapshotPatch.js +28 -0
  49. package/runtime/lib/lifecycle/patch/snapshotPatch.js.map +1 -1
  50. package/runtime/lib/lifecycle/patch/updateMainThread.js +20 -13
  51. package/runtime/lib/lifecycle/patch/updateMainThread.js.map +1 -1
  52. package/runtime/lib/lifecycle/reload.js +0 -2
  53. package/runtime/lib/lifecycle/reload.js.map +1 -1
  54. package/runtime/lib/lynx/lazy-bundle.js +0 -19
  55. package/runtime/lib/lynx/lazy-bundle.js.map +1 -1
  56. package/runtime/lib/lynx/performance.js +2 -2
  57. package/runtime/lib/lynx/performance.js.map +1 -1
  58. package/runtime/lib/lynx/runWithForce.js +2 -2
  59. package/runtime/lib/lynx/runWithForce.js.map +1 -1
  60. package/runtime/lib/lynx-api.js +17 -3
  61. package/runtime/lib/lynx-api.js.map +1 -1
  62. package/runtime/lib/lynx.js +16 -1
  63. package/runtime/lib/lynx.js.map +1 -1
  64. package/runtime/lib/pendingListUpdates.d.ts +2 -1
  65. package/runtime/lib/pendingListUpdates.js +16 -4
  66. package/runtime/lib/pendingListUpdates.js.map +1 -1
  67. package/runtime/lib/renderToOpcodes/constants.d.ts +2 -0
  68. package/runtime/lib/renderToOpcodes/constants.js +2 -0
  69. package/runtime/lib/renderToOpcodes/constants.js.map +1 -1
  70. package/runtime/lib/renderToOpcodes/index.js +36 -11
  71. package/runtime/lib/renderToOpcodes/index.js.map +1 -1
  72. package/runtime/lib/root.d.ts +6 -0
  73. package/runtime/lib/root.js +4 -0
  74. package/runtime/lib/root.js.map +1 -1
  75. package/runtime/lib/snapshot/gesture.js +2 -2
  76. package/runtime/lib/snapshot/gesture.js.map +1 -1
  77. package/runtime/lib/snapshot/platformInfo.js +5 -3
  78. package/runtime/lib/snapshot/platformInfo.js.map +1 -1
  79. package/runtime/lib/snapshot/ref.d.ts +2 -2
  80. package/runtime/lib/snapshot/spread.js +3 -1
  81. package/runtime/lib/snapshot/spread.js.map +1 -1
  82. package/runtime/lib/snapshot/workletEvent.js +2 -2
  83. package/runtime/lib/snapshot/workletEvent.js.map +1 -1
  84. package/runtime/lib/snapshot/workletRef.js +2 -2
  85. package/runtime/lib/snapshot/workletRef.js.map +1 -1
  86. package/runtime/lib/snapshot.js +13 -7
  87. package/runtime/lib/snapshot.js.map +1 -1
  88. package/runtime/lib/utils.d.ts +2 -0
  89. package/runtime/lib/utils.js +23 -2
  90. package/runtime/lib/utils.js.map +1 -1
  91. package/testing-library/dist/env/vitest.js +20 -10
  92. package/testing-library/dist/vitest-global-setup.js +0 -6
  93. package/testing-library/dist/vitest.config.js +1 -4
  94. package/transform/dist/wasm.cjs +1 -1
  95. package/types/react.d.ts +13 -1
  96. package/runtime/lib/lifecycle/patch/isMainThreadHydrationFinished.d.ts +0 -2
  97. package/runtime/lib/lifecycle/patch/isMainThreadHydrationFinished.js.map +0 -1
  98. package/runtime/src/backgroundSnapshot.ts +0 -501
  99. package/runtime/src/compat/componentIs.ts +0 -30
  100. package/runtime/src/compat/initData.ts +0 -150
  101. package/runtime/src/compat/lynxComponent.ts +0 -79
  102. package/runtime/src/debug/debug.ts +0 -9
  103. package/runtime/src/debug/printSnapshot.ts +0 -28
  104. package/runtime/src/debug/profile.ts +0 -55
  105. package/runtime/src/document.ts +0 -84
  106. package/runtime/src/gesture/processGesture.ts +0 -89
  107. package/runtime/src/gesture/processGestureBagkround.ts +0 -19
  108. package/runtime/src/gesture/types.ts +0 -44
  109. package/runtime/src/hooks/react.ts +0 -62
  110. package/runtime/src/hooks/useLynxGlobalEventListener.ts +0 -59
  111. package/runtime/src/hydrate.ts +0 -368
  112. package/runtime/src/index.ts +0 -94
  113. package/runtime/src/internal.ts +0 -63
  114. package/runtime/src/legacy-react-runtime/index.ts +0 -42
  115. package/runtime/src/lifecycle/destroy.ts +0 -34
  116. package/runtime/src/lifecycle/event/delayEvents.ts +0 -11
  117. package/runtime/src/lifecycle/event/delayLifecycleEvents.ts +0 -15
  118. package/runtime/src/lifecycle/event/jsReady.ts +0 -34
  119. package/runtime/src/lifecycle/pass.ts +0 -14
  120. package/runtime/src/lifecycle/patch/commit.ts +0 -214
  121. package/runtime/src/lifecycle/patch/error.ts +0 -61
  122. package/runtime/src/lifecycle/patch/isMainThreadHydrationFinished.ts +0 -13
  123. package/runtime/src/lifecycle/patch/snapshotPatch.ts +0 -65
  124. package/runtime/src/lifecycle/patch/snapshotPatchApply.ts +0 -145
  125. package/runtime/src/lifecycle/patch/updateMainThread.ts +0 -64
  126. package/runtime/src/lifecycle/ref/delay.ts +0 -99
  127. package/runtime/src/lifecycle/reload.ts +0 -97
  128. package/runtime/src/lifecycle/render.ts +0 -54
  129. package/runtime/src/lifecycleConstant.ts +0 -21
  130. package/runtime/src/list.ts +0 -307
  131. package/runtime/src/listUpdateInfo.ts +0 -221
  132. package/runtime/src/lynx/calledByNative.ts +0 -160
  133. package/runtime/src/lynx/component.ts +0 -113
  134. package/runtime/src/lynx/dynamic-js.ts +0 -36
  135. package/runtime/src/lynx/env.ts +0 -109
  136. package/runtime/src/lynx/injectLepusMethods.ts +0 -53
  137. package/runtime/src/lynx/lazy-bundle.ts +0 -175
  138. package/runtime/src/lynx/performance.ts +0 -148
  139. package/runtime/src/lynx/runWithForce.ts +0 -67
  140. package/runtime/src/lynx/tt.ts +0 -215
  141. package/runtime/src/lynx-api.ts +0 -455
  142. package/runtime/src/lynx.ts +0 -58
  143. package/runtime/src/opcodes.ts +0 -155
  144. package/runtime/src/pendingListUpdates.ts +0 -18
  145. package/runtime/src/renderToOpcodes/constants.ts +0 -24
  146. package/runtime/src/renderToOpcodes/index.ts +0 -306
  147. package/runtime/src/root.ts +0 -23
  148. package/runtime/src/snapshot/dynamicPartType.ts +0 -16
  149. package/runtime/src/snapshot/event.ts +0 -33
  150. package/runtime/src/snapshot/gesture.ts +0 -30
  151. package/runtime/src/snapshot/list.ts +0 -36
  152. package/runtime/src/snapshot/platformInfo.ts +0 -62
  153. package/runtime/src/snapshot/ref.ts +0 -139
  154. package/runtime/src/snapshot/spread.ts +0 -330
  155. package/runtime/src/snapshot/workletEvent.ts +0 -35
  156. package/runtime/src/snapshot/workletRef.ts +0 -88
  157. package/runtime/src/snapshot.ts +0 -634
  158. package/runtime/src/snapshotInstanceHydrationMap.ts +0 -17
  159. package/runtime/src/utils.ts +0 -44
  160. package/runtime/src/worklet/ctx.ts +0 -22
  161. package/runtime/src/worklet/destroy.ts +0 -16
  162. package/runtime/src/worklet/execMap.ts +0 -51
  163. package/runtime/src/worklet/functionCall.ts +0 -42
  164. package/runtime/src/worklet/functionality.ts +0 -29
  165. package/runtime/src/worklet/hmr.ts +0 -34
  166. package/runtime/src/worklet/indexMap.ts +0 -23
  167. package/runtime/src/worklet/runOnBackground.ts +0 -147
  168. package/runtime/src/worklet/runOnMainThread.ts +0 -50
  169. package/runtime/src/worklet/transformToWorklet.ts +0 -26
  170. package/runtime/src/worklet/workletRef.ts +0 -231
  171. package/runtime/src/worklet/workletRefPool.ts +0 -29
@@ -1,634 +0,0 @@
1
- // Copyright 2024 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.
4
-
5
- /**
6
- * Core snapshot system that implements a compiler-hinted virtual DOM.
7
- *
8
- * Key components:
9
- * 1. {@link Snapshot}: Template definition generated at compile time
10
- * 2. {@link SnapshotInstance}: Runtime instance in the main thread
11
- * 3. {@link BackgroundSnapshotInstance}: Runtime instance in the background thread
12
- *
13
- * The system uses static analysis to identify dynamic parts and generate
14
- * optimized update instructions, avoiding full virtual DOM diffing.
15
- */
16
-
17
- import type { Worklet, WorkletRefImpl } from '@lynx-js/react/worklet-runtime/bindings';
18
-
19
- import type { BackgroundSnapshotInstance } from './backgroundSnapshot.js';
20
- import { SnapshotOperation, __globalSnapshotPatch } from './lifecycle/patch/snapshotPatch.js';
21
- import { ListUpdateInfoRecording } from './listUpdateInfo.js';
22
- import { __pendingListUpdates } from './pendingListUpdates.js';
23
- import { DynamicPartType } from './snapshot/dynamicPartType.js';
24
- import { snapshotDestroyList } from './snapshot/list.js';
25
- import type { PlatformInfo } from './snapshot/platformInfo.js';
26
- import { unref } from './snapshot/ref.js';
27
- import { isDirectOrDeepEqual } from './utils.js';
28
-
29
- /**
30
- * A snapshot definition that contains all the information needed to create and update elements
31
- * This is generated at compile time through static analysis of the JSX
32
- */
33
- export interface Snapshot {
34
- create: null | ((ctx: SnapshotInstance) => FiberElement[]);
35
- update: null | ((ctx: SnapshotInstance, index: number, oldValue: any) => void)[];
36
- slot: [DynamicPartType, number][];
37
-
38
- isListHolder?: boolean;
39
- cssId?: number | undefined;
40
- entryName?: string | undefined;
41
- refAndSpreadIndexes?: number[] | null;
42
- }
43
-
44
- export let __page: FiberElement;
45
- export let __pageId = 0;
46
- export function setupPage(page: FiberElement): void {
47
- __page = page;
48
- __pageId = __GetElementUniqueID(page);
49
- }
50
-
51
- export function clearPage(): void {
52
- __page = undefined as unknown as FiberElement;
53
- __pageId = 0;
54
- }
55
-
56
- export const snapshotManager: {
57
- values: Map<string, Snapshot>;
58
- } = {
59
- values: /* @__PURE__ */ new Map<string, Snapshot>([
60
- [
61
- 'root',
62
- {
63
- create() {
64
- /* v8 ignore start */
65
- if (__JS__ && !__DEV__) {
66
- return [];
67
- }
68
- /* v8 ignore stop */
69
- return [__page!];
70
- },
71
- update: [],
72
- slot: [[DynamicPartType.Children, 0]],
73
- isListHolder: false,
74
- cssId: 0,
75
- },
76
- ],
77
- [
78
- 'wrapper',
79
- {
80
- create() {
81
- /* v8 ignore start */
82
- if (__JS__ && !__DEV__) {
83
- return [];
84
- }
85
- /* v8 ignore stop */
86
- return [__CreateWrapperElement(__pageId)];
87
- },
88
- update: [],
89
- slot: [[DynamicPartType.Children, 0]],
90
- isListHolder: false,
91
- },
92
- ],
93
- [
94
- null as unknown as string,
95
- {
96
- create() {
97
- /* v8 ignore start */
98
- if (__JS__ && !__DEV__) {
99
- return [];
100
- }
101
- /* v8 ignore stop */
102
- return [__CreateElement('raw-text', __pageId)];
103
- },
104
- update: [
105
- ctx => {
106
- /* v8 ignore start */
107
- if (__JS__ && !__DEV__) {
108
- return;
109
- }
110
- /* v8 ignore stop */
111
- if (ctx.__elements) {
112
- __SetAttribute(ctx.__elements[0]!, 'text', ctx.__values![0]);
113
- }
114
- },
115
- ],
116
- slot: [],
117
- isListHolder: false,
118
- },
119
- ],
120
- ]),
121
- };
122
-
123
- export const snapshotInstanceManager: {
124
- nextId: number;
125
- values: Map<number, SnapshotInstance>;
126
- clear(): void;
127
- } = {
128
- nextId: 0,
129
- values: /* @__PURE__ */ new Map<number, SnapshotInstance>(),
130
- clear() {
131
- // not resetting `nextId` to prevent id collision
132
- this.values.clear();
133
- },
134
- };
135
-
136
- export const backgroundSnapshotInstanceManager: {
137
- nextId: number;
138
- values: Map<number, BackgroundSnapshotInstance>;
139
- clear(): void;
140
- updateId(id: number, newId: number): void;
141
- getValueBySign(str: string): unknown;
142
- } = {
143
- nextId: 0,
144
- values: /* @__PURE__ */ new Map<number, BackgroundSnapshotInstance>(),
145
- clear() {
146
- // not resetting `nextId` to prevent id collision
147
- this.values.clear();
148
- },
149
- updateId(id: number, newId: number) {
150
- const values = this.values;
151
- const si = values.get(id)!;
152
- values.delete(id);
153
- values.set(newId, si);
154
- si.__id = newId;
155
- },
156
- getValueBySign(str: string): unknown {
157
- const res = str?.split(':');
158
- if (!res || (res.length != 2 && res.length != 3)) {
159
- throw new Error('Invalid ctx format: ' + str);
160
- }
161
- const id = Number(res[0]);
162
- const expIndex = Number(res[1]);
163
- const ctx = this.values.get(id);
164
- if (!ctx) {
165
- return null;
166
- }
167
- const spreadKey = res[2];
168
- if (res[1] === '__extraProps') {
169
- if (spreadKey) {
170
- return ctx.__extraProps![spreadKey];
171
- }
172
- throw new Error('unreachable');
173
- } else {
174
- if (spreadKey) {
175
- return (ctx.__values![expIndex] as { [spreadKey]: unknown })[spreadKey];
176
- } else {
177
- return ctx.__values![expIndex];
178
- }
179
- }
180
- },
181
- };
182
-
183
- export function entryUniqID(uniqID: string, entryName?: string): string {
184
- return entryName ? `${entryName}:${uniqID}` : uniqID;
185
- }
186
-
187
- export function createSnapshot(
188
- uniqID: string,
189
- create: Snapshot['create'] | null,
190
- update: Snapshot['update'] | null,
191
- slot: Snapshot['slot'],
192
- cssId: number | undefined,
193
- entryName: string | undefined,
194
- refAndSpreadIndexes: number[] | null,
195
- ): string {
196
- if (
197
- __DEV__ && __JS__
198
- // `__globalSnapshotPatch` does not exist before hydration,
199
- // so the snapshot of the first screen will not be sent to the main thread.
200
- && __globalSnapshotPatch
201
- && !snapshotManager.values.has(entryUniqID(uniqID, entryName))
202
- // `create` may be `null` when loading a lazy bundle after hydration.
203
- && create !== null
204
- ) {
205
- // We only update the lepus snapshot if the `uniqID` is different.
206
- // This means that `uniqID` is considered the "hash" of the snapshot.
207
- // When HMR (Hot Module Replacement) or fast refresh updates occur, `createSnapshot` will be re-executed with the new snapshot definition.
208
- __globalSnapshotPatch.push(
209
- SnapshotOperation.DEV_ONLY_AddSnapshot,
210
- uniqID,
211
- // We use `Function.prototype.toString` to serialize the `create` and `update` functions for Lepus.
212
- // This allows the updates to be applied to Lepus.
213
- // As a result, both the static part (`create`) and the dynamic parts (`update` and `slot`) can be updated.
214
- create.toString(),
215
- update?.map(f => f.toString()) ?? [],
216
- slot,
217
- cssId,
218
- entryName,
219
- );
220
- }
221
-
222
- uniqID = entryUniqID(uniqID, entryName);
223
-
224
- const s: Snapshot = { create, update, slot, cssId, entryName, refAndSpreadIndexes };
225
- snapshotManager.values.set(uniqID, s);
226
- if (slot && slot[0] && slot[0][0] === DynamicPartType.ListChildren) {
227
- s.isListHolder = true;
228
- }
229
- return uniqID;
230
- }
231
-
232
- export interface WithChildren {
233
- childNodes: WithChildren[];
234
- }
235
-
236
- export function traverseSnapshotInstance<I extends WithChildren>(
237
- si: I,
238
- callback: (si: I) => void,
239
- ): void {
240
- const c = si.childNodes;
241
- callback(si);
242
- for (const vv of c) {
243
- traverseSnapshotInstance(vv as I, callback);
244
- }
245
- }
246
-
247
- export interface SerializedSnapshotInstance {
248
- id: number;
249
- type: string;
250
- values?: any[] | undefined;
251
- extraProps?: Record<string, unknown> | undefined;
252
- children?: SerializedSnapshotInstance[] | undefined;
253
- }
254
-
255
- const DEFAULT_ENTRY_NAME = '__Card__';
256
- const DEFAULT_CSS_ID = 0;
257
-
258
- /**
259
- * The runtime instance of a {@link Snapshot} on the main thread that manages
260
- * the actual elements and handles updates to dynamic parts.
261
- *
262
- * This class is designed to be compatible with Preact's {@link ContainerNode}
263
- * interface for Preact's renderer to operate upon.
264
- */
265
- export class SnapshotInstance {
266
- __id: number;
267
- __snapshot_def: Snapshot;
268
- __elements?: FiberElement[] | undefined;
269
- __element_root?: FiberElement | undefined;
270
- __values?: unknown[] | undefined;
271
- __current_slot_index = 0;
272
- __worklet_ref_set?: Set<WorkletRefImpl<any> | Worklet>;
273
- __listItemPlatformInfo?: PlatformInfo;
274
- __extraProps?: Record<string, unknown> | undefined;
275
-
276
- constructor(public type: string, id?: number) {
277
- this.__snapshot_def = snapshotManager.values.get(type)!;
278
- // Suspense uses 'div'
279
- if (!this.__snapshot_def && type !== 'div') {
280
- throw new Error('Snapshot not found: ' + type);
281
- }
282
-
283
- id ??= snapshotInstanceManager.nextId -= 1;
284
- this.__id = id;
285
- snapshotInstanceManager.values.set(id, this);
286
- }
287
-
288
- ensureElements(): void {
289
- const { create, slot, isListHolder, cssId, entryName } = this.__snapshot_def;
290
- const elements = create!(this);
291
- this.__elements = elements;
292
- this.__element_root = elements[0];
293
-
294
- if (cssId === undefined) {
295
- // This means either:
296
- // CSS Scope is removed(We only need to call `__SetCSSId` when there is `entryName`)
297
- // Or an old bundle(`__SetCSSId` is called in `create`), we skip calling `__SetCSSId`
298
- if (entryName !== DEFAULT_ENTRY_NAME && entryName !== undefined) {
299
- __SetCSSId(this.__elements, DEFAULT_CSS_ID, entryName);
300
- }
301
- } else {
302
- // cssId !== undefined
303
- if (entryName !== DEFAULT_ENTRY_NAME && entryName !== undefined) {
304
- // For lazy bundle, we need add `entryName` to the third params
305
- __SetCSSId(this.__elements, cssId, entryName);
306
- } else {
307
- __SetCSSId(this.__elements, cssId);
308
- }
309
- }
310
-
311
- const values = this.__values;
312
- if (values) {
313
- this.__values = undefined;
314
- this.setAttribute('values', values);
315
- }
316
-
317
- if (isListHolder) {
318
- // never recurse into list's children
319
- } else {
320
- let index = 0;
321
- let child = this.__firstChild;
322
- while (child) {
323
- child.ensureElements();
324
-
325
- const [type, elementIndex] = slot[index]!;
326
- switch (type) {
327
- case DynamicPartType.Slot: {
328
- __ReplaceElement(child.__element_root!, elements[elementIndex]!);
329
- elements[elementIndex] = child.__element_root!;
330
- index++;
331
- break;
332
- }
333
- /* v8 ignore start */
334
- case DynamicPartType.MultiChildren: {
335
- if (__GetTag(elements[elementIndex]!) === 'wrapper') {
336
- __ReplaceElement(child.__element_root!, elements[elementIndex]!);
337
- } else {
338
- __AppendElement(elements[elementIndex]!, child.__element_root!);
339
- }
340
- index++;
341
- break;
342
- }
343
- /* v8 ignore end */
344
- case DynamicPartType.Children:
345
- case DynamicPartType.ListChildren: {
346
- __AppendElement(elements[elementIndex]!, child.__element_root!);
347
- break;
348
- }
349
- }
350
-
351
- child = child.__nextSibling;
352
- }
353
- }
354
- }
355
-
356
- unRenderElements(): void {
357
- const { isListHolder } = this.__snapshot_def;
358
- this.__elements = undefined;
359
- this.__element_root = undefined;
360
-
361
- if (isListHolder) {
362
- // never recurse into list's children
363
- } else {
364
- let child = this.__firstChild;
365
- while (child) {
366
- child.unRenderElements();
367
- child = child.__nextSibling;
368
- }
369
- }
370
- }
371
-
372
- takeElements(): SnapshotInstance {
373
- const a = Object.create(SnapshotInstance.prototype) as SnapshotInstance;
374
-
375
- a.__id = this.__id;
376
- a.__snapshot_def = this.__snapshot_def;
377
- a.__values = this.__values;
378
-
379
- // all clear
380
- a.__parent = null;
381
- a.__firstChild = null;
382
- a.__lastChild = null;
383
- a.__nextSibling = null;
384
- a.__previousSibling = null;
385
-
386
- this.childNodes.map(c => c.takeElements()).forEach(node => a.__insertBefore(node));
387
-
388
- a.__elements = this.__elements;
389
- a.__element_root = this.__element_root;
390
-
391
- this.__elements = undefined;
392
- this.__element_root = undefined;
393
- return a;
394
- }
395
-
396
- tearDown(): void {
397
- traverseSnapshotInstance(this, v => {
398
- v.__parent = null;
399
- v.__previousSibling = null;
400
- v.__nextSibling = null;
401
- });
402
- }
403
-
404
- // onCreate?: () => void;
405
- // onAttach?: () => void;
406
- // onDetach?: () => void;
407
- // onRef?: () => void;
408
- // onUnref?: () => void;
409
-
410
- private __parent: SnapshotInstance | null = null;
411
- private __firstChild: SnapshotInstance | null = null;
412
- private __lastChild: SnapshotInstance | null = null;
413
- private __previousSibling: SnapshotInstance | null = null;
414
- private __nextSibling: SnapshotInstance | null = null;
415
-
416
- get parentNode(): SnapshotInstance | null {
417
- return this.__parent;
418
- }
419
-
420
- get nextSibling(): SnapshotInstance | null {
421
- return this.__nextSibling;
422
- }
423
-
424
- // get isConnected() {
425
- // return !!this.__parent;
426
- // }
427
-
428
- contains(child: SnapshotInstance): boolean {
429
- return child.parentNode === this;
430
- }
431
-
432
- get childNodes(): SnapshotInstance[] {
433
- const nodes: SnapshotInstance[] = [];
434
- let node = this.__firstChild;
435
- while (node) {
436
- nodes.push(node);
437
- node = node.__nextSibling;
438
- }
439
- return nodes;
440
- }
441
-
442
- __insertBefore(node: SnapshotInstance, beforeNode?: SnapshotInstance): void {
443
- // If the node already has a parent, remove it from its current parent
444
- if (node.__parent) {
445
- node.__parent.__removeChild(node);
446
- }
447
-
448
- // If beforeNode is not provided, add the new node as the last child
449
- if (beforeNode) {
450
- // If beforeNode is provided, insert the new node before beforeNode
451
- if (beforeNode.__previousSibling) {
452
- beforeNode.__previousSibling.__nextSibling = node;
453
- node.__previousSibling = beforeNode.__previousSibling;
454
- } else {
455
- this.__firstChild = node;
456
- node.__previousSibling = null;
457
- }
458
- beforeNode.__previousSibling = node;
459
- node.__nextSibling = beforeNode;
460
- node.__parent = this;
461
- } else {
462
- if (this.__lastChild) {
463
- this.__lastChild.__nextSibling = node;
464
- node.__previousSibling = this.__lastChild;
465
- } else {
466
- this.__firstChild = node;
467
- node.__previousSibling = null;
468
- }
469
- this.__lastChild = node;
470
- node.__parent = this;
471
- node.__nextSibling = null;
472
- }
473
- }
474
-
475
- __removeChild(node: SnapshotInstance): void {
476
- if (node.__parent !== this) {
477
- throw new Error('The node to be removed is not a child of this node.');
478
- }
479
-
480
- if (node.__previousSibling) {
481
- node.__previousSibling.__nextSibling = node.__nextSibling;
482
- } else {
483
- this.__firstChild = node.__nextSibling;
484
- }
485
-
486
- if (node.__nextSibling) {
487
- node.__nextSibling.__previousSibling = node.__previousSibling;
488
- } else {
489
- this.__lastChild = node.__previousSibling;
490
- }
491
-
492
- node.__parent = null;
493
- node.__previousSibling = null;
494
- node.__nextSibling = null;
495
- }
496
-
497
- insertBefore(newNode: SnapshotInstance, existingNode?: SnapshotInstance): void {
498
- const __snapshot_def = this.__snapshot_def;
499
- if (__snapshot_def.isListHolder) {
500
- (__pendingListUpdates.values[this.__id] ??= new ListUpdateInfoRecording(
501
- this,
502
- )).onInsertBefore(newNode, existingNode);
503
- this.__insertBefore(newNode, existingNode);
504
- return;
505
- }
506
-
507
- const shouldRemove = newNode.__parent === this;
508
- this.__insertBefore(newNode, existingNode);
509
- const __elements = this.__elements;
510
- if (__elements) {
511
- if (!newNode.__elements) {
512
- newNode.ensureElements();
513
- }
514
- } else {
515
- return;
516
- }
517
-
518
- const count = __snapshot_def.slot.length;
519
- if (count === 1) {
520
- const [, elementIndex] = __snapshot_def.slot[0]!;
521
- const parent = __elements[elementIndex]!;
522
- if (shouldRemove) {
523
- __RemoveElement(parent, newNode.__element_root!);
524
- }
525
- if (existingNode) {
526
- __InsertElementBefore(
527
- parent,
528
- newNode.__element_root!,
529
- existingNode.__element_root,
530
- );
531
- } else {
532
- __AppendElement(parent, newNode.__element_root!);
533
- }
534
- } else if (count > 1) {
535
- const index = this.__current_slot_index++;
536
- const [s, elementIndex] = __snapshot_def.slot[index]!;
537
-
538
- if (s === DynamicPartType.Slot) {
539
- __ReplaceElement(newNode.__element_root!, __elements[elementIndex]!);
540
- __elements[elementIndex] = newNode.__element_root!;
541
-
542
- /* v8 ignore start */
543
- } else if (s === DynamicPartType.MultiChildren) {
544
- if (__GetTag(__elements[elementIndex]!) === 'wrapper') {
545
- __ReplaceElement(newNode.__element_root!, __elements[elementIndex]!);
546
- } else {
547
- __AppendElement(__elements[elementIndex]!, newNode.__element_root!);
548
- }
549
- }
550
- /* v8 ignore end */
551
- }
552
- }
553
-
554
- removeChild(child: SnapshotInstance): void {
555
- const __snapshot_def = this.__snapshot_def;
556
- if (__snapshot_def.isListHolder) {
557
- (__pendingListUpdates.values[this.__id] ??= new ListUpdateInfoRecording(
558
- this,
559
- )).onRemoveChild(child);
560
-
561
- this.__removeChild(child);
562
- traverseSnapshotInstance(child, v => {
563
- snapshotInstanceManager.values.delete(v.__id);
564
- });
565
- // mark this child as deleted
566
- child.__id = 0;
567
- return;
568
- }
569
-
570
- unref(child, true);
571
- if (this.__elements) {
572
- const [, elementIndex] = __snapshot_def.slot[0]!;
573
- __RemoveElement(this.__elements[elementIndex]!, child.__element_root!);
574
- }
575
-
576
- if (child.__snapshot_def.isListHolder) {
577
- snapshotDestroyList(child);
578
- }
579
-
580
- this.__removeChild(child);
581
- traverseSnapshotInstance(child, v => {
582
- v.__parent = null;
583
- v.__previousSibling = null;
584
- v.__nextSibling = null;
585
- delete v.__elements;
586
- delete v.__element_root;
587
- snapshotInstanceManager.values.delete(v.__id);
588
- });
589
- }
590
-
591
- setAttribute(key: string | number, value: any): void {
592
- if (key === 'values') {
593
- const oldValues = this.__values;
594
- const values = value as unknown[];
595
- this.__values = values;
596
- if (oldValues) {
597
- for (let index = 0; index < values.length; index++) {
598
- this.callUpdateIfNotDirectOrDeepEqual(index, oldValues[index], values[index]);
599
- }
600
- } else {
601
- for (let index = 0; index < values.length; index++) {
602
- this.callUpdateIfNotDirectOrDeepEqual(index, undefined, values[index]);
603
- }
604
- }
605
- return;
606
- }
607
-
608
- if (typeof key === 'string') {
609
- // for more flexible usage, we allow setting non-indexed attributes
610
- (this.__extraProps ??= {})[key] = value;
611
- return;
612
- }
613
-
614
- this.__values ??= [];
615
- this.callUpdateIfNotDirectOrDeepEqual(key, this.__values[key], this.__values[key] = value);
616
- }
617
-
618
- toJSON(): Omit<SerializedSnapshotInstance, 'children'> & { children: SnapshotInstance[] | undefined } {
619
- return {
620
- id: this.__id,
621
- type: this.type,
622
- values: this.__values,
623
- extraProps: this.__extraProps,
624
- children: this.__firstChild ? this.childNodes : undefined,
625
- };
626
- }
627
-
628
- callUpdateIfNotDirectOrDeepEqual(index: number, oldValue: any, newValue: any): void {
629
- if (isDirectOrDeepEqual(oldValue, newValue)) {}
630
- else {
631
- this.__snapshot_def.update![index]!(this, index, oldValue);
632
- }
633
- }
634
- }
@@ -1,17 +0,0 @@
1
- // Copyright 2024 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.
4
-
5
- /**
6
- * A map to store hydration states between snapshot instances.
7
- * K->V: main thread snapshotInstance IDs -> background snapshotInstance IDs.
8
- *
9
- * The map is used by the ref system to translate between snapshot instance IDs when
10
- * operations need to cross the thread boundary during the commit phase.
11
- */
12
- const hydrationMap: Map<number, number> = new Map<number, number>();
13
-
14
- /**
15
- * @internal
16
- */
17
- export { hydrationMap };
@@ -1,44 +0,0 @@
1
- // Copyright 2024 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.
4
- export function isDirectOrDeepEqual(a: any, b: any): boolean {
5
- if (a === b) {
6
- return true;
7
- }
8
- if (
9
- typeof a == 'object' && a !== null && typeof b == 'object' && b !== null && JSON.stringify(a) === JSON.stringify(b)
10
- ) {
11
- return true;
12
- }
13
- return false;
14
- }
15
-
16
- export function isEmptyObject(obj?: object): obj is Record<string, never> {
17
- for (const _ in obj) return false;
18
- return true;
19
- }
20
-
21
- export function isSdkVersionGt(major: number, minor: number): boolean {
22
- const lynxSdkVersion: string = SystemInfo.lynxSdkVersion || '1.0';
23
- const version = lynxSdkVersion.split('.');
24
- return Number(version[0]) > major || (Number(version[0]) == major && Number(version[1]) > minor);
25
- }
26
-
27
- export function pick<T extends object, K extends keyof T>(obj: T, keys: Iterable<K>): Pick<T, K> {
28
- const result: Partial<Pick<T, K>> = {};
29
- for (const key of keys) {
30
- if (key in obj) {
31
- result[key] = obj[key];
32
- }
33
- }
34
- return result as Pick<T, K>;
35
- }
36
-
37
- export function maybePromise<T>(value: unknown): value is Promise<T> {
38
- return (
39
- typeof value === 'object'
40
- && value !== null
41
- // @ts-expect-error the check is safe
42
- && typeof value.then === 'function'
43
- );
44
- }