@lynx-js/react 0.110.1 → 0.111.1
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.
- package/CHANGELOG.md +50 -0
- package/components/lib/DeferredListItem.d.ts +7 -0
- package/components/lib/DeferredListItem.jsx +40 -0
- package/components/lib/DeferredListItem.jsx.map +1 -0
- package/components/lib/index.d.ts +1 -0
- package/components/lib/index.js +1 -0
- package/components/lib/index.js.map +1 -1
- package/components/src/DeferredListItem.tsx +56 -0
- package/components/src/index.ts +1 -0
- package/package.json +1 -1
- package/refresh/.turbo/turbo-build.log +7 -3
- package/refresh/dist/index.js +223 -284
- package/refresh/package.json +3 -4
- package/refresh/rslib.config.ts +24 -0
- package/runtime/lazy/react-lepus.js +1 -0
- package/runtime/lazy/react.js +1 -0
- package/runtime/lepus/index.d.ts +1 -1
- package/runtime/lepus/index.js +44 -0
- package/runtime/lib/backgroundSnapshot.d.ts +2 -1
- package/runtime/lib/backgroundSnapshot.js +62 -40
- package/runtime/lib/backgroundSnapshot.js.map +1 -1
- package/runtime/lib/compat/initData.js +10 -0
- package/runtime/lib/compat/initData.js.map +1 -1
- package/runtime/lib/index.d.ts +2 -2
- package/runtime/lib/index.js +2 -2
- package/runtime/lib/index.js.map +1 -1
- package/runtime/lib/lifecycle/patch/commit.js +5 -5
- package/runtime/lib/lifecycle/patch/commit.js.map +1 -1
- package/runtime/lib/lifecycle/patch/snapshotPatch.d.ts +9 -9
- package/runtime/lib/lifecycle/patch/snapshotPatch.js +9 -10
- package/runtime/lib/lifecycle/patch/snapshotPatch.js.map +1 -1
- package/runtime/lib/lifecycle/patch/updateMainThread.js +7 -8
- package/runtime/lib/lifecycle/patch/updateMainThread.js.map +1 -1
- package/runtime/lib/lifecycleConstant.d.ts +2 -1
- package/runtime/lib/lifecycleConstant.js +1 -0
- package/runtime/lib/lifecycleConstant.js.map +1 -1
- package/runtime/lib/list.js +102 -12
- package/runtime/lib/list.js.map +1 -1
- package/runtime/lib/lynx/calledByNative.js +6 -9
- package/runtime/lib/lynx/calledByNative.js.map +1 -1
- package/runtime/lib/lynx/component.js +11 -14
- package/runtime/lib/lynx/component.js.map +1 -1
- package/runtime/lib/lynx/env.js +1 -2
- package/runtime/lib/lynx/env.js.map +1 -1
- package/runtime/lib/lynx/lazy-bundle.js +48 -21
- package/runtime/lib/lynx/lazy-bundle.js.map +1 -1
- package/runtime/lib/lynx/performance.d.ts +3 -19
- package/runtime/lib/lynx/performance.js +25 -26
- package/runtime/lib/lynx/performance.js.map +1 -1
- package/runtime/lib/lynx/tt.js +10 -5
- package/runtime/lib/lynx/tt.js.map +1 -1
- package/runtime/lib/lynx-api.d.ts +78 -1
- package/runtime/lib/lynx-api.js.map +1 -1
- package/runtime/lib/snapshot.d.ts +2 -0
- package/runtime/lib/snapshot.js +19 -5
- package/runtime/lib/snapshot.js.map +1 -1
- package/runtime/lib/utils.d.ts +1 -0
- package/runtime/lib/utils.js +6 -0
- package/runtime/lib/utils.js.map +1 -1
- package/runtime/src/backgroundSnapshot.ts +74 -55
- package/runtime/src/compat/initData.ts +10 -0
- package/runtime/src/index.ts +2 -0
- package/runtime/src/lifecycle/patch/commit.ts +5 -11
- package/runtime/src/lifecycle/patch/snapshotPatch.ts +9 -9
- package/runtime/src/lifecycle/patch/updateMainThread.ts +7 -8
- package/runtime/src/lifecycleConstant.ts +1 -0
- package/runtime/src/list.ts +118 -15
- package/runtime/src/lynx/calledByNative.ts +6 -8
- package/runtime/src/lynx/component.ts +17 -29
- package/runtime/src/lynx/env.ts +1 -2
- package/runtime/src/lynx/lazy-bundle.ts +55 -20
- package/runtime/src/lynx/performance.ts +26 -27
- package/runtime/src/lynx/tt.ts +10 -11
- package/runtime/src/lynx-api.ts +77 -1
- package/runtime/src/snapshot.ts +20 -5
- package/runtime/src/utils.ts +9 -0
- package/testing-library/dist/env/vitest.js +6 -3
- package/testing-library/dist/index.d.ts +4 -1
- package/testing-library/dist/pure.js +4 -2
- package/testing-library/dist/vitest-global-setup.js +2 -2
- package/testing-library/dist/vitest.config.js +38 -1
- package/testing-library/types/entry.d.ts +3 -2
- package/transform/dist/wasm.cjs +1 -1
- package/types/react.d.ts +21 -1
- package/types/react.docs.d.ts +1 -1
- package/worklet-runtime/dist/dev.js +403 -506
- package/worklet-runtime/dist/main.js +1 -517
- package/worklet-runtime/lib/workletRuntime.js +5 -5
- package/worklet-runtime/lib/workletRuntime.js.map +1 -1
|
@@ -23,13 +23,7 @@ import type { VNode } from 'preact';
|
|
|
23
23
|
import { options } from 'preact';
|
|
24
24
|
|
|
25
25
|
import { LifecycleConstant } from '../../lifecycleConstant.js';
|
|
26
|
-
import {
|
|
27
|
-
PerformanceTimingKeys,
|
|
28
|
-
globalPipelineOptions,
|
|
29
|
-
markTiming,
|
|
30
|
-
markTimingLegacy,
|
|
31
|
-
setPipeline,
|
|
32
|
-
} from '../../lynx/performance.js';
|
|
26
|
+
import { globalPipelineOptions, markTiming, markTimingLegacy, setPipeline } from '../../lynx/performance.js';
|
|
33
27
|
import { COMMIT } from '../../renderToOpcodes/constants.js';
|
|
34
28
|
import { applyQueuedRefs } from '../../snapshot/ref.js';
|
|
35
29
|
import { backgroundSnapshotInstanceManager } from '../../snapshot.js';
|
|
@@ -88,8 +82,8 @@ function replaceCommitHook(): void {
|
|
|
88
82
|
}
|
|
89
83
|
|
|
90
84
|
// Mark the end of virtual DOM diffing phase for performance tracking
|
|
91
|
-
markTimingLegacy(
|
|
92
|
-
markTiming(
|
|
85
|
+
markTimingLegacy('updateDiffVdomEnd');
|
|
86
|
+
markTiming('diffVdomEnd');
|
|
93
87
|
|
|
94
88
|
const backgroundSnapshotInstancesToRemove = globalBackgroundSnapshotInstancesToRemove;
|
|
95
89
|
globalBackgroundSnapshotInstancesToRemove = [];
|
|
@@ -167,7 +161,7 @@ function commitPatchUpdate(patchList: PatchList, patchOptions: Omit<PatchOptions
|
|
|
167
161
|
if (__PROFILE__) {
|
|
168
162
|
console.profile('commitChanges');
|
|
169
163
|
}
|
|
170
|
-
markTiming(
|
|
164
|
+
markTiming('packChangesStart');
|
|
171
165
|
const obj: {
|
|
172
166
|
data: string;
|
|
173
167
|
patchOptions: PatchOptions;
|
|
@@ -178,7 +172,7 @@ function commitPatchUpdate(patchList: PatchList, patchOptions: Omit<PatchOptions
|
|
|
178
172
|
reloadVersion: getReloadVersion(),
|
|
179
173
|
},
|
|
180
174
|
};
|
|
181
|
-
markTiming(
|
|
175
|
+
markTiming('packChangesEnd');
|
|
182
176
|
if (globalPipelineOptions) {
|
|
183
177
|
obj.patchOptions.pipelineOptions = globalPipelineOptions;
|
|
184
178
|
setPipeline(undefined);
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
* efficient transmission between threads and application to element tree.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
export const
|
|
12
|
-
CreateElement,
|
|
13
|
-
InsertBefore,
|
|
14
|
-
RemoveChild,
|
|
15
|
-
SetAttribute,
|
|
16
|
-
SetAttributes,
|
|
11
|
+
export const SnapshotOperation = {
|
|
12
|
+
CreateElement: 0,
|
|
13
|
+
InsertBefore: 1,
|
|
14
|
+
RemoveChild: 2,
|
|
15
|
+
SetAttribute: 3,
|
|
16
|
+
SetAttributes: 4,
|
|
17
17
|
|
|
18
|
-
DEV_ONLY_AddSnapshot
|
|
19
|
-
DEV_ONLY_RegisterWorklet
|
|
20
|
-
}
|
|
18
|
+
DEV_ONLY_AddSnapshot: 100,
|
|
19
|
+
DEV_ONLY_RegisterWorklet: 101,
|
|
20
|
+
} as const;
|
|
21
21
|
|
|
22
22
|
// Operation format definitions:
|
|
23
23
|
//
|
|
@@ -8,7 +8,7 @@ import type { PatchList, PatchOptions } from './commit.js';
|
|
|
8
8
|
import { setMainThreadHydrationFinished } from './isMainThreadHydrationFinished.js';
|
|
9
9
|
import { snapshotPatchApply } from './snapshotPatchApply.js';
|
|
10
10
|
import { LifecycleConstant } from '../../lifecycleConstant.js';
|
|
11
|
-
import {
|
|
11
|
+
import { markTiming, setPipeline } from '../../lynx/performance.js';
|
|
12
12
|
import { __pendingListUpdates } from '../../pendingListUpdates.js';
|
|
13
13
|
import { applyRefQueue } from '../../snapshot/workletRef.js';
|
|
14
14
|
import { __page } from '../../snapshot.js';
|
|
@@ -25,12 +25,12 @@ function updateMainThread(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
setPipeline(patchOptions.pipelineOptions);
|
|
28
|
-
markTiming(
|
|
29
|
-
markTiming(
|
|
28
|
+
markTiming('mtsRenderStart');
|
|
29
|
+
markTiming('parseChangesStart');
|
|
30
30
|
const { patchList, flushOptions = {} } = JSON.parse(data) as PatchList;
|
|
31
31
|
|
|
32
|
-
markTiming(
|
|
33
|
-
markTiming(
|
|
32
|
+
markTiming('parseChangesEnd');
|
|
33
|
+
markTiming('patchChangesStart');
|
|
34
34
|
|
|
35
35
|
for (const { snapshotPatch, workletRefInitValuePatch } of patchList) {
|
|
36
36
|
updateWorkletRefInitValueChanges(workletRefInitValuePatch);
|
|
@@ -42,8 +42,8 @@ function updateMainThread(
|
|
|
42
42
|
// console.debug('********** Lepus updatePatch:');
|
|
43
43
|
// printSnapshotInstance(snapshotInstanceManager.values.get(-1)!);
|
|
44
44
|
}
|
|
45
|
-
markTiming(
|
|
46
|
-
markTiming(
|
|
45
|
+
markTiming('patchChangesEnd');
|
|
46
|
+
markTiming('mtsRenderEnd');
|
|
47
47
|
if (patchOptions.isHydration) {
|
|
48
48
|
setMainThreadHydrationFinished(true);
|
|
49
49
|
}
|
|
@@ -51,7 +51,6 @@ function updateMainThread(
|
|
|
51
51
|
if (patchOptions.pipelineOptions) {
|
|
52
52
|
flushOptions.pipelineOptions = patchOptions.pipelineOptions;
|
|
53
53
|
}
|
|
54
|
-
// TODO: triggerDataUpdated?
|
|
55
54
|
__FlushElementTree(__page, flushOptions);
|
|
56
55
|
}
|
|
57
56
|
|
package/runtime/src/list.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
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 { LifecycleConstant } from './lifecycleConstant.js';
|
|
4
5
|
import { applyRefQueue } from './snapshot/workletRef.js';
|
|
5
6
|
import type { SnapshotInstance } from './snapshot.js';
|
|
7
|
+
import { maybePromise } from './utils.js';
|
|
6
8
|
|
|
7
9
|
export const gSignMap: Record<number, Map<number, SnapshotInstance>> = {};
|
|
8
10
|
export const gRecycleMap: Record<number, Map<string, Map<number, SnapshotInstance>>> = {};
|
|
9
11
|
const gParentWeakMap: WeakMap<SnapshotInstance, unknown> = new WeakMap();
|
|
12
|
+
const resolvedPromise = /* @__PURE__ */ Promise.resolve();
|
|
10
13
|
|
|
11
14
|
export function clearListGlobal(): void {
|
|
12
15
|
for (const key in gSignMap) {
|
|
@@ -38,10 +41,10 @@ export function componentAtIndexFactory(
|
|
|
38
41
|
}
|
|
39
42
|
});
|
|
40
43
|
|
|
41
|
-
const
|
|
44
|
+
const componentAtChildCtx = (
|
|
42
45
|
list: FiberElement,
|
|
43
46
|
listID: number,
|
|
44
|
-
|
|
47
|
+
childCtx: SnapshotInstance,
|
|
45
48
|
operationID: number,
|
|
46
49
|
enableReuseNotification: boolean,
|
|
47
50
|
enableBatchRender: boolean = false,
|
|
@@ -53,13 +56,55 @@ export function componentAtIndexFactory(
|
|
|
53
56
|
throw new Error('componentAtIndex called on removed list');
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
const childCtx = ctx[cellIndex];
|
|
57
|
-
if (!childCtx) {
|
|
58
|
-
throw new Error('childCtx not found');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
59
|
const platformInfo = childCtx.__listItemPlatformInfo ?? {};
|
|
62
60
|
|
|
61
|
+
// The lifecycle of this `__extraProps.isReady`:
|
|
62
|
+
// 0 -> Promise<number> -> 1
|
|
63
|
+
// 0: The initial state, the list-item is not ready yet, we will send a event to background
|
|
64
|
+
// when `componentAtIndex` is called on it
|
|
65
|
+
// Promise<number>: A promise that will be resolved when the list-item is ready
|
|
66
|
+
// 1: The list-item is ready, we can use it to render the list
|
|
67
|
+
if (childCtx.__extraProps?.['isReady'] === 0) {
|
|
68
|
+
if (
|
|
69
|
+
typeof __GetAttributeByName === 'function'
|
|
70
|
+
&& __GetAttributeByName(list, 'custom-list-name') === 'list-container'
|
|
71
|
+
) {
|
|
72
|
+
// we are in supported env
|
|
73
|
+
// do not throw
|
|
74
|
+
} else {
|
|
75
|
+
throw new Error(
|
|
76
|
+
'Unsupported: `<list-item/>` with `defer={true}` must be used with `<list custom-list-name="list-container"/>`',
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
__OnLifecycleEvent([LifecycleConstant.publishEvent, {
|
|
81
|
+
handlerName: `${childCtx.__id}:__extraProps:onComponentAtIndex`,
|
|
82
|
+
data: {},
|
|
83
|
+
}]);
|
|
84
|
+
|
|
85
|
+
let p: Promise<number>;
|
|
86
|
+
return (p = new Promise<number>((resolve) => {
|
|
87
|
+
Object.defineProperty(childCtx.__extraProps, 'isReady', {
|
|
88
|
+
set(isReady) {
|
|
89
|
+
if (isReady === 1) {
|
|
90
|
+
delete childCtx.__extraProps!['isReady'];
|
|
91
|
+
childCtx.__extraProps!['isReady'] = 1;
|
|
92
|
+
|
|
93
|
+
void resolvedPromise.then(() => {
|
|
94
|
+
// the cellIndex may be changed already, but the `childCtx` is the same
|
|
95
|
+
resolve(componentAtChildCtx(list, listID, childCtx, operationID, enableReuseNotification));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
get() {
|
|
100
|
+
return p;
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}));
|
|
104
|
+
} else if (maybePromise<number>(childCtx.__extraProps?.['isReady'])) {
|
|
105
|
+
throw new Error('componentAtIndex was called on a pending deferred list item');
|
|
106
|
+
}
|
|
107
|
+
|
|
63
108
|
const uniqID = childCtx.type + (platformInfo['reuse-identifier'] ?? '');
|
|
64
109
|
const recycleSignMap = recycleMap.get(uniqID);
|
|
65
110
|
|
|
@@ -102,6 +147,11 @@ export function componentAtIndexFactory(
|
|
|
102
147
|
oldCtx.unRenderElements();
|
|
103
148
|
if (!oldCtx.__id) {
|
|
104
149
|
oldCtx.tearDown();
|
|
150
|
+
} else if (oldCtx.__extraProps?.['isReady'] === 1) {
|
|
151
|
+
__OnLifecycleEvent([LifecycleConstant.publishEvent, {
|
|
152
|
+
handlerName: `${oldCtx.__id}:__extraProps:onRecycleComponent`,
|
|
153
|
+
data: {},
|
|
154
|
+
}]);
|
|
105
155
|
}
|
|
106
156
|
const root = childCtx.__element_root!;
|
|
107
157
|
applyRefQueue();
|
|
@@ -156,25 +206,78 @@ export function componentAtIndexFactory(
|
|
|
156
206
|
return sign;
|
|
157
207
|
};
|
|
158
208
|
|
|
159
|
-
|
|
209
|
+
function componentAtIndex(
|
|
210
|
+
list: FiberElement,
|
|
211
|
+
listID: number,
|
|
212
|
+
cellIndex: number,
|
|
213
|
+
operationID: number,
|
|
214
|
+
enableReuseNotification: boolean,
|
|
215
|
+
) {
|
|
216
|
+
const childCtx = ctx[cellIndex];
|
|
217
|
+
if (!childCtx) {
|
|
218
|
+
throw new Error('childCtx not found');
|
|
219
|
+
}
|
|
220
|
+
const r = componentAtChildCtx(list, listID, childCtx, operationID, enableReuseNotification);
|
|
221
|
+
|
|
222
|
+
/* v8 ignore start */
|
|
223
|
+
if (process.env['NODE_ENV'] === 'test') {
|
|
224
|
+
return r;
|
|
225
|
+
} else {
|
|
226
|
+
return typeof r === 'number' ? r : undefined;
|
|
227
|
+
}
|
|
228
|
+
/* v8 ignore end */
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function componentAtIndexes(
|
|
160
232
|
list: FiberElement,
|
|
161
233
|
listID: number,
|
|
162
234
|
cellIndexes: number[],
|
|
163
235
|
operationIDs: number[],
|
|
164
236
|
enableReuseNotification: boolean,
|
|
165
237
|
asyncFlush: boolean,
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
238
|
+
) {
|
|
239
|
+
let hasUnready = false;
|
|
240
|
+
const p: Array<Promise<number> | number> = [];
|
|
241
|
+
|
|
242
|
+
cellIndexes.forEach((cellIndex, index) => {
|
|
243
|
+
const operationID = operationIDs[index]!;
|
|
244
|
+
const childCtx = ctx[cellIndex];
|
|
245
|
+
if (!childCtx) {
|
|
246
|
+
throw new Error('childCtx not found');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const u = componentAtChildCtx(list, listID, childCtx, operationID, enableReuseNotification, true, asyncFlush);
|
|
250
|
+
if (typeof u === 'number') {
|
|
251
|
+
// ready
|
|
252
|
+
} else {
|
|
253
|
+
hasUnready = true;
|
|
254
|
+
}
|
|
255
|
+
p.push(u);
|
|
170
256
|
});
|
|
257
|
+
|
|
258
|
+
// We need __FlushElementTree twice:
|
|
259
|
+
// 1. The first time is sync, we flush the items that are ready, with unready items' uiSign as -1.
|
|
260
|
+
// 2. The second time is async, with all the uiSigns.
|
|
261
|
+
// NOTE: The `operationIDs` passed to __FlushElementTree must be the one passed in,
|
|
262
|
+
// not the one generated by any code here, to workaround a bug of Lynx Engine.
|
|
263
|
+
// So we CANNOT split the `operationIDs` into two parts: one for ready items, one for unready items.
|
|
264
|
+
if (hasUnready) {
|
|
265
|
+
void Promise.all(p).then((uiSigns) => {
|
|
266
|
+
__FlushElementTree(list, {
|
|
267
|
+
triggerLayout: true,
|
|
268
|
+
operationIDs,
|
|
269
|
+
elementIDs: uiSigns,
|
|
270
|
+
listID,
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
}
|
|
171
274
|
__FlushElementTree(list, {
|
|
172
275
|
triggerLayout: true,
|
|
173
|
-
operationIDs
|
|
174
|
-
elementIDs:
|
|
276
|
+
operationIDs,
|
|
277
|
+
elementIDs: cellIndexes.map((_, index) => typeof p[index] === 'number' ? p[index] : -1),
|
|
175
278
|
listID,
|
|
176
279
|
});
|
|
177
|
-
}
|
|
280
|
+
}
|
|
178
281
|
return [componentAtIndex, componentAtIndexes] as const;
|
|
179
282
|
}
|
|
180
283
|
|
|
@@ -12,7 +12,7 @@ import { __root, setRoot } from '../root.js';
|
|
|
12
12
|
import { applyRefQueue } from '../snapshot/workletRef.js';
|
|
13
13
|
import { SnapshotInstance, __page, setupPage } from '../snapshot.js';
|
|
14
14
|
import { isEmptyObject } from '../utils.js';
|
|
15
|
-
import {
|
|
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(
|
|
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
|
-
|
|
142
|
+
flushOptions.triggerDataUpdated = true;
|
|
143
|
+
markTiming('updateDiffVdomEnd');
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
109
|
+
markTimingLegacy('updateSetStateTrigger', timingFlag);
|
|
122
110
|
this[NEXT_STATE][PerfSpecificKey] = '';
|
|
123
111
|
}
|
|
124
112
|
};
|
package/runtime/src/lynx/env.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
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
|
|
56
|
+
case 'updateSetStateTrigger': {
|
|
57
57
|
shouldMarkDiffVdomStart = true;
|
|
58
58
|
shouldMarkDiffVdomEnd = true;
|
|
59
59
|
timingFlag = timingFlag_;
|
|
60
60
|
break;
|
|
61
61
|
}
|
|
62
|
-
case
|
|
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
|
|
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!,
|
|
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,
|
|
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(
|
|
125
|
+
markTiming('diffVdomStart', true);
|
|
126
126
|
}
|
|
127
127
|
if (shouldMarkDiffVdomStart) {
|
|
128
|
-
markTimingLegacy(
|
|
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,
|