@lynx-js/react 0.109.1 → 0.110.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 (143) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/package.json +2 -2
  3. package/refresh/.turbo/turbo-build.log +1 -1
  4. package/refresh/package.json +1 -1
  5. package/runtime/lib/backgroundSnapshot.d.ts +2 -1
  6. package/runtime/lib/backgroundSnapshot.js +65 -42
  7. package/runtime/lib/backgroundSnapshot.js.map +1 -1
  8. package/runtime/lib/hooks/react.js +3 -3
  9. package/runtime/lib/hooks/react.js.map +1 -1
  10. package/runtime/lib/lifecycle/destroy.js +1 -0
  11. package/runtime/lib/lifecycle/destroy.js.map +1 -1
  12. package/runtime/lib/lifecycle/event/delayEvents.js +3 -0
  13. package/runtime/lib/lifecycle/event/delayEvents.js.map +1 -1
  14. package/runtime/lib/lifecycle/event/delayLifecycleEvents.d.ts +3 -2
  15. package/runtime/lib/lifecycle/event/delayLifecycleEvents.js +1 -12
  16. package/runtime/lib/lifecycle/event/delayLifecycleEvents.js.map +1 -1
  17. package/runtime/lib/lifecycle/event/jsReady.d.ts +1 -1
  18. package/runtime/lib/lifecycle/event/jsReady.js +3 -2
  19. package/runtime/lib/lifecycle/event/jsReady.js.map +1 -1
  20. package/runtime/lib/lifecycle/patch/commit.d.ts +0 -2
  21. package/runtime/lib/lifecycle/patch/commit.js +8 -36
  22. package/runtime/lib/lifecycle/patch/commit.js.map +1 -1
  23. package/runtime/lib/lifecycle/patch/error.d.ts +8 -0
  24. package/runtime/lib/lifecycle/patch/error.js +47 -0
  25. package/runtime/lib/lifecycle/patch/error.js.map +1 -0
  26. package/runtime/lib/lifecycle/patch/isMainThreadHydrationFinished.js +3 -0
  27. package/runtime/lib/lifecycle/patch/isMainThreadHydrationFinished.js.map +1 -1
  28. package/runtime/lib/lifecycle/patch/snapshotPatch.d.ts +2 -2
  29. package/runtime/lib/lifecycle/patch/snapshotPatch.js.map +1 -1
  30. package/runtime/lib/lifecycle/patch/snapshotPatchApply.js +18 -11
  31. package/runtime/lib/lifecycle/patch/snapshotPatchApply.js.map +1 -1
  32. package/runtime/lib/lifecycle/patch/updateMainThread.d.ts +0 -1
  33. package/runtime/lib/lifecycle/patch/updateMainThread.js +6 -13
  34. package/runtime/lib/lifecycle/patch/updateMainThread.js.map +1 -1
  35. package/runtime/lib/lifecycle/ref/delay.d.ts +31 -0
  36. package/runtime/lib/lifecycle/ref/delay.js +80 -0
  37. package/runtime/lib/lifecycle/ref/delay.js.map +1 -0
  38. package/runtime/lib/lifecycle/reload.d.ts +1 -1
  39. package/runtime/lib/lifecycle/reload.js +7 -4
  40. package/runtime/lib/lifecycle/reload.js.map +1 -1
  41. package/runtime/lib/lifecycle/render.js +3 -2
  42. package/runtime/lib/lifecycle/render.js.map +1 -1
  43. package/runtime/lib/lifecycleConstant.d.ts +10 -7
  44. package/runtime/lib/lifecycleConstant.js +8 -8
  45. package/runtime/lib/lifecycleConstant.js.map +1 -1
  46. package/runtime/lib/list.d.ts +1 -1
  47. package/runtime/lib/list.js +9 -7
  48. package/runtime/lib/list.js.map +1 -1
  49. package/runtime/lib/lynx/calledByNative.js +8 -5
  50. package/runtime/lib/lynx/calledByNative.js.map +1 -1
  51. package/runtime/lib/lynx/component.js +7 -0
  52. package/runtime/lib/lynx/component.js.map +1 -1
  53. package/runtime/lib/lynx/dynamic-js.d.ts +5 -1
  54. package/runtime/lib/lynx/dynamic-js.js +1 -0
  55. package/runtime/lib/lynx/dynamic-js.js.map +1 -1
  56. package/runtime/lib/lynx/env.d.ts +1 -1
  57. package/runtime/lib/lynx/env.js +13 -13
  58. package/runtime/lib/lynx/env.js.map +1 -1
  59. package/runtime/lib/lynx/lazy-bundle.js +7 -5
  60. package/runtime/lib/lynx/lazy-bundle.js.map +1 -1
  61. package/runtime/lib/lynx/performance.js +1 -1
  62. package/runtime/lib/lynx/performance.js.map +1 -1
  63. package/runtime/lib/lynx/runWithForce.js +3 -0
  64. package/runtime/lib/lynx/runWithForce.js.map +1 -1
  65. package/runtime/lib/lynx/tt.js +12 -33
  66. package/runtime/lib/lynx/tt.js.map +1 -1
  67. package/runtime/lib/lynx-api.d.ts +1 -1
  68. package/runtime/lib/lynx.js +5 -6
  69. package/runtime/lib/lynx.js.map +1 -1
  70. package/runtime/lib/snapshot/ref.d.ts +14 -9
  71. package/runtime/lib/snapshot/ref.js +64 -73
  72. package/runtime/lib/snapshot/ref.js.map +1 -1
  73. package/runtime/lib/snapshot/spread.js +9 -8
  74. package/runtime/lib/snapshot/spread.js.map +1 -1
  75. package/runtime/lib/snapshot/workletRef.d.ts +3 -3
  76. package/runtime/lib/snapshot/workletRef.js +27 -8
  77. package/runtime/lib/snapshot/workletRef.js.map +1 -1
  78. package/runtime/lib/snapshot.d.ts +4 -4
  79. package/runtime/lib/snapshot.js +28 -13
  80. package/runtime/lib/snapshot.js.map +1 -1
  81. package/runtime/lib/snapshotInstanceHydrationMap.d.ts +9 -0
  82. package/runtime/lib/snapshotInstanceHydrationMap.js +16 -0
  83. package/runtime/lib/snapshotInstanceHydrationMap.js.map +1 -0
  84. package/runtime/lib/worklet/workletRef.js +1 -2
  85. package/runtime/lib/worklet/workletRef.js.map +1 -1
  86. package/runtime/src/backgroundSnapshot.ts +74 -47
  87. package/runtime/src/hooks/react.ts +3 -3
  88. package/runtime/src/lifecycle/destroy.ts +1 -0
  89. package/runtime/src/lifecycle/event/delayEvents.ts +3 -0
  90. package/runtime/src/lifecycle/event/delayLifecycleEvents.ts +7 -13
  91. package/runtime/src/lifecycle/event/jsReady.ts +4 -3
  92. package/runtime/src/lifecycle/patch/commit.ts +10 -41
  93. package/runtime/src/lifecycle/patch/error.ts +61 -0
  94. package/runtime/src/lifecycle/patch/isMainThreadHydrationFinished.ts +3 -0
  95. package/runtime/src/lifecycle/patch/snapshotPatch.ts +2 -2
  96. package/runtime/src/lifecycle/patch/snapshotPatchApply.ts +35 -28
  97. package/runtime/src/lifecycle/patch/updateMainThread.ts +7 -16
  98. package/runtime/src/lifecycle/ref/delay.ts +99 -0
  99. package/runtime/src/lifecycle/reload.ts +9 -6
  100. package/runtime/src/lifecycle/render.ts +3 -2
  101. package/runtime/src/lifecycleConstant.ts +11 -7
  102. package/runtime/src/list.ts +9 -7
  103. package/runtime/src/lynx/calledByNative.ts +14 -9
  104. package/runtime/src/lynx/component.ts +9 -0
  105. package/runtime/src/lynx/dynamic-js.ts +5 -1
  106. package/runtime/src/lynx/env.ts +17 -17
  107. package/runtime/src/lynx/lazy-bundle.ts +22 -14
  108. package/runtime/src/lynx/performance.ts +1 -1
  109. package/runtime/src/lynx/runWithForce.ts +9 -5
  110. package/runtime/src/lynx/tt.ts +19 -37
  111. package/runtime/src/lynx-api.ts +1 -1
  112. package/runtime/src/lynx.ts +6 -6
  113. package/runtime/src/snapshot/ref.ts +77 -87
  114. package/runtime/src/snapshot/spread.ts +8 -8
  115. package/runtime/src/snapshot/workletRef.ts +35 -9
  116. package/runtime/src/snapshot.ts +39 -20
  117. package/runtime/src/snapshotInstanceHydrationMap.ts +17 -0
  118. package/runtime/src/worklet/workletRef.ts +1 -2
  119. package/testing-library/dist/env/vitest.js +10 -8
  120. package/testing-library/dist/index.js +3 -3
  121. package/testing-library/dist/pure.js +93 -92
  122. package/testing-library/dist/vitest-global-setup.js +41 -41
  123. package/testing-library/dist/vitest.config.js +17 -14
  124. package/transform/dist/wasm.cjs +1 -1
  125. package/worklet-runtime/dist/dev.js +1 -4
  126. package/worklet-runtime/dist/main.js +0 -4
  127. package/worklet-runtime/lib/bindings/bindings.d.ts +1 -1
  128. package/worklet-runtime/lib/bindings/bindings.js +1 -26
  129. package/worklet-runtime/lib/bindings/bindings.js.map +1 -1
  130. package/worklet-runtime/lib/bindings/index.d.ts +2 -1
  131. package/worklet-runtime/lib/bindings/index.js +2 -1
  132. package/worklet-runtime/lib/bindings/index.js.map +1 -1
  133. package/worklet-runtime/lib/bindings/observers.d.ts +14 -0
  134. package/worklet-runtime/lib/bindings/observers.js +31 -0
  135. package/worklet-runtime/lib/bindings/observers.js.map +1 -0
  136. package/worklet-runtime/lib/hydrate.js +0 -5
  137. package/worklet-runtime/lib/hydrate.js.map +1 -1
  138. package/runtime/lib/lifecycle/delayUnmount.d.ts +0 -8
  139. package/runtime/lib/lifecycle/delayUnmount.js +0 -65
  140. package/runtime/lib/lifecycle/delayUnmount.js.map +0 -1
  141. package/runtime/src/lifecycle/delayUnmount.ts +0 -77
  142. package/worklet-runtime/dist/dev.js.map +0 -8
  143. package/worklet-runtime/dist/main.js.map +0 -8
