@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
package/types/react.d.ts CHANGED
@@ -161,8 +161,20 @@ declare module '@lynx-js/types' {
161
161
  * <HeavyComponent />
162
162
  * </list-item>
163
163
  * ```
164
+ *
165
+ * @example
166
+ *
167
+ * Turn on the `unmountRecycled` switch to uninstall invisible JSX nodes.
168
+ * If they are components, related lifecycle (e.g. `componentWillUnmount` and cleanup of `useEffect`) will be executed accordingly.
169
+ * If they are intrinsic element, they will be `unref`-ed (`ref` will be set to `null` or cleanup of `ref` will be executed).
170
+ *
171
+ * ```tsx
172
+ * <list-item defer={{ unmountRecycled: true }} item-key="some-item">
173
+ * <WillBeUnmountIfRecycled />
174
+ * </list-item>
175
+ * ```
164
176
  */
165
- 'defer'?: boolean | undefined;
177
+ 'defer'?: boolean | { unmountRecycled?: boolean } | undefined;
166
178
  }
167
179
 
168
180
  export interface FrameworkRenderingTimings {
@@ -1,2 +0,0 @@
1
- export declare let isMainThreadHydrationFinished: boolean;
2
- export declare function setMainThreadHydrationFinished(isFinished: boolean): void;
@@ -1 +0,0 @@
1
- {"version":3,"file":"isMainThreadHydrationFinished.js","sourceRoot":"","sources":["../../../src/lifecycle/patch/isMainThreadHydrationFinished.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAE9E,MAAM,CAAC,IAAI,6BAA6B,GAAG,KAAK,CAAC;AAEjD,MAAM,UAAU,8BAA8B,CAAC,UAAmB;IAChE,IAAI,UAAU,IAAI,CAAC,6BAA6B,EAAE,CAAC;QACjD,mBAAmB,EAAE,CAAC;IACxB,CAAC;IACD,6BAA6B,GAAG,UAAU,CAAC;AAC7C,CAAC"}
@@ -1,501 +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
- * Background snapshot implementation that runs in the background thread.
7
- *
8
- * This is the mirror of main thread's {@link SnapshotInstance}:
9
- */
10
-
11
- import type { Worklet } from '@lynx-js/react/worklet-runtime/bindings';
12
-
13
- import { processGestureBackground } from './gesture/processGestureBagkround.js';
14
- import type { GestureKind } from './gesture/types.js';
15
- import { diffArrayAction, diffArrayLepus } from './hydrate.js';
16
- import { globalBackgroundSnapshotInstancesToRemove } from './lifecycle/patch/commit.js';
17
- import type { SnapshotPatch } from './lifecycle/patch/snapshotPatch.js';
18
- import {
19
- SnapshotOperation,
20
- __globalSnapshotPatch,
21
- initGlobalSnapshotPatch,
22
- takeGlobalSnapshotPatch,
23
- } from './lifecycle/patch/snapshotPatch.js';
24
- import { globalPipelineOptions } from './lynx/performance.js';
25
- import { DynamicPartType } from './snapshot/dynamicPartType.js';
26
- import { clearQueuedRefs, queueRefAttrUpdate } from './snapshot/ref.js';
27
- import type { Ref } from './snapshot/ref.js';
28
- import { transformSpread } from './snapshot/spread.js';
29
- import type { SerializedSnapshotInstance, Snapshot } from './snapshot.js';
30
- import { backgroundSnapshotInstanceManager, snapshotManager, traverseSnapshotInstance } from './snapshot.js';
31
- import { hydrationMap } from './snapshotInstanceHydrationMap.js';
32
- import { isDirectOrDeepEqual } from './utils.js';
33
- import { onPostWorkletCtx } from './worklet/ctx.js';
34
-
35
- export class BackgroundSnapshotInstance {
36
- constructor(public type: string) {
37
- this.__snapshot_def = snapshotManager.values.get(type)!;
38
- const id = this.__id = backgroundSnapshotInstanceManager.nextId += 1;
39
- backgroundSnapshotInstanceManager.values.set(id, this);
40
-
41
- __globalSnapshotPatch?.push(SnapshotOperation.CreateElement, type, id);
42
- }
43
-
44
- __id: number;
45
- __values: any[] | undefined;
46
- __snapshot_def: Snapshot;
47
- __extraProps?: Record<string, unknown> | undefined;
48
-
49
- private __parent: BackgroundSnapshotInstance | null = null;
50
- private __firstChild: BackgroundSnapshotInstance | null = null;
51
- private __lastChild: BackgroundSnapshotInstance | null = null;
52
- private __previousSibling: BackgroundSnapshotInstance | null = null;
53
- private __nextSibling: BackgroundSnapshotInstance | null = null;
54
-
55
- get parentNode(): BackgroundSnapshotInstance | null {
56
- return this.__parent;
57
- }
58
-
59
- get nextSibling(): BackgroundSnapshotInstance | null {
60
- return this.__nextSibling;
61
- }
62
-
63
- // get isConnected() {
64
- // return !!this.__parent;
65
- // }
66
-
67
- contains(child: BackgroundSnapshotInstance): boolean {
68
- return child.parentNode === this;
69
- }
70
-
71
- // TODO: write tests for this
72
- // This will be called in `lazy`/`Suspense`.
73
- // We currently ignore this since we did not find a way to test.
74
- /* v8 ignore start */
75
- appendChild(child: BackgroundSnapshotInstance): void {
76
- return this.insertBefore(child);
77
- }
78
- /* v8 ignore stop */
79
-
80
- insertBefore(
81
- node: BackgroundSnapshotInstance,
82
- beforeNode?: BackgroundSnapshotInstance,
83
- ): void {
84
- __globalSnapshotPatch?.push(
85
- SnapshotOperation.InsertBefore,
86
- this.__id,
87
- node.__id,
88
- beforeNode?.__id,
89
- );
90
-
91
- // If the node already has a parent, remove it from its current parent
92
- const p = node.__parent;
93
- if (p) {
94
- if (node.__previousSibling) {
95
- node.__previousSibling.__nextSibling = node.__nextSibling;
96
- } else {
97
- p.__firstChild = node.__nextSibling;
98
- }
99
-
100
- if (node.__nextSibling) {
101
- node.__nextSibling.__previousSibling = node.__previousSibling;
102
- } else {
103
- p.__lastChild = node.__previousSibling;
104
- }
105
- }
106
-
107
- // If beforeNode is not provided, add the new node as the last child
108
- if (beforeNode) {
109
- // If beforeNode is provided, insert the new node before beforeNode
110
- if (beforeNode.__previousSibling) {
111
- beforeNode.__previousSibling.__nextSibling = node;
112
- node.__previousSibling = beforeNode.__previousSibling;
113
- } else {
114
- this.__firstChild = node;
115
- node.__previousSibling = null;
116
- }
117
- beforeNode.__previousSibling = node;
118
- node.__nextSibling = beforeNode;
119
- node.__parent = this;
120
- } else {
121
- if (this.__lastChild) {
122
- this.__lastChild.__nextSibling = node;
123
- node.__previousSibling = this.__lastChild;
124
- } else {
125
- this.__firstChild = node;
126
- node.__previousSibling = null;
127
- }
128
- this.__lastChild = node;
129
- node.__parent = this;
130
- node.__nextSibling = null;
131
- }
132
- }
133
-
134
- removeChild(node: BackgroundSnapshotInstance): void {
135
- __globalSnapshotPatch?.push(
136
- SnapshotOperation.RemoveChild,
137
- this.__id,
138
- node.__id,
139
- );
140
-
141
- if (node.__parent !== this) {
142
- throw new Error('The node to be removed is not a child of this node.');
143
- }
144
-
145
- if (node.__previousSibling) {
146
- node.__previousSibling.__nextSibling = node.__nextSibling;
147
- } else {
148
- this.__firstChild = node.__nextSibling;
149
- }
150
-
151
- if (node.__nextSibling) {
152
- node.__nextSibling.__previousSibling = node.__previousSibling;
153
- } else {
154
- this.__lastChild = node.__previousSibling;
155
- }
156
-
157
- node.__parent = null;
158
- node.__previousSibling = null;
159
- node.__nextSibling = null;
160
-
161
- traverseSnapshotInstance(node, v => {
162
- v.__parent = null;
163
- v.__previousSibling = null;
164
- v.__nextSibling = null;
165
- if (v.__values) {
166
- v.__snapshot_def.refAndSpreadIndexes?.forEach((i) => {
167
- const value = v.__values![i] as unknown;
168
- if (value && (typeof value === 'object' || typeof value === 'function')) {
169
- if ('__spread' in value && 'ref' in value) {
170
- queueRefAttrUpdate(value.ref as Ref, null, v.__id, i);
171
- } else if ('__ref' in value) {
172
- queueRefAttrUpdate(value as Ref, null, v.__id, i);
173
- }
174
- }
175
- });
176
- }
177
- globalBackgroundSnapshotInstancesToRemove.push(v.__id);
178
- });
179
- }
180
-
181
- get childNodes(): BackgroundSnapshotInstance[] {
182
- const nodes: BackgroundSnapshotInstance[] = [];
183
- let node = this.__firstChild;
184
- while (node) {
185
- nodes.push(node);
186
- if (node === this.__lastChild) {
187
- break;
188
- }
189
- node = node.__nextSibling;
190
- }
191
- return nodes;
192
- }
193
-
194
- setAttribute(key: string | number, value: unknown): void {
195
- if (__PROFILE__) {
196
- console.profile('setAttribute');
197
- }
198
- if (key === 'values') {
199
- if (__globalSnapshotPatch) {
200
- const oldValues = this.__values;
201
- if (oldValues) {
202
- for (let index = 0; index < (value as unknown[]).length; index++) {
203
- const { needUpdate, valueToCommit } = this.setAttributeImpl(
204
- (value as unknown[])[index],
205
- oldValues[index],
206
- index,
207
- );
208
- if (needUpdate) {
209
- __globalSnapshotPatch.push(
210
- SnapshotOperation.SetAttribute,
211
- this.__id,
212
- index,
213
- valueToCommit,
214
- );
215
- }
216
- }
217
- } else {
218
- const patch = [];
219
- const length = (value as unknown[]).length;
220
- for (let index = 0; index < length; ++index) {
221
- const { valueToCommit } = this.setAttributeImpl((value as unknown[])[index], null, index);
222
- patch[index] = valueToCommit;
223
- }
224
- __globalSnapshotPatch.push(
225
- SnapshotOperation.SetAttributes,
226
- this.__id,
227
- patch,
228
- );
229
- }
230
- } else {
231
- this.__snapshot_def.refAndSpreadIndexes?.forEach((index) => {
232
- const v = (value as unknown[])[index];
233
- if (v && (typeof v === 'object' || typeof v === 'function')) {
234
- if ('__spread' in v && 'ref' in v) {
235
- queueRefAttrUpdate(null, v.ref as Ref, this.__id, index);
236
- } else if ('__ref' in v) {
237
- queueRefAttrUpdate(null, v as Ref, this.__id, index);
238
- }
239
- }
240
- });
241
- }
242
- this.__values = value as unknown[];
243
- if (__PROFILE__) {
244
- console.profileEnd();
245
- }
246
- return;
247
- }
248
-
249
- if (typeof key === 'string') {
250
- (this.__extraProps ??= {})[key] = value;
251
- } else {
252
- // old path (`this.setAttribute(0, xxx)`)
253
- // is reserved as slow path
254
- (this.__values ??= [])[key] = value;
255
- }
256
- __globalSnapshotPatch?.push(
257
- SnapshotOperation.SetAttribute,
258
- this.__id,
259
- key,
260
- value,
261
- );
262
- if (__PROFILE__) {
263
- console.profileEnd();
264
- }
265
- }
266
-
267
- private setAttributeImpl(newValue: unknown, oldValue: unknown, index: number): {
268
- needUpdate: boolean;
269
- valueToCommit: unknown;
270
- } {
271
- if (!newValue) {
272
- // `oldValue` can't be a spread.
273
- if (oldValue && typeof oldValue === 'object' && '__ref' in oldValue) {
274
- queueRefAttrUpdate(oldValue as Ref, null, this.__id, index);
275
- }
276
- return { needUpdate: oldValue !== newValue, valueToCommit: newValue };
277
- }
278
-
279
- const newType = typeof newValue;
280
- if (newType === 'object') {
281
- const newValueObj = newValue as Record<string, unknown>;
282
- if ('__spread' in newValueObj) {
283
- const oldSpread = (oldValue as { __spread?: Record<string, unknown> } | undefined)?.__spread;
284
- const newSpread = transformSpread(this, index, newValueObj);
285
- const needUpdate = !isDirectOrDeepEqual(oldSpread, newSpread);
286
- // use __spread to cache the transform result for next diff
287
- newValueObj['__spread'] = newSpread;
288
- queueRefAttrUpdate(
289
- oldSpread && ((oldValue as { ref?: Ref }).ref),
290
- newValueObj['ref'] as Ref,
291
- this.__id,
292
- index,
293
- );
294
- if (needUpdate) {
295
- for (const key in newSpread) {
296
- const newSpreadValue = newSpread[key];
297
- if (!newSpreadValue) {
298
- continue;
299
- }
300
- if ((newSpreadValue as { _wkltId?: string })._wkltId) {
301
- newSpread[key] = onPostWorkletCtx(newSpreadValue as Worklet);
302
- } else if ((newSpreadValue as { __isGesture?: boolean }).__isGesture) {
303
- processGestureBackground(newSpreadValue as GestureKind);
304
- } else if (key == '__lynx_timing_flag' && oldSpread?.[key] != newSpreadValue && globalPipelineOptions) {
305
- globalPipelineOptions.needTimestamps = true;
306
- }
307
- }
308
- }
309
- return { needUpdate, valueToCommit: newSpread };
310
- }
311
- if ('__ref' in newValueObj) {
312
- queueRefAttrUpdate(oldValue as Ref, newValueObj as Ref, this.__id, index);
313
- return { needUpdate: false, valueToCommit: 1 };
314
- }
315
- if ('_wkltId' in newValueObj) {
316
- return { needUpdate: true, valueToCommit: onPostWorkletCtx(newValueObj as Worklet) };
317
- }
318
- if ('__isGesture' in newValueObj) {
319
- processGestureBackground(newValueObj as unknown as GestureKind);
320
- return { needUpdate: true, valueToCommit: newValue };
321
- }
322
- if ('__ltf' in newValueObj) {
323
- // __lynx_timing_flag
324
- if (globalPipelineOptions && (oldValue as { __ltf?: unknown } | undefined)?.__ltf != newValueObj['__ltf']) {
325
- globalPipelineOptions.needTimestamps = true;
326
- return { needUpdate: true, valueToCommit: newValue };
327
- }
328
- return { needUpdate: false, valueToCommit: newValue };
329
- }
330
- return { needUpdate: !isDirectOrDeepEqual(oldValue, newValue), valueToCommit: newValue };
331
- }
332
- if (newType === 'function') {
333
- if ((newValue as { __ref?: unknown }).__ref) {
334
- queueRefAttrUpdate(oldValue as Ref, newValue as Ref, this.__id, index);
335
- return { needUpdate: false, valueToCommit: 1 };
336
- }
337
- /* event */
338
- return { needUpdate: !oldValue, valueToCommit: 1 };
339
- }
340
- return { needUpdate: oldValue !== newValue, valueToCommit: newValue };
341
- }
342
- }
343
-
344
- export function hydrate(
345
- before: SerializedSnapshotInstance,
346
- after: BackgroundSnapshotInstance,
347
- ): SnapshotPatch {
348
- initGlobalSnapshotPatch();
349
-
350
- const helper2 = (afters: BackgroundSnapshotInstance[], parentId: number, targetId?: number) => {
351
- for (const child of afters) {
352
- const id = child.__id;
353
- __globalSnapshotPatch!.push(SnapshotOperation.CreateElement, child.type, id);
354
- const values = child.__values;
355
- if (values) {
356
- child.__values = undefined;
357
- child.setAttribute('values', values);
358
- }
359
- const extraProps = child.__extraProps;
360
- for (const key in extraProps) {
361
- child.setAttribute(key, extraProps[key]);
362
- }
363
- helper2(child.childNodes, id);
364
- __globalSnapshotPatch!.push(SnapshotOperation.InsertBefore, parentId, id, targetId);
365
- }
366
- };
367
-
368
- const helper = (
369
- before: SerializedSnapshotInstance,
370
- after: BackgroundSnapshotInstance,
371
- ) => {
372
- hydrationMap.set(after.__id, before.id);
373
- backgroundSnapshotInstanceManager.updateId(after.__id, before.id);
374
- after.__values?.forEach((value: unknown, index) => {
375
- const old: unknown = before.values![index];
376
-
377
- if (value) {
378
- if (typeof value === 'object') {
379
- if ('__spread' in value) {
380
- // `value.__spread` my contain event ids using snapshot ids before hydration. Remove it.
381
- delete value.__spread;
382
- const __spread = transformSpread(after, index, value);
383
- for (const key in __spread) {
384
- const v = __spread[key];
385
- if (v && typeof v === 'object') {
386
- if ('_wkltId' in v) {
387
- onPostWorkletCtx(v as Worklet);
388
- } else if ('__isGesture' in v) {
389
- processGestureBackground(v as GestureKind);
390
- }
391
- }
392
- }
393
- (after.__values![index]! as Record<string, unknown>)['__spread'] = __spread;
394
- value = __spread;
395
- } else if ('__ref' in value) {
396
- // skip patch
397
- value = old;
398
- } else if ('_wkltId' in value) {
399
- onPostWorkletCtx(value as Worklet);
400
- } else if ('__isGesture' in value) {
401
- processGestureBackground(value as GestureKind);
402
- }
403
- } else if (typeof value === 'function') {
404
- if ('__ref' in value) {
405
- // skip patch
406
- value = old;
407
- } else {
408
- value = `${after.__id}:${index}:`;
409
- }
410
- }
411
- }
412
-
413
- if (!isDirectOrDeepEqual(value, old)) {
414
- __globalSnapshotPatch!.push(
415
- SnapshotOperation.SetAttribute,
416
- after.__id,
417
- index,
418
- value,
419
- );
420
- }
421
- });
422
-
423
- if (after.__extraProps) {
424
- for (const key in after.__extraProps) {
425
- const value = after.__extraProps[key];
426
- const old = before.extraProps?.[key];
427
- if (!isDirectOrDeepEqual(value, old)) {
428
- __globalSnapshotPatch!.push(
429
- SnapshotOperation.SetAttribute,
430
- after.__id,
431
- key,
432
- value,
433
- );
434
- }
435
- }
436
- }
437
-
438
- const { slot } = after.__snapshot_def;
439
-
440
- const beforeChildNodes = before.children ?? [];
441
- const afterChildNodes = after.childNodes;
442
-
443
- if (!slot) {
444
- return;
445
- }
446
-
447
- slot.forEach(([type], index) => {
448
- switch (type) {
449
- case DynamicPartType.Slot:
450
- case DynamicPartType.MultiChildren: {
451
- // TODO: the following null assertions are not 100% safe
452
- const v1 = beforeChildNodes[index]!;
453
- const v2 = afterChildNodes[index]!;
454
- helper(v1, v2);
455
- break;
456
- }
457
- case DynamicPartType.Children:
458
- case DynamicPartType.ListChildren: {
459
- const diffResult = diffArrayLepus(
460
- beforeChildNodes,
461
- afterChildNodes,
462
- (a, b) => a.type === b.type,
463
- (a, b) => {
464
- helper(a, b);
465
- },
466
- );
467
- diffArrayAction(
468
- beforeChildNodes,
469
- diffResult,
470
- (node, target) => {
471
- helper2([node], before.id, target?.id);
472
- return undefined as unknown as SerializedSnapshotInstance;
473
- },
474
- node => {
475
- __globalSnapshotPatch!.push(
476
- SnapshotOperation.RemoveChild,
477
- before.id,
478
- node.id,
479
- );
480
- },
481
- (node, target) => {
482
- // changedList.push([SnapshotOperation.RemoveChild, before.id, node.id]);
483
- __globalSnapshotPatch!.push(
484
- SnapshotOperation.InsertBefore,
485
- before.id,
486
- node.id,
487
- target?.id,
488
- );
489
- },
490
- );
491
- break;
492
- }
493
- }
494
- });
495
- };
496
-
497
- helper(before, after);
498
- // Hydration should not trigger ref updates. They were incorrectly triggered when using `setAttribute` to add values to the patch list.
499
- clearQueuedRefs();
500
- return takeGlobalSnapshotPatch()!;
501
- }
@@ -1,30 +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
- import type { FC } from 'react';
6
-
7
- // for better reuse if runtime is changed
8
- export function factory(
9
- { createElement, useMemo, Suspense, lazy }: typeof import('react'),
10
- loadLazyBundle: any,
11
- ): FC<{ is: string }> {
12
- /**
13
- * @internal a polyfill for <component is=? />
14
- */
15
- const __ComponentIsPolyfill: FC<{ is: string }> = ({ is, ...props }) => {
16
- if (typeof is !== 'string') {
17
- lynx.reportError(
18
- new Error(
19
- 'You must provide a string to props `is` when using syntax `<component is=? />`.',
20
- ),
21
- );
22
- return null;
23
- }
24
- // @ts-ignore
25
- const D = useMemo(() => lazy(() => loadLazyBundle(is)), [is]);
26
- return createElement(Suspense, { key: is }, createElement(D, props));
27
- };
28
-
29
- return __ComponentIsPolyfill;
30
- }