@lynx-js/react 0.110.1 → 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.
- package/CHANGELOG.md +44 -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 +1 -1
- 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/index.d.ts +4 -1
- package/testing-library/dist/pure.js +1 -1
- 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
|
@@ -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,
|
package/runtime/src/lynx/tt.ts
CHANGED
|
@@ -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(
|
|
77
|
+
markTiming('hydrateParseSnapshotStart');
|
|
84
78
|
const before = JSON.parse(lepusSide) as SerializedSnapshotInstance;
|
|
85
|
-
markTiming(
|
|
86
|
-
markTiming(
|
|
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(
|
|
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
|
|
package/runtime/src/lynx-api.ts
CHANGED
|
@@ -218,6 +218,82 @@ export interface InitData {}
|
|
|
218
218
|
|
|
219
219
|
export { withInitDataInState };
|
|
220
220
|
|
|
221
|
+
/**
|
|
222
|
+
* The data processors that registered with {@link Lynx.registerDataProcessors}.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
*
|
|
226
|
+
* Extending `dataProcessors` interface
|
|
227
|
+
*
|
|
228
|
+
* ```ts
|
|
229
|
+
* import type { DataProcessors as WellKnownDataProcessors } from '@lynx-js/react';
|
|
230
|
+
*
|
|
231
|
+
* declare module '@lynx-js/react' {
|
|
232
|
+
* interface DataProcessors extends WellKnownDataProcessors {
|
|
233
|
+
* foo(bar: string): number;
|
|
234
|
+
* }
|
|
235
|
+
* }
|
|
236
|
+
* ```
|
|
237
|
+
*
|
|
238
|
+
* Then you can use `lynx.registerDataProcessors` with types.
|
|
239
|
+
*
|
|
240
|
+
* ```js
|
|
241
|
+
* lynx.registerDataProcessors({
|
|
242
|
+
* dataProcessors: {
|
|
243
|
+
* foo(bar) {
|
|
244
|
+
* return 1;
|
|
245
|
+
* }
|
|
246
|
+
* }
|
|
247
|
+
* })
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @public
|
|
251
|
+
*/
|
|
252
|
+
export interface DataProcessors {
|
|
253
|
+
/**
|
|
254
|
+
* Optional processor to override screen metrics used by the app
|
|
255
|
+
*
|
|
256
|
+
* @param metrics - The physical screen dimensions in pixels
|
|
257
|
+
*
|
|
258
|
+
* @returns New screen dimensions to be used by the app
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
*
|
|
262
|
+
* ```ts
|
|
263
|
+
* lynx.registerDataProcessors({
|
|
264
|
+
* dataProcessors: {
|
|
265
|
+
* getScreenMetricsOverride: (metrics) => {
|
|
266
|
+
* // Force a specific aspect ratio
|
|
267
|
+
* return {
|
|
268
|
+
* width: metrics.width,
|
|
269
|
+
* height: metrics.width * (16/9)
|
|
270
|
+
* };
|
|
271
|
+
* }
|
|
272
|
+
* }
|
|
273
|
+
* });
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
getScreenMetricsOverride?(metrics: {
|
|
277
|
+
/**
|
|
278
|
+
* The physical pixel width of the screen
|
|
279
|
+
*/
|
|
280
|
+
width: number;
|
|
281
|
+
/**
|
|
282
|
+
* The physical pixel height of the screen
|
|
283
|
+
*/
|
|
284
|
+
height: number;
|
|
285
|
+
}): { width: number; height: number };
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Custom unknown data processors.
|
|
289
|
+
*
|
|
290
|
+
* @remarks
|
|
291
|
+
*
|
|
292
|
+
* You may extends the `DataProcessors` interface for better TypeScript types. See {@link DataProcessors}.
|
|
293
|
+
*/
|
|
294
|
+
[processorName: string]: (...args: any[]) => any;
|
|
295
|
+
}
|
|
296
|
+
|
|
221
297
|
/**
|
|
222
298
|
* Definition of DataProcessor(s)
|
|
223
299
|
* @public
|
|
@@ -238,7 +314,7 @@ export interface DataProcessorDefinition {
|
|
|
238
314
|
*
|
|
239
315
|
* @public
|
|
240
316
|
*/
|
|
241
|
-
dataProcessors?:
|
|
317
|
+
dataProcessors?: DataProcessors;
|
|
242
318
|
}
|
|
243
319
|
|
|
244
320
|
/**
|
package/runtime/src/snapshot.ts
CHANGED
|
@@ -165,10 +165,17 @@ export const backgroundSnapshotInstanceManager: {
|
|
|
165
165
|
return null;
|
|
166
166
|
}
|
|
167
167
|
const spreadKey = res[2];
|
|
168
|
-
if (
|
|
169
|
-
|
|
168
|
+
if (res[1] === '__extraProps') {
|
|
169
|
+
if (spreadKey) {
|
|
170
|
+
return ctx.__extraProps![spreadKey];
|
|
171
|
+
}
|
|
172
|
+
throw new Error('unreachable');
|
|
170
173
|
} else {
|
|
171
|
-
|
|
174
|
+
if (spreadKey) {
|
|
175
|
+
return (ctx.__values![expIndex] as { [spreadKey]: unknown })[spreadKey];
|
|
176
|
+
} else {
|
|
177
|
+
return ctx.__values![expIndex];
|
|
178
|
+
}
|
|
172
179
|
}
|
|
173
180
|
},
|
|
174
181
|
};
|
|
@@ -241,6 +248,7 @@ export interface SerializedSnapshotInstance {
|
|
|
241
248
|
id: number;
|
|
242
249
|
type: string;
|
|
243
250
|
values?: any[] | undefined;
|
|
251
|
+
extraProps?: Record<string, unknown> | undefined;
|
|
244
252
|
children?: SerializedSnapshotInstance[] | undefined;
|
|
245
253
|
}
|
|
246
254
|
|
|
@@ -263,6 +271,7 @@ export class SnapshotInstance {
|
|
|
263
271
|
__current_slot_index = 0;
|
|
264
272
|
__worklet_ref_set?: Set<WorkletRefImpl<any> | Worklet>;
|
|
265
273
|
__listItemPlatformInfo?: PlatformInfo;
|
|
274
|
+
__extraProps?: Record<string, unknown> | undefined;
|
|
266
275
|
|
|
267
276
|
constructor(public type: string, id?: number) {
|
|
268
277
|
this.__snapshot_def = snapshotManager.values.get(type)!;
|
|
@@ -596,9 +605,14 @@ export class SnapshotInstance {
|
|
|
596
605
|
return;
|
|
597
606
|
}
|
|
598
607
|
|
|
599
|
-
|
|
608
|
+
if (typeof key === 'string') {
|
|
609
|
+
// for more flexible usage, we allow setting non-indexed attributes
|
|
610
|
+
(this.__extraProps ??= {})[key] = value;
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
|
|
600
614
|
this.__values ??= [];
|
|
601
|
-
this.callUpdateIfNotDirectOrDeepEqual(
|
|
615
|
+
this.callUpdateIfNotDirectOrDeepEqual(key, this.__values[key], this.__values[key] = value);
|
|
602
616
|
}
|
|
603
617
|
|
|
604
618
|
toJSON(): Omit<SerializedSnapshotInstance, 'children'> & { children: SnapshotInstance[] | undefined } {
|
|
@@ -606,6 +620,7 @@ export class SnapshotInstance {
|
|
|
606
620
|
id: this.__id,
|
|
607
621
|
type: this.type,
|
|
608
622
|
values: this.__values,
|
|
623
|
+
extraProps: this.__extraProps,
|
|
609
624
|
children: this.__firstChild ? this.childNodes : undefined,
|
|
610
625
|
};
|
|
611
626
|
}
|
package/runtime/src/utils.ts
CHANGED
|
@@ -33,3 +33,12 @@ export function pick<T extends object, K extends keyof T>(obj: T, keys: Iterable
|
|
|
33
33
|
}
|
|
34
34
|
return result as Pick<T, K>;
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
export function maybePromise<T>(value: unknown): value is Promise<T> {
|
|
38
|
+
return (
|
|
39
|
+
typeof value === 'object'
|
|
40
|
+
&& value !== null
|
|
41
|
+
// @ts-expect-error the check is safe
|
|
42
|
+
&& typeof value.then === 'function'
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { act } from 'preact/test-utils';
|
|
1
2
|
import { ARIARole } from 'aria-query';
|
|
2
3
|
import { ComponentChild } from 'preact';
|
|
3
4
|
import { ComponentType } from 'preact';
|
|
@@ -5,6 +6,8 @@ import { JSDOM } from 'jsdom';
|
|
|
5
6
|
import { OptionsReceived } from 'pretty-format';
|
|
6
7
|
import * as prettyFormat from 'pretty-format';
|
|
7
8
|
|
|
9
|
+
export { act }
|
|
10
|
+
|
|
8
11
|
export declare type AllByAttribute = (
|
|
9
12
|
attribute: string,
|
|
10
13
|
container: HTMLElement,
|
|
@@ -1493,7 +1496,7 @@ export declare interface waitForOptions {
|
|
|
1493
1496
|
*
|
|
1494
1497
|
* It will be useful when you want to wait for the next event loop to finish.
|
|
1495
1498
|
*
|
|
1496
|
-
* @
|
|
1499
|
+
* @deprecated Please use `act` instead
|
|
1497
1500
|
*/
|
|
1498
1501
|
export declare function waitSchedule(): Promise<void>;
|
|
1499
1502
|
|
|
@@ -14725,4 +14725,4 @@ var __webpack_exports__waitForElementToBeRemoved = dom_esm.mz;
|
|
|
14725
14725
|
var __webpack_exports__within = dom_esm.uh;
|
|
14726
14726
|
var __webpack_exports__wrapAllByQueryWithSuggestion = dom_esm.bH;
|
|
14727
14727
|
var __webpack_exports__wrapSingleQueryWithSuggestion = dom_esm.kG;
|
|
14728
|
-
export { cleanup, fireEvent, pure_render as render, renderHook, waitSchedule, __webpack_exports__buildQueries as buildQueries, __webpack_exports__configure as configure, __webpack_exports__createEvent as createEvent, __webpack_exports__findAllByAltText as findAllByAltText, __webpack_exports__findAllByDisplayValue as findAllByDisplayValue, __webpack_exports__findAllByLabelText as findAllByLabelText, __webpack_exports__findAllByPlaceholderText as findAllByPlaceholderText, __webpack_exports__findAllByRole as findAllByRole, __webpack_exports__findAllByTestId as findAllByTestId, __webpack_exports__findAllByText as findAllByText, __webpack_exports__findAllByTitle as findAllByTitle, __webpack_exports__findByAltText as findByAltText, __webpack_exports__findByDisplayValue as findByDisplayValue, __webpack_exports__findByLabelText as findByLabelText, __webpack_exports__findByPlaceholderText as findByPlaceholderText, __webpack_exports__findByRole as findByRole, __webpack_exports__findByTestId as findByTestId, __webpack_exports__findByText as findByText, __webpack_exports__findByTitle as findByTitle, __webpack_exports__getAllByAltText as getAllByAltText, __webpack_exports__getAllByDisplayValue as getAllByDisplayValue, __webpack_exports__getAllByLabelText as getAllByLabelText, __webpack_exports__getAllByPlaceholderText as getAllByPlaceholderText, __webpack_exports__getAllByRole as getAllByRole, __webpack_exports__getAllByTestId as getAllByTestId, __webpack_exports__getAllByText as getAllByText, __webpack_exports__getAllByTitle as getAllByTitle, __webpack_exports__getByAltText as getByAltText, __webpack_exports__getByDisplayValue as getByDisplayValue, __webpack_exports__getByLabelText as getByLabelText, __webpack_exports__getByPlaceholderText as getByPlaceholderText, __webpack_exports__getByRole as getByRole, __webpack_exports__getByTestId as getByTestId, __webpack_exports__getByText as getByText, __webpack_exports__getByTitle as getByTitle, __webpack_exports__getConfig as getConfig, __webpack_exports__getDefaultNormalizer as getDefaultNormalizer, __webpack_exports__getElementError as getElementError, __webpack_exports__getMultipleElementsFoundError as getMultipleElementsFoundError, __webpack_exports__getNodeText as getNodeText, __webpack_exports__getQueriesForElement as getQueriesForElement, __webpack_exports__getRoles as getRoles, __webpack_exports__getSuggestedQuery as getSuggestedQuery, __webpack_exports__isInaccessible as isInaccessible, __webpack_exports__logDOM as logDOM, __webpack_exports__logRoles as logRoles, __webpack_exports__makeFindQuery as makeFindQuery, __webpack_exports__makeGetAllQuery as makeGetAllQuery, __webpack_exports__makeSingleQuery as makeSingleQuery, __webpack_exports__prettyDOM as prettyDOM, __webpack_exports__prettyFormat as prettyFormat, __webpack_exports__queries as queries, __webpack_exports__queryAllByAltText as queryAllByAltText, __webpack_exports__queryAllByAttribute as queryAllByAttribute, __webpack_exports__queryAllByDisplayValue as queryAllByDisplayValue, __webpack_exports__queryAllByLabelText as queryAllByLabelText, __webpack_exports__queryAllByPlaceholderText as queryAllByPlaceholderText, __webpack_exports__queryAllByRole as queryAllByRole, __webpack_exports__queryAllByTestId as queryAllByTestId, __webpack_exports__queryAllByText as queryAllByText, __webpack_exports__queryAllByTitle as queryAllByTitle, __webpack_exports__queryByAltText as queryByAltText, __webpack_exports__queryByAttribute as queryByAttribute, __webpack_exports__queryByDisplayValue as queryByDisplayValue, __webpack_exports__queryByLabelText as queryByLabelText, __webpack_exports__queryByPlaceholderText as queryByPlaceholderText, __webpack_exports__queryByRole as queryByRole, __webpack_exports__queryByTestId as queryByTestId, __webpack_exports__queryByText as queryByText, __webpack_exports__queryByTitle as queryByTitle, __webpack_exports__queryHelpers as queryHelpers, __webpack_exports__screen as screen, __webpack_exports__waitFor as waitFor, __webpack_exports__waitForElementToBeRemoved as waitForElementToBeRemoved, __webpack_exports__within as within, __webpack_exports__wrapAllByQueryWithSuggestion as wrapAllByQueryWithSuggestion, __webpack_exports__wrapSingleQueryWithSuggestion as wrapSingleQueryWithSuggestion };
|
|
14728
|
+
export { act, cleanup, fireEvent, pure_render as render, renderHook, waitSchedule, __webpack_exports__buildQueries as buildQueries, __webpack_exports__configure as configure, __webpack_exports__createEvent as createEvent, __webpack_exports__findAllByAltText as findAllByAltText, __webpack_exports__findAllByDisplayValue as findAllByDisplayValue, __webpack_exports__findAllByLabelText as findAllByLabelText, __webpack_exports__findAllByPlaceholderText as findAllByPlaceholderText, __webpack_exports__findAllByRole as findAllByRole, __webpack_exports__findAllByTestId as findAllByTestId, __webpack_exports__findAllByText as findAllByText, __webpack_exports__findAllByTitle as findAllByTitle, __webpack_exports__findByAltText as findByAltText, __webpack_exports__findByDisplayValue as findByDisplayValue, __webpack_exports__findByLabelText as findByLabelText, __webpack_exports__findByPlaceholderText as findByPlaceholderText, __webpack_exports__findByRole as findByRole, __webpack_exports__findByTestId as findByTestId, __webpack_exports__findByText as findByText, __webpack_exports__findByTitle as findByTitle, __webpack_exports__getAllByAltText as getAllByAltText, __webpack_exports__getAllByDisplayValue as getAllByDisplayValue, __webpack_exports__getAllByLabelText as getAllByLabelText, __webpack_exports__getAllByPlaceholderText as getAllByPlaceholderText, __webpack_exports__getAllByRole as getAllByRole, __webpack_exports__getAllByTestId as getAllByTestId, __webpack_exports__getAllByText as getAllByText, __webpack_exports__getAllByTitle as getAllByTitle, __webpack_exports__getByAltText as getByAltText, __webpack_exports__getByDisplayValue as getByDisplayValue, __webpack_exports__getByLabelText as getByLabelText, __webpack_exports__getByPlaceholderText as getByPlaceholderText, __webpack_exports__getByRole as getByRole, __webpack_exports__getByTestId as getByTestId, __webpack_exports__getByText as getByText, __webpack_exports__getByTitle as getByTitle, __webpack_exports__getConfig as getConfig, __webpack_exports__getDefaultNormalizer as getDefaultNormalizer, __webpack_exports__getElementError as getElementError, __webpack_exports__getMultipleElementsFoundError as getMultipleElementsFoundError, __webpack_exports__getNodeText as getNodeText, __webpack_exports__getQueriesForElement as getQueriesForElement, __webpack_exports__getRoles as getRoles, __webpack_exports__getSuggestedQuery as getSuggestedQuery, __webpack_exports__isInaccessible as isInaccessible, __webpack_exports__logDOM as logDOM, __webpack_exports__logRoles as logRoles, __webpack_exports__makeFindQuery as makeFindQuery, __webpack_exports__makeGetAllQuery as makeGetAllQuery, __webpack_exports__makeSingleQuery as makeSingleQuery, __webpack_exports__prettyDOM as prettyDOM, __webpack_exports__prettyFormat as prettyFormat, __webpack_exports__queries as queries, __webpack_exports__queryAllByAltText as queryAllByAltText, __webpack_exports__queryAllByAttribute as queryAllByAttribute, __webpack_exports__queryAllByDisplayValue as queryAllByDisplayValue, __webpack_exports__queryAllByLabelText as queryAllByLabelText, __webpack_exports__queryAllByPlaceholderText as queryAllByPlaceholderText, __webpack_exports__queryAllByRole as queryAllByRole, __webpack_exports__queryAllByTestId as queryAllByTestId, __webpack_exports__queryAllByText as queryAllByText, __webpack_exports__queryAllByTitle as queryAllByTitle, __webpack_exports__queryByAltText as queryByAltText, __webpack_exports__queryByAttribute as queryByAttribute, __webpack_exports__queryByDisplayValue as queryByDisplayValue, __webpack_exports__queryByLabelText as queryByLabelText, __webpack_exports__queryByPlaceholderText as queryByPlaceholderText, __webpack_exports__queryByRole as queryByRole, __webpack_exports__queryByTestId as queryByTestId, __webpack_exports__queryByText as queryByText, __webpack_exports__queryByTitle as queryByTitle, __webpack_exports__queryHelpers as queryHelpers, __webpack_exports__screen as screen, __webpack_exports__waitFor as waitFor, __webpack_exports__waitForElementToBeRemoved as waitForElementToBeRemoved, __webpack_exports__within as within, __webpack_exports__wrapAllByQueryWithSuggestion as wrapAllByQueryWithSuggestion, __webpack_exports__wrapSingleQueryWithSuggestion as wrapSingleQueryWithSuggestion };
|
|
@@ -16,7 +16,39 @@ async function ensurePackagesInstalled() {
|
|
|
16
16
|
}
|
|
17
17
|
const createVitestConfig = async (options)=>{
|
|
18
18
|
await ensurePackagesInstalled();
|
|
19
|
-
const
|
|
19
|
+
const runtimeOSSPkgName = '@lynx-js/react';
|
|
20
|
+
const runtimePkgName = options?.runtimePkgName ?? runtimeOSSPkgName;
|
|
21
|
+
const runtimeDir = path.dirname(vitest_config_require.resolve(`${runtimePkgName}/package.json`));
|
|
22
|
+
const runtimeOSSDir = path.dirname(vitest_config_require.resolve(`${runtimeOSSPkgName}/package.json`, {
|
|
23
|
+
paths: [
|
|
24
|
+
runtimeDir
|
|
25
|
+
]
|
|
26
|
+
}));
|
|
27
|
+
const preactDir = path.dirname(vitest_config_require.resolve('preact/package.json', {
|
|
28
|
+
paths: [
|
|
29
|
+
runtimeOSSDir
|
|
30
|
+
]
|
|
31
|
+
}));
|
|
32
|
+
const generateAlias = (pkgName, pkgDir, resolveDir)=>{
|
|
33
|
+
const pkgExports = vitest_config_require(path.join(pkgDir, 'package.json')).exports;
|
|
34
|
+
const pkgAlias = [];
|
|
35
|
+
Object.keys(pkgExports).forEach((key)=>{
|
|
36
|
+
const name = path.posix.join(pkgName, key);
|
|
37
|
+
pkgAlias.push({
|
|
38
|
+
find: new RegExp('^' + name + '$'),
|
|
39
|
+
replacement: vitest_config_require.resolve(name, {
|
|
40
|
+
paths: [
|
|
41
|
+
resolveDir
|
|
42
|
+
]
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
return pkgAlias;
|
|
47
|
+
};
|
|
48
|
+
const runtimeOSSAlias = generateAlias(runtimeOSSPkgName, runtimeOSSDir, runtimeDir);
|
|
49
|
+
let runtimeAlias = [];
|
|
50
|
+
if (runtimePkgName !== runtimeOSSPkgName) runtimeAlias = generateAlias(runtimePkgName, runtimeDir, vitest_config_dirname);
|
|
51
|
+
const preactAlias = generateAlias('preact', preactDir, runtimeOSSDir);
|
|
20
52
|
function transformReactLynxPlugin() {
|
|
21
53
|
return {
|
|
22
54
|
name: 'transformReactLynxPlugin',
|
|
@@ -83,6 +115,11 @@ const createVitestConfig = async (options)=>{
|
|
|
83
115
|
globals: true,
|
|
84
116
|
setupFiles: [
|
|
85
117
|
path.join(vitest_config_dirname, 'vitest-global-setup')
|
|
118
|
+
],
|
|
119
|
+
alias: [
|
|
120
|
+
...runtimeOSSAlias,
|
|
121
|
+
...runtimeAlias,
|
|
122
|
+
...preactAlias
|
|
86
123
|
]
|
|
87
124
|
}
|
|
88
125
|
});
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
import { queries, Queries, BoundFunction } from '@testing-library/dom';
|
|
11
11
|
import { LynxElement, type ElementTree, type LynxTestingEnv } from '@lynx-js/testing-environment';
|
|
12
12
|
import { ComponentChild, ComponentType } from 'preact';
|
|
13
|
+
import { act } from 'preact/test-utils';
|
|
13
14
|
export * from '@testing-library/dom';
|
|
14
|
-
export { ElementTree, LynxTestingEnv };
|
|
15
|
+
export { ElementTree, LynxTestingEnv, act };
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* The options for {@link render}.
|
|
@@ -252,6 +253,6 @@ export function renderHook<Result, Props>(
|
|
|
252
253
|
*
|
|
253
254
|
* It will be useful when you want to wait for the next event loop to finish.
|
|
254
255
|
*
|
|
255
|
-
* @
|
|
256
|
+
* @deprecated Please use `act` instead
|
|
256
257
|
*/
|
|
257
258
|
export function waitSchedule(): Promise<void>;
|