@lynx-js/react 0.111.1 → 0.111.2
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 +52 -0
- package/components/lib/DeferredListItem.d.ts +3 -1
- package/components/lib/DeferredListItem.jsx +4 -2
- package/components/lib/DeferredListItem.jsx.map +1 -1
- package/components/src/DeferredListItem.tsx +5 -3
- package/package.json +6 -1
- package/refresh/.turbo/turbo-build.log +1 -1
- package/runtime/debug/index.cjs +8 -0
- package/runtime/debug/index.d.ts +4 -0
- package/runtime/debug/index.js +5 -0
- package/runtime/lib/alog/index.d.ts +1 -0
- package/runtime/lib/alog/index.js +8 -0
- package/runtime/lib/alog/index.js.map +1 -0
- package/runtime/lib/alog/render.d.ts +1 -0
- package/runtime/lib/alog/render.js +19 -0
- package/runtime/lib/alog/render.js.map +1 -0
- package/runtime/lib/backgroundSnapshot.d.ts +1 -0
- package/runtime/lib/backgroundSnapshot.js +31 -17
- package/runtime/lib/backgroundSnapshot.js.map +1 -1
- package/runtime/lib/debug/component-stack.d.ts +33 -0
- package/runtime/lib/debug/component-stack.js +145 -0
- package/runtime/lib/debug/component-stack.js.map +1 -0
- package/runtime/lib/debug/formatPatch.d.ts +2 -0
- package/runtime/lib/debug/formatPatch.js +27 -0
- package/runtime/lib/debug/formatPatch.js.map +1 -0
- package/runtime/lib/debug/printSnapshot.d.ts +1 -1
- package/runtime/lib/debug/printSnapshot.js +0 -4
- package/runtime/lib/debug/printSnapshot.js.map +1 -1
- package/runtime/lib/debug/profile.js +1 -3
- package/runtime/lib/debug/profile.js.map +1 -1
- package/runtime/lib/hydrate.js +11 -7
- package/runtime/lib/hydrate.js.map +1 -1
- package/runtime/lib/lifecycle/patch/commit.js +1 -1
- package/runtime/lib/lifecycle/patch/commit.js.map +1 -1
- package/runtime/lib/lifecycle/patch/snapshotPatch.d.ts +4 -0
- package/runtime/lib/lifecycle/patch/snapshotPatch.js +28 -0
- package/runtime/lib/lifecycle/patch/snapshotPatch.js.map +1 -1
- package/runtime/lib/lynx.js +9 -0
- package/runtime/lib/lynx.js.map +1 -1
- package/runtime/lib/pendingListUpdates.d.ts +2 -1
- package/runtime/lib/pendingListUpdates.js +16 -4
- package/runtime/lib/pendingListUpdates.js.map +1 -1
- package/runtime/lib/renderToOpcodes/constants.d.ts +2 -0
- package/runtime/lib/renderToOpcodes/constants.js +2 -0
- package/runtime/lib/renderToOpcodes/constants.js.map +1 -1
- package/runtime/lib/root.d.ts +6 -0
- package/runtime/lib/root.js +4 -0
- package/runtime/lib/root.js.map +1 -1
- package/runtime/lib/snapshot/platformInfo.js +5 -3
- package/runtime/lib/snapshot/platformInfo.js.map +1 -1
- package/runtime/lib/snapshot/ref.d.ts +2 -2
- package/runtime/lib/snapshot/spread.js +3 -1
- package/runtime/lib/snapshot/spread.js.map +1 -1
- package/runtime/lib/snapshot.js +13 -7
- package/runtime/lib/snapshot.js.map +1 -1
- package/runtime/lib/utils.d.ts +2 -0
- package/runtime/lib/utils.js +23 -2
- package/runtime/lib/utils.js.map +1 -1
- package/testing-library/dist/env/vitest.js +12 -4
- package/types/react.d.ts +13 -1
- package/runtime/src/backgroundSnapshot.ts +0 -501
- package/runtime/src/compat/componentIs.ts +0 -30
- package/runtime/src/compat/initData.ts +0 -150
- package/runtime/src/compat/lynxComponent.ts +0 -79
- package/runtime/src/debug/debug.ts +0 -9
- package/runtime/src/debug/printSnapshot.ts +0 -28
- package/runtime/src/debug/profile.ts +0 -55
- package/runtime/src/document.ts +0 -84
- package/runtime/src/gesture/processGesture.ts +0 -89
- package/runtime/src/gesture/processGestureBagkround.ts +0 -19
- package/runtime/src/gesture/types.ts +0 -44
- package/runtime/src/hooks/react.ts +0 -62
- package/runtime/src/hooks/useLynxGlobalEventListener.ts +0 -59
- package/runtime/src/hydrate.ts +0 -368
- package/runtime/src/index.ts +0 -94
- package/runtime/src/internal.ts +0 -63
- package/runtime/src/legacy-react-runtime/index.ts +0 -42
- package/runtime/src/lifecycle/destroy.ts +0 -34
- package/runtime/src/lifecycle/event/delayEvents.ts +0 -11
- package/runtime/src/lifecycle/event/delayLifecycleEvents.ts +0 -15
- package/runtime/src/lifecycle/event/jsReady.ts +0 -34
- package/runtime/src/lifecycle/pass.ts +0 -14
- package/runtime/src/lifecycle/patch/commit.ts +0 -214
- package/runtime/src/lifecycle/patch/error.ts +0 -61
- package/runtime/src/lifecycle/patch/isMainThreadHydrationFinished.ts +0 -13
- package/runtime/src/lifecycle/patch/snapshotPatch.ts +0 -65
- package/runtime/src/lifecycle/patch/snapshotPatchApply.ts +0 -145
- package/runtime/src/lifecycle/patch/updateMainThread.ts +0 -64
- package/runtime/src/lifecycle/ref/delay.ts +0 -99
- package/runtime/src/lifecycle/reload.ts +0 -97
- package/runtime/src/lifecycle/render.ts +0 -54
- package/runtime/src/lifecycleConstant.ts +0 -21
- package/runtime/src/list.ts +0 -307
- package/runtime/src/listUpdateInfo.ts +0 -221
- package/runtime/src/lynx/calledByNative.ts +0 -160
- package/runtime/src/lynx/component.ts +0 -113
- package/runtime/src/lynx/dynamic-js.ts +0 -36
- package/runtime/src/lynx/env.ts +0 -109
- package/runtime/src/lynx/injectLepusMethods.ts +0 -53
- package/runtime/src/lynx/lazy-bundle.ts +0 -175
- package/runtime/src/lynx/performance.ts +0 -148
- package/runtime/src/lynx/runWithForce.ts +0 -67
- package/runtime/src/lynx/tt.ts +0 -215
- package/runtime/src/lynx-api.ts +0 -455
- package/runtime/src/lynx.ts +0 -58
- package/runtime/src/opcodes.ts +0 -155
- package/runtime/src/pendingListUpdates.ts +0 -18
- package/runtime/src/renderToOpcodes/constants.ts +0 -24
- package/runtime/src/renderToOpcodes/index.ts +0 -306
- package/runtime/src/root.ts +0 -23
- package/runtime/src/snapshot/dynamicPartType.ts +0 -16
- package/runtime/src/snapshot/event.ts +0 -33
- package/runtime/src/snapshot/gesture.ts +0 -30
- package/runtime/src/snapshot/list.ts +0 -36
- package/runtime/src/snapshot/platformInfo.ts +0 -62
- package/runtime/src/snapshot/ref.ts +0 -139
- package/runtime/src/snapshot/spread.ts +0 -330
- package/runtime/src/snapshot/workletEvent.ts +0 -35
- package/runtime/src/snapshot/workletRef.ts +0 -88
- package/runtime/src/snapshot.ts +0 -634
- package/runtime/src/snapshotInstanceHydrationMap.ts +0 -17
- package/runtime/src/utils.ts +0 -44
- package/runtime/src/worklet/ctx.ts +0 -22
- package/runtime/src/worklet/destroy.ts +0 -16
- package/runtime/src/worklet/execMap.ts +0 -51
- package/runtime/src/worklet/functionCall.ts +0 -42
- package/runtime/src/worklet/functionality.ts +0 -29
- package/runtime/src/worklet/hmr.ts +0 -34
- package/runtime/src/worklet/indexMap.ts +0 -23
- package/runtime/src/worklet/runOnBackground.ts +0 -147
- package/runtime/src/worklet/runOnMainThread.ts +0 -50
- package/runtime/src/worklet/transformToWorklet.ts +0 -26
- package/runtime/src/worklet/workletRef.ts +0 -231
- package/runtime/src/worklet/workletRefPool.ts +0 -29
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Implements the commit phase of the rendering lifecycle.
|
|
7
|
-
* This module patches Preact's commit phase to integrate with the snapshot system,
|
|
8
|
-
* handling the collection and transmission of patches between threads.
|
|
9
|
-
*
|
|
10
|
-
* The commit phase is responsible for:
|
|
11
|
-
* - Collecting patches from the snapshot system
|
|
12
|
-
* - Managing commit tasks and their execution
|
|
13
|
-
* - Coordinating with the native layer for updates
|
|
14
|
-
* - Handling performance timing and pipeline options
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* This module patches Preact's commit phase by hacking into the internal of
|
|
19
|
-
* its [options](https://preactjs.com/guide/v10/options/) API
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import type { VNode } from 'preact';
|
|
23
|
-
import { options } from 'preact';
|
|
24
|
-
|
|
25
|
-
import { LifecycleConstant } from '../../lifecycleConstant.js';
|
|
26
|
-
import { globalPipelineOptions, markTiming, markTimingLegacy, setPipeline } from '../../lynx/performance.js';
|
|
27
|
-
import { COMMIT } from '../../renderToOpcodes/constants.js';
|
|
28
|
-
import { applyQueuedRefs } from '../../snapshot/ref.js';
|
|
29
|
-
import { backgroundSnapshotInstanceManager } from '../../snapshot.js';
|
|
30
|
-
import { isEmptyObject } from '../../utils.js';
|
|
31
|
-
import { takeWorkletRefInitValuePatch } from '../../worklet/workletRefPool.js';
|
|
32
|
-
import { getReloadVersion } from '../pass.js';
|
|
33
|
-
import type { SnapshotPatch } from './snapshotPatch.js';
|
|
34
|
-
import { takeGlobalSnapshotPatch } from './snapshotPatch.js';
|
|
35
|
-
|
|
36
|
-
let globalFlushOptions: FlushOptions = {};
|
|
37
|
-
|
|
38
|
-
const globalCommitTaskMap: Map<number, () => void> = /*@__PURE__*/ new Map<number, () => void>();
|
|
39
|
-
let nextCommitTaskId = 1;
|
|
40
|
-
|
|
41
|
-
let globalBackgroundSnapshotInstancesToRemove: number[] = [];
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* A single patch operation.
|
|
45
|
-
*/
|
|
46
|
-
interface Patch {
|
|
47
|
-
// TODO: ref: do we need `id`?
|
|
48
|
-
id: number;
|
|
49
|
-
snapshotPatch?: SnapshotPatch;
|
|
50
|
-
workletRefInitValuePatch?: [id: number, value: unknown][];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* List of patches to be applied in a single update cycle with flush options.
|
|
55
|
-
*/
|
|
56
|
-
interface PatchList {
|
|
57
|
-
patchList: Patch[];
|
|
58
|
-
flushOptions?: FlushOptions;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Configuration options for patch operations
|
|
63
|
-
*/
|
|
64
|
-
interface PatchOptions {
|
|
65
|
-
pipelineOptions?: PipelineOptions;
|
|
66
|
-
reloadVersion: number;
|
|
67
|
-
isHydration?: boolean;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Replaces Preact's default commit hook with our custom implementation
|
|
72
|
-
*/
|
|
73
|
-
function replaceCommitHook(): void {
|
|
74
|
-
// This is actually not used since Preact use `hooks._commit` for callbacks of `useLayoutEffect`.
|
|
75
|
-
const originalPreactCommit = options[COMMIT];
|
|
76
|
-
const commit = async (vnode: VNode, commitQueue: any[]) => {
|
|
77
|
-
// Skip commit phase for MT runtime
|
|
78
|
-
if (__MAIN_THREAD__) {
|
|
79
|
-
// for testing only
|
|
80
|
-
commitQueue.length = 0;
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Mark the end of virtual DOM diffing phase for performance tracking
|
|
85
|
-
markTimingLegacy('updateDiffVdomEnd');
|
|
86
|
-
markTiming('diffVdomEnd');
|
|
87
|
-
|
|
88
|
-
const backgroundSnapshotInstancesToRemove = globalBackgroundSnapshotInstancesToRemove;
|
|
89
|
-
globalBackgroundSnapshotInstancesToRemove = [];
|
|
90
|
-
|
|
91
|
-
const commitTaskId = genCommitTaskId();
|
|
92
|
-
|
|
93
|
-
// Register the commit task
|
|
94
|
-
globalCommitTaskMap.set(commitTaskId, () => {
|
|
95
|
-
if (backgroundSnapshotInstancesToRemove.length) {
|
|
96
|
-
setTimeout(() => {
|
|
97
|
-
backgroundSnapshotInstancesToRemove.forEach(id => {
|
|
98
|
-
backgroundSnapshotInstanceManager.values.delete(id);
|
|
99
|
-
});
|
|
100
|
-
}, 10000);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Collect patches for this update
|
|
105
|
-
const snapshotPatch = takeGlobalSnapshotPatch();
|
|
106
|
-
const flushOptions = globalFlushOptions;
|
|
107
|
-
const workletRefInitValuePatch = takeWorkletRefInitValuePatch();
|
|
108
|
-
globalFlushOptions = {};
|
|
109
|
-
if (!snapshotPatch && workletRefInitValuePatch.length === 0) {
|
|
110
|
-
// before hydration, skip patch
|
|
111
|
-
applyQueuedRefs();
|
|
112
|
-
originalPreactCommit?.(vnode, commitQueue);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const patch: Patch = {
|
|
117
|
-
id: commitTaskId,
|
|
118
|
-
};
|
|
119
|
-
// TODO: check all fields in `flushOptions` from runtime3
|
|
120
|
-
if (snapshotPatch?.length) {
|
|
121
|
-
patch.snapshotPatch = snapshotPatch;
|
|
122
|
-
}
|
|
123
|
-
if (workletRefInitValuePatch.length) {
|
|
124
|
-
patch.workletRefInitValuePatch = workletRefInitValuePatch;
|
|
125
|
-
}
|
|
126
|
-
const patchList: PatchList = {
|
|
127
|
-
patchList: [patch],
|
|
128
|
-
};
|
|
129
|
-
if (!isEmptyObject(flushOptions)) {
|
|
130
|
-
patchList.flushOptions = flushOptions;
|
|
131
|
-
}
|
|
132
|
-
const obj = commitPatchUpdate(patchList, {});
|
|
133
|
-
|
|
134
|
-
// Send the update to the native layer
|
|
135
|
-
lynx.getNativeApp().callLepusMethod(LifecycleConstant.patchUpdate, obj, () => {
|
|
136
|
-
const commitTask = globalCommitTaskMap.get(commitTaskId);
|
|
137
|
-
if (commitTask) {
|
|
138
|
-
commitTask();
|
|
139
|
-
globalCommitTaskMap.delete(commitTaskId);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
applyQueuedRefs();
|
|
144
|
-
originalPreactCommit?.(vnode, commitQueue);
|
|
145
|
-
};
|
|
146
|
-
options[COMMIT] = commit as ((...args: Parameters<typeof commit>) => void);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Prepares the patch update for transmission to the native layer
|
|
151
|
-
*/
|
|
152
|
-
function commitPatchUpdate(patchList: PatchList, patchOptions: Omit<PatchOptions, 'reloadVersion'>): {
|
|
153
|
-
data: string;
|
|
154
|
-
patchOptions: PatchOptions;
|
|
155
|
-
} {
|
|
156
|
-
// console.debug('********** JS update:');
|
|
157
|
-
// printSnapshotInstance(
|
|
158
|
-
// (backgroundSnapshotInstanceManager.values.get(1) || backgroundSnapshotInstanceManager.values.get(-1))!,
|
|
159
|
-
// );
|
|
160
|
-
// console.debug('commitPatchUpdate: ', JSON.stringify(patchList));
|
|
161
|
-
if (__PROFILE__) {
|
|
162
|
-
console.profile('commitChanges');
|
|
163
|
-
}
|
|
164
|
-
markTiming('packChangesStart');
|
|
165
|
-
const obj: {
|
|
166
|
-
data: string;
|
|
167
|
-
patchOptions: PatchOptions;
|
|
168
|
-
} = {
|
|
169
|
-
data: JSON.stringify(patchList),
|
|
170
|
-
patchOptions: {
|
|
171
|
-
...patchOptions,
|
|
172
|
-
reloadVersion: getReloadVersion(),
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
markTiming('packChangesEnd');
|
|
176
|
-
if (globalPipelineOptions) {
|
|
177
|
-
obj.patchOptions.pipelineOptions = globalPipelineOptions;
|
|
178
|
-
setPipeline(undefined);
|
|
179
|
-
}
|
|
180
|
-
if (__PROFILE__) {
|
|
181
|
-
console.profileEnd();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return obj;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Generates a unique ID for commit tasks
|
|
189
|
-
*/
|
|
190
|
-
function genCommitTaskId(): number {
|
|
191
|
-
return nextCommitTaskId++;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Resets the commit task ID counter
|
|
196
|
-
*/
|
|
197
|
-
function clearCommitTaskId(): void {
|
|
198
|
-
nextCommitTaskId = 1;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* @internal
|
|
203
|
-
*/
|
|
204
|
-
export {
|
|
205
|
-
clearCommitTaskId,
|
|
206
|
-
commitPatchUpdate,
|
|
207
|
-
genCommitTaskId,
|
|
208
|
-
globalBackgroundSnapshotInstancesToRemove,
|
|
209
|
-
globalCommitTaskMap,
|
|
210
|
-
globalFlushOptions,
|
|
211
|
-
replaceCommitHook,
|
|
212
|
-
type PatchList,
|
|
213
|
-
type PatchOptions,
|
|
214
|
-
};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// Copyright 2025 The Lynx Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
|
|
5
|
-
import { backgroundSnapshotInstanceManager, snapshotManager } from '../../snapshot.js';
|
|
6
|
-
|
|
7
|
-
export const ctxNotFoundType = 'Lynx.Error.CtxNotFound';
|
|
8
|
-
|
|
9
|
-
const errorMsg = 'snapshotPatchApply failed: ctx not found';
|
|
10
|
-
|
|
11
|
-
let ctxNotFoundEventListener: ((e: RuntimeProxy.Event) => void) | null = null;
|
|
12
|
-
|
|
13
|
-
export interface CtxNotFoundData {
|
|
14
|
-
id: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function sendCtxNotFoundEventToBackground(id: number): void {
|
|
18
|
-
/* v8 ignore next 3 */
|
|
19
|
-
if (!lynx.getJSContext) {
|
|
20
|
-
throw new Error(errorMsg);
|
|
21
|
-
}
|
|
22
|
-
lynx.getJSContext().dispatchEvent({
|
|
23
|
-
type: ctxNotFoundType,
|
|
24
|
-
data: {
|
|
25
|
-
id,
|
|
26
|
-
} as CtxNotFoundData,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function reportCtxNotFound(data: CtxNotFoundData): void {
|
|
31
|
-
const id = data.id;
|
|
32
|
-
const instance = backgroundSnapshotInstanceManager.values.get(id);
|
|
33
|
-
|
|
34
|
-
let snapshotType = 'null';
|
|
35
|
-
|
|
36
|
-
if (instance && instance.__snapshot_def) {
|
|
37
|
-
for (const [snapshotId, snapshot] of snapshotManager.values.entries()) {
|
|
38
|
-
if (snapshot === instance.__snapshot_def) {
|
|
39
|
-
snapshotType = snapshotId;
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
lynx.reportError(new Error(`${errorMsg}, snapshot type: '${snapshotType}'`));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function addCtxNotFoundEventListener(): void {
|
|
49
|
-
ctxNotFoundEventListener = (e) => {
|
|
50
|
-
reportCtxNotFound(e.data as CtxNotFoundData);
|
|
51
|
-
};
|
|
52
|
-
lynx.getCoreContext?.().addEventListener(ctxNotFoundType, ctxNotFoundEventListener);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function removeCtxNotFoundEventListener(): void {
|
|
56
|
-
const coreContext = lynx.getCoreContext?.();
|
|
57
|
-
if (coreContext && ctxNotFoundEventListener) {
|
|
58
|
-
coreContext.removeEventListener(ctxNotFoundType, ctxNotFoundEventListener);
|
|
59
|
-
ctxNotFoundEventListener = null;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Copyright 2025 The Lynx Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
import { onHydrationFinished } from '@lynx-js/react/worklet-runtime/bindings';
|
|
5
|
-
|
|
6
|
-
export let isMainThreadHydrationFinished = false;
|
|
7
|
-
|
|
8
|
-
export function setMainThreadHydrationFinished(isFinished: boolean): void {
|
|
9
|
-
if (isFinished && !isMainThreadHydrationFinished) {
|
|
10
|
-
onHydrationFinished();
|
|
11
|
-
}
|
|
12
|
-
isMainThreadHydrationFinished = isFinished;
|
|
13
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Defines the core patch operations for the snapshot system.
|
|
7
|
-
* The patch operations are designed to be serializable and minimal, allowing
|
|
8
|
-
* efficient transmission between threads and application to element tree.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
export const SnapshotOperation = {
|
|
12
|
-
CreateElement: 0,
|
|
13
|
-
InsertBefore: 1,
|
|
14
|
-
RemoveChild: 2,
|
|
15
|
-
SetAttribute: 3,
|
|
16
|
-
SetAttributes: 4,
|
|
17
|
-
|
|
18
|
-
DEV_ONLY_AddSnapshot: 100,
|
|
19
|
-
DEV_ONLY_RegisterWorklet: 101,
|
|
20
|
-
} as const;
|
|
21
|
-
|
|
22
|
-
// Operation format definitions:
|
|
23
|
-
//
|
|
24
|
-
// [opcode: SnapshotOperation.CreateElement, type: string, id: number]
|
|
25
|
-
// [opcode: SnapshotOperation.InsertBefore, parentId: number, id: number, beforeId: number | undefined]
|
|
26
|
-
// [opcode: SnapshotOperation.RemoveChild, parentId: number, childId: number]
|
|
27
|
-
// [opcode: SnapshotOperation.SetAttribute, id: number, dynamicPartIndex: number, value: any]
|
|
28
|
-
// [opcode: SnapshotOperation.SetAttributes, id: number, value: any]
|
|
29
|
-
// [
|
|
30
|
-
// opcode: SnapshotOperation.DEV_ONLY_AddSnapshot,
|
|
31
|
-
// uniqID: string,
|
|
32
|
-
// create: string,
|
|
33
|
-
// update: string[],
|
|
34
|
-
// /** The same as Snapshot['slot'] */
|
|
35
|
-
// slot: [DynamicPartType, number][],
|
|
36
|
-
// cssId: number | undefined,
|
|
37
|
-
// entryName: string | undefined
|
|
38
|
-
// ]
|
|
39
|
-
// [
|
|
40
|
-
// opcode: SnapshotOperation.DEV_ONLY_RegisterWorklet,
|
|
41
|
-
// hash: string,
|
|
42
|
-
// fn: string,
|
|
43
|
-
// ]
|
|
44
|
-
|
|
45
|
-
export type SnapshotPatch = unknown[];
|
|
46
|
-
|
|
47
|
-
export let __globalSnapshotPatch: SnapshotPatch | undefined;
|
|
48
|
-
|
|
49
|
-
export function takeGlobalSnapshotPatch(): SnapshotPatch | undefined {
|
|
50
|
-
if (__globalSnapshotPatch) {
|
|
51
|
-
const list = __globalSnapshotPatch;
|
|
52
|
-
__globalSnapshotPatch = [];
|
|
53
|
-
return list;
|
|
54
|
-
} else {
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function initGlobalSnapshotPatch(): void {
|
|
60
|
-
__globalSnapshotPatch = [];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function deinitGlobalSnapshotPatch(): void {
|
|
64
|
-
__globalSnapshotPatch = undefined;
|
|
65
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Implements the patch application logic for the snapshot system.
|
|
7
|
-
* This module is responsible for interpreting and executing patch operations
|
|
8
|
-
* that were generated in the background thread, applying them to the DOM
|
|
9
|
-
* in the main thread.
|
|
10
|
-
*
|
|
11
|
-
* The module handles various operations like element creation, insertion,
|
|
12
|
-
* removal, and attribute updates, ensuring they are applied in the correct
|
|
13
|
-
* order and with proper error handling.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { sendCtxNotFoundEventToBackground } from './error.js';
|
|
17
|
-
import type { SnapshotPatch } from './snapshotPatch.js';
|
|
18
|
-
import { SnapshotOperation } from './snapshotPatch.js';
|
|
19
|
-
import type { DynamicPartType } from '../../snapshot/dynamicPartType.js';
|
|
20
|
-
import {
|
|
21
|
-
SnapshotInstance,
|
|
22
|
-
createSnapshot,
|
|
23
|
-
entryUniqID,
|
|
24
|
-
snapshotInstanceManager,
|
|
25
|
-
snapshotManager,
|
|
26
|
-
} from '../../snapshot.js';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Applies a patch of snapshot operations to the main thread.
|
|
30
|
-
* This is the counterpart to the patch generation in the background thread.
|
|
31
|
-
* Each operation in the patch is processed sequentially to update the DOM.
|
|
32
|
-
*/
|
|
33
|
-
export function snapshotPatchApply(snapshotPatch: SnapshotPatch): void {
|
|
34
|
-
const length = snapshotPatch.length;
|
|
35
|
-
for (let i = 0; i < length; ++i) {
|
|
36
|
-
switch (snapshotPatch[i]) {
|
|
37
|
-
case SnapshotOperation.CreateElement: {
|
|
38
|
-
const type = snapshotPatch[++i] as string;
|
|
39
|
-
const id = snapshotPatch[++i] as number;
|
|
40
|
-
new SnapshotInstance(type, id);
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
case SnapshotOperation.InsertBefore: {
|
|
44
|
-
const parentId = snapshotPatch[++i] as number;
|
|
45
|
-
const childId = snapshotPatch[++i] as number;
|
|
46
|
-
const beforeId = snapshotPatch[++i] as number | undefined;
|
|
47
|
-
const parent = snapshotInstanceManager.values.get(parentId);
|
|
48
|
-
const child = snapshotInstanceManager.values.get(childId);
|
|
49
|
-
const existingNode = snapshotInstanceManager.values.get(beforeId!);
|
|
50
|
-
if (!parent || !child) {
|
|
51
|
-
sendCtxNotFoundEventToBackground(parent ? childId : parentId);
|
|
52
|
-
} else {
|
|
53
|
-
parent.insertBefore(child, existingNode);
|
|
54
|
-
}
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
case SnapshotOperation.RemoveChild: {
|
|
58
|
-
const parentId = snapshotPatch[++i] as number;
|
|
59
|
-
const childId = snapshotPatch[++i] as number;
|
|
60
|
-
const parent = snapshotInstanceManager.values.get(parentId);
|
|
61
|
-
const child = snapshotInstanceManager.values.get(childId);
|
|
62
|
-
if (!parent || !child) {
|
|
63
|
-
sendCtxNotFoundEventToBackground(parent ? childId : parentId);
|
|
64
|
-
} else {
|
|
65
|
-
parent.removeChild(child);
|
|
66
|
-
}
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
case SnapshotOperation.SetAttribute: {
|
|
70
|
-
const id = snapshotPatch[++i] as number;
|
|
71
|
-
const dynamicPartIndex = snapshotPatch[++i] as number;
|
|
72
|
-
const value = snapshotPatch[++i];
|
|
73
|
-
const si = snapshotInstanceManager.values.get(id);
|
|
74
|
-
if (si) {
|
|
75
|
-
si.setAttribute(dynamicPartIndex, value);
|
|
76
|
-
} else {
|
|
77
|
-
sendCtxNotFoundEventToBackground(id);
|
|
78
|
-
}
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
case SnapshotOperation.SetAttributes: {
|
|
82
|
-
const id = snapshotPatch[++i] as number;
|
|
83
|
-
const values = snapshotPatch[++i];
|
|
84
|
-
const si = snapshotInstanceManager.values.get(id);
|
|
85
|
-
if (si) {
|
|
86
|
-
si.setAttribute('values', values);
|
|
87
|
-
} else {
|
|
88
|
-
sendCtxNotFoundEventToBackground(id);
|
|
89
|
-
}
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
case SnapshotOperation.DEV_ONLY_AddSnapshot: {
|
|
93
|
-
if (__DEV__) {
|
|
94
|
-
const uniqID = snapshotPatch[++i] as string;
|
|
95
|
-
const create = snapshotPatch[++i] as string;
|
|
96
|
-
const update = snapshotPatch[++i] as string[];
|
|
97
|
-
const slot = snapshotPatch[++i] as [DynamicPartType, number][];
|
|
98
|
-
const cssId = (snapshotPatch[++i] ?? 0) as number;
|
|
99
|
-
const entryName = snapshotPatch[++i] as string | undefined;
|
|
100
|
-
|
|
101
|
-
if (!snapshotManager.values.has(entryUniqID(uniqID, entryName))) {
|
|
102
|
-
// HMR-related
|
|
103
|
-
// Update the evaluated snapshots from JS.
|
|
104
|
-
createSnapshot(
|
|
105
|
-
uniqID,
|
|
106
|
-
evaluate<(ctx: SnapshotInstance) => FiberElement[]>(create),
|
|
107
|
-
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
108
|
-
update.map<(ctx: SnapshotInstance, index: number, oldValue: any) => void>(evaluate),
|
|
109
|
-
slot,
|
|
110
|
-
cssId,
|
|
111
|
-
entryName,
|
|
112
|
-
null,
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
// case SnapshotOperation.DEV_ONLY_RegisterWorklet: {
|
|
119
|
-
// // HMR-related
|
|
120
|
-
// if (__DEV__) {
|
|
121
|
-
// const hash: string = snapshotPatch[++i];
|
|
122
|
-
// const fnStr: string = snapshotPatch[++i];
|
|
123
|
-
// const fn = evaluate<(ctx: SnapshotInstance) => FiberElement[]>(fnStr);
|
|
124
|
-
// registerWorklet('main-thread', hash, fn);
|
|
125
|
-
// }
|
|
126
|
-
// break;
|
|
127
|
-
// }
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/* v8 ignore start */
|
|
133
|
-
/**
|
|
134
|
-
* Evaluates a string as code with ReactLynx runtime injected.
|
|
135
|
-
* Used for HMR (Hot Module Replacement) to update snapshot definitions.
|
|
136
|
-
*/
|
|
137
|
-
function evaluate<T>(code: string): T {
|
|
138
|
-
if (__DEV__) {
|
|
139
|
-
// We are using `eval` here to make the updated snapshot to access variables like `__webpack_require__`.
|
|
140
|
-
// See: https://github.com/lynx-family/lynx-stack/issues/983.
|
|
141
|
-
return eval(`(() => ${code})()`) as T;
|
|
142
|
-
}
|
|
143
|
-
throw new Error('unreachable: evaluate is not supported in production');
|
|
144
|
-
}
|
|
145
|
-
/* v8 ignore stop */
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// Copyright 2025 The Lynx Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
|
|
5
|
-
import { updateWorkletRefInitValueChanges } from '@lynx-js/react/worklet-runtime/bindings';
|
|
6
|
-
|
|
7
|
-
import type { PatchList, PatchOptions } from './commit.js';
|
|
8
|
-
import { setMainThreadHydrationFinished } from './isMainThreadHydrationFinished.js';
|
|
9
|
-
import { snapshotPatchApply } from './snapshotPatchApply.js';
|
|
10
|
-
import { LifecycleConstant } from '../../lifecycleConstant.js';
|
|
11
|
-
import { markTiming, setPipeline } from '../../lynx/performance.js';
|
|
12
|
-
import { __pendingListUpdates } from '../../pendingListUpdates.js';
|
|
13
|
-
import { applyRefQueue } from '../../snapshot/workletRef.js';
|
|
14
|
-
import { __page } from '../../snapshot.js';
|
|
15
|
-
import { getReloadVersion } from '../pass.js';
|
|
16
|
-
|
|
17
|
-
function updateMainThread(
|
|
18
|
-
{ data, patchOptions }: {
|
|
19
|
-
data: string;
|
|
20
|
-
patchOptions: PatchOptions;
|
|
21
|
-
},
|
|
22
|
-
): void {
|
|
23
|
-
if ((patchOptions.reloadVersion) < getReloadVersion()) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
setPipeline(patchOptions.pipelineOptions);
|
|
28
|
-
markTiming('mtsRenderStart');
|
|
29
|
-
markTiming('parseChangesStart');
|
|
30
|
-
const { patchList, flushOptions = {} } = JSON.parse(data) as PatchList;
|
|
31
|
-
|
|
32
|
-
markTiming('parseChangesEnd');
|
|
33
|
-
markTiming('patchChangesStart');
|
|
34
|
-
|
|
35
|
-
for (const { snapshotPatch, workletRefInitValuePatch } of patchList) {
|
|
36
|
-
updateWorkletRefInitValueChanges(workletRefInitValuePatch);
|
|
37
|
-
__pendingListUpdates.clear();
|
|
38
|
-
if (snapshotPatch) {
|
|
39
|
-
snapshotPatchApply(snapshotPatch);
|
|
40
|
-
}
|
|
41
|
-
__pendingListUpdates.flush();
|
|
42
|
-
// console.debug('********** Lepus updatePatch:');
|
|
43
|
-
// printSnapshotInstance(snapshotInstanceManager.values.get(-1)!);
|
|
44
|
-
}
|
|
45
|
-
markTiming('patchChangesEnd');
|
|
46
|
-
markTiming('mtsRenderEnd');
|
|
47
|
-
if (patchOptions.isHydration) {
|
|
48
|
-
setMainThreadHydrationFinished(true);
|
|
49
|
-
}
|
|
50
|
-
applyRefQueue();
|
|
51
|
-
if (patchOptions.pipelineOptions) {
|
|
52
|
-
flushOptions.pipelineOptions = patchOptions.pipelineOptions;
|
|
53
|
-
}
|
|
54
|
-
__FlushElementTree(__page, flushOptions);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function injectUpdateMainThread(): void {
|
|
58
|
-
Object.assign(globalThis, { [LifecycleConstant.patchUpdate]: updateMainThread });
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @internal
|
|
63
|
-
*/
|
|
64
|
-
export { injectUpdateMainThread };
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
|
|
5
|
-
import type { NodesRef, SelectorQuery } from '@lynx-js/types';
|
|
6
|
-
|
|
7
|
-
import { hydrationMap } from '../../snapshotInstanceHydrationMap.js';
|
|
8
|
-
|
|
9
|
-
type RefTask = (nodesRef: NodesRef) => SelectorQuery;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* A flag to indicate whether UI operations should be delayed.
|
|
13
|
-
* When set to true, UI operations will be queued in the `delayedUiOps` array
|
|
14
|
-
* and executed later when `runDelayedUiOps` is called.
|
|
15
|
-
* This is used before hydration to ensure UI operations are batched
|
|
16
|
-
* and executed at the appropriate time.
|
|
17
|
-
*/
|
|
18
|
-
const shouldDelayUiOps = { value: true };
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* An array of functions that will be executed later when `runDelayedUiOps` is called.
|
|
22
|
-
* These functions contain UI operations that need to be delayed.
|
|
23
|
-
*/
|
|
24
|
-
const delayedUiOps: (() => void)[] = [];
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Runs a task either immediately or delays it based on the `shouldDelayUiOps` flag.
|
|
28
|
-
* @param task - The function to execute.
|
|
29
|
-
*/
|
|
30
|
-
function runOrDelay(task: () => void): void {
|
|
31
|
-
if (shouldDelayUiOps.value) {
|
|
32
|
-
delayedUiOps.push(task);
|
|
33
|
-
} else {
|
|
34
|
-
task();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Executes all delayed UI operations.
|
|
40
|
-
*/
|
|
41
|
-
function runDelayedUiOps(): void {
|
|
42
|
-
for (const task of delayedUiOps) {
|
|
43
|
-
task();
|
|
44
|
-
}
|
|
45
|
-
shouldDelayUiOps.value = false;
|
|
46
|
-
delayedUiOps.length = 0;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* A proxy class designed for managing and executing reference-based tasks.
|
|
51
|
-
* It delays the execution of tasks until hydration is complete.
|
|
52
|
-
*/
|
|
53
|
-
class RefProxy {
|
|
54
|
-
private readonly refAttr: [snapshotInstanceId: number, expIndex: number];
|
|
55
|
-
private task: RefTask | undefined;
|
|
56
|
-
|
|
57
|
-
constructor(refAttr: [snapshotInstanceId: number, expIndex: number]) {
|
|
58
|
-
this.refAttr = refAttr;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private setTask<K extends keyof NodesRef>(
|
|
62
|
-
method: K,
|
|
63
|
-
args: Parameters<NodesRef[K]>,
|
|
64
|
-
): this {
|
|
65
|
-
this.task = (nodesRef) => {
|
|
66
|
-
return (nodesRef[method] as unknown as (...args: any[]) => SelectorQuery)(...args);
|
|
67
|
-
};
|
|
68
|
-
return this;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
invoke(...args: Parameters<NodesRef['invoke']>): RefProxy {
|
|
72
|
-
return new RefProxy(this.refAttr).setTask('invoke', args);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
path(...args: Parameters<NodesRef['path']>): RefProxy {
|
|
76
|
-
return new RefProxy(this.refAttr).setTask('path', args);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
fields(...args: Parameters<NodesRef['fields']>): RefProxy {
|
|
80
|
-
return new RefProxy(this.refAttr).setTask('fields', args);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
setNativeProps(...args: Parameters<NodesRef['setNativeProps']>): RefProxy {
|
|
84
|
-
return new RefProxy(this.refAttr).setTask('setNativeProps', args);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
exec(): void {
|
|
88
|
-
runOrDelay(() => {
|
|
89
|
-
const realRefId = hydrationMap.get(this.refAttr[0]) ?? this.refAttr[0];
|
|
90
|
-
const refSelector = `[react-ref-${realRefId}-${this.refAttr[1]}]`;
|
|
91
|
-
this.task!(lynx.createSelectorQuery().select(refSelector)).exec();
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @internal
|
|
98
|
-
*/
|
|
99
|
-
export { RefProxy, runDelayedUiOps, shouldDelayUiOps };
|