@@ -9,15 +9,16 @@ import { LifecycleConstant } from '../lifecycleConstant.js';
9
9
  import { __pendingListUpdates } from '../list.js';
10
10
  import { ssrHydrateByOpcodes } from '../opcodes.js';
11
11
  import { __root, setRoot } from '../root.js';
12
- import { takeGlobalRefPatchMap } from '../snapshot/ref.js';
13
12
  import { SnapshotInstance, __page, setupPage } from '../snapshot.js';
14
13
  import { isEmptyObject } from '../utils.js';
15
14
  import { PerformanceTimingKeys, markTiming, setPipeline } from './performance.js';
15
+ import { applyRefQueue } from '../snapshot/workletRef.js';
16
16
 
17
17
  function ssrEncode() {
18
18
  const { __opcodes } = __root;
19
19
  delete __root.__opcodes;
20
20
 
21
+ // eslint-disable-next-line @typescript-eslint/unbound-method
21
22
  const oldToJSON = SnapshotInstance.prototype.toJSON;
22
23
  SnapshotInstance.prototype.toJSON = function(this: SnapshotInstance): any {
23
24
  return [
@@ -44,8 +45,13 @@ function ssrHydrate(info: string) {
44
45
  setupPage(nativePage);
45
46
  const refsMap = __GetTemplateParts(nativePage);
46
47
 
47
- const { __opcodes, __root_values } = JSON.parse(info);
48
- __root_values && __root.setAttribute('values', __root_values);
48
+ const { __opcodes, __root_values } = JSON.parse(info) as {
49
+ __opcodes: unknown[];
50
+ __root_values: unknown[] | undefined;
51
+ };
52
+ if (__root_values) {
53
+ __root.setAttribute('values', __root_values);
54
+ }
49
55
  ssrHydrateByOpcodes(__opcodes, __root as SnapshotInstance, refsMap);
50
56
 
51
57
  (__root as SnapshotInstance).__elements = [nativePage];
@@ -74,11 +80,11 @@ function injectCalledByNative(): void {
74
80
  });
75
81
  }
76
82
 
77
- function renderPage(data: any): void {
83
+ function renderPage(data: Record<string, unknown> | undefined): void {
78
84
  // reset `jsReady` state
79
85
  resetJSReady();
80
86
 
81
- lynx.__initData = data || {};
87
+ lynx.__initData = data ?? {};
82
88
 
83
89
  setupPage(__CreatePage('0', 0));
84
90
  (__root as SnapshotInstance).ensureElements();
@@ -88,13 +94,14 @@ function renderPage(data: any): void {
88
94
  // always call this before `__FlushElementTree`
89
95
  // (There is an implicit `__FlushElementTree` in `renderPage`)
90
96
  __pendingListUpdates.flush();
97
+ applyRefQueue();
91
98
 
92
99
  if (__FIRST_SCREEN_SYNC_TIMING__ === 'immediately') {
93
100
  jsReady();
94
101
  }
95
102
  }
96
103
 
97
- function updatePage(data: any, options?: UpdatePageOption): void {
104
+ function updatePage(data: Record<string, unknown> | undefined, options?: UpdatePageOption): void {
98
105
  if (options?.reloadTemplate) {
99
106
  reloadMainThread(data, options);
100
107
  return;
@@ -118,9 +125,6 @@ function updatePage(data: any, options?: UpdatePageOption): void {
118
125
  markTiming(PerformanceTimingKeys.updateDiffVdomStart);
119
126
  {
120
127
  __pendingListUpdates.clear();
121
-
122
- // ignore ref & unref before jsReady
123
- takeGlobalRefPatchMap();
124
128
  renderMainThread();
125
129
  // As said by codename `jsReadyEventIdSwap`, this swap will only be used for event remap,
126
130
  // because ref & unref cause by previous render will be ignored
@@ -132,6 +136,7 @@ function updatePage(data: any, options?: UpdatePageOption): void {
132
136
 
133
137
  // always call this before `__FlushElementTree`
134
138
  __pendingListUpdates.flush();
139
+ applyRefQueue();
135
140
  }
136
141
  markTiming(PerformanceTimingKeys.updateDiffVdomEnd);
137
142
  }
@@ -1,6 +1,9 @@
1
1
  // Copyright 2024 The Lynx Authors. All rights reserved.
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
+
5
+ /* eslint-disable */
6
+
4
7
  import { Component } from 'preact';
5
8
 
6
9
  import { PerfSpecificKey, PerformanceTimingKeys, markTimingLegacy } from './performance.js';
@@ -20,11 +23,14 @@ if (__JS__) {
20
23
  ),
21
24
  );
22
25
  }
26
+ // @ts-expect-error hack lynx-kernel
23
27
  return lynxCoreInject.tt._reactLynx.ReactComponent.prototype.getNodeRef
24
28
  .call(
25
29
  {
26
30
  _type: '',
31
+ // @ts-expect-error hack lynx-kernel
27
32
  _nativeApp: lynxCoreInject.tt._nativeApp,
33
+ // @ts-expect-error hack lynx-kernel
28
34
  _uiModule: lynxCoreInject.tt._nativeApp.nativeModuleProxy.LynxUIMethodModule,
29
35
  _reactAppInstance: lynxCoreInject.tt,
30
36
  },
@@ -41,11 +47,14 @@ if (__JS__) {
41
47
  ),
42
48
  );
43
49
  }
50
+ // @ts-expect-error hack lynx-kernel
44
51
  return lynxCoreInject.tt._reactLynx.ReactComponent.prototype
45
52
  .getNodeRefFromRoot.call(
46
53
  {
47
54
  _type: '',
55
+ // @ts-expect-error hack lynx-kernel
48
56
  _nativeApp: lynxCoreInject.tt._nativeApp,
57
+ // @ts-expect-error hack lynx-kernel
49
58
  _uiModule: lynxCoreInject.tt._nativeApp.nativeModuleProxy.LynxUIMethodModule,
50
59
  _reactAppInstance: lynxCoreInject.tt,
51
60
  },
@@ -9,6 +9,7 @@ export function loadDynamicJS<T>(url: string): Promise<T> {
9
9
  new Error(`A dynamic import (to "${url}") is leaked to Lepus bundle.`),
10
10
  { errorCode: 202 },
11
11
  );
12
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
12
13
  return Promise.reject();
13
14
  }
14
15
  return new Promise((resolve, reject) => {
@@ -22,7 +23,10 @@ export function loadDynamicJS<T>(url: string): Promise<T> {
22
23
  });
23
24
  }
24
25
 
25
- export function __dynamicImport<T>(url: string, options?: any): Promise<T> {
26
+ export function __dynamicImport<T>(
27
+ url: string,
28
+ options?: { with?: { type?: 'component' | 'tsx' | 'jsx' } },
29
+ ): Promise<T> {
26
30
  const t = options?.with?.type;
27
31
  if (t === 'component' || t === 'tsx' || t === 'jsx') {
28
32
  return loadLazyBundle<any>(url);
@@ -1,25 +1,24 @@
1
1
  // Copyright 2024 The Lynx Authors. All rights reserved.
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
- import type { DataProcessorDefinition } from '../lynx-api.js';
4
+ import type { DataProcessorDefinition, InitData, InitDataRaw } from '../lynx-api.js';
5
5
 
6
- export function setupLynxTestingEnv(): void {
6
+ export function setupLynxEnv(): void {
7
7
  if (!__LEPUS__) {
8
8
  const { initData, updateData } = lynxCoreInject.tt._params;
9
- // @ts-ignore
10
9
  lynx.__initData = { ...initData, ...updateData };
11
10
  lynx.registerDataProcessors = function() {};
12
11
  }
13
12
 
14
13
  if (__LEPUS__) {
15
- // @ts-ignore
16
14
  lynx.__initData = {
17
15
  /* available only in renderPage */
18
16
  };
19
- // @ts-ignore
20
- globalThis.SystemInfo = lynx.SystemInfo || {};
17
+ // @ts-expect-error no type for lynx.SystemInfo
18
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
19
+ globalThis.SystemInfo = lynx.SystemInfo ?? {};
21
20
 
22
- lynx.reportError = function(e: any) {
21
+ lynx.reportError = function(e: Error) {
23
22
  _ReportError(e, {
24
23
  errorCode: 1101, // ErrCode::LYNX_ERROR_CODE_LEPUS in Lynx/base/debug/error_code.h
25
24
  });
@@ -33,13 +32,14 @@ export function setupLynxTestingEnv(): void {
33
32
  };
34
33
 
35
34
  {
35
+ // eslint-disable-next-line unicorn/consistent-function-scoping
36
36
  function __name(empty: string) {
37
37
  return `Native${empty}Modules`;
38
38
  }
39
39
  // TODO(hongzhiyuan.hzy): make sure this is run before any other code (especially code access `NativeModules`)
40
- // @ts-ignore
40
+ // @ts-expect-error hack
41
41
  if (typeof globalThis[__name('')] === 'undefined') {
42
- // @ts-ignore
42
+ // @ts-expect-error hack
43
43
  globalThis[__name('')] = undefined;
44
44
  }
45
45
  }
@@ -48,13 +48,12 @@ export function setupLynxTestingEnv(): void {
48
48
  dataProcessorDefinition?: DataProcessorDefinition,
49
49
  ) {
50
50
  let hasDefaultDataProcessorExecuted = false;
51
- // @ts-ignore
52
51
  globalThis.processData = (data, processorName) => {
53
52
  if (__PROFILE__) {
54
53
  console.profile('processData');
55
54
  }
56
55
 
57
- let r;
56
+ let r: InitData | InitDataRaw;
58
57
  try {
59
58
  if (processorName) {
60
59
  r = dataProcessorDefinition?.dataProcessors?.[processorName]?.(data)
@@ -63,7 +62,7 @@ export function setupLynxTestingEnv(): void {
63
62
  r = dataProcessorDefinition?.defaultDataProcessor?.(data) ?? data;
64
63
  }
65
64
  } catch (e: any) {
66
- lynx.reportError(e);
65
+ lynx.reportError(e as Error);
67
66
  // when there is an error
68
67
  // we should perform like dataProcessor returns nothing
69
68
  // so use `{}` rather than `data`
@@ -75,20 +74,22 @@ export function setupLynxTestingEnv(): void {
75
74
  }
76
75
 
77
76
  if (hasDefaultDataProcessorExecuted === false) {
78
- // @ts-ignore
77
+ // @ts-expect-error todo: add types to i18n logic
79
78
  if (globalThis.__I18N_RESOURCE_TRANSLATION__) {
80
79
  r = {
81
80
  ...r,
82
- // @ts-ignore
81
+ // @ts-expect-error todo: add types to i18n logic
82
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
83
83
  __I18N_RESOURCE_TRANSLATION__: globalThis.__I18N_RESOURCE_TRANSLATION__,
84
84
  };
85
85
  }
86
86
 
87
- // @ts-ignore
87
+ // @ts-expect-error todo: add types to __EXTRACT_STR__
88
88
  if (__EXTRACT_STR__) {
89
89
  r = {
90
90
  ...r,
91
- // @ts-ignore
91
+ // @ts-expect-error todo: add types to __EXTRACT_STR__
92
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
92
93
  _EXTRACT_STR: __EXTRACT_STR_IDENT_FLAG__,
93
94
  };
94
95
  }
@@ -100,7 +101,6 @@ export function setupLynxTestingEnv(): void {
100
101
  }
101
102
 
102
103
  return r;
103
- // TODO
104
104
  };
105
105
  };
106
106
 
@@ -9,18 +9,24 @@ import { Fragment, lazy as backgroundLazy, createElement } from 'preact/compat';
9
9
  * const App2 = lazy(() => import("./x").then(({App2}) => ({default: App2})))
10
10
  * @internal
11
11
  */
12
- export const makeSyncThen = function<T>(result: T) {
13
- return function(this: Promise<T>, onF?: Function): Promise<T> {
12
+ export const makeSyncThen = function<T>(result: T): Promise<T>['then'] {
13
+ return function<TR1 = T, TR2 = never>(
14
+ this: Promise<T>,
15
+ onF?: ((value: T) => TR1 | PromiseLike<TR1>) | null,
16
+ _onR?: ((reason: any) => TR2 | PromiseLike<TR2>) | null,
17
+ ): Promise<TR1 | TR2> {
14
18
  if (onF) {
15
- let ret;
19
+ let ret: TR1 | PromiseLike<TR1>;
16
20
  try {
17
21
  ret = onF(result);
18
22
  } catch (e) {
19
- return Promise.reject(e);
23
+ // if (onR) {
24
+ // return Promise.resolve(onR(e));
25
+ // }
26
+ return Promise.reject(e as Error);
20
27
  }
21
28
 
22
- // @ts-ignore
23
- if (ret && typeof ret.then === 'function' /* `thenable` object */) {
29
+ if (ret && typeof (ret as PromiseLike<TR1>).then === 'function' /* `thenable` object */) {
24
30
  // lazy(() =>
25
31
  // import("./x").then(() => new Promise(...))
26
32
  // )
@@ -39,12 +45,14 @@ export const makeSyncThen = function<T>(result: T) {
39
45
  }
40
46
 
41
47
  const p = Promise.resolve(ret);
42
- // @ts-ignore
43
- p.then = makeSyncThen(ret);
44
- return p;
48
+
49
+ const then = makeSyncThen(ret as TR1);
50
+ p.then = then as Promise<Awaited<TR1>>['then'];
51
+
52
+ return p as Promise<TR1 | TR2>;
45
53
  }
46
54
 
47
- return this;
55
+ return this as Promise<TR1 | TR2>;
48
56
  };
49
57
  };
50
58
 
@@ -66,7 +74,7 @@ export const loadLazyBundle: <
66
74
  const query = __QueryComponent(source);
67
75
  let result: T;
68
76
  try {
69
- result = query.evalResult;
77
+ result = query.evalResult as T;
70
78
  } catch (e) {
71
79
  // Here we cannot return a rejected promise
72
80
  // (which will eventually be an unhandled rejection and cause unnecessary redbox)
@@ -79,12 +87,11 @@ export const loadLazyBundle: <
79
87
  // Why we should modify the implementation of `then`?
80
88
  // We should make it `sync` so lepus first-screen render can use result above instantly
81
89
  // We also should keep promise shape
82
- // @ts-ignore
83
90
  r.then = makeSyncThen(result);
84
91
  return r;
85
92
  } else if (__JS__) {
86
93
  return new Promise((resolve, reject) => {
87
- const callback: (result: any) => void = result => {
94
+ const callback: (result: { code: number; detail: { schema: string } }) => void = result => {
88
95
  const { code, detail } = result;
89
96
  if (code === 0) {
90
97
  const { schema } = detail;
@@ -92,7 +99,7 @@ export const loadLazyBundle: <
92
99
  // `code === 0` means that the lazy bundle has been successfully parsed. However,
93
100
  // its javascript files may still fail to run, which would prevent the retrieval of the exports object.
94
101
  if (exports) {
95
- resolve(exports);
102
+ resolve(exports as T);
96
103
  return;
97
104
  }
98
105
  }
@@ -121,6 +128,7 @@ export function mainThreadLazy<T>(loader: () => Promise<{ default: T } | T>) {
121
128
  function _Lazy(props: any) {
122
129
  try {
123
130
  // @ts-expect-error `Lazy` returned from `backgroundLazy` should be a FC
131
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
124
132
  return Lazy(props);
125
133
  } catch (e) {
126
134
  // We should never throw at mainThread
@@ -4,8 +4,8 @@
4
4
  import { options } from 'preact';
5
5
  import type { VNode } from 'preact';
6
6
 
7
- import { DIFF } from '../renderToOpcodes/constants.js';
8
7
  import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js';
8
+ import { DIFF } from '../renderToOpcodes/constants.js';
9
9
  import { isSdkVersionGt } from '../utils.js';
10
10
 
11
11
  enum PerformanceTimingKeys {
@@ -1,5 +1,9 @@
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.
1
4
  import { options } from 'preact';
2
- import type { VNode } from 'preact';
5
+ import type { Component, VNode } from 'preact';
6
+
3
7
  import { COMPONENT, DIFF, DIFFED, FORCE } from '../renderToOpcodes/constants.js';
4
8
 
5
9
  const sForcedVNode = Symbol('FORCE');
@@ -8,7 +12,7 @@ type PatchedVNode = VNode & { [sForcedVNode]?: true };
8
12
 
9
13
  export function runWithForce(cb: () => void): void {
10
14
  // save vnode and its `_component` in WeakMap
11
- const m = new WeakMap<VNode, any>();
15
+ const m = new WeakMap<VNode, Component>();
12
16
 
13
17
  const oldDiff = options[DIFF];
14
18
 
@@ -22,13 +26,13 @@ export function runWithForce(cb: () => void): void {
22
26
  // but it will be set later
23
27
  Object.defineProperty(vnode, COMPONENT, {
24
28
  configurable: true,
25
- set(c) {
29
+ set(c: Component) {
26
30
  m.set(vnode, c);
27
31
  if (c) {
28
32
  c[FORCE] = true;
29
33
  }
30
34
  },
31
- get() {
35
+ get(): Component | undefined {
32
36
  return m.get(vnode);
33
37
  },
34
38
  });
@@ -50,7 +54,7 @@ export function runWithForce(cb: () => void): void {
50
54
  delete vnode[COMPONENT];
51
55
  delete vnode[sForcedVNode];
52
56
  // restore
53
- vnode[COMPONENT] = m.get(vnode);
57
+ vnode[COMPONENT] = m.get(vnode)!;
54
58
  }
55
59
  };
56
60
 
@@ -4,6 +4,7 @@
4
4
  import { render } from 'preact';
5
5
 
6
6
  import { LifecycleConstant, NativeUpdateDataType } from '../lifecycleConstant.js';
7
+ import type { FirstScreenData } from '../lifecycleConstant.js';
7
8
  import {
8
9
  PerformanceTimingFlags,
9
10
  PerformanceTimingKeys,
@@ -18,17 +19,18 @@ import { delayedEvents, delayedPublishEvent } from '../lifecycle/event/delayEven
18
19
  import { delayLifecycleEvent, delayedLifecycleEvents } from '../lifecycle/event/delayLifecycleEvents.js';
19
20
  import { commitPatchUpdate, genCommitTaskId, globalCommitTaskMap } from '../lifecycle/patch/commit.js';
20
21
  import type { PatchList } from '../lifecycle/patch/commit.js';
22
+ import { removeCtxNotFoundEventListener } from '../lifecycle/patch/error.js';
23
+ import { runDelayedUiOps } from '../lifecycle/ref/delay.js';
21
24
  import { reloadBackground } from '../lifecycle/reload.js';
22
25
  import { CHILDREN } from '../renderToOpcodes/constants.js';
23
26
  import { __root } from '../root.js';
24
- import { globalRefsToSet, updateBackgroundRefs } from '../snapshot/ref.js';
25
27
  import { backgroundSnapshotInstanceManager } from '../snapshot.js';
28
+ import type { SerializedSnapshotInstance } from '../snapshot.js';
26
29
  import { destroyWorklet } from '../worklet/destroy.js';
27
30
 
28
31
  export { runWithForce };
29
32
 
30
33
  function injectTt(): void {
31
- // @ts-ignore
32
34
  const tt = lynxCoreInject.tt;
33
35
  tt.OnLifecycleEvent = onLifecycleEvent;
34
36
  tt.publishEvent = delayedPublishEvent;
@@ -36,6 +38,7 @@ function injectTt(): void {
36
38
  tt.callDestroyLifetimeFun = () => {
37
39
  destroyWorklet();
38
40
  destroyBackground();
41
+ removeCtxNotFoundEventListener();
39
42
  };
40
43
  tt.updateGlobalProps = updateGlobalProps;
41
44
  tt.updateCardData = updateCardData;
@@ -45,7 +48,7 @@ function injectTt(): void {
45
48
  };
46
49
  }
47
50
 
48
- function onLifecycleEvent([type, data]: [string, any]) {
51
+ function onLifecycleEvent([type, data]: [LifecycleConstant, unknown]) {
49
52
  const hasRootRendered = CHILDREN in __root;
50
53
  // never called `render(<App/>, __root)`
51
54
  // happens if user call `root.render()` async
@@ -69,16 +72,16 @@ function onLifecycleEvent([type, data]: [string, any]) {
69
72
  }
70
73
  }
71
74
 
72
- function onLifecycleEventImpl(type: string, data: any): void {
75
+ function onLifecycleEventImpl(type: LifecycleConstant, data: unknown): void {
73
76
  switch (type) {
74
77
  case LifecycleConstant.firstScreen: {
75
- const { root: lepusSide, refPatch, jsReadyEventIdSwap } = data;
78
+ const { root: lepusSide, jsReadyEventIdSwap } = data as FirstScreenData;
76
79
  if (__PROFILE__) {
77
80
  console.profile('hydrate');
78
81
  }
79
82
  beginPipeline(true, PipelineOrigins.reactLynxHydrate, PerformanceTimingFlags.reactLynxHydrate);
80
83
  markTiming(PerformanceTimingKeys.hydrateParseSnapshotStart);
81
- const before = JSON.parse(lepusSide);
84
+ const before = JSON.parse(lepusSide) as SerializedSnapshotInstance;
82
85
  markTiming(PerformanceTimingKeys.hydrateParseSnapshotEnd);
83
86
  markTiming(PerformanceTimingKeys.diffVdomStart);
84
87
  const snapshotPatch = hydrate(
@@ -95,8 +98,9 @@ function onLifecycleEventImpl(type: string, data: any): void {
95
98
  if (delayedEvents) {
96
99
  delayedEvents.forEach((args) => {
97
100
  const [handlerName, data] = args;
101
+ // eslint-disable-next-line prefer-const
98
102
  let [idStr, ...rest] = handlerName.split(':');
99
- while (jsReadyEventIdSwap[idStr!]) idStr = jsReadyEventIdSwap[idStr!];
103
+ while (jsReadyEventIdSwap[idStr!]) idStr = jsReadyEventIdSwap[idStr!]?.toString();
100
104
  try {
101
105
  publishEvent([idStr, ...rest].join(':'), data);
102
106
  } catch (e) {
@@ -109,16 +113,6 @@ function onLifecycleEventImpl(type: string, data: any): void {
109
113
  lynxCoreInject.tt.publishEvent = publishEvent;
110
114
  lynxCoreInject.tt.publicComponentEvent = publicComponentEvent;
111
115
 
112
- if (__PROFILE__) {
113
- console.profile('patchRef');
114
- }
115
- if (refPatch) {
116
- globalRefsToSet.set(0, JSON.parse(refPatch));
117
- updateBackgroundRefs(0);
118
- }
119
- if (__PROFILE__) {
120
- console.profileEnd();
121
- }
122
116
  // console.debug("********** After hydration:");
123
117
  // printSnapshotInstance(__root as BackgroundSnapshotInstance);
124
118
  if (__PROFILE__) {
@@ -131,7 +125,6 @@ function onLifecycleEventImpl(type: string, data: any): void {
131
125
  const obj = commitPatchUpdate(patchList, { isHydration: true });
132
126
 
133
127
  lynx.getNativeApp().callLepusMethod(LifecycleConstant.patchUpdate, obj, () => {
134
- updateBackgroundRefs(commitTaskId);
135
128
  globalCommitTaskMap.forEach((commitTask, id) => {
136
129
  if (id > commitTaskId) {
137
130
  return;
@@ -140,23 +133,14 @@ function onLifecycleEventImpl(type: string, data: any): void {
140
133
  globalCommitTaskMap.delete(id);
141
134
  });
142
135
  });
136
+ runDelayedUiOps();
143
137
  break;
144
138
  }
145
139
  case LifecycleConstant.globalEventFromLepus: {
146
- const [eventName, params] = data;
140
+ const [eventName, params] = data as [string, Record<string, any>];
147
141
  lynx.getJSModule('GlobalEventEmitter').trigger(eventName, params);
148
142
  break;
149
143
  }
150
- case LifecycleConstant.ref: {
151
- const { refPatch, commitTaskId } = data;
152
- if (commitTaskId) {
153
- globalRefsToSet.set(commitTaskId, JSON.parse(refPatch));
154
- } else {
155
- globalRefsToSet.set(0, JSON.parse(refPatch));
156
- updateBackgroundRefs(0);
157
- }
158
- break;
159
- }
160
144
  }
161
145
  }
162
146
 
@@ -175,14 +159,13 @@ function flushDelayedLifecycleEvents(): void {
175
159
  }
176
160
 
177
161
  function publishEvent(handlerName: string, data: unknown) {
178
- // TODO: delay js events until js ready
179
162
  lynxCoreInject.tt.callBeforePublishEvent?.(data);
180
163
  const eventHandler = backgroundSnapshotInstanceManager.getValueBySign(
181
164
  handlerName,
182
165
  );
183
166
  if (eventHandler) {
184
167
  try {
185
- (eventHandler as Function)(data);
168
+ (eventHandler as (...args: unknown[]) => void)(data);
186
169
  } catch (e) {
187
170
  lynx.reportError(e as Error);
188
171
  }
@@ -204,10 +187,11 @@ function updateGlobalProps(newData: Record<string, any>): void {
204
187
  // can be batched with updateFromRoot
205
188
  // This is already done because updateFromRoot will consume all dirty flags marked by
206
189
  // the setState, and setState's flush will be a noop. No extra diffs will be needed.
207
- Promise.resolve().then(() => {
190
+ void Promise.resolve().then(() => {
191
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
208
192
  runWithForce(() => render(__root.__jsx, __root as any));
209
193
  });
210
- lynxCoreInject.tt.GlobalEventEmitter.emit('onGlobalPropsChanged');
194
+ lynxCoreInject.tt.GlobalEventEmitter.emit('onGlobalPropsChanged', undefined);
211
195
  }
212
196
 
213
197
  function updateCardData(newData: Record<string, any>, options?: Record<string, any>): void {
@@ -219,16 +203,14 @@ function updateCardData(newData: Record<string, any>, options?: Record<string, a
219
203
  ),
220
204
  );
221
205
  }
222
- const { type = NativeUpdateDataType.UPDATE } = options || {};
206
+ const { type = NativeUpdateDataType.UPDATE } = options ?? {};
223
207
  if (type == NativeUpdateDataType.RESET) {
224
- // @ts-ignore
225
208
  lynx.__initData = {};
226
209
  }
227
210
 
228
211
  // COW when modify `lynx.__initData` to make sure Provider & Consumer works
229
- // @ts-ignore
230
212
  lynx.__initData = Object.assign({}, lynx.__initData, restNewData);
231
- lynxCoreInject.tt.GlobalEventEmitter.emit('onDataChanged');
213
+ lynxCoreInject.tt.GlobalEventEmitter.emit('onDataChanged', undefined);
232
214
  }
233
215
 
234
216
  export { injectTt, flushDelayedLifecycleEvents };
@@ -235,7 +235,7 @@ export interface DataProcessorDefinition {
235
235
  *
236
236
  * @public
237
237
  */
238
- dataProcessors?: Record<string, Function>;
238
+ dataProcessors?: Record<string, ((rawInitData: InitDataRaw) => InitData)>;
239
239
  }
240
240
 
241
241
  /**
@@ -7,14 +7,15 @@ import './hooks/react.js';
7
7
 
8
8
  import { initProfileHook } from './debug/profile.js';
9
9
  import { document, setupBackgroundDocument } from './document.js';
10
- import { initDelayUnmount } from './lifecycle/delayUnmount.js';
11
- import { replaceCommitHook, replaceRequestAnimationFrame } from './lifecycle/patch/commit.js';
10
+ import { replaceCommitHook } from './lifecycle/patch/commit.js';
11
+ import { addCtxNotFoundEventListener } from './lifecycle/patch/error.js';
12
12
  import { injectUpdateMainThread } from './lifecycle/patch/updateMainThread.js';
13
13
  import { injectCalledByNative } from './lynx/calledByNative.js';
14
- import { setupLynxTestingEnv } from './lynx/env.js';
14
+ import { setupLynxEnv } from './lynx/env.js';
15
15
  import { injectLepusMethods } from './lynx/injectLepusMethods.js';
16
16
  import { initTimingAPI } from './lynx/performance.js';
17
17
  import { injectTt } from './lynx/tt.js';
18
+
18
19
  export { runWithForce } from './lynx/runWithForce.js';
19
20
 
20
21
  // @ts-expect-error Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature
@@ -44,14 +45,13 @@ if (__BACKGROUND__) {
44
45
  options.document = document as any;
45
46
  setupBackgroundDocument();
46
47
  injectTt();
48
+ addCtxNotFoundEventListener();
47
49
 
48
50
  if (process.env['NODE_ENV'] === 'test') {}
49
51
  else {
50
52
  replaceCommitHook();
51
- replaceRequestAnimationFrame();
52
53
  initTimingAPI();
53
- initDelayUnmount();
54
54
  }
55
55
  }
56
56
 
57
- setupLynxTestingEnv();
57
+ setupLynxEnv();