@lynx-js/react 0.110.0 → 0.111.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 (164) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/components/lib/DeferredListItem.d.ts +7 -0
  3. package/components/lib/DeferredListItem.jsx +40 -0
  4. package/components/lib/DeferredListItem.jsx.map +1 -0
  5. package/components/lib/Page.js.map +1 -1
  6. package/components/lib/index.d.ts +1 -0
  7. package/components/lib/index.js +1 -0
  8. package/components/lib/index.js.map +1 -1
  9. package/components/src/DeferredListItem.tsx +56 -0
  10. package/components/src/Page.ts +1 -1
  11. package/components/src/index.ts +1 -0
  12. package/package.json +1 -1
  13. package/refresh/.turbo/turbo-build.log +1 -1
  14. package/runtime/lazy/react-lepus.js +1 -0
  15. package/runtime/lazy/react.js +1 -0
  16. package/runtime/lepus/index.d.ts +1 -1
  17. package/runtime/lepus/index.js +44 -0
  18. package/runtime/lib/backgroundSnapshot.d.ts +2 -1
  19. package/runtime/lib/backgroundSnapshot.js +64 -41
  20. package/runtime/lib/backgroundSnapshot.js.map +1 -1
  21. package/runtime/lib/compat/initData.d.ts +7 -5
  22. package/runtime/lib/compat/initData.js +11 -2
  23. package/runtime/lib/compat/initData.js.map +1 -1
  24. package/runtime/lib/compat/lynxComponent.js +10 -12
  25. package/runtime/lib/compat/lynxComponent.js.map +1 -1
  26. package/runtime/lib/debug/profile.js +1 -0
  27. package/runtime/lib/debug/profile.js.map +1 -1
  28. package/runtime/lib/gesture/processGestureBagkround.d.ts +1 -1
  29. package/runtime/lib/gesture/processGestureBagkround.js +4 -1
  30. package/runtime/lib/gesture/processGestureBagkround.js.map +1 -1
  31. package/runtime/lib/gesture/types.js.map +1 -1
  32. package/runtime/lib/hooks/useLynxGlobalEventListener.d.ts +1 -1
  33. package/runtime/lib/hydrate.d.ts +1 -1
  34. package/runtime/lib/hydrate.js +5 -4
  35. package/runtime/lib/hydrate.js.map +1 -1
  36. package/runtime/lib/index.d.ts +2 -2
  37. package/runtime/lib/index.js +2 -2
  38. package/runtime/lib/index.js.map +1 -1
  39. package/runtime/lib/internal.d.ts +3 -2
  40. package/runtime/lib/internal.js +3 -2
  41. package/runtime/lib/internal.js.map +1 -1
  42. package/runtime/lib/legacy-react-runtime/index.js +1 -1
  43. package/runtime/lib/legacy-react-runtime/index.js.map +1 -1
  44. package/runtime/lib/lifecycle/patch/commit.js +5 -5
  45. package/runtime/lib/lifecycle/patch/commit.js.map +1 -1
  46. package/runtime/lib/lifecycle/patch/snapshotPatch.d.ts +9 -9
  47. package/runtime/lib/lifecycle/patch/snapshotPatch.js +9 -10
  48. package/runtime/lib/lifecycle/patch/snapshotPatch.js.map +1 -1
  49. package/runtime/lib/lifecycle/patch/snapshotPatchApply.js.map +1 -1
  50. package/runtime/lib/lifecycle/patch/updateMainThread.js +11 -12
  51. package/runtime/lib/lifecycle/patch/updateMainThread.js.map +1 -1
  52. package/runtime/lib/lifecycle/reload.js +1 -1
  53. package/runtime/lib/lifecycle/reload.js.map +1 -1
  54. package/runtime/lib/lifecycleConstant.d.ts +2 -1
  55. package/runtime/lib/lifecycleConstant.js +1 -0
  56. package/runtime/lib/lifecycleConstant.js.map +1 -1
  57. package/runtime/lib/list.d.ts +2 -46
  58. package/runtime/lib/list.js +124 -211
  59. package/runtime/lib/list.js.map +1 -1
  60. package/runtime/lib/listUpdateInfo.d.ts +38 -0
  61. package/runtime/lib/listUpdateInfo.js +152 -0
  62. package/runtime/lib/listUpdateInfo.js.map +1 -0
  63. package/runtime/lib/lynx/calledByNative.js +8 -11
  64. package/runtime/lib/lynx/calledByNative.js.map +1 -1
  65. package/runtime/lib/lynx/component.js +11 -14
  66. package/runtime/lib/lynx/component.js.map +1 -1
  67. package/runtime/lib/lynx/env.js +1 -2
  68. package/runtime/lib/lynx/env.js.map +1 -1
  69. package/runtime/lib/lynx/lazy-bundle.js +48 -21
  70. package/runtime/lib/lynx/lazy-bundle.js.map +1 -1
  71. package/runtime/lib/lynx/performance.d.ts +3 -19
  72. package/runtime/lib/lynx/performance.js +25 -26
  73. package/runtime/lib/lynx/performance.js.map +1 -1
  74. package/runtime/lib/lynx/tt.js +10 -5
  75. package/runtime/lib/lynx/tt.js.map +1 -1
  76. package/runtime/lib/lynx-api.d.ts +78 -1
  77. package/runtime/lib/lynx-api.js +3 -0
  78. package/runtime/lib/lynx-api.js.map +1 -1
  79. package/runtime/lib/lynx.js +1 -0
  80. package/runtime/lib/lynx.js.map +1 -1
  81. package/runtime/lib/opcodes.js +2 -1
  82. package/runtime/lib/opcodes.js.map +1 -1
  83. package/runtime/lib/pendingListUpdates.d.ts +6 -0
  84. package/runtime/lib/pendingListUpdates.js +16 -0
  85. package/runtime/lib/pendingListUpdates.js.map +1 -0
  86. package/runtime/lib/renderToOpcodes/index.js +7 -7
  87. package/runtime/lib/renderToOpcodes/index.js.map +1 -1
  88. package/runtime/lib/snapshot/dynamicPartType.d.ts +12 -0
  89. package/runtime/lib/snapshot/dynamicPartType.js +17 -0
  90. package/runtime/lib/snapshot/dynamicPartType.js.map +1 -0
  91. package/runtime/lib/snapshot/gesture.js +3 -0
  92. package/runtime/lib/snapshot/gesture.js.map +1 -1
  93. package/runtime/lib/snapshot/list.d.ts +3 -0
  94. package/runtime/lib/snapshot/list.js +23 -0
  95. package/runtime/lib/snapshot/list.js.map +1 -0
  96. package/runtime/lib/snapshot/platformInfo.d.ts +10 -0
  97. package/runtime/lib/snapshot/platformInfo.js +6 -3
  98. package/runtime/lib/snapshot/platformInfo.js.map +1 -1
  99. package/runtime/lib/snapshot/ref.d.ts +3 -0
  100. package/runtime/lib/snapshot/ref.js.map +1 -1
  101. package/runtime/lib/snapshot/spread.d.ts +2 -2
  102. package/runtime/lib/snapshot/spread.js +4 -5
  103. package/runtime/lib/snapshot/spread.js.map +1 -1
  104. package/runtime/lib/snapshot/workletEvent.js +1 -1
  105. package/runtime/lib/snapshot/workletEvent.js.map +1 -1
  106. package/runtime/lib/snapshot/workletRef.d.ts +1 -1
  107. package/runtime/lib/snapshot/workletRef.js.map +1 -1
  108. package/runtime/lib/snapshot.d.ts +7 -14
  109. package/runtime/lib/snapshot.js +36 -31
  110. package/runtime/lib/snapshot.js.map +1 -1
  111. package/runtime/lib/snapshotInstanceHydrationMap.js.map +1 -1
  112. package/runtime/lib/utils.d.ts +1 -0
  113. package/runtime/lib/utils.js +7 -1
  114. package/runtime/lib/utils.js.map +1 -1
  115. package/runtime/src/backgroundSnapshot.ts +78 -63
  116. package/runtime/src/compat/initData.ts +20 -9
  117. package/runtime/src/compat/lynxComponent.ts +12 -13
  118. package/runtime/src/debug/profile.ts +1 -0
  119. package/runtime/src/gesture/processGestureBagkround.ts +5 -1
  120. package/runtime/src/gesture/types.ts +3 -0
  121. package/runtime/src/hooks/useLynxGlobalEventListener.ts +1 -1
  122. package/runtime/src/hydrate.ts +6 -4
  123. package/runtime/src/index.ts +2 -0
  124. package/runtime/src/internal.ts +3 -2
  125. package/runtime/src/legacy-react-runtime/index.ts +1 -1
  126. package/runtime/src/lifecycle/patch/commit.ts +5 -11
  127. package/runtime/src/lifecycle/patch/snapshotPatch.ts +9 -9
  128. package/runtime/src/lifecycle/patch/snapshotPatchApply.ts +1 -1
  129. package/runtime/src/lifecycle/patch/updateMainThread.ts +11 -12
  130. package/runtime/src/lifecycle/reload.ts +1 -1
  131. package/runtime/src/lifecycleConstant.ts +1 -0
  132. package/runtime/src/list.ts +143 -278
  133. package/runtime/src/listUpdateInfo.ts +221 -0
  134. package/runtime/src/lynx/calledByNative.ts +8 -10
  135. package/runtime/src/lynx/component.ts +17 -29
  136. package/runtime/src/lynx/env.ts +1 -2
  137. package/runtime/src/lynx/lazy-bundle.ts +55 -20
  138. package/runtime/src/lynx/performance.ts +26 -27
  139. package/runtime/src/lynx/tt.ts +10 -11
  140. package/runtime/src/lynx-api.ts +81 -2
  141. package/runtime/src/lynx.ts +1 -0
  142. package/runtime/src/opcodes.ts +2 -1
  143. package/runtime/src/pendingListUpdates.ts +18 -0
  144. package/runtime/src/renderToOpcodes/index.ts +7 -7
  145. package/runtime/src/snapshot/dynamicPartType.ts +16 -0
  146. package/runtime/src/snapshot/gesture.ts +3 -0
  147. package/runtime/src/snapshot/list.ts +36 -0
  148. package/runtime/src/snapshot/platformInfo.ts +19 -5
  149. package/runtime/src/snapshot/ref.ts +1 -0
  150. package/runtime/src/snapshot/spread.ts +42 -17
  151. package/runtime/src/snapshot/workletEvent.ts +1 -1
  152. package/runtime/src/snapshot/workletRef.ts +1 -1
  153. package/runtime/src/snapshot.ts +41 -34
  154. package/runtime/src/snapshotInstanceHydrationMap.ts +1 -1
  155. package/runtime/src/utils.ts +12 -3
  156. package/testing-library/dist/env/vitest.js +3 -3
  157. package/testing-library/dist/index.d.ts +4 -1
  158. package/testing-library/dist/pure.js +1 -1
  159. package/testing-library/dist/vitest.config.js +45 -8
  160. package/testing-library/types/entry.d.ts +3 -2
  161. package/transform/cjs/main.cjs +4 -0
  162. package/transform/dist/wasm.cjs +1 -1
  163. package/types/react.d.ts +21 -1
  164. package/types/react.docs.d.ts +1 -1
