@lynx-js/react 0.110.0 → 0.110.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 +6 -0
- package/components/lib/Page.js.map +1 -1
- package/components/src/Page.ts +1 -1
- package/package.json +1 -1
- package/refresh/.turbo/turbo-build.log +1 -1
- package/runtime/lib/backgroundSnapshot.js +2 -1
- package/runtime/lib/backgroundSnapshot.js.map +1 -1
- package/runtime/lib/compat/initData.d.ts +7 -5
- package/runtime/lib/compat/initData.js +1 -2
- package/runtime/lib/compat/initData.js.map +1 -1
- package/runtime/lib/compat/lynxComponent.js +10 -12
- package/runtime/lib/compat/lynxComponent.js.map +1 -1
- package/runtime/lib/debug/profile.js +1 -0
- package/runtime/lib/debug/profile.js.map +1 -1
- package/runtime/lib/gesture/processGestureBagkround.d.ts +1 -1
- package/runtime/lib/gesture/processGestureBagkround.js +4 -1
- package/runtime/lib/gesture/processGestureBagkround.js.map +1 -1
- package/runtime/lib/gesture/types.js.map +1 -1
- package/runtime/lib/hooks/useLynxGlobalEventListener.d.ts +1 -1
- package/runtime/lib/hydrate.d.ts +1 -1
- package/runtime/lib/hydrate.js +5 -4
- package/runtime/lib/hydrate.js.map +1 -1
- package/runtime/lib/internal.d.ts +3 -2
- package/runtime/lib/internal.js +3 -2
- package/runtime/lib/internal.js.map +1 -1
- package/runtime/lib/legacy-react-runtime/index.js +1 -1
- package/runtime/lib/legacy-react-runtime/index.js.map +1 -1
- package/runtime/lib/lifecycle/patch/snapshotPatchApply.js.map +1 -1
- package/runtime/lib/lifecycle/patch/updateMainThread.js +4 -4
- package/runtime/lib/lifecycle/patch/updateMainThread.js.map +1 -1
- package/runtime/lib/lifecycle/reload.js +1 -1
- package/runtime/lib/lifecycle/reload.js.map +1 -1
- package/runtime/lib/list.d.ts +2 -46
- package/runtime/lib/list.js +23 -200
- package/runtime/lib/list.js.map +1 -1
- package/runtime/lib/listUpdateInfo.d.ts +38 -0
- package/runtime/lib/listUpdateInfo.js +152 -0
- package/runtime/lib/listUpdateInfo.js.map +1 -0
- package/runtime/lib/lynx/calledByNative.js +2 -2
- package/runtime/lib/lynx/calledByNative.js.map +1 -1
- package/runtime/lib/lynx-api.js +3 -0
- package/runtime/lib/lynx-api.js.map +1 -1
- package/runtime/lib/lynx.js +1 -0
- package/runtime/lib/lynx.js.map +1 -1
- package/runtime/lib/opcodes.js +2 -1
- package/runtime/lib/opcodes.js.map +1 -1
- package/runtime/lib/pendingListUpdates.d.ts +6 -0
- package/runtime/lib/pendingListUpdates.js +16 -0
- package/runtime/lib/pendingListUpdates.js.map +1 -0
- package/runtime/lib/renderToOpcodes/index.js +7 -7
- package/runtime/lib/renderToOpcodes/index.js.map +1 -1
- package/runtime/lib/snapshot/dynamicPartType.d.ts +12 -0
- package/runtime/lib/snapshot/dynamicPartType.js +17 -0
- package/runtime/lib/snapshot/dynamicPartType.js.map +1 -0
- package/runtime/lib/snapshot/gesture.js +3 -0
- package/runtime/lib/snapshot/gesture.js.map +1 -1
- package/runtime/lib/snapshot/list.d.ts +3 -0
- package/runtime/lib/snapshot/list.js +23 -0
- package/runtime/lib/snapshot/list.js.map +1 -0
- package/runtime/lib/snapshot/platformInfo.d.ts +10 -0
- package/runtime/lib/snapshot/platformInfo.js +6 -3
- package/runtime/lib/snapshot/platformInfo.js.map +1 -1
- package/runtime/lib/snapshot/ref.d.ts +3 -0
- package/runtime/lib/snapshot/ref.js.map +1 -1
- package/runtime/lib/snapshot/spread.d.ts +2 -2
- package/runtime/lib/snapshot/spread.js +4 -5
- package/runtime/lib/snapshot/spread.js.map +1 -1
- package/runtime/lib/snapshot/workletEvent.js +1 -1
- package/runtime/lib/snapshot/workletEvent.js.map +1 -1
- package/runtime/lib/snapshot/workletRef.d.ts +1 -1
- package/runtime/lib/snapshot/workletRef.js.map +1 -1
- package/runtime/lib/snapshot.d.ts +5 -14
- package/runtime/lib/snapshot.js +18 -27
- package/runtime/lib/snapshot.js.map +1 -1
- package/runtime/lib/snapshotInstanceHydrationMap.js.map +1 -1
- package/runtime/lib/utils.js +1 -1
- package/runtime/lib/utils.js.map +1 -1
- package/runtime/src/backgroundSnapshot.ts +4 -8
- package/runtime/src/compat/initData.ts +10 -9
- package/runtime/src/compat/lynxComponent.ts +12 -13
- package/runtime/src/debug/profile.ts +1 -0
- package/runtime/src/gesture/processGestureBagkround.ts +5 -1
- package/runtime/src/gesture/types.ts +3 -0
- package/runtime/src/hooks/useLynxGlobalEventListener.ts +1 -1
- package/runtime/src/hydrate.ts +6 -4
- package/runtime/src/internal.ts +3 -2
- package/runtime/src/legacy-react-runtime/index.ts +1 -1
- package/runtime/src/lifecycle/patch/snapshotPatchApply.ts +1 -1
- package/runtime/src/lifecycle/patch/updateMainThread.ts +5 -5
- package/runtime/src/lifecycle/reload.ts +1 -1
- package/runtime/src/list.ts +26 -264
- package/runtime/src/listUpdateInfo.ts +221 -0
- package/runtime/src/lynx/calledByNative.ts +2 -2
- package/runtime/src/lynx-api.ts +4 -1
- package/runtime/src/lynx.ts +1 -0
- package/runtime/src/opcodes.ts +2 -1
- package/runtime/src/pendingListUpdates.ts +18 -0
- package/runtime/src/renderToOpcodes/index.ts +7 -7
- package/runtime/src/snapshot/dynamicPartType.ts +16 -0
- package/runtime/src/snapshot/gesture.ts +3 -0
- package/runtime/src/snapshot/list.ts +36 -0
- package/runtime/src/snapshot/platformInfo.ts +19 -5
- package/runtime/src/snapshot/ref.ts +1 -0
- package/runtime/src/snapshot/spread.ts +42 -17
- package/runtime/src/snapshot/workletEvent.ts +1 -1
- package/runtime/src/snapshot/workletRef.ts +1 -1
- package/runtime/src/snapshot.ts +23 -31
- package/runtime/src/snapshotInstanceHydrationMap.ts +1 -1
- package/runtime/src/utils.ts +3 -3
- package/testing-library/dist/env/vitest.js +3 -3
- package/testing-library/dist/vitest.config.js +7 -7
- package/transform/cjs/main.cjs +4 -0
package/runtime/lib/utils.js
CHANGED
package/runtime/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAC1D,MAAM,UAAU,mBAAmB,CAAC,CAAM,EAAE,CAAM;IAChD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IACE,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EACnH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,KAAK,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAC1D,MAAM,UAAU,mBAAmB,CAAC,CAAM,EAAE,CAAM;IAChD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IACE,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EACnH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,KAAK,MAAM,CAAC,IAAI,GAAG;QAAE,OAAO,KAAK,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,KAAa;IACzD,MAAM,cAAc,GAAW,UAAU,CAAC,cAAc,IAAI,KAAK,CAAC;IAClE,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,IAAI,CAAsC,GAAM,EAAE,IAAiB;IACjF,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,MAAoB,CAAC;AAC9B,CAAC"}
|
|
@@ -22,16 +22,12 @@ import {
|
|
|
22
22
|
takeGlobalSnapshotPatch,
|
|
23
23
|
} from './lifecycle/patch/snapshotPatch.js';
|
|
24
24
|
import { globalPipelineOptions } from './lynx/performance.js';
|
|
25
|
+
import { DynamicPartType } from './snapshot/dynamicPartType.js';
|
|
25
26
|
import { clearQueuedRefs, queueRefAttrUpdate } from './snapshot/ref.js';
|
|
26
27
|
import type { Ref } from './snapshot/ref.js';
|
|
27
28
|
import { transformSpread } from './snapshot/spread.js';
|
|
28
29
|
import type { SerializedSnapshotInstance, Snapshot } from './snapshot.js';
|
|
29
|
-
import {
|
|
30
|
-
DynamicPartType,
|
|
31
|
-
backgroundSnapshotInstanceManager,
|
|
32
|
-
snapshotManager,
|
|
33
|
-
traverseSnapshotInstance,
|
|
34
|
-
} from './snapshot.js';
|
|
30
|
+
import { backgroundSnapshotInstanceManager, snapshotManager, traverseSnapshotInstance } from './snapshot.js';
|
|
35
31
|
import { hydrationMap } from './snapshotInstanceHydrationMap.js';
|
|
36
32
|
import { isDirectOrDeepEqual } from './utils.js';
|
|
37
33
|
import { onPostWorkletCtx } from './worklet/ctx.js';
|
|
@@ -206,7 +202,7 @@ export class BackgroundSnapshotInstance {
|
|
|
206
202
|
for (let index = 0; index < value.length; index++) {
|
|
207
203
|
const { needUpdate, valueToCommit } = this.setAttributeImpl(value[index], oldValues[index], index);
|
|
208
204
|
if (needUpdate) {
|
|
209
|
-
__globalSnapshotPatch
|
|
205
|
+
__globalSnapshotPatch.push(
|
|
210
206
|
SnapshotOperation.SetAttribute,
|
|
211
207
|
this.__id,
|
|
212
208
|
index,
|
|
@@ -221,7 +217,7 @@ export class BackgroundSnapshotInstance {
|
|
|
221
217
|
const { valueToCommit } = this.setAttributeImpl(value[index], null, index);
|
|
222
218
|
patch[index] = valueToCommit;
|
|
223
219
|
}
|
|
224
|
-
__globalSnapshotPatch
|
|
220
|
+
__globalSnapshotPatch.push(
|
|
225
221
|
SnapshotOperation.SetAttributes,
|
|
226
222
|
this.__id,
|
|
227
223
|
patch,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
2
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
3
|
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
import type {
|
|
4
|
+
import type { ComponentChildren, Consumer, Context, Provider } from 'preact';
|
|
5
|
+
import type { ComponentClass } from 'react';
|
|
5
6
|
|
|
6
7
|
import { useLynxGlobalEventListener } from '../hooks/useLynxGlobalEventListener.js';
|
|
7
8
|
|
|
@@ -11,23 +12,24 @@ type Getter<T> = {
|
|
|
11
12
|
|
|
12
13
|
// for better reuse if runtime is changed
|
|
13
14
|
export function factory<Data>(
|
|
14
|
-
{ createContext, useState, createElement, useLynxGlobalEventListener: useListener }:
|
|
15
|
+
{ createContext, useState, createElement, useLynxGlobalEventListener: useListener }: {
|
|
16
|
+
createContext: typeof import('preact').createContext;
|
|
17
|
+
useState: typeof import('preact/hooks').useState;
|
|
18
|
+
createElement: typeof import('preact').createElement;
|
|
15
19
|
useLynxGlobalEventListener: typeof useLynxGlobalEventListener;
|
|
16
20
|
},
|
|
17
21
|
prop: '__globalProps' | '__initData',
|
|
18
22
|
eventName: string,
|
|
19
23
|
): Getter<{
|
|
20
24
|
Context: Context<Data>;
|
|
21
|
-
Provider:
|
|
22
|
-
children?: ReactNode | undefined;
|
|
23
|
-
}>;
|
|
25
|
+
Provider: Provider<Data>;
|
|
24
26
|
Consumer: Consumer<Data>;
|
|
25
27
|
use: () => Data;
|
|
26
28
|
useChanged: (callback: (data: Data) => void) => void;
|
|
27
29
|
}> {
|
|
28
30
|
const Context = createContext({} as Data);
|
|
29
31
|
|
|
30
|
-
const Provider
|
|
32
|
+
const Provider = ({ children }: { children?: ComponentChildren }) => {
|
|
31
33
|
const [__, set] = useState<Data>(lynx[prop] as Data);
|
|
32
34
|
|
|
33
35
|
const handleChange = () => {
|
|
@@ -58,8 +60,7 @@ export function factory<Data>(
|
|
|
58
60
|
|
|
59
61
|
const useChanged = (callback: (__: Data) => void) => {
|
|
60
62
|
if (!__LEPUS__) {
|
|
61
|
-
|
|
62
|
-
useListener<(__: unknown) => void>(eventName, callback);
|
|
63
|
+
useListener(eventName, callback);
|
|
63
64
|
}
|
|
64
65
|
};
|
|
65
66
|
|
|
@@ -98,7 +99,7 @@ export function factory<Data>(
|
|
|
98
99
|
* @public
|
|
99
100
|
*/
|
|
100
101
|
export function withInitDataInState<P, S>(App: ComponentClass<P, S>): ComponentClass<P, S> {
|
|
101
|
-
const isClassComponent = 'prototype' in App && App.prototype
|
|
102
|
+
const isClassComponent = 'prototype' in App && 'render' in App.prototype;
|
|
102
103
|
if (!isClassComponent) {
|
|
103
104
|
// return as-is when not class component
|
|
104
105
|
return App;
|
|
@@ -9,15 +9,15 @@ export function wrapWithLynxComponent(
|
|
|
9
9
|
jsxComponent: any,
|
|
10
10
|
): ReactNode {
|
|
11
11
|
const C = jsxComponent.type;
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
if (
|
|
13
|
+
typeof C === 'function' && (C === ComponentFromReactRuntime || C.prototype instanceof ComponentFromReactRuntime)
|
|
14
|
+
) {
|
|
15
|
+
if (jsxSnapshot.length === 1) {
|
|
16
|
+
return jsxSnapshot(jsxComponent);
|
|
17
|
+
} else {
|
|
18
|
+
// spread
|
|
19
|
+
if (!jsxComponent.props.removeComponentElement) {
|
|
20
|
+
return jsxSnapshot(jsxComponent, takeComponentAttributes(jsxComponent));
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -25,8 +25,7 @@ export function wrapWithLynxComponent(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// @ts-expect-error
|
|
28
|
-
export class ComponentFromReactRuntime extends Component {
|
|
29
|
-
}
|
|
28
|
+
export class ComponentFromReactRuntime extends Component {}
|
|
30
29
|
|
|
31
30
|
const __COMPONENT_ATTRIBUTES__ = /* @__PURE__ */ new Set([
|
|
32
31
|
'name',
|
|
@@ -68,8 +67,8 @@ function takeComponentAttributes(jsxComponent: any): Record<string, any> {
|
|
|
68
67
|
|| k === 'dataSet'
|
|
69
68
|
|| k === 'data-set'
|
|
70
69
|
|| k === 'removeComponentElement'
|
|
71
|
-
||
|
|
72
|
-
||
|
|
70
|
+
|| (/^(global-bind|bind|catch|capture-bind|capture-catch)([A-Za-z]+)$/.exec(k))
|
|
71
|
+
|| (/^data-([A-Za-z]+)$/.exec(k))
|
|
73
72
|
) {
|
|
74
73
|
attributes[k] = jsxComponent.props[k];
|
|
75
74
|
delete jsxComponent.props[k];
|
|
@@ -29,6 +29,7 @@ export function initProfileHook(): void {
|
|
|
29
29
|
const oldRender = options[RENDER];
|
|
30
30
|
options[RENDER] = function(vnode: VNode & { [COMPONENT]: Component }) {
|
|
31
31
|
const displayName = getDisplayName(vnode.type as ComponentClass);
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
32
33
|
const originalRender = vnode[COMPONENT].render;
|
|
33
34
|
vnode[COMPONENT].render = function render(this, props, state, context) {
|
|
34
35
|
// This __PROFILE__ is used for DCE testing
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// Copyright 2025 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
import { GestureTypeInner } from './types.js';
|
|
5
|
+
import type { BaseGesture, ComposedGesture, GestureKind } from './types.js';
|
|
1
6
|
import { onPostWorkletCtx } from '../worklet/ctx.js';
|
|
2
|
-
import { type GestureKind, GestureTypeInner, type ComposedGesture, type BaseGesture } from './types.js';
|
|
3
7
|
|
|
4
8
|
export function processGestureBackground(gesture: GestureKind): void {
|
|
5
9
|
if (gesture.type === GestureTypeInner.COMPOSED) {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2025 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
1
4
|
import type { Worklet } from '@lynx-js/react/worklet-runtime/bindings';
|
|
2
5
|
|
|
3
6
|
export enum GestureTypeInner {
|
|
@@ -31,7 +31,7 @@ import { useEffect, useMemo, useRef } from 'preact/hooks';
|
|
|
31
31
|
* @param listener - Event handler
|
|
32
32
|
* @public
|
|
33
33
|
*/
|
|
34
|
-
export function useLynxGlobalEventListener<T extends (...args:
|
|
34
|
+
export function useLynxGlobalEventListener<T extends (...args: any[]) => void>(
|
|
35
35
|
eventName: string,
|
|
36
36
|
listener: T,
|
|
37
37
|
): void {
|
package/runtime/src/hydrate.ts
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
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
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { componentAtIndexFactory, enqueueComponentFactory } from './list.js';
|
|
6
|
+
import { __pendingListUpdates } from './pendingListUpdates.js';
|
|
7
|
+
import { DynamicPartType } from './snapshot/dynamicPartType.js';
|
|
6
8
|
import { unref } from './snapshot/ref.js';
|
|
7
|
-
import {
|
|
9
|
+
import type { SnapshotInstance } from './snapshot.js';
|
|
8
10
|
import { isEmptyObject } from './utils.js';
|
|
9
11
|
|
|
10
12
|
export interface DiffResult<K> {
|
|
@@ -215,7 +217,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
|
|
|
215
217
|
}
|
|
216
218
|
|
|
217
219
|
let swap;
|
|
218
|
-
if (swap = options?.swap) {
|
|
220
|
+
if ((swap = options?.swap)) {
|
|
219
221
|
swap[before.__id] = after.__id;
|
|
220
222
|
}
|
|
221
223
|
|
|
@@ -349,7 +351,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
|
|
|
349
351
|
|
|
350
352
|
const listElement = before.__elements![elementIndex]!;
|
|
351
353
|
__SetAttribute(listElement, 'update-list-info', info);
|
|
352
|
-
const [componentAtIndex, componentAtIndexes] = componentAtIndexFactory(afterChildNodes);
|
|
354
|
+
const [componentAtIndex, componentAtIndexes] = componentAtIndexFactory(afterChildNodes, hydrate);
|
|
353
355
|
__UpdateListCallbacks(
|
|
354
356
|
listElement,
|
|
355
357
|
componentAtIndex,
|
package/runtime/src/internal.ts
CHANGED
|
@@ -9,10 +9,11 @@ import './lynx.js';
|
|
|
9
9
|
|
|
10
10
|
import { factory as factory2 } from './compat/componentIs.js';
|
|
11
11
|
import { useMemo } from './hooks/react.js';
|
|
12
|
-
import { snapshotCreateList } from './list.js';
|
|
13
12
|
import { loadLazyBundle } from './lynx/lazy-bundle.js';
|
|
14
13
|
import { __root } from './root.js';
|
|
15
|
-
import { DynamicPartType
|
|
14
|
+
import { DynamicPartType } from './snapshot/dynamicPartType.js';
|
|
15
|
+
import { snapshotCreateList } from './snapshot/list.js';
|
|
16
|
+
import { SnapshotInstance, __page, __pageId, createSnapshot, snapshotManager } from './snapshot.js';
|
|
16
17
|
|
|
17
18
|
export { __page, __pageId, __root };
|
|
18
19
|
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
ComponentFromReactRuntime as Component,
|
|
9
9
|
ComponentFromReactRuntime as PureComponent,
|
|
10
10
|
} from '../compat/lynxComponent.js';
|
|
11
|
-
import { useCallback, useEffect, useMemo, useReducer,
|
|
11
|
+
import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from '../hooks/react.js';
|
|
12
12
|
|
|
13
13
|
/* v8 ignore next 3 */
|
|
14
14
|
function __runInJS<T>(value: T): T | undefined | null {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { sendCtxNotFoundEventToBackground } from './error.js';
|
|
17
17
|
import type { SnapshotPatch } from './snapshotPatch.js';
|
|
18
18
|
import { SnapshotOperation } from './snapshotPatch.js';
|
|
19
|
+
import type { DynamicPartType } from '../../snapshot/dynamicPartType.js';
|
|
19
20
|
import {
|
|
20
21
|
SnapshotInstance,
|
|
21
22
|
createSnapshot,
|
|
@@ -23,7 +24,6 @@ import {
|
|
|
23
24
|
snapshotInstanceManager,
|
|
24
25
|
snapshotManager,
|
|
25
26
|
} from '../../snapshot.js';
|
|
26
|
-
import type { DynamicPartType } from '../../snapshot.js';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Applies a patch of snapshot operations to the main thread.
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
import { updateWorkletRefInitValueChanges } from '@lynx-js/react/worklet-runtime/bindings';
|
|
6
6
|
|
|
7
|
-
import { LifecycleConstant } from '../../lifecycleConstant.js';
|
|
8
|
-
import { __pendingListUpdates } from '../../list.js';
|
|
9
|
-
import { PerformanceTimingKeys, markTiming, setPipeline } from '../../lynx/performance.js';
|
|
10
|
-
import { __page } from '../../snapshot.js';
|
|
11
|
-
import { getReloadVersion } from '../pass.js';
|
|
12
7
|
import type { PatchList, PatchOptions } from './commit.js';
|
|
13
8
|
import { setMainThreadHydrationFinished } from './isMainThreadHydrationFinished.js';
|
|
14
9
|
import { snapshotPatchApply } from './snapshotPatchApply.js';
|
|
10
|
+
import { LifecycleConstant } from '../../lifecycleConstant.js';
|
|
11
|
+
import { PerformanceTimingKeys, markTiming, setPipeline } from '../../lynx/performance.js';
|
|
12
|
+
import { __pendingListUpdates } from '../../pendingListUpdates.js';
|
|
15
13
|
import { applyRefQueue } from '../../snapshot/workletRef.js';
|
|
14
|
+
import { __page } from '../../snapshot.js';
|
|
15
|
+
import { getReloadVersion } from '../pass.js';
|
|
16
16
|
|
|
17
17
|
function updateMainThread(
|
|
18
18
|
{ data, patchOptions }: {
|
|
@@ -11,7 +11,7 @@ import { render } from 'preact';
|
|
|
11
11
|
|
|
12
12
|
import { hydrate } from '../hydrate.js';
|
|
13
13
|
import { LifecycleConstant } from '../lifecycleConstant.js';
|
|
14
|
-
import { __pendingListUpdates } from '../
|
|
14
|
+
import { __pendingListUpdates } from '../pendingListUpdates.js';
|
|
15
15
|
import { __root, setRoot } from '../root.js';
|
|
16
16
|
import { destroyBackground } from './destroy.js';
|
|
17
17
|
import { applyRefQueue } from '../snapshot/workletRef.js';
|
package/runtime/src/list.ts
CHANGED
|
@@ -1,240 +1,12 @@
|
|
|
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 { hydrate } from './hydrate.js';
|
|
5
4
|
import { applyRefQueue } from './snapshot/workletRef.js';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
export interface ListUpdateInfo {
|
|
9
|
-
flush(): void;
|
|
10
|
-
onInsertBefore(
|
|
11
|
-
newNode: SnapshotInstance,
|
|
12
|
-
existingNode?: SnapshotInstance,
|
|
13
|
-
): void;
|
|
14
|
-
onRemoveChild(child: SnapshotInstance): void;
|
|
15
|
-
onSetAttribute(child: SnapshotInstance, attr: any, oldAttr: any): void;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface InsertAction {
|
|
19
|
-
position: number;
|
|
20
|
-
type: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface UpdateAction {
|
|
24
|
-
from: number;
|
|
25
|
-
to: number;
|
|
26
|
-
type: string;
|
|
27
|
-
flush: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface ListOperations {
|
|
31
|
-
insertAction: InsertAction[];
|
|
32
|
-
removeAction: number[];
|
|
33
|
-
updateAction: UpdateAction[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// class ListUpdateInfoDiffing implements ListUpdateInfo {
|
|
37
|
-
// private oldChildNodes: SnapshotInstance[];
|
|
38
|
-
// constructor(private list: SnapshotInstance) {
|
|
39
|
-
// this.oldChildNodes = list.childNodes;
|
|
40
|
-
// }
|
|
41
|
-
// flush(): void {
|
|
42
|
-
// Object.defineProperty(SnapshotInstance.prototype, "key", {
|
|
43
|
-
// get: function () {
|
|
44
|
-
// return this.values[0]["item-key"];
|
|
45
|
-
// },
|
|
46
|
-
// });
|
|
47
|
-
|
|
48
|
-
// }
|
|
49
|
-
// onInsertBefore(newNode: SnapshotInstance, existingNode?: SnapshotInstance | undefined): void {}
|
|
50
|
-
// onRemoveChild(child: SnapshotInstance): void {}
|
|
51
|
-
// onSetAttribute(child: SnapshotInstance, attr: any): void {
|
|
52
|
-
// throw new Error("Method not implemented.");
|
|
53
|
-
// }
|
|
54
|
-
// }
|
|
55
|
-
|
|
56
|
-
export class ListUpdateInfoRecording implements ListUpdateInfo {
|
|
57
|
-
constructor(private list: SnapshotInstance) {
|
|
58
|
-
this.oldChildNodes = list.childNodes;
|
|
59
|
-
// this.oldChildNodesSet = new Set(this.oldChildNodes);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// private __commitAndReset() {
|
|
63
|
-
// (this.__pendingAttributes ??= []).push(this.__toAttribute());
|
|
64
|
-
// this.oldChildNodes = this.list.childNodes;
|
|
65
|
-
// this.oldChildNodesSet = new Set(this.oldChildNodes);
|
|
66
|
-
// this.removeChild1.clear();
|
|
67
|
-
// this.removeChild2.clear();
|
|
68
|
-
// this.insertBefore.clear();
|
|
69
|
-
// this.appendChild.length = 0;
|
|
70
|
-
// this.platformInfoUpdate.clear();
|
|
71
|
-
// }
|
|
72
|
-
|
|
73
|
-
flush(): void {
|
|
74
|
-
const elementIndex = this.list.__snapshot_def.slot[0]![1];
|
|
75
|
-
const listElement = this.list.__elements![elementIndex]!;
|
|
76
|
-
// this.__pendingAttributes?.forEach(pendingAttribute => {
|
|
77
|
-
// __SetAttribute(listElement, "update-list-info", pendingAttribute);
|
|
78
|
-
// __FlushElementTree(listElement);
|
|
79
|
-
// });
|
|
80
|
-
__SetAttribute(listElement, 'update-list-info', this.__toAttribute());
|
|
81
|
-
const [componentAtIndex, componentAtIndexes] = componentAtIndexFactory(this.list.childNodes);
|
|
82
|
-
__UpdateListCallbacks(
|
|
83
|
-
listElement,
|
|
84
|
-
componentAtIndex,
|
|
85
|
-
enqueueComponentFactory(),
|
|
86
|
-
componentAtIndexes,
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
private oldChildNodes: SnapshotInstance[];
|
|
91
|
-
// private oldChildNodesSet: Set<SnapshotInstance>;
|
|
92
|
-
private removeChild = new Set<SnapshotInstance>();
|
|
93
|
-
private insertBefore = new Map<SnapshotInstance, SnapshotInstance[]>(); // insert V before K
|
|
94
|
-
private appendChild = [] as SnapshotInstance[];
|
|
95
|
-
private platformInfoUpdate = new Map<SnapshotInstance, any>();
|
|
96
|
-
|
|
97
|
-
onInsertBefore(newNode: SnapshotInstance, existingNode?: SnapshotInstance): void {
|
|
98
|
-
// @ts-ignore
|
|
99
|
-
if (newNode.__parent) {
|
|
100
|
-
// if (!this.oldChildNodesSet.has(newNode)) {
|
|
101
|
-
// this.__commitAndReset();
|
|
102
|
-
// }
|
|
103
|
-
this.removeChild.add(newNode);
|
|
104
|
-
}
|
|
105
|
-
if (existingNode) {
|
|
106
|
-
// if (!this.oldChildNodesSet.has(existingNode)) {
|
|
107
|
-
// this.__commitAndReset();
|
|
108
|
-
// }
|
|
109
|
-
const newChildren = this.insertBefore.get(existingNode) ?? [];
|
|
110
|
-
newChildren.push(newNode);
|
|
111
|
-
this.insertBefore.set(existingNode, newChildren);
|
|
112
|
-
} else {
|
|
113
|
-
this.appendChild.push(newNode);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
onRemoveChild(child: SnapshotInstance): void {
|
|
118
|
-
// if (!this.oldChildNodesSet.has(child)) {
|
|
119
|
-
// this.__commitAndReset();
|
|
120
|
-
// }
|
|
121
|
-
this.removeChild.add(child);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
onSetAttribute(child: SnapshotInstance, attr: any, _oldAttr: any): void {
|
|
125
|
-
this.platformInfoUpdate.set(child, attr);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private __toAttribute(): ListOperations {
|
|
129
|
-
const { removeChild, insertBefore, appendChild, platformInfoUpdate } = this;
|
|
130
|
-
|
|
131
|
-
const removals: number[] = [];
|
|
132
|
-
const insertions: InsertAction[] = [];
|
|
133
|
-
const updates: UpdateAction[] = [];
|
|
134
|
-
|
|
135
|
-
let j = 0;
|
|
136
|
-
for (let i = 0; i < this.oldChildNodes.length; i++, j++) {
|
|
137
|
-
const child = this.oldChildNodes[i]!;
|
|
138
|
-
if (platformInfoUpdate.has(child)) {
|
|
139
|
-
updates.push({
|
|
140
|
-
...platformInfoUpdate.get(child),
|
|
141
|
-
from: +j,
|
|
142
|
-
to: +j,
|
|
143
|
-
// no flush
|
|
144
|
-
flush: false,
|
|
145
|
-
type: child.type,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
if (insertBefore.has(child)) {
|
|
149
|
-
const children = insertBefore.get(child)!;
|
|
150
|
-
children.forEach(c => {
|
|
151
|
-
insertions.push({
|
|
152
|
-
position: j,
|
|
153
|
-
type: c.type,
|
|
154
|
-
...c.__listItemPlatformInfo,
|
|
155
|
-
});
|
|
156
|
-
j++;
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
if (removeChild.has(child)) {
|
|
160
|
-
removals.push(i);
|
|
161
|
-
removeChild.delete(child);
|
|
162
|
-
j--;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
for (let i = 0; i < appendChild.length; i++) {
|
|
166
|
-
const child = appendChild[i]!;
|
|
167
|
-
insertions.push({
|
|
168
|
-
position: j + i,
|
|
169
|
-
type: child.type,
|
|
170
|
-
...child.__listItemPlatformInfo,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
insertions.sort((a, b) => a.position - b.position);
|
|
175
|
-
removals.sort((a, b) => a - b);
|
|
176
|
-
|
|
177
|
-
if (
|
|
178
|
-
SystemInfo.lynxSdkVersion === '2.14'
|
|
179
|
-
|| SystemInfo.lynxSdkVersion === '2.15'
|
|
180
|
-
|| SystemInfo.lynxSdkVersion === '2.16'
|
|
181
|
-
|| SystemInfo.lynxSdkVersion === '2.17'
|
|
182
|
-
|| SystemInfo.lynxSdkVersion === '2.18'
|
|
183
|
-
) {
|
|
184
|
-
const elementIndex = this.list.__snapshot_def.slot[0]![1];
|
|
185
|
-
const listElement = this.list.__elements![elementIndex]!;
|
|
186
|
-
|
|
187
|
-
// `__GetAttributeByName` is available since Lynx 2.14
|
|
188
|
-
if (__GetAttributeByName(listElement, 'custom-list-name') === 'list-container') {
|
|
189
|
-
// `updateAction` must be full (not incremental) when Lynx version <= 2.18 and
|
|
190
|
-
// when `custom-list-name` is `list-container` (available when Lynx version >= 2.14) is true,
|
|
191
|
-
updates.length = 0;
|
|
192
|
-
this.list.childNodes.forEach((child, index) => {
|
|
193
|
-
updates.push({
|
|
194
|
-
...child.__listItemPlatformInfo,
|
|
195
|
-
from: index,
|
|
196
|
-
to: index,
|
|
197
|
-
// no flush
|
|
198
|
-
flush: false,
|
|
199
|
-
type: child.type,
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
insertAction: insertions,
|
|
207
|
-
removeAction: removals,
|
|
208
|
-
updateAction: updates,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
toJSON(): [ListOperations] {
|
|
213
|
-
// if (this.__pendingAttributes) {
|
|
214
|
-
// return [...this.__pendingAttributes, this.__toAttribute()];
|
|
215
|
-
// } else {
|
|
216
|
-
// return [this.__toAttribute()];
|
|
217
|
-
// }
|
|
218
|
-
|
|
219
|
-
return [this.__toAttribute()] as const;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export const __pendingListUpdates = {
|
|
224
|
-
values: {} as Record<number, ListUpdateInfo>,
|
|
225
|
-
clear(): void {
|
|
226
|
-
this.values = {};
|
|
227
|
-
},
|
|
228
|
-
flush(): void {
|
|
229
|
-
Object.values(this.values).forEach(update => {
|
|
230
|
-
update.flush();
|
|
231
|
-
});
|
|
232
|
-
this.clear();
|
|
233
|
-
},
|
|
234
|
-
};
|
|
5
|
+
import type { SnapshotInstance } from './snapshot.js';
|
|
235
6
|
|
|
236
7
|
export const gSignMap: Record<number, Map<number, SnapshotInstance>> = {};
|
|
237
8
|
export const gRecycleMap: Record<number, Map<string, Map<number, SnapshotInstance>>> = {};
|
|
9
|
+
const gParentWeakMap: WeakMap<SnapshotInstance, unknown> = new WeakMap();
|
|
238
10
|
|
|
239
11
|
export function clearListGlobal(): void {
|
|
240
12
|
for (const key in gSignMap) {
|
|
@@ -247,7 +19,25 @@ export function clearListGlobal(): void {
|
|
|
247
19
|
|
|
248
20
|
export function componentAtIndexFactory(
|
|
249
21
|
ctx: SnapshotInstance[],
|
|
22
|
+
hydrateFunction: (before: SnapshotInstance, after: SnapshotInstance) => void,
|
|
250
23
|
): [ComponentAtIndexCallback, ComponentAtIndexesCallback] {
|
|
24
|
+
// A hack workaround to ensure childCtx has no direct reference through `__parent` to list,
|
|
25
|
+
// to avoid memory leak.
|
|
26
|
+
// TODO(hzy): make `__parent` a WeakRef or `#__parent` in the future.
|
|
27
|
+
ctx.forEach((childCtx) => {
|
|
28
|
+
if (gParentWeakMap.has(childCtx)) {
|
|
29
|
+
// do it only once
|
|
30
|
+
} else {
|
|
31
|
+
gParentWeakMap.set(childCtx, childCtx.parentNode!);
|
|
32
|
+
Object.defineProperty(childCtx, '__parent', {
|
|
33
|
+
get: () => gParentWeakMap.get(childCtx)!,
|
|
34
|
+
set: (value: unknown) => {
|
|
35
|
+
gParentWeakMap.set(childCtx, value);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
251
41
|
const componentAtIndex = (
|
|
252
42
|
list: FiberElement,
|
|
253
43
|
listID: number,
|
|
@@ -268,7 +58,7 @@ export function componentAtIndexFactory(
|
|
|
268
58
|
throw new Error('childCtx not found');
|
|
269
59
|
}
|
|
270
60
|
|
|
271
|
-
const platformInfo = childCtx.__listItemPlatformInfo
|
|
61
|
+
const platformInfo = childCtx.__listItemPlatformInfo ?? {};
|
|
272
62
|
|
|
273
63
|
const uniqID = childCtx.type + (platformInfo['reuse-identifier'] ?? '');
|
|
274
64
|
const recycleSignMap = recycleMap.get(uniqID);
|
|
@@ -308,7 +98,7 @@ export function componentAtIndexFactory(
|
|
|
308
98
|
const [first] = recycleSignMap;
|
|
309
99
|
const [sign, oldCtx] = first!;
|
|
310
100
|
recycleSignMap.delete(sign);
|
|
311
|
-
|
|
101
|
+
hydrateFunction(oldCtx, childCtx);
|
|
312
102
|
oldCtx.unRenderElements();
|
|
313
103
|
if (!oldCtx.__id) {
|
|
314
104
|
oldCtx.tearDown();
|
|
@@ -325,7 +115,7 @@ export function componentAtIndexFactory(
|
|
|
325
115
|
if (enableReuseNotification) {
|
|
326
116
|
flushOptions.listReuseNotification = {
|
|
327
117
|
listElement: list,
|
|
328
|
-
itemKey: platformInfo['item-key']
|
|
118
|
+
itemKey: platformInfo['item-key']!,
|
|
329
119
|
};
|
|
330
120
|
}
|
|
331
121
|
__FlushElementTree(root, flushOptions);
|
|
@@ -336,7 +126,7 @@ export function componentAtIndexFactory(
|
|
|
336
126
|
if (enableReuseNotification) {
|
|
337
127
|
flushOptions.listReuseNotification = {
|
|
338
128
|
listElement: list,
|
|
339
|
-
itemKey: platformInfo['item-key']
|
|
129
|
+
itemKey: platformInfo['item-key']!,
|
|
340
130
|
};
|
|
341
131
|
}
|
|
342
132
|
__FlushElementTree(root, flushOptions);
|
|
@@ -389,6 +179,7 @@ export function componentAtIndexFactory(
|
|
|
389
179
|
}
|
|
390
180
|
|
|
391
181
|
export function enqueueComponentFactory(): EnqueueComponentCallback {
|
|
182
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
392
183
|
const enqueueComponent = (_: FiberElement, listID: number, sign: number) => {
|
|
393
184
|
const signMap = gSignMap[listID];
|
|
394
185
|
const recycleMap = gRecycleMap[listID];
|
|
@@ -401,7 +192,7 @@ export function enqueueComponentFactory(): EnqueueComponentCallback {
|
|
|
401
192
|
return;
|
|
402
193
|
}
|
|
403
194
|
|
|
404
|
-
const platformInfo = childCtx.__listItemPlatformInfo
|
|
195
|
+
const platformInfo = childCtx.__listItemPlatformInfo ?? {};
|
|
405
196
|
|
|
406
197
|
const uniqID = childCtx.type + (platformInfo['reuse-identifier'] ?? '');
|
|
407
198
|
if (!recycleMap.has(uniqID)) {
|
|
@@ -411,32 +202,3 @@ export function enqueueComponentFactory(): EnqueueComponentCallback {
|
|
|
411
202
|
};
|
|
412
203
|
return enqueueComponent;
|
|
413
204
|
}
|
|
414
|
-
|
|
415
|
-
export function snapshotCreateList(
|
|
416
|
-
pageId: number,
|
|
417
|
-
_ctx: SnapshotInstance,
|
|
418
|
-
_expIndex: number,
|
|
419
|
-
): FiberElement {
|
|
420
|
-
const signMap = new Map<number, SnapshotInstance>();
|
|
421
|
-
const recycleMap = new Map<string, Map<number, SnapshotInstance>>();
|
|
422
|
-
const [componentAtIndex, componentAtIndexes] = componentAtIndexFactory([]);
|
|
423
|
-
const list = __CreateList(
|
|
424
|
-
pageId,
|
|
425
|
-
componentAtIndex,
|
|
426
|
-
enqueueComponentFactory(),
|
|
427
|
-
{},
|
|
428
|
-
componentAtIndexes,
|
|
429
|
-
);
|
|
430
|
-
const listID = __GetElementUniqueID(list);
|
|
431
|
-
gSignMap[listID] = signMap;
|
|
432
|
-
gRecycleMap[listID] = recycleMap;
|
|
433
|
-
return list;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
export function snapshotDestroyList(si: SnapshotInstance): void {
|
|
437
|
-
const [, elementIndex] = si.__snapshot_def.slot[0]!;
|
|
438
|
-
const list = si.__elements![elementIndex]!;
|
|
439
|
-
const listID = __GetElementUniqueID(list);
|
|
440
|
-
delete gSignMap[listID];
|
|
441
|
-
delete gRecycleMap[listID];
|
|
442
|
-
}
|