@@ -0,0 +1,221 @@
1
+ // Copyright 2025 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 { hydrate } from './hydrate.js';
6
+ import { componentAtIndexFactory, enqueueComponentFactory } from './list.js';
7
+ import type { SnapshotInstance } from './snapshot.js';
8
+
9
+ export interface ListUpdateInfo {
10
+ flush(): void;
11
+ onInsertBefore(
12
+ newNode: SnapshotInstance,
13
+ existingNode?: SnapshotInstance,
14
+ ): void;
15
+ onRemoveChild(child: SnapshotInstance): void;
16
+ onSetAttribute(child: SnapshotInstance, attr: any, oldAttr: any): void;
17
+ }
18
+
19
+ // class ListUpdateInfoDiffing implements ListUpdateInfo {
20
+ // private oldChildNodes: SnapshotInstance[];
21
+ // constructor(private list: SnapshotInstance) {
22
+ // this.oldChildNodes = list.childNodes;
23
+ // }
24
+ // flush(): void {
25
+ // Object.defineProperty(SnapshotInstance.prototype, "key", {
26
+ // get: function () {
27
+ // return this.values[0]["item-key"];
28
+ // },
29
+ // });
30
+
31
+ // }
32
+ // onInsertBefore(newNode: SnapshotInstance, existingNode?: SnapshotInstance | undefined): void {}
33
+ // onRemoveChild(child: SnapshotInstance): void {}
34
+ // onSetAttribute(child: SnapshotInstance, attr: any): void {
35
+ // throw new Error("Method not implemented.");
36
+ // }
37
+ // }
38
+
39
+ interface InsertAction {
40
+ position: number;
41
+ type: string;
42
+ }
43
+
44
+ interface UpdateAction {
45
+ from: number;
46
+ to: number;
47
+ type: string;
48
+ flush: boolean;
49
+ }
50
+
51
+ interface ListOperations {
52
+ insertAction: InsertAction[];
53
+ removeAction: number[];
54
+ updateAction: UpdateAction[];
55
+ }
56
+
57
+ export class ListUpdateInfoRecording implements ListUpdateInfo {
58
+ constructor(private list: SnapshotInstance) {
59
+ this.oldChildNodes = list.childNodes;
60
+ // this.oldChildNodesSet = new Set(this.oldChildNodes);
61
+ }
62
+
63
+ // private __commitAndReset() {
64
+ // (this.__pendingAttributes ??= []).push(this.__toAttribute());
65
+ // this.oldChildNodes = this.list.childNodes;
66
+ // this.oldChildNodesSet = new Set(this.oldChildNodes);
67
+ // this.removeChild1.clear();
68
+ // this.removeChild2.clear();
69
+ // this.insertBefore.clear();
70
+ // this.appendChild.length = 0;
71
+ // this.platformInfoUpdate.clear();
72
+ // }
73
+
74
+ flush(): void {
75
+ const elementIndex = this.list.__snapshot_def.slot[0]![1];
76
+ const listElement = this.list.__elements![elementIndex]!;
77
+ // this.__pendingAttributes?.forEach(pendingAttribute => {
78
+ // __SetAttribute(listElement, "update-list-info", pendingAttribute);
79
+ // __FlushElementTree(listElement);
80
+ // });
81
+ __SetAttribute(listElement, 'update-list-info', this.__toAttribute());
82
+ const [componentAtIndex, componentAtIndexes] = componentAtIndexFactory(this.list.childNodes, hydrate);
83
+ __UpdateListCallbacks(
84
+ listElement,
85
+ componentAtIndex,
86
+ enqueueComponentFactory(),
87
+ componentAtIndexes,
88
+ );
89
+ }
90
+
91
+ private oldChildNodes: SnapshotInstance[];
92
+ // private oldChildNodesSet: Set<SnapshotInstance>;
93
+ private removeChild = new Set<SnapshotInstance>();
94
+ private insertBefore = new Map<SnapshotInstance, SnapshotInstance[]>(); // insert V before K
95
+ private appendChild = [] as SnapshotInstance[];
96
+ private platformInfoUpdate = new Map<SnapshotInstance, any>();
97
+
98
+ onInsertBefore(newNode: SnapshotInstance, existingNode?: SnapshotInstance): void {
99
+ if (newNode.parentNode) {
100
+ // if (!this.oldChildNodesSet.has(newNode)) {
101
+ // this.__commitAndReset();
102
+ // }
103
+ this.removeChild.add(newNode);
104
+ }
105
+ if (existingNode) {
106
+ // if (!this.oldChildNodesSet.has(existingNode)) {
107
+ // this.__commitAndReset();
108
+ // }
109
+ const newChildren = this.insertBefore.get(existingNode) ?? [];
110
+ newChildren.push(newNode);
111
+ this.insertBefore.set(existingNode, newChildren);
112
+ } else {
113
+ this.appendChild.push(newNode);
114
+ }
115
+ }
116
+
117
+ onRemoveChild(child: SnapshotInstance): void {
118
+ // if (!this.oldChildNodesSet.has(child)) {
119
+ // this.__commitAndReset();
120
+ // }
121
+ this.removeChild.add(child);
122
+ }
123
+
124
+ onSetAttribute(child: SnapshotInstance, attr: any, _oldAttr: any): void {
125
+ this.platformInfoUpdate.set(child, attr);
126
+ }
127
+
128
+ private __toAttribute(): ListOperations {
129
+ const { removeChild, insertBefore, appendChild, platformInfoUpdate } = this;
130
+
131
+ const removals: number[] = [];
132
+ const insertions: InsertAction[] = [];
133
+ const updates: UpdateAction[] = [];
134
+
135
+ let j = 0;
136
+ for (let i = 0; i < this.oldChildNodes.length; i++, j++) {
137
+ const child = this.oldChildNodes[i]!;
138
+ if (platformInfoUpdate.has(child)) {
139
+ updates.push({
140
+ ...platformInfoUpdate.get(child),
141
+ from: +j,
142
+ to: +j,
143
+ // no flush
144
+ flush: false,
145
+ type: child.type,
146
+ } as UpdateAction);
147
+ }
148
+ if (insertBefore.has(child)) {
149
+ const children = insertBefore.get(child)!;
150
+ children.forEach(c => {
151
+ insertions.push({
152
+ position: j,
153
+ type: c.type,
154
+ ...c.__listItemPlatformInfo,
155
+ } as InsertAction);
156
+ j++;
157
+ });
158
+ }
159
+ if (removeChild.has(child)) {
160
+ removals.push(i);
161
+ removeChild.delete(child);
162
+ j--;
163
+ }
164
+ }
165
+ for (let i = 0; i < appendChild.length; i++) {
166
+ const child = appendChild[i]!;
167
+ insertions.push({
168
+ position: j + i,
169
+ type: child.type,
170
+ ...child.__listItemPlatformInfo,
171
+ } as InsertAction);
172
+ }
173
+
174
+ insertions.sort((a, b) => a.position - b.position);
175
+ removals.sort((a, b) => a - b);
176
+
177
+ if (
178
+ SystemInfo.lynxSdkVersion === '2.14'
179
+ || SystemInfo.lynxSdkVersion === '2.15'
180
+ || SystemInfo.lynxSdkVersion === '2.16'
181
+ || SystemInfo.lynxSdkVersion === '2.17'
182
+ || SystemInfo.lynxSdkVersion === '2.18'
183
+ ) {
184
+ const elementIndex = this.list.__snapshot_def.slot[0]![1];
185
+ const listElement = this.list.__elements![elementIndex]!;
186
+
187
+ // `__GetAttributeByName` is available since Lynx 2.14
188
+ if (__GetAttributeByName(listElement, 'custom-list-name') === 'list-container') {
189
+ // `updateAction` must be full (not incremental) when Lynx version <= 2.18 and
190
+ // when `custom-list-name` is `list-container` (available when Lynx version >= 2.14) is true,
191
+ updates.length = 0;
192
+ this.list.childNodes.forEach((child, index) => {
193
+ updates.push({
194
+ ...child.__listItemPlatformInfo,
195
+ from: index,
196
+ to: index,
197
+ // no flush
198
+ flush: false,
199
+ type: child.type,
200
+ } as UpdateAction);
201
+ });
202
+ }
203
+ }
204
+
205
+ return {
206
+ insertAction: insertions,
207
+ removeAction: removals,
208
+ updateAction: updates,
209
+ };
210
+ }
211
+
212
+ toJSON(): [ListOperations] {
213
+ // if (this.__pendingAttributes) {
214
+ // return [...this.__pendingAttributes, this.__toAttribute()];
215
+ // } else {
216
+ // return [this.__toAttribute()];
217
+ // }
218
+
219
+ return [this.__toAttribute()] as const;
220
+ }
221
+ }
@@ -6,13 +6,13 @@ import { isJSReady, jsReady, jsReadyEventIdSwap, resetJSReady } from '../lifecyc
6
6
  import { reloadMainThread } from '../lifecycle/reload.js';
7
7
  import { renderMainThread } from '../lifecycle/render.js';
8
8
  import { LifecycleConstant } from '../lifecycleConstant.js';
9
- import { __pendingListUpdates } from '../list.js';
10
9
  import { ssrHydrateByOpcodes } from '../opcodes.js';
10
+ import { __pendingListUpdates } from '../pendingListUpdates.js';
11
11
  import { __root, setRoot } from '../root.js';
12
+ import { applyRefQueue } from '../snapshot/workletRef.js';
12
13
  import { SnapshotInstance, __page, setupPage } from '../snapshot.js';
13
14
  import { isEmptyObject } from '../utils.js';
14
- import { PerformanceTimingKeys, markTiming, setPipeline } from './performance.js';
15
- import { applyRefQueue } from '../snapshot/workletRef.js';
15
+ import { markTiming, setPipeline } from './performance.js';
16
16
 
17
17
  function ssrEncode() {
18
18
  const { __opcodes } = __root;
@@ -116,13 +116,14 @@ function updatePage(data: Record<string, unknown> | undefined, options?: UpdateP
116
116
  Object.assign(lynx.__initData, data);
117
117
  }
118
118
 
119
+ const flushOptions = options ?? {};
119
120
  if (!isJSReady) {
120
121
  const oldRoot = __root;
121
122
  setRoot(new SnapshotInstance('root'));
122
123
  __root.__jsx = oldRoot.__jsx;
123
124
 
124
125
  setPipeline(options?.pipelineOptions);
125
- markTiming(PerformanceTimingKeys.updateDiffVdomStart);
126
+ markTiming('updateDiffVdomStart');
126
127
  {
127
128
  __pendingListUpdates.clear();
128
129
  renderMainThread();
@@ -138,14 +139,11 @@ function updatePage(data: Record<string, unknown> | undefined, options?: UpdateP
138
139
  __pendingListUpdates.flush();
139
140
  applyRefQueue();
140
141
  }
141
- markTiming(PerformanceTimingKeys.updateDiffVdomEnd);
142
+ flushOptions.triggerDataUpdated = true;
143
+ markTiming('updateDiffVdomEnd');
142
144
  }
143
145
 
144
- if (options) {
145
- __FlushElementTree(__page, options);
146
- } else {
147
- __FlushElementTree();
148
- }
146
+ __FlushElementTree(__page, flushOptions);
149
147
  }
150
148
 
151
149
  function updateGlobalProps(_data: any, options?: UpdatePageOption): void {
@@ -6,23 +6,28 @@
6
6
 
7
7
  import { Component } from 'preact';
8
8
 
9
- import { PerfSpecificKey, PerformanceTimingKeys, markTimingLegacy } from './performance.js';
9
+ import { PerfSpecificKey, markTimingLegacy } from './performance.js';
10
10
  import { globalFlushOptions } from '../lifecycle/patch/commit.js';
11
11
  import { NEXT_STATE } from '../renderToOpcodes/constants.js';
12
12
 
13
13
  if (__JS__) {
14
- const __Component = Component as any;
15
-
16
- __Component.prototype._reactAppInstance = lynxCoreInject.tt;
17
-
18
- __Component.prototype.getNodeRef = function(a: string, b?: boolean) {
14
+ function reportRefDeprecationError(fnName: string, newFnName: string) {
19
15
  if (!__DISABLE_CREATE_SELECTOR_QUERY_INCOMPATIBLE_WARNING__) {
20
16
  lynx.reportError(
21
17
  new Error(
22
- 'getNodeRef is deprecated and has different behavior in ReactLynx 3.0, please use ref or lynx.createSelectorQuery instead.',
18
+ `${fnName} is deprecated and has different behavior in ReactLynx 3.0, please use ref or ${newFnName} instead.`,
23
19
  ),
24
20
  );
25
21
  }
22
+ }
23
+
24
+ const __Component = Component as any;
25
+
26
+ __Component.prototype._reactAppInstance = lynxCoreInject.tt;
27
+
28
+ __Component.prototype.getNodeRef = function(a: string, b?: boolean) {
29
+ reportRefDeprecationError('getNodeRef', 'lynx.createSelectorQuery');
30
+
26
31
  // @ts-expect-error hack lynx-kernel
27
32
  return lynxCoreInject.tt._reactLynx.ReactComponent.prototype.getNodeRef
28
33
  .call(
@@ -40,13 +45,8 @@ if (__JS__) {
40
45
  };
41
46
 
42
47
  __Component.prototype.getNodeRefFromRoot = function(a: string) {
43
- if (!__DISABLE_CREATE_SELECTOR_QUERY_INCOMPATIBLE_WARNING__) {
44
- lynx.reportError(
45
- new Error(
46
- 'getNodeRefFromRoot is deprecated and has different behavior in ReactLynx 3.0, please use ref or lynx.createSelectorQuery instead.',
47
- ),
48
- );
49
- }
48
+ reportRefDeprecationError('getNodeRefFromRoot', 'lynx.createSelectorQuery');
49
+
50
50
  // @ts-expect-error hack lynx-kernel
51
51
  return lynxCoreInject.tt._reactLynx.ReactComponent.prototype
52
52
  .getNodeRefFromRoot.call(
@@ -88,26 +88,14 @@ if (__JS__) {
88
88
  };
89
89
 
90
90
  __Component.prototype.getElementById = function(id: string) {
91
- if (!__DISABLE_CREATE_SELECTOR_QUERY_INCOMPATIBLE_WARNING__) {
92
- lynx.reportError(
93
- new Error(
94
- 'getElementById on component instance is deprecated and has different behavior in ReactLynx 3.0, please use ref or lynx.getElementById instead.',
95
- ),
96
- );
97
- }
91
+ reportRefDeprecationError('getElementById', 'lynx.getElementById');
98
92
  return lynx.getElementById(id);
99
93
  };
100
94
 
101
95
  __Component.prototype.GlobalEventEmitter = lynxCoreInject.tt.GlobalEventEmitter;
102
96
 
103
97
  __Component.prototype.createSelectorQuery = function() {
104
- if (!__DISABLE_CREATE_SELECTOR_QUERY_INCOMPATIBLE_WARNING__) {
105
- lynx.reportError(
106
- new Error(
107
- 'createSelectorQuery on component instance is deprecated and has different behavior in ReactLynx 3.0, please use ref or lynx.createSelectorQuery instead.',
108
- ),
109
- );
110
- }
98
+ reportRefDeprecationError('createSelectorQuery on component instance', 'lynx.createSelectorQuery');
111
99
  return lynx.createSelectorQuery();
112
100
  };
113
101
 
@@ -118,7 +106,7 @@ if (__JS__) {
118
106
  const timingFlag = this[NEXT_STATE][PerfSpecificKey];
119
107
  if (timingFlag) {
120
108
  globalFlushOptions.__lynx_timing_flag = timingFlag;
121
- markTimingLegacy(PerformanceTimingKeys.updateSetStateTrigger, timingFlag);
109
+ markTimingLegacy('updateSetStateTrigger', timingFlag);
122
110
  this[NEXT_STATE][PerfSpecificKey] = '';
123
111
  }
124
112
  };
@@ -56,8 +56,7 @@ export function setupLynxEnv(): void {
56
56
  let r: InitData | InitDataRaw;
57
57
  try {
58
58
  if (processorName) {
59
- r = dataProcessorDefinition?.dataProcessors?.[processorName]?.(data)
60
- ?? data;
59
+ r = dataProcessorDefinition?.dataProcessors?.[processorName]?.(data) as InitData ?? data;
61
60
  } else {
62
61
  r = dataProcessorDefinition?.defaultDataProcessor?.(data) ?? data;
63
62
  }
@@ -33,7 +33,7 @@ export const makeSyncThen = function<T>(result: T): Promise<T>['then'] {
33
33
  // Calling `then` and passing a callback is standard behavior
34
34
  // but in Lepus runtime the callback will never be called
35
35
  // So can be simplified to code below
36
- return new Promise(() => {});
36
+ return ret as Promise<TR1>;
37
37
 
38
38
  // TODO(hongzhiyuan.hzy): Avoid warning that cannot be turned-off, so the warning is commented
39
39
  // lynx.reportError(
@@ -90,27 +90,40 @@ export const loadLazyBundle: <
90
90
  r.then = makeSyncThen(result);
91
91
  return r;
92
92
  } else if (__JS__) {
93
- return new Promise((resolve, reject) => {
94
- const callback: (result: { code: number; detail: { schema: string } }) => void = result => {
95
- const { code, detail } = result;
96
- if (code === 0) {
97
- const { schema } = detail;
98
- const exports = lynxCoreInject.tt.getDynamicComponentExports(schema);
99
- // `code === 0` means that the lazy bundle has been successfully parsed. However,
100
- // its javascript files may still fail to run, which would prevent the retrieval of the exports object.
101
- if (exports) {
102
- resolve(exports as T);
103
- return;
104
- }
93
+ const resolver = withSyncResolvers<T>();
94
+
95
+ const callback: (result: { code: number; detail: { schema: string } }) => void = result => {
96
+ const { code, detail } = result;
97
+ if (code === 0) {
98
+ const { schema } = detail;
99
+ const exports = lynxCoreInject.tt.getDynamicComponentExports(schema);
100
+ // `code === 0` means that the lazy bundle has been successfully parsed. However,
101
+ // its javascript files may still fail to run, which would prevent the retrieval of the exports object.
102
+ if (exports) {
103
+ resolver.resolve(exports as T);
104
+ return;
105
105
  }
106
- reject(new Error('Lazy bundle load failed: ' + JSON.stringify(result)));
107
- };
108
- if (typeof lynx.QueryComponent === 'function') {
109
- lynx.QueryComponent(source, callback);
110
- } else {
111
- lynx.getNativeLynx().QueryComponent!(source, callback);
112
106
  }
113
- });
107
+ resolver.reject(new Error('Lazy bundle load failed: ' + JSON.stringify(result)));
108
+ };
109
+ if (typeof lynx.QueryComponent === 'function') {
110
+ lynx.QueryComponent(source, callback);
111
+ } else {
112
+ lynx.getNativeLynx().QueryComponent!(source, callback);
113
+ }
114
+
115
+ if (resolver.result !== null) {
116
+ const p = Promise.resolve(resolver.result);
117
+ p.then = makeSyncThen(resolver.result) as Promise<Awaited<T>>['then'];
118
+ return p;
119
+ } else if (resolver.error === null) {
120
+ return new Promise((_resolve, _reject) => {
121
+ resolver.resolve = _resolve;
122
+ resolver.reject = _reject;
123
+ });
124
+ } else {
125
+ return Promise.reject(resolver.error);
126
+ }
114
127
  }
115
128
 
116
129
  throw new Error('unreachable');
@@ -119,6 +132,28 @@ export const loadLazyBundle: <
119
132
  return loadLazyBundle;
120
133
  })();
121
134
 
135
+ function withSyncResolvers<T>() {
136
+ 'background-only';
137
+
138
+ const resolver: {
139
+ result: T | null;
140
+ error: Error | null;
141
+ resolve(result: T): void;
142
+ reject(error: Error): void;
143
+ } = {
144
+ resolve: (result: T): void => {
145
+ resolver.result = result;
146
+ },
147
+ reject: (error: Error): void => {
148
+ resolver.error = error;
149
+ },
150
+ result: null,
151
+ error: null,
152
+ };
153
+
154
+ return resolver;
155
+ }
156
+
122
157
  /**
123
158
  * @internal
124
159
  */
@@ -8,24 +8,24 @@ import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js';
8
8
  import { DIFF } from '../renderToOpcodes/constants.js';
9
9
  import { isSdkVersionGt } from '../utils.js';
10
10
 
11
- enum PerformanceTimingKeys {
12
- updateSetStateTrigger,
13
- updateDiffVdomStart,
14
- updateDiffVdomEnd,
11
+ const PerformanceTimingKeys = [
12
+ 'updateSetStateTrigger',
13
+ 'updateDiffVdomStart',
14
+ 'updateDiffVdomEnd',
15
15
  // updateSetStateTrigger, updateDiffVdomStart and updateDiffVdomEnd is deprecated
16
- diffVdomStart,
17
- diffVdomEnd,
18
- packChangesStart,
19
- packChangesEnd,
20
- parseChangesStart,
21
- parseChangesEnd,
22
- patchChangesStart,
23
- patchChangesEnd,
24
- hydrateParseSnapshotStart,
25
- hydrateParseSnapshotEnd,
26
- mtsRenderStart,
27
- mtsRenderEnd,
28
- }
16
+ 'diffVdomStart',
17
+ 'diffVdomEnd',
18
+ 'packChangesStart',
19
+ 'packChangesEnd',
20
+ 'parseChangesStart',
21
+ 'parseChangesEnd',
22
+ 'patchChangesStart',
23
+ 'patchChangesEnd',
24
+ 'hydrateParseSnapshotStart',
25
+ 'hydrateParseSnapshotEnd',
26
+ 'mtsRenderStart',
27
+ 'mtsRenderEnd',
28
+ ] as const;
29
29
 
30
30
  const PerformanceTimingFlags = {
31
31
  reactLynxHydrate: 'react_lynx_hydrate',
@@ -51,15 +51,15 @@ let globalPipelineOptions: PipelineOptions | undefined;
51
51
  /**
52
52
  * @deprecated used by old timing api(setState timing flag)
53
53
  */
54
- function markTimingLegacy(key: PerformanceTimingKeys, timingFlag_?: string): void {
54
+ function markTimingLegacy(key: typeof PerformanceTimingKeys[number], timingFlag_?: string): void {
55
55
  switch (key) {
56
- case PerformanceTimingKeys.updateSetStateTrigger: {
56
+ case 'updateSetStateTrigger': {
57
57
  shouldMarkDiffVdomStart = true;
58
58
  shouldMarkDiffVdomEnd = true;
59
59
  timingFlag = timingFlag_;
60
60
  break;
61
61
  }
62
- case PerformanceTimingKeys.updateDiffVdomStart: {
62
+ case 'updateDiffVdomStart': {
63
63
  /* v8 ignore start */
64
64
  if (!shouldMarkDiffVdomStart) {
65
65
  return;
@@ -68,7 +68,7 @@ function markTimingLegacy(key: PerformanceTimingKeys, timingFlag_?: string): voi
68
68
  shouldMarkDiffVdomStart = false;
69
69
  break;
70
70
  }
71
- case PerformanceTimingKeys.updateDiffVdomEnd: {
71
+ case 'updateDiffVdomEnd': {
72
72
  if (!shouldMarkDiffVdomEnd) {
73
73
  return;
74
74
  }
@@ -76,7 +76,7 @@ function markTimingLegacy(key: PerformanceTimingKeys, timingFlag_?: string): voi
76
76
  break;
77
77
  }
78
78
  }
79
- lynx.getNativeApp().markTiming?.(timingFlag!, PerformanceTimingKeys[key]);
79
+ lynx.getNativeApp().markTiming?.(timingFlag!, key);
80
80
  }
81
81
 
82
82
  function beginPipeline(needTimestamps: boolean, pipelineOrigin: PipelineOrigin, timingFlag?: string): void {
@@ -109,9 +109,9 @@ function setPipeline(pipeline: PipelineOptions | undefined): void {
109
109
  globalPipelineOptions = pipeline;
110
110
  }
111
111
 
112
- function markTiming(timestampKey: PerformanceTimingKeys, force?: boolean): void {
112
+ function markTiming(timestampKey: typeof PerformanceTimingKeys[number], force?: boolean): void {
113
113
  if (globalPipelineOptions && (force || globalPipelineOptions.needTimestamps)) {
114
- lynx.performance?._markTiming?.(globalPipelineOptions.pipelineID, PerformanceTimingKeys[timestampKey]);
114
+ lynx.performance?._markTiming?.(globalPipelineOptions.pipelineID, timestampKey);
115
115
  }
116
116
  }
117
117
 
@@ -122,10 +122,10 @@ function initTimingAPI(): void {
122
122
  if (__JS__ && __globalSnapshotPatch) {
123
123
  if (!globalPipelineOptions) {
124
124
  beginPipeline(false, PipelineOrigins.updateTriggeredByBts);
125
- markTiming(PerformanceTimingKeys.diffVdomStart, true);
125
+ markTiming('diffVdomStart', true);
126
126
  }
127
127
  if (shouldMarkDiffVdomStart) {
128
- markTimingLegacy(PerformanceTimingKeys.updateDiffVdomStart);
128
+ markTimingLegacy('updateDiffVdomStart');
129
129
  }
130
130
  }
131
131
  oldDiff?.(vnode);
@@ -136,7 +136,6 @@ function initTimingAPI(): void {
136
136
  * @internal
137
137
  */
138
138
  export {
139
- PerformanceTimingKeys,
140
139
  PerformanceTimingFlags,
141
140
  PipelineOrigins,
142
141
  PerfSpecificKey,
@@ -5,13 +5,7 @@ import { render } from 'preact';
5
5
 
6
6
  import { LifecycleConstant, NativeUpdateDataType } from '../lifecycleConstant.js';
7
7
  import type { FirstScreenData } from '../lifecycleConstant.js';
8
- import {
9
- PerformanceTimingFlags,
10
- PerformanceTimingKeys,
11
- PipelineOrigins,
12
- beginPipeline,
13
- markTiming,
14
- } from './performance.js';
8
+ import { PerformanceTimingFlags, PipelineOrigins, beginPipeline, markTiming } from './performance.js';
15
9
  import { BackgroundSnapshotInstance, hydrate } from '../backgroundSnapshot.js';
16
10
  import { runWithForce } from './runWithForce.js';
17
11
  import { destroyBackground } from '../lifecycle/destroy.js';
@@ -80,10 +74,10 @@ function onLifecycleEventImpl(type: LifecycleConstant, data: unknown): void {
80
74
  console.profile('hydrate');
81
75
  }
82
76
  beginPipeline(true, PipelineOrigins.reactLynxHydrate, PerformanceTimingFlags.reactLynxHydrate);
83
- markTiming(PerformanceTimingKeys.hydrateParseSnapshotStart);
77
+ markTiming('hydrateParseSnapshotStart');
84
78
  const before = JSON.parse(lepusSide) as SerializedSnapshotInstance;
85
- markTiming(PerformanceTimingKeys.hydrateParseSnapshotEnd);
86
- markTiming(PerformanceTimingKeys.diffVdomStart);
79
+ markTiming('hydrateParseSnapshotEnd');
80
+ markTiming('diffVdomStart');
87
81
  const snapshotPatch = hydrate(
88
82
  before,
89
83
  __root as BackgroundSnapshotInstance,
@@ -91,7 +85,7 @@ function onLifecycleEventImpl(type: LifecycleConstant, data: unknown): void {
91
85
  if (__PROFILE__) {
92
86
  console.profileEnd();
93
87
  }
94
- markTiming(PerformanceTimingKeys.diffVdomEnd);
88
+ markTiming('diffVdomEnd');
95
89
 
96
90
  // TODO: It seems `delayedEvents` and `delayedLifecycleEvents` should be merged into one array to ensure the proper order of events.
97
91
  flushDelayedLifecycleEvents();
@@ -141,6 +135,11 @@ function onLifecycleEventImpl(type: LifecycleConstant, data: unknown): void {
141
135
  lynx.getJSModule('GlobalEventEmitter').trigger(eventName, params);
142
136
  break;
143
137
  }
138
+ case LifecycleConstant.publishEvent: {
139
+ const { handlerName, data: d } = data as { handlerName: string; data: unknown };
140
+ lynxCoreInject.tt.publishEvent(handlerName, d);
141
+ break;
142
+ }
144
143
  }
145
144
  }
146
145