diff --git a/.changeset/dlxg-utsc-owqi.md b/.changeset/dlxg-utsc-owqi.md
new file mode 100644
index 0000000000..a78783f6d9
--- /dev/null
+++ b/.changeset/dlxg-utsc-owqi.md
@@ -0,0 +1,5 @@
+---
+"@lynx-js/react": minor
+---
+
+Refactor preact to support multi-slots children and reduce the number and depth of snapshot.
diff --git a/.changeset/flat-bats-create.md b/.changeset/flat-bats-create.md
new file mode 100644
index 0000000000..9fc16dd8c5
--- /dev/null
+++ b/.changeset/flat-bats-create.md
@@ -0,0 +1,5 @@
+---
+"@lynx-js/react-rsbuild-plugin": patch
+---
+
+Supports @lynx-js/react 0.120.0
diff --git a/.github/react-runtime.instructions.md b/.github/react-runtime.instructions.md
new file mode 100644
index 0000000000..cc2b05cd23
--- /dev/null
+++ b/.github/react-runtime.instructions.md
@@ -0,0 +1,6 @@
+---
+applyTo: "packages/react/runtime/**"
+---
+
+When updating runtime snapshot tests for preview preact builds that carry named children props like `$0` and slot-index semantics, keep `list` host snapshots isolated from surrounding `view`/`text` snapshots by creating a standalone `__SNAPSHOT__({HOLE}
)` and inserting it into the outer snapshot.
+Do not drop `packages/react/runtime/__test__/list.test.jsx` cases added on `main`; preserve nested-list recording and `__DestroyLifetime` callback cleanup assertions while adapting expectations to the new snapshot structure.
diff --git a/.github/react-transform.instructions.md b/.github/react-transform.instructions.md
index 2228cdcbca..6a0623319c 100644
--- a/.github/react-transform.instructions.md
+++ b/.github/react-transform.instructions.md
@@ -2,6 +2,7 @@
applyTo: "packages/react/transform/**/*"
---
+When validating SWC transform snapshot changes, update the Rust fixtures with `UPDATE=1 cargo test -p swc_plugin_snapshot` and `UPDATE=1 cargo test -p swc_plugin_list --features napi` so the stored snapshots match the current transform output.
When a crate exposes both core Rust structs and `napi` wrapper structs with the same semantic shape, keep internal transform pipelines and shared `Rc>` state on the core types and convert to the `napi` types only at the JS boundary. Do not mix `swc_plugin_*::napi::*` record types into internal plugin wiring such as `.with_*_records(...)`, or wasm builds can fail with mismatched type errors.
When recording source locations from SWC spans, guard `SourceMap::lookup_char_pos` for synthetic spans such as `DUMMY_SP` (`span.lo == 0`). Compat and other transforms may synthesize JSX nodes with default spans, and wasm builds can surface panics from source map lookups on those spans as `RuntimeError: unreachable`.
Expose recorded columns as 1-based values so `uiSourceMapRecords` can be fed directly into editor locations such as VS Code without an extra offset conversion.
diff --git a/packages/react-umd/rslib.config.ts b/packages/react-umd/rslib.config.ts
index 82f936f186..aed02459ff 100644
--- a/packages/react-umd/rslib.config.ts
+++ b/packages/react-umd/rslib.config.ts
@@ -15,4 +15,7 @@ export default defineExternalBundleRslibConfig({
cleanDistPath: false,
distPath: './dist',
},
+ performance: {
+ buildCache: false,
+ },
});
diff --git a/packages/react/package.json b/packages/react/package.json
index 0f344d5738..5bd27b01f6 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -196,7 +196,7 @@
"build": "rslib build"
},
"dependencies": {
- "preact": "npm:@lynx-js/internal-preact@10.28.4-2d1d67a"
+ "preact": "npm:@lynx-js/internal-preact@10.28.4-dfff9aa"
},
"devDependencies": {
"@lynx-js/types": "3.7.0",
diff --git a/packages/react/runtime/__test__/basic.test.jsx b/packages/react/runtime/__test__/basic.test.jsx
index ede6922cd9..f4d7b0fced 100644
--- a/packages/react/runtime/__test__/basic.test.jsx
+++ b/packages/react/runtime/__test__/basic.test.jsx
@@ -102,6 +102,8 @@ describe('insertBefore', () => {
const b = new SnapshotInstance(snapshot2);
const c = new SnapshotInstance(snapshot2);
+ b.__slotIndex = 0;
+ c.__slotIndex = 1;
a.insertBefore(b);
a.insertBefore(c);
@@ -114,23 +116,27 @@ describe('insertBefore', () => {
/>
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
`);
@@ -154,14 +160,7 @@ describe('insertBefore', () => {
const a = new SnapshotInstance(snapshot1);
a.ensureElements();
- // Insert two wrappers for stable slot index
- const b = new SnapshotInstance('wrapper');
- const c = new SnapshotInstance('wrapper');
expect(a.__current_slot_index).toBe(0);
- a.insertBefore(b);
- expect(a.__current_slot_index).toBe(1);
- a.insertBefore(c);
- expect(a.__current_slot_index).toBe(2);
expect(a.__element_root).toMatchInlineSnapshot(`
@@ -175,12 +174,14 @@ describe('insertBefore', () => {
`);
const d = new SnapshotInstance(snapshot2);
+ d.__slotIndex = 0;
const e = new SnapshotInstance(snapshot2);
+ e.__slotIndex = 1;
- b.insertBefore(d);
- c.insertBefore(e);
+ a.insertBefore(d);
+ a.insertBefore(e);
- expect(a.__current_slot_index).toBe(2);
+ expect(a.__current_slot_index).toBe(0);
expect(a.__element_root).toMatchInlineSnapshot(`
@@ -209,9 +210,9 @@ describe('insertBefore', () => {
`);
- b.removeChild(d);
+ a.removeChild(d);
- expect(a.__current_slot_index).toBe(2);
+ expect(a.__current_slot_index).toBe(0);
expect(a.__element_root).toMatchInlineSnapshot(`
@@ -252,6 +253,9 @@ describe('insertBefore', () => {
const a = new SnapshotInstance(snapshot1);
const b = new SnapshotInstance(snapshot2);
const c = new SnapshotInstance(snapshot2);
+ b.__slotIndex = 0;
+ c.__slotIndex = 1;
+
a.insertBefore(b);
a.insertBefore(c);
@@ -265,23 +269,27 @@ describe('insertBefore', () => {
/>
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
`);
@@ -467,42 +475,88 @@ describe('setAttribute', () => {
describe('dynamic key in snapshot', () => {
it('multiple slots 0', () => {
+ const snapshotFoo = __SNAPSHOT__(foo);
+ const snapshotBar = __SNAPSHOT__(bar);
+ const snapshotWithDynamicKey = __SNAPSHOT__(
+
+
+ {snapshotFoo}
+
+
+ {snapshotBar}
+
+ ,
+ );
+
const snapshot = __SNAPSHOT__(
-
-
- {foo}
-
-
- {bar}
-
-
+ {snapshotWithDynamicKey}
,
);
const a = new SnapshotInstance(snapshot);
a.ensureElements();
+ expect(a.__element_root).toMatchInlineSnapshot(``);
+
+ const b = new SnapshotInstance(snapshotWithDynamicKey);
+ b.__slotIndex = 0;
+
+ a.insertBefore(b);
+
expect(a.__element_root).toMatchInlineSnapshot(`
-
+
+
+
+
+ `);
+
+ const foo = new SnapshotInstance(snapshotFoo);
+ foo.__slotIndex = 0;
+ const bar = new SnapshotInstance(snapshotBar);
+ bar.__slotIndex = 1;
+ b.insertBefore(foo);
+ b.insertBefore(bar);
+
+ expect(a.__element_root).toMatchInlineSnapshot(`
+
+
+
+
+
+
+
+
+
+
+
+
`);
});
it('multiple slots 2', () => {
+ const snapshotFoo = __SNAPSHOT__(foo);
+ const snapshotBar = __SNAPSHOT__(bar);
const snapshot = __SNAPSHOT__(
- {foo}
+ {snapshotFoo}
- {bar}
+ {snapshotBar}
,
@@ -515,23 +569,61 @@ describe('dynamic key in snapshot', () => {
-
+
+
+
+
`);
- });
- it('multiple slots 3', () => {
- const snapshot = __SNAPSHOT__(
-
- Hello {HOLE}
-
+ const foo = new SnapshotInstance(snapshotFoo);
+ foo.__slotIndex = 0;
+ const bar = new SnapshotInstance(snapshotBar);
+ bar.__slotIndex = 1;
+ a.insertBefore(foo);
+ a.insertBefore(bar);
+
+ expect(a.__element_root).toMatchInlineSnapshot(`
+
+
- {foo}
+
+
+
- {bar}
+
+
+
+
+ `);
+ });
+
+ it('multiple slots 3', () => {
+ const snapshotFoo = __SNAPSHOT__(foo);
+ const snapshotBar = __SNAPSHOT__(bar);
+ const snapshotDynamic = __SNAPSHOT__(
+
+
+ {snapshotFoo}
+
+
+ {snapshotBar}
+
+ ,
+ );
+ const snapshot = __SNAPSHOT__(
+
+ Hello {HOLE}
+ {snapshotDynamic}
,
);
@@ -546,11 +638,68 @@ describe('dynamic key in snapshot', () => {
/>
-
+
+
+ `);
+
+ const b = new SnapshotInstance(snapshotDynamic);
+ b.__slotIndex = 1;
+ a.insertBefore(b);
+
+ expect(a.__element_root).toMatchInlineSnapshot(`
+
+
+
-
+
+
+
+
+
+
+
+
+ `);
+
+ const foo = new SnapshotInstance(snapshotFoo);
+ foo.__slotIndex = 0;
+ const bar = new SnapshotInstance(snapshotBar);
+ bar.__slotIndex = 1;
+ b.insertBefore(foo);
+ b.insertBefore(bar);
+
+ expect(a.__element_root).toMatchInlineSnapshot(`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`);
});
diff --git a/packages/react/runtime/__test__/debug/backgroundSnapshot-profile.test.jsx b/packages/react/runtime/__test__/debug/backgroundSnapshot-profile.test.jsx
index 8f94a51a07..78170ee72e 100644
--- a/packages/react/runtime/__test__/debug/backgroundSnapshot-profile.test.jsx
+++ b/packages/react/runtime/__test__/debug/backgroundSnapshot-profile.test.jsx
@@ -55,11 +55,14 @@ function createBeforeTree() {
const root = new SnapshotInstance(ROOT);
const a = new SnapshotInstance(ITEM_A);
+ a.__slotIndex = 0;
a.setAttribute(0, 'a-old');
a.setAttribute('meta', 'meta-old');
const b = new SnapshotInstance(ITEM_B);
+ b.__slotIndex = 0;
const c = new SnapshotInstance(ITEM_C);
+ c.__slotIndex = 0;
root.insertBefore(a);
root.insertBefore(b);
@@ -72,7 +75,9 @@ function createAfterTree(metaValue) {
const root = new BackgroundSnapshotInstance(ROOT);
const b = new BackgroundSnapshotInstance(ITEM_B);
+ b.__slotIndex = 0;
const a = new BackgroundSnapshotInstance(ITEM_A);
+ a.__slotIndex = 0;
a.setAttribute(0, 'a-new');
a.setAttribute('meta', metaValue);
@@ -82,11 +87,43 @@ function createAfterTree(metaValue) {
return root;
}
+function createBeforeTreeWithProfileInsert() {
+ const root = new SnapshotInstance(ROOT);
+ const a = new SnapshotInstance(ITEM_A);
+ a.__slotIndex = 0;
+ const c = new SnapshotInstance(ITEM_C);
+ c.__slotIndex = 0;
+
+ root.insertBefore(a);
+ root.insertBefore(c);
+
+ return JSON.parse(JSON.stringify(root));
+}
+
+function createAfterTreeWithProfileInsert() {
+ const root = new BackgroundSnapshotInstance(ROOT);
+ const b = new BackgroundSnapshotInstance(ITEM_B);
+ b.__slotIndex = 0;
+ const a = new BackgroundSnapshotInstance(ITEM_A);
+ a.__slotIndex = 0;
+ const c = new BackgroundSnapshotInstance(ITEM_C);
+ c.__slotIndex = 0;
+
+ root.insertBefore(b);
+ root.insertBefore(a);
+ root.insertBefore(c);
+
+ return root;
+}
+
function createBeforeTreeWithDefinedTargetMove() {
const root = new SnapshotInstance(ROOT);
const a = new SnapshotInstance(ITEM_A);
+ a.__slotIndex = 0;
const b = new SnapshotInstance(ITEM_B);
+ b.__slotIndex = 0;
const c = new SnapshotInstance(ITEM_C);
+ c.__slotIndex = 0;
root.insertBefore(a);
root.insertBefore(b);
@@ -98,8 +135,11 @@ function createBeforeTreeWithDefinedTargetMove() {
function createAfterTreeWithDefinedTargetMove() {
const root = new BackgroundSnapshotInstance(ROOT);
const b = new BackgroundSnapshotInstance(ITEM_B);
+ b.__slotIndex = 0;
const a = new BackgroundSnapshotInstance(ITEM_A);
+ a.__slotIndex = 0;
const c = new BackgroundSnapshotInstance(ITEM_C);
+ c.__slotIndex = 0;
root.insertBefore(b);
root.insertBefore(a);
@@ -224,7 +264,7 @@ describe('backgroundSnapshot profile', () => {
}),
expect.objectContaining({
op: SnapshotOperation.InsertBefore,
- args: [before.id, before.children[0].id, undefined],
+ args: [before.id, before.children[0].id, undefined, 0],
}),
]),
);
@@ -256,6 +296,58 @@ describe('backgroundSnapshot profile', () => {
expect(insertBeforeCalls.some(([, option]) => option?.args?.targetId === '')).toBe(true);
});
+ it('should profile reconstructInstanceTree for inserted children', () => {
+ globalThis.__PROFILE__ = true;
+
+ const before = createBeforeTreeWithProfileInsert();
+ const after = createAfterTreeWithProfileInsert();
+
+ lynx.performance.profileStart.mockClear();
+ lynx.performance.profileEnd.mockClear();
+
+ hydrate(before, after);
+
+ const reconstructCalls = lynx.performance.profileStart.mock.calls.filter(
+ ([traceName]) => traceName === 'ReactLynx::BSI::reconstructInstanceTree',
+ );
+
+ expect(reconstructCalls).toHaveLength(1);
+ expect(reconstructCalls[0][1]).toEqual(
+ expect.objectContaining({
+ args: expect.objectContaining({
+ id: String(after.childNodes[0].__id),
+ snapshotType: after.childNodes[0].type,
+ }),
+ }),
+ );
+ });
+
+ it('should profile move branch with defined target id', () => {
+ globalThis.__PROFILE__ = true;
+
+ const before = createBeforeTreeWithDefinedTargetMove();
+ const after = createAfterTreeWithDefinedTargetMove();
+
+ lynx.performance.profileStart.mockClear();
+ lynx.performance.profileEnd.mockClear();
+
+ const patch = hydrate(before, after);
+ const operations = decodePatch(patch);
+ const moveWithDefinedTarget = operations.find(({ op, args }) => (
+ op === SnapshotOperation.InsertBefore
+ && args[0] === before.id
+ && args[2] === before.children[2].id
+ ));
+ const insertBeforeCalls = lynx.performance.profileStart.mock.calls.filter(
+ ([traceName]) => traceName === 'ReactLynx::hydrate::insertBefore',
+ );
+
+ expect(moveWithDefinedTarget).toBeDefined();
+ expect(
+ insertBeforeCalls.some(([, option]) => option?.args?.targetId === String(before.children[2].id)),
+ ).toBe(true);
+ });
+
it('should apply non-profile move branch with defined target id', () => {
globalThis.__PROFILE__ = false;
diff --git a/packages/react/runtime/__test__/debug/formatPatch.test.ts b/packages/react/runtime/__test__/debug/formatPatch.test.ts
index cd85df45bf..57baa68610 100644
--- a/packages/react/runtime/__test__/debug/formatPatch.test.ts
+++ b/packages/react/runtime/__test__/debug/formatPatch.test.ts
@@ -12,6 +12,7 @@ describe('formatPatch', () => {
1,
2,
undefined,
+ 0,
SnapshotOperation.RemoveChild,
1,
2,
@@ -32,7 +33,7 @@ describe('formatPatch', () => {
const formatted = prettyFormatSnapshotPatch(snapshotPatch);
expect(formatted).toEqual([
{ op: 'CreateElement', type: 'span', id: 2 },
- { op: 'InsertBefore', parentId: 1, childId: 2, beforeId: undefined },
+ { op: 'InsertBefore', parentId: 1, childId: 2, beforeId: undefined, slotIndex: 0 },
{ op: 'RemoveChild', parentId: 1, childId: 2 },
{ op: 'SetAttribute', id: 2, dynamicPartIndex: 1, value: 'disabled' },
{ op: 'SetAttributes', id: 2, values: { hidden: true } },
diff --git a/packages/react/runtime/__test__/delayed-lifecycle-events.test.jsx b/packages/react/runtime/__test__/delayed-lifecycle-events.test.jsx
index c3684ff0b5..77d43cbc5d 100644
--- a/packages/react/runtime/__test__/delayed-lifecycle-events.test.jsx
+++ b/packages/react/runtime/__test__/delayed-lifecycle-events.test.jsx
@@ -31,7 +31,7 @@ describe('delayedLifecycleEvents', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_1"}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_1","__slotIndex":0}]}",
},
],
],
@@ -44,7 +44,7 @@ describe('delayedLifecycleEvents', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_1"}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_1","__slotIndex":0}]}",
},
],
]
diff --git a/packages/react/runtime/__test__/hydrate.test.jsx b/packages/react/runtime/__test__/hydrate.test.jsx
index 0f77fb1bff..7a234b995f 100644
--- a/packages/react/runtime/__test__/hydrate.test.jsx
+++ b/packages/react/runtime/__test__/hydrate.test.jsx
@@ -49,8 +49,11 @@ describe('dual-runtime hydrate', () => {
const a = new SnapshotInstance(s);
a.ensureElements();
const b1 = new SnapshotInstance(s1);
+ b1.__slotIndex = 0;
const b2 = new SnapshotInstance(s1);
+ b2.__slotIndex = 0;
const b3 = new SnapshotInstance(s1);
+ b3.__slotIndex = 0;
b1.setAttribute(0, 'id~');
a.insertBefore(b1);
a.insertBefore(b2);
@@ -98,10 +101,15 @@ describe('dual-runtime hydrate', () => {
const aa = new BackgroundSnapshotInstance(s);
const bb1 = new BackgroundSnapshotInstance(s1);
+ bb1.__slotIndex = 0;
const bb2 = new BackgroundSnapshotInstance(s2);
+ bb2.__slotIndex = 0;
const bb3 = new BackgroundSnapshotInstance(s1);
+ bb3.__slotIndex = 0;
const bb4 = new BackgroundSnapshotInstance(s1);
+ bb4.__slotIndex = 0;
const bb5 = new BackgroundSnapshotInstance(s1);
+ bb5.__slotIndex = 0;
bb1.setAttribute(0, '~id');
bb5.setAttribute(0, '~id2');
aa.insertBefore(bb1);
@@ -111,8 +119,11 @@ describe('dual-runtime hydrate', () => {
aa.insertBefore(bb5);
const cc1 = new BackgroundSnapshotInstance(s3);
+ cc1.__slotIndex = 0;
const cc2 = new BackgroundSnapshotInstance(s3);
+ cc2.__slotIndex = 0;
const cc3 = new BackgroundSnapshotInstance(s1);
+ cc3.__slotIndex = 0;
cc3.setAttribute(0, '~id3');
bb2.insertBefore(cc1);
bb2.insertBefore(cc2);
@@ -135,6 +146,7 @@ describe('dual-runtime hydrate', () => {
7,
undefined,
0,
+ 0,
"__snapshot_a94a8_test_4",
8,
1,
@@ -142,6 +154,7 @@ describe('dual-runtime hydrate', () => {
8,
undefined,
0,
+ 0,
"__snapshot_a94a8_test_2",
9,
4,
@@ -153,11 +166,13 @@ describe('dual-runtime hydrate', () => {
3,
9,
undefined,
+ 0,
1,
-1,
3,
-3,
0,
+ 0,
"__snapshot_a94a8_test_2",
6,
4,
@@ -169,6 +184,7 @@ describe('dual-runtime hydrate', () => {
-1,
6,
undefined,
+ 0,
]
`);
backgroundSnapshotInstanceManager.values.forEach((v, k) => {
@@ -181,9 +197,13 @@ describe('dual-runtime hydrate', () => {
const a = new SnapshotInstance(s);
a.ensureElements();
const b1 = new SnapshotInstance(s1);
+ b1.__slotIndex = 0;
const b2 = new SnapshotInstance(s1);
+ b2.__slotIndex = 0;
const b3 = new SnapshotInstance(s1);
+ b3.__slotIndex = 0;
const b4 = new SnapshotInstance(s1);
+ b4.__slotIndex = 0;
a.insertBefore(b1);
a.insertBefore(b2);
a.insertBefore(b3);
@@ -192,8 +212,11 @@ describe('dual-runtime hydrate', () => {
const aa = new BackgroundSnapshotInstance(s);
const bb1 = new BackgroundSnapshotInstance(s1);
+ bb1.__slotIndex = 0;
const bb2 = new BackgroundSnapshotInstance(s1);
+ bb2.__slotIndex = 0;
const bb3 = new BackgroundSnapshotInstance(s1);
+ bb3.__slotIndex = 0;
aa.insertBefore(bb1);
aa.insertBefore(bb2);
aa.insertBefore(bb3);
@@ -211,9 +234,13 @@ describe('dual-runtime hydrate', () => {
const a = new SnapshotInstance(s);
a.ensureElements();
const b1 = new SnapshotInstance(s1);
+ b1.__slotIndex = 0;
const b2 = new SnapshotInstance(s1);
+ b2.__slotIndex = 0;
const b3 = new SnapshotInstance(s2);
+ b3.__slotIndex = 0;
const b4 = new SnapshotInstance(s1);
+ b4.__slotIndex = 0;
a.insertBefore(b1);
a.insertBefore(b2);
a.insertBefore(b3);
@@ -222,9 +249,13 @@ describe('dual-runtime hydrate', () => {
const aa = new BackgroundSnapshotInstance(s);
const bb1 = new BackgroundSnapshotInstance(s1);
+ bb1.__slotIndex = 0;
const bb2 = new BackgroundSnapshotInstance(s2);
+ bb2.__slotIndex = 0;
const bb3 = new BackgroundSnapshotInstance(s1);
+ bb3.__slotIndex = 0;
const bb4 = new BackgroundSnapshotInstance(s1);
+ bb4.__slotIndex = 0;
aa.insertBefore(bb1);
aa.insertBefore(bb2);
aa.insertBefore(bb3);
@@ -236,6 +267,7 @@ describe('dual-runtime hydrate', () => {
-1,
-3,
-5,
+ 0,
]
`);
});
@@ -258,6 +290,7 @@ describe('dual-runtime hydrate', () => {
-1,
2,
undefined,
+ undefined,
0,
"__snapshot_a94a8_test_3",
3,
@@ -265,6 +298,7 @@ describe('dual-runtime hydrate', () => {
-1,
3,
undefined,
+ undefined,
]
`);
});
@@ -287,24 +321,34 @@ describe('dual-runtime hydrate - with slot (multi-children)', () => {
const a = new SnapshotInstance(s);
a.ensureElements();
const b1 = new SnapshotInstance(slot1);
+ b1.__slotIndex = 0;
const b2 = new SnapshotInstance(slot2);
+ b2.__slotIndex = 1;
a.insertBefore(b1);
a.insertBefore(b2);
const c1 = new SnapshotInstance(s1);
+ c1.__slotIndex = 0;
const c2 = new SnapshotInstance(s1);
+ c2.__slotIndex = 0;
const c3 = new SnapshotInstance(s1);
+ c3.__slotIndex = 0;
b1.insertBefore(c1);
b1.insertBefore(c2);
b2.insertBefore(c3);
const aa = new BackgroundSnapshotInstance(s);
const bb1 = new BackgroundSnapshotInstance(slot1);
+ bb1.__slotIndex = 0;
const bb2 = new BackgroundSnapshotInstance(slot2);
+ bb2.__slotIndex = 1;
aa.insertBefore(bb1);
aa.insertBefore(bb2);
const cc1 = new BackgroundSnapshotInstance(s1);
+ cc1.__slotIndex = 0;
const cc2 = new BackgroundSnapshotInstance(s1);
+ cc2.__slotIndex = 0;
const cc3 = new BackgroundSnapshotInstance(s1);
+ cc3.__slotIndex = 0;
bb1.insertBefore(cc1);
bb2.insertBefore(cc2);
bb2.insertBefore(cc3);
@@ -321,6 +365,7 @@ describe('dual-runtime hydrate - with slot (multi-children)', () => {
-3,
6,
undefined,
+ 0,
]
`);
});
diff --git a/packages/react/runtime/__test__/lifecycle.test.jsx b/packages/react/runtime/__test__/lifecycle.test.jsx
index 29db60d394..ea8b6ed70a 100644
--- a/packages/react/runtime/__test__/lifecycle.test.jsx
+++ b/packages/react/runtime/__test__/lifecycle.test.jsx
@@ -120,7 +120,7 @@ describe('componentDidMount', () => {
expect(mtCallback[0]).toEqual(LifecycleConstant.patchUpdate);
expect(mtCallback[1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":6,"snapshotPatch":[0,"__snapshot_a94a8_test_3",2,0,null,3,3,3,0,1,1,2,3,null,1,1,2,null]}]}",
+ "data": "{"patchList":[{"id":6,"snapshotPatch":[0,"__snapshot_a94a8_test_3",2,0,null,3,3,3,0,1,1,2,3,null,0,1,1,2,null,0]}]}",
"patchOptions": {
"reloadVersion": 0,
},
@@ -167,7 +167,7 @@ describe('componentDidMount', () => {
expect(mtCallback[0]).toEqual(LifecycleConstant.patchUpdate);
expect(mtCallback[1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":9,"snapshotPatch":[0,"__snapshot_a94a8_test_4",2,0,null,3,3,3,0,1,1,2,3,null,1,1,2,null]}]}",
+ "data": "{"patchList":[{"id":9,"snapshotPatch":[0,"__snapshot_a94a8_test_4",2,0,null,3,3,3,0,1,1,2,3,null,0,1,1,2,null,0]}]}",
"patchOptions": {
"reloadVersion": 0,
},
@@ -550,7 +550,7 @@ describe('useState', () => {
await waitSchedule();
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1].data).toMatchInlineSnapshot(
- `"{"patchList":[{"id":27,"snapshotPatch":[0,"__snapshot_a94a8_test_15",2,4,2,[false,{"str":"str"}],1,-1,2,null]}]}"`,
+ `"{"patchList":[{"id":27,"snapshotPatch":[0,"__snapshot_a94a8_test_15",2,4,2,[false,{"str":"str"}],1,-1,2,null,0]}]}"`,
);
}
});
diff --git a/packages/react/runtime/__test__/lifecycle/reload.test.jsx b/packages/react/runtime/__test__/lifecycle/reload.test.jsx
index 22bb645e80..9073b307ff 100644
--- a/packages/react/runtime/__test__/lifecycle/reload.test.jsx
+++ b/packages/react/runtime/__test__/lifecycle/reload.test.jsx
@@ -123,7 +123,7 @@ describe('reload', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":3,"snapshotPatch":[3,-5,0,{"dataX2":"WorldX2"},3,-7,0,"update",3,-8,0,{"attr":{"dataX2":"WorldX2"}}]}]}",
+ "data": "{"patchList":[{"id":3,"snapshotPatch":[3,-2,0,{"dataX2":"WorldX2"},3,-4,0,"update",3,-5,0,{"attr":{"dataX2":"WorldX2"}}]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -234,7 +234,7 @@ describe('reload', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":4,"snapshotPatch":[3,-7,0,"???"]}]}",
+ "data": "{"patchList":[{"id":4,"snapshotPatch":[3,-4,0,"???"]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -305,7 +305,7 @@ describe('reload', () => {
[
"rLynxFirstScreen",
{
- "root": "{"id":-9,"type":"root","children":[{"id":-13,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-10,"type":"__snapshot_a94a8_test_3","children":[{"id":-14,"type":null,"values":["Enjoy"]}]},{"id":-11,"type":"__snapshot_a94a8_test_4","children":[{"id":-15,"type":null,"values":["World"]}]},{"id":-12,"type":"wrapper","children":[{"id":-16,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}]}]}]}]}",
+ "root": "{"id":-6,"type":"root","children":[{"id":-7,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-8,"type":null,"values":["Enjoy"],"__slotIndex":0},{"id":-9,"type":null,"values":["World"],"__slotIndex":1},{"id":-10,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}],"__slotIndex":2}],"__slotIndex":0}]}",
},
],
],
@@ -386,7 +386,7 @@ describe('reload', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":8,"snapshotPatch":[3,-15,0,"update"]}]}",
+ "data": "{"patchList":[{"id":8,"snapshotPatch":[3,-9,0,"update"]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -535,7 +535,7 @@ describe('reload', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":11,"snapshotPatch":[3,-5,0,{"dataX2":"WorldX2"},3,-7,0,"update",3,-8,0,{"attr":{"dataX2":"WorldX2"}}]}]}",
+ "data": "{"patchList":[{"id":11,"snapshotPatch":[3,-2,0,{"dataX2":"WorldX2"},3,-4,0,"update",3,-5,0,{"attr":{"dataX2":"WorldX2"}}]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -650,7 +650,7 @@ describe('reload', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":12,"snapshotPatch":[3,-7,0,"???"]}]}",
+ "data": "{"patchList":[{"id":12,"snapshotPatch":[3,-4,0,"???"]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -723,7 +723,7 @@ describe('reload', () => {
[
"rLynxFirstScreen",
{
- "root": "{"id":-9,"type":"root","children":[{"id":-10,"type":"__snapshot_a94a8_test_5","children":[{"id":-14,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-11,"type":"__snapshot_a94a8_test_3","children":[{"id":-15,"type":null,"values":["Enjoy"]}]},{"id":-12,"type":"__snapshot_a94a8_test_4","children":[{"id":-16,"type":null,"values":["World"]}]},{"id":-13,"type":"wrapper","children":[{"id":-17,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}]}]}]}]}]}",
+ "root": "{"id":-6,"type":"root","children":[{"id":-7,"type":"__snapshot_a94a8_test_3","children":[{"id":-8,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-9,"type":null,"values":["Enjoy"],"__slotIndex":0},{"id":-10,"type":null,"values":["World"],"__slotIndex":1},{"id":-11,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}],"__slotIndex":2}],"__slotIndex":0}],"__slotIndex":0}]}",
},
],
],
@@ -806,7 +806,7 @@ describe('reload', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":16,"snapshotPatch":[3,-16,0,"update"]}]}",
+ "data": "{"patchList":[{"id":16,"snapshotPatch":[3,-10,0,"update"]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -884,17 +884,17 @@ describe('reload', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
],
"removeAction": [],
@@ -943,17 +943,17 @@ describe('reload', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
],
"removeAction": [],
@@ -1022,17 +1022,17 @@ describe('reload', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
],
"removeAction": [],
@@ -1081,17 +1081,17 @@ describe('reload', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
],
"removeAction": [],
@@ -1297,24 +1297,18 @@ describe('firstScreenSyncTiming - jsReady', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {
- "-1": -9,
- "-10": -18,
- "-11": -19,
- "-12": -20,
- "-13": -21,
- "-14": -22,
- "-15": -23,
- "-16": -24,
- "-2": -10,
- "-3": -11,
- "-4": -12,
- "-5": -13,
- "-6": -14,
- "-7": -15,
- "-8": -16,
- "-9": -17,
+ "-1": -6,
+ "-10": -15,
+ "-2": -7,
+ "-3": -8,
+ "-4": -9,
+ "-5": -10,
+ "-6": -11,
+ "-7": -12,
+ "-8": -13,
+ "-9": -14,
},
- "root": "{"id":-17,"type":"root","children":[{"id":-21,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-18,"type":"__snapshot_a94a8_test_3","children":[{"id":-22,"type":null,"values":["Hello 2"]}]},{"id":-19,"type":"__snapshot_a94a8_test_4","children":[{"id":-23,"type":null,"values":["World"]}]},{"id":-20,"type":"wrapper","children":[{"id":-24,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}]}]}]}]}",
+ "root": "{"id":-11,"type":"root","children":[{"id":-12,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-13,"type":null,"values":["Hello 2"],"__slotIndex":0},{"id":-14,"type":null,"values":["World"],"__slotIndex":1},{"id":-15,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}],"__slotIndex":2}],"__slotIndex":0}]}",
},
],
]
@@ -1322,7 +1316,7 @@ describe('firstScreenSyncTiming - jsReady', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"snapshotPatch":[2,-17,-21,0,"__snapshot_a94a8_test_5",2,0,"__snapshot_a94a8_test_2",3,4,3,[{"dataX":"WorldX"}],0,"__snapshot_a94a8_test_3",4,0,null,5,4,5,["Hello 2"],1,4,5,null,1,3,4,null,0,"__snapshot_a94a8_test_4",6,0,null,7,4,7,["World"],1,6,7,null,1,3,6,null,0,"wrapper",8,0,"__snapshot_a94a8_test_1",9,4,9,[{"attr":{"dataX":"WorldX"}}],1,8,9,null,1,3,8,null,1,2,3,null,1,-17,2,null],"id":21}]}",
+ "data": "{"patchList":[{"snapshotPatch":[2,-11,-12,0,"__snapshot_a94a8_test_3",2,0,"__snapshot_a94a8_test_2",3,4,3,[{"dataX":"WorldX"}],0,null,4,4,4,["Hello 2"],1,3,4,null,0,0,null,5,4,5,["World"],1,3,5,null,1,0,"__snapshot_a94a8_test_1",6,4,6,[{"attr":{"dataX":"WorldX"}}],1,3,6,null,2,1,2,3,null,0,1,-11,2,null,0],"id":21}]}",
"patchOptions": {
"isHydration": true,
"pipelineOptions": {
@@ -1364,17 +1358,17 @@ describe('firstScreenSyncTiming - jsReady', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
],
"removeAction": [],
@@ -1404,17 +1398,17 @@ describe('firstScreenSyncTiming - jsReady', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
],
"removeAction": [],
@@ -1449,17 +1443,17 @@ describe('firstScreenSyncTiming - jsReady', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_8",
+ "type": "__snapshot_a94a8_test_6",
},
],
"removeAction": [],
@@ -1517,7 +1511,7 @@ describe('firstScreenSyncTiming - jsReady', () => {
"-5": -13,
"-9": -17,
},
- "root": "{"id":-17,"type":"root","children":[{"id":-21,"type":"__snapshot_a94a8_test_7","children":[{"id":-18,"type":"__snapshot_a94a8_test_8","values":[{"item-key":0}],"children":[{"id":-22,"type":"__snapshot_a94a8_test_6","values":["a"]}]},{"id":-19,"type":"__snapshot_a94a8_test_8","values":[{"item-key":1}],"children":[{"id":-23,"type":"__snapshot_a94a8_test_6","values":["b"]}]},{"id":-20,"type":"__snapshot_a94a8_test_8","values":[{"item-key":2}],"children":[{"id":-24,"type":"__snapshot_a94a8_test_6","values":["c"]}]}]}]}",
+ "root": "{"id":-17,"type":"root","children":[{"id":-21,"type":"__snapshot_a94a8_test_5","children":[{"id":-18,"type":"__snapshot_a94a8_test_6","values":[{"item-key":0}],"children":[{"id":-22,"type":"__snapshot_a94a8_test_4","values":["a"],"__slotIndex":0}],"__slotIndex":0},{"id":-19,"type":"__snapshot_a94a8_test_6","values":[{"item-key":1}],"children":[{"id":-23,"type":"__snapshot_a94a8_test_4","values":["b"],"__slotIndex":0}],"__slotIndex":0},{"id":-20,"type":"__snapshot_a94a8_test_6","values":[{"item-key":2}],"children":[{"id":-24,"type":"__snapshot_a94a8_test_4","values":["c"],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0}]}",
},
],
]
@@ -1579,17 +1573,17 @@ describe('firstScreenSyncTiming - jsReady', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_10",
+ "type": "__snapshot_a94a8_test_8",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_10",
+ "type": "__snapshot_a94a8_test_8",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_10",
+ "type": "__snapshot_a94a8_test_8",
},
],
"removeAction": [],
@@ -1619,17 +1613,17 @@ describe('firstScreenSyncTiming - jsReady', () => {
{
"item-key": 0,
"position": 0,
- "type": "__snapshot_a94a8_test_10",
+ "type": "__snapshot_a94a8_test_8",
},
{
"item-key": 1,
"position": 1,
- "type": "__snapshot_a94a8_test_10",
+ "type": "__snapshot_a94a8_test_8",
},
{
"item-key": 2,
"position": 2,
- "type": "__snapshot_a94a8_test_10",
+ "type": "__snapshot_a94a8_test_8",
},
],
"removeAction": [],
@@ -1681,7 +1675,7 @@ describe('firstScreenSyncTiming - jsReady', () => {
"-2": -10,
"-6": -14,
},
- "root": "{"id":-10,"type":"root","children":[{"id":-14,"type":"__snapshot_a94a8_test_9","children":[{"id":-11,"type":"__snapshot_a94a8_test_10","values":[{"item-key":0}],"children":[{"id":-15,"type":"__snapshot_a94a8_test_6","values":["a"]}]},{"id":-12,"type":"__snapshot_a94a8_test_10","values":[{"item-key":1}],"children":[{"id":-16,"type":"__snapshot_a94a8_test_6","values":["b"]}]},{"id":-13,"type":"__snapshot_a94a8_test_10","values":[{"item-key":2}],"children":[{"id":-17,"type":"__snapshot_a94a8_test_6","values":["c"]}]}]}]}",
+ "root": "{"id":-10,"type":"root","children":[{"id":-14,"type":"__snapshot_a94a8_test_7","children":[{"id":-11,"type":"__snapshot_a94a8_test_8","values":[{"item-key":0}],"children":[{"id":-15,"type":"__snapshot_a94a8_test_4","values":["a"],"__slotIndex":0}],"__slotIndex":0},{"id":-12,"type":"__snapshot_a94a8_test_8","values":[{"item-key":1}],"children":[{"id":-16,"type":"__snapshot_a94a8_test_4","values":["b"],"__slotIndex":0}],"__slotIndex":0},{"id":-13,"type":"__snapshot_a94a8_test_8","values":[{"item-key":2}],"children":[{"id":-17,"type":"__snapshot_a94a8_test_4","values":["c"],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0}]}",
},
],
]
@@ -1874,7 +1868,7 @@ describe('firstScreenSyncTiming - jsReady', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-17,"type":"root","children":[{"id":-21,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-18,"type":"__snapshot_a94a8_test_3","children":[{"id":-22,"type":null,"values":["Hello 2"]}]},{"id":-19,"type":"__snapshot_a94a8_test_4","children":[{"id":-23,"type":null,"values":["World"]}]},{"id":-20,"type":"wrapper","children":[{"id":-24,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}]}]}]}]}",
+ "root": "{"id":-11,"type":"root","children":[{"id":-12,"type":"__snapshot_a94a8_test_2","values":[{"dataX":"WorldX"}],"children":[{"id":-13,"type":null,"values":["Hello 2"],"__slotIndex":0},{"id":-14,"type":null,"values":["World"],"__slotIndex":1},{"id":-15,"type":"__snapshot_a94a8_test_1","values":[{"attr":{"dataX":"WorldX"}}],"__slotIndex":2}],"__slotIndex":0}]}",
},
],
]
@@ -1882,7 +1876,7 @@ describe('firstScreenSyncTiming - jsReady', () => {
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"snapshotPatch":[2,-17,-21,0,"__snapshot_a94a8_test_5",2,0,"__snapshot_a94a8_test_2",3,4,3,[{"dataX":"WorldX"}],0,"__snapshot_a94a8_test_3",4,0,null,5,4,5,["Hello 2"],1,4,5,null,1,3,4,null,0,"__snapshot_a94a8_test_4",6,0,null,7,4,7,["World"],1,6,7,null,1,3,6,null,0,"wrapper",8,0,"__snapshot_a94a8_test_1",9,4,9,[{"attr":{"dataX":"WorldX"}}],1,8,9,null,1,3,8,null,1,2,3,null,1,-17,2,null],"id":27}]}",
+ "data": "{"patchList":[{"snapshotPatch":[2,-11,-12,0,"__snapshot_a94a8_test_3",2,0,"__snapshot_a94a8_test_2",3,4,3,[{"dataX":"WorldX"}],0,null,4,4,4,["Hello 2"],1,3,4,null,0,0,null,5,4,5,["World"],1,3,5,null,1,0,"__snapshot_a94a8_test_1",6,4,6,[{"attr":{"dataX":"WorldX"}}],1,3,6,null,2,1,2,3,null,0,1,-11,2,null,0],"id":27}]}",
"patchOptions": {
"isHydration": true,
"pipelineOptions": {
diff --git a/packages/react/runtime/__test__/list.test.jsx b/packages/react/runtime/__test__/list.test.jsx
index 70ea0303e0..600daae508 100644
--- a/packages/react/runtime/__test__/list.test.jsx
+++ b/packages/react/runtime/__test__/list.test.jsx
@@ -79,9 +79,12 @@ describe('list', () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s2 = __SNAPSHOT__(World);
const s3 = __SNAPSHOT__(
@@ -93,17 +96,19 @@ describe('list', () => {
a.ensureElements();
const b = new SnapshotInstance(s1);
+ const b1 = new SnapshotInstance(s11);
const c = new SnapshotInstance(s2);
a.insertBefore(b);
+ b.insertBefore(b1);
a.insertBefore(c);
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
expect(a.__element_root).toMatchInlineSnapshot(`
@@ -119,7 +124,9 @@ describe('list', () => {
text="111"
/>
-
+
+
+
{
`);
- expect(b.childNodes.length).toMatchInlineSnapshot(`3`);
+ expect(b1.childNodes.length).toMatchInlineSnapshot(`3`);
b.insertBefore(d2);
b.removeChild(d2);
- expect(b.childNodes.length).toMatchInlineSnapshot(`2`);
+ expect(b1.childNodes.length).toMatchInlineSnapshot(`2`);
});
it('list slot count > 1 (the wrapper should be generated)', async function() {
const s1 = __SNAPSHOT__(
111
-
- {HOLE}
-
-
+ {HOLE}
{HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+
+ {HOLE}
+
+
,
+ );
const s2 = __SNAPSHOT__(World);
const a = new SnapshotInstance(s);
a.ensureElements();
const b = new SnapshotInstance(s1);
+ const b1 = new SnapshotInstance(s11);
const c = new SnapshotInstance(s2);
a.insertBefore(b);
+ b.insertBefore(b1);
a.insertBefore(c);
expect(a.__element_root).toMatchInlineSnapshot(`
@@ -173,8 +185,9 @@ describe('list', () => {
text="111"
/>
-
-
+
+
+
{
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s2 = __SNAPSHOT__(World);
const s3 = __SNAPSHOT__(
@@ -217,36 +233,38 @@ describe(`list "update-list-info"`, () => {
a.ensureElements();
const b = new SnapshotInstance(s1);
+ const b1 = new SnapshotInstance(s11);
const c = new SnapshotInstance(s2);
a.insertBefore(b);
+ b.insertBefore(b1);
a.insertBefore(c);
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
- expect(b.childNodes.length).toMatchInlineSnapshot(`3`);
+ expect(b1.childNodes.length).toMatchInlineSnapshot(`3`);
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-6": [
+ "-8": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_14",
+ "type": "__snapshot_a94a8_test_16",
},
{
"position": 1,
- "type": "__snapshot_a94a8_test_14",
+ "type": "__snapshot_a94a8_test_16",
},
{
"position": 2,
- "type": "__snapshot_a94a8_test_14",
+ "type": "__snapshot_a94a8_test_16",
},
],
"removeAction": [],
@@ -262,31 +280,31 @@ describe(`list "update-list-info"`, () => {
const d5 = new SnapshotInstance(s3);
const d6 = new SnapshotInstance(s4);
const d7 = new SnapshotInstance(s4);
- b.insertBefore(d4);
- b.insertBefore(d5, d2);
- b.insertBefore(d6, d2);
- b.insertBefore(d7, d2);
- b.removeChild(d2);
+ b1.insertBefore(d4);
+ b1.insertBefore(d5, d2);
+ b1.insertBefore(d6, d2);
+ b1.insertBefore(d7, d2);
+ b1.removeChild(d2);
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-6": [
+ "-8": [
{
"insertAction": [
{
"position": 1,
- "type": "__snapshot_a94a8_test_14",
+ "type": "__snapshot_a94a8_test_16",
},
{
"position": 2,
- "type": "__snapshot_a94a8_test_15",
+ "type": "__snapshot_a94a8_test_17",
},
{
"position": 3,
- "type": "__snapshot_a94a8_test_15",
+ "type": "__snapshot_a94a8_test_17",
},
{
"position": 5,
- "type": "__snapshot_a94a8_test_14",
+ "type": "__snapshot_a94a8_test_16",
},
],
"removeAction": [
@@ -301,15 +319,15 @@ describe(`list "update-list-info"`, () => {
{
__pendingListUpdates.clearAttachedLists();
- b.insertBefore(d3); // move
+ b1.insertBefore(d3); // move
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-6": [
+ "-8": [
{
"insertAction": [
{
"position": 5,
- "type": "__snapshot_a94a8_test_14",
+ "type": "__snapshot_a94a8_test_16",
},
],
"removeAction": [
@@ -327,13 +345,19 @@ describe(`list "update-list-info"`, () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const b = new SnapshotInstance(s1);
b.ensureElements();
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+
const s3 = __SNAPSHOT__(
World
@@ -343,16 +367,16 @@ describe(`list "update-list-info"`, () => {
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
__pendingListUpdates.clearAttachedLists();
d1.setAttribute(0, { 'item-key': 1 });
d3.setAttribute(0, { 'item-key': 3 });
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-2": [
+ "-4": [
{
"insertAction": [],
"removeAction": [],
@@ -362,14 +386,14 @@ describe(`list "update-list-info"`, () => {
"from": 0,
"item-key": 1,
"to": 0,
- "type": "__snapshot_a94a8_test_17",
+ "type": "__snapshot_a94a8_test_20",
},
{
"flush": false,
"from": 2,
"item-key": 3,
"to": 2,
- "type": "__snapshot_a94a8_test_17",
+ "type": "__snapshot_a94a8_test_20",
},
],
},
@@ -389,9 +413,12 @@ describe(`list componentAtIndex`, () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s3 = __SNAPSHOT__(
@@ -402,14 +429,16 @@ describe(`list componentAtIndex`, () => {
it('basic componentAtIndex after insert', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
// initial there is no child, because "update-list-info" is not flush
expect(() => {
@@ -418,9 +447,9 @@ describe(`list componentAtIndex`, () => {
// only call componentAtIndex after flush
__pendingListUpdates.flush();
- expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`4`);
- expect(elementTree.triggerComponentAtIndex(listRef, 1)).toMatchInlineSnapshot(`7`);
- expect(elementTree.triggerComponentAtIndex(listRef, 2)).toMatchInlineSnapshot(`10`);
+ expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`5`);
+ expect(elementTree.triggerComponentAtIndex(listRef, 1)).toMatchInlineSnapshot(`8`);
+ expect(elementTree.triggerComponentAtIndex(listRef, 2)).toMatchInlineSnapshot(`11`);
});
it('remove list si', () => {
@@ -429,7 +458,9 @@ describe(`list componentAtIndex`, () => {
const b = new SnapshotInstance(s1);
a.insertBefore(b);
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
expect(() => {
elementTree.triggerComponentAtIndex(listRef, 0);
}).toThrowErrorMatchingInlineSnapshot(`[Error: childCtx not found]`);
@@ -437,13 +468,12 @@ describe(`list componentAtIndex`, () => {
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
__pendingListUpdates.flush();
- a.removeChild(b);
-
+ b.removeChild(b1);
expect(listRef.componentAtIndex()).toBe(-1);
expect(listRef.enqueueComponent()).toBeUndefined();
expect(listRef.componentAtIndexes()).toBeUndefined();
@@ -452,7 +482,9 @@ describe(`list componentAtIndex`, () => {
it('should reuse and hydrate', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -468,12 +500,12 @@ describe(`list componentAtIndex`, () => {
const c3 = new SnapshotInstance(s3);
const c4 = new SnapshotInstance(s3);
const c5 = new SnapshotInstance(s3);
- b.insertBefore(c0);
- b.insertBefore(c1);
- b.insertBefore(c2);
- b.insertBefore(c3);
- b.insertBefore(c4);
- b.insertBefore(c5);
+ b1.insertBefore(c0);
+ b1.insertBefore(c1);
+ b1.insertBefore(c2);
+ b1.insertBefore(c3);
+ b1.insertBefore(c4);
+ b1.insertBefore(c5);
// item-key
c0.setAttribute(0, { 'item-key': 'key-0' });
@@ -530,32 +562,32 @@ describe(`list componentAtIndex`, () => {
{
"item-key": "key-0",
"position": 0,
- "type": "__snapshot_a94a8_test_21",
+ "type": "__snapshot_a94a8_test_25",
},
{
"item-key": "key-1",
"position": 1,
- "type": "__snapshot_a94a8_test_21",
+ "type": "__snapshot_a94a8_test_25",
},
{
"item-key": "key-2",
"position": 2,
- "type": "__snapshot_a94a8_test_21",
+ "type": "__snapshot_a94a8_test_25",
},
{
"item-key": "key-3",
"position": 3,
- "type": "__snapshot_a94a8_test_21",
+ "type": "__snapshot_a94a8_test_25",
},
{
"item-key": "key-4",
"position": 4,
- "type": "__snapshot_a94a8_test_21",
+ "type": "__snapshot_a94a8_test_25",
},
{
"item-key": "key-5",
"position": 5,
- "type": "__snapshot_a94a8_test_21",
+ "type": "__snapshot_a94a8_test_25",
},
],
"removeAction": [],
@@ -570,7 +602,7 @@ describe(`list componentAtIndex`, () => {
@@ -585,7 +617,7 @@ describe(`list componentAtIndex`, () => {
@@ -600,7 +632,7 @@ describe(`list componentAtIndex`, () => {
@@ -615,7 +647,7 @@ describe(`list componentAtIndex`, () => {
@@ -634,24 +666,34 @@ describe(`list componentAtIndex`, () => {
it('should reuse and hydrate - with childNodes', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const c0 = new SnapshotInstance(_s3);
+ c0.__slotIndex = 0;
const c1 = new SnapshotInstance(_s3);
+ c1.__slotIndex = 0;
const c2 = new SnapshotInstance(_s3);
- b.insertBefore(c0);
- b.insertBefore(c1);
- b.insertBefore(c2);
+ c2.__slotIndex = 0;
+ b1.insertBefore(c0);
+ b1.insertBefore(c1);
+ b1.insertBefore(c2);
const c0_d0 = new SnapshotInstance(_s4);
+ c0_d0.__slotIndex = 0;
const c0_d1 = new SnapshotInstance(_s5);
+ c0_d1.__slotIndex = 0;
c0.insertBefore(c0_d0);
c0.insertBefore(c0_d1);
const c1_d0 = new SnapshotInstance(_s4);
+ c1_d0.__slotIndex = 0;
c1.insertBefore(c1_d0);
const c2_d0 = new SnapshotInstance(_s5);
+ c2_d0.__slotIndex = 0;
c2.insertBefore(c2_d0);
__pendingListUpdates.flush();
@@ -742,7 +784,9 @@ describe(`list componentAtIndex`, () => {
it('should reuse and hydrate - with childNodes - move', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__({HOLE});
const s4 = __SNAPSHOT__(Hello);
@@ -750,23 +794,33 @@ describe(`list componentAtIndex`, () => {
const s6 = __SNAPSHOT__(!);
const c0 = new SnapshotInstance(s3);
+ c0.__slotIndex = 0;
const c1 = new SnapshotInstance(s3);
- b.insertBefore(c0);
- b.insertBefore(c1);
+ c1.__slotIndex = 0;
+ b1.insertBefore(c0);
+ b1.insertBefore(c1);
const c0_d0 = new SnapshotInstance(s4);
+ c0_d0.__slotIndex = 0;
const c0_d1 = new SnapshotInstance(s5);
+ c0_d1.__slotIndex = 0;
const c0_d2 = new SnapshotInstance(s6);
+ c0_d2.__slotIndex = 0;
const c0_d0_ = new SnapshotInstance(s4);
+ c0_d0_.__slotIndex = 0;
c0.insertBefore(c0_d0);
c0.insertBefore(c0_d1);
c0.insertBefore(c0_d2);
c0.insertBefore(c0_d0_);
const c1_d0 = new SnapshotInstance(s4);
+ c1_d0.__slotIndex = 0;
const c1_d1 = new SnapshotInstance(s5);
+ c1_d1.__slotIndex = 0;
const c1_d2 = new SnapshotInstance(s6);
+ c1_d2.__slotIndex = 0;
const c1_d0_ = new SnapshotInstance(s4);
+ c1_d0_.__slotIndex = 0;
c1.insertBefore(c1_d0);
c1.insertBefore(c1_d2);
c1.insertBefore(c1_d1);
@@ -786,11 +840,11 @@ describe(`list componentAtIndex`, () => {
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_25",
+ "type": "__snapshot_a94a8_test_29",
},
{
"position": 1,
- "type": "__snapshot_a94a8_test_25",
+ "type": "__snapshot_a94a8_test_29",
},
],
"removeAction": [],
@@ -837,11 +891,11 @@ describe(`list componentAtIndex`, () => {
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_25",
+ "type": "__snapshot_a94a8_test_29",
},
{
"position": 1,
- "type": "__snapshot_a94a8_test_25",
+ "type": "__snapshot_a94a8_test_29",
},
],
"removeAction": [],
@@ -883,7 +937,9 @@ describe(`list componentAtIndex`, () => {
it('should reuse and hydrate - item removed can be reused correctly', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const c0 = new SnapshotInstance(_s3);
const c1 = new SnapshotInstance(_s3);
@@ -904,12 +960,12 @@ describe(`list componentAtIndex`, () => {
c.insertBefore(d3);
});
- b.insertBefore(c0);
- b.insertBefore(c1);
- b.insertBefore(c2);
- b.insertBefore(c3);
- b.insertBefore(c4);
- b.insertBefore(c5);
+ b1.insertBefore(c0);
+ b1.insertBefore(c1);
+ b1.insertBefore(c2);
+ b1.insertBefore(c3);
+ b1.insertBefore(c4);
+ b1.insertBefore(c5);
// item-key
c0.setAttribute(0, { 'item-key': 'key-0' });
@@ -940,7 +996,7 @@ describe(`list componentAtIndex`, () => {
elementTree.triggerEnqueueComponent(listRef, 99999);
}
- b.removeChild(c3);
+ b1.removeChild(c3);
__pendingListUpdates.flush();
elementTree.triggerEnqueueComponent(listRef, component[3]);
@@ -1008,8 +1064,8 @@ describe(`list componentAtIndex`, () => {
,
{
- "elementID": 31,
- "listID": 3,
+ "elementID": 32,
+ "listID": 4,
"operationID": undefined,
"triggerLayout": true,
},
@@ -1022,27 +1078,37 @@ describe(`list componentAtIndex`, () => {
it('should reuse and hydrate - with slot', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
{HOLE}!{HOLE}
,
);
+ const x = {HOLE};
const slot = __SNAPSHOT__({HOLE});
+ const slotInner = __SNAPSHOT__();
const c0 = new SnapshotInstance(s3);
const c1 = new SnapshotInstance(s3);
- b.insertBefore(c0);
- b.insertBefore(c1);
+ b1.insertBefore(c0);
+ b1.insertBefore(c1);
const c0_d0 = new SnapshotInstance(slot);
+ c0_d0.__slotIndex = 0;
+ c0_d0.insertBefore(new SnapshotInstance(slotInner));
const c0_d1 = new SnapshotInstance(slot);
+ c0_d1.__slotIndex = 1;
+ c0_d1.insertBefore(new SnapshotInstance(slotInner));
c0.insertBefore(c0_d0);
c0.insertBefore(c0_d1);
const c1_d0 = new SnapshotInstance(slot);
+ c1_d0.insertBefore(new SnapshotInstance(slotInner));
const c1_d1 = new SnapshotInstance(slot);
+ c1_d1.insertBefore(new SnapshotInstance(slotInner));
c1.insertBefore(c1_d0);
c1.insertBefore(c1_d1);
@@ -1066,11 +1132,11 @@ describe(`list componentAtIndex`, () => {
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_29",
+ "type": "__snapshot_a94a8_test_33",
},
{
"position": 1,
- "type": "__snapshot_a94a8_test_29",
+ "type": "__snapshot_a94a8_test_33",
},
],
"removeAction": [],
@@ -1080,15 +1146,23 @@ describe(`list componentAtIndex`, () => {
}
>
-
+
+
+
+
+
-
+
+
+
+
+
`);
@@ -1097,7 +1171,9 @@ describe(`list componentAtIndex`, () => {
it('should handle continuous componentAtIndex on same index', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -1108,9 +1184,9 @@ describe(`list componentAtIndex`, () => {
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
// initial there is no child, because "update-list-info" is not flush
expect(() => {
@@ -1119,14 +1195,16 @@ describe(`list componentAtIndex`, () => {
// only call componentAtIndex after flush
__pendingListUpdates.flush();
- expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`4`);
- expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`7`); // should return a new uiSign
+ expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`5`);
+ expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`8`); // should return a new uiSign
});
it('should handle continuous componentAtIndex on same index - self reuse', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -1137,9 +1215,9 @@ describe(`list componentAtIndex`, () => {
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
// initial there is no child, because "update-list-info" is not flush
expect(() => {
@@ -1149,15 +1227,17 @@ describe(`list componentAtIndex`, () => {
// only call componentAtIndex after flush
__pendingListUpdates.flush();
let uiSign;
- expect(uiSign = elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`4`);
+ expect(uiSign = elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`5`);
elementTree.triggerEnqueueComponent(listRef, uiSign);
- expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`4`); // should reuse self
+ expect(elementTree.triggerComponentAtIndex(listRef, 0)).toMatchInlineSnapshot(`5`); // should reuse self
});
it('should handle componentAtIndex when `enableReuseNotification` is true', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -1177,12 +1257,12 @@ describe(`list componentAtIndex`, () => {
d3.setAttribute(0, { 'item-key': '3' });
d4.setAttribute(0, { 'item-key': '4' });
d5.setAttribute(0, { 'item-key': '5' });
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
- b.insertBefore(d4);
- b.insertBefore(d5);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
+ b1.insertBefore(d4);
+ b1.insertBefore(d5);
__pendingListUpdates.flush();
@@ -1214,27 +1294,27 @@ describe(`list componentAtIndex`, () => {
expect(fn.mock.calls).toMatchInlineSnapshot(`
[
[
- 4,
+ 5,
undefined,
],
[
- 7,
+ 8,
undefined,
],
[
- 10,
+ 11,
undefined,
],
[
- 13,
+ 14,
undefined,
],
[
- 4,
+ 5,
"4",
],
[
- 7,
+ 8,
"5",
],
]
@@ -1244,7 +1324,9 @@ describe(`list componentAtIndex`, () => {
it('should handle componentAtIndex when there is `reuse-identifier`', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const d0 = new SnapshotInstance(s3);
const d1 = new SnapshotInstance(s3);
@@ -1260,12 +1342,12 @@ describe(`list componentAtIndex`, () => {
d4.setAttribute(0, { 'item-key': '4', 'reuse-identifier': 'b' });
d5.setAttribute(0, { 'item-key': '5', 'reuse-identifier': 'b' });
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
- b.insertBefore(d4);
- b.insertBefore(d5);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
+ b1.insertBefore(d4);
+ b1.insertBefore(d5);
__pendingListUpdates.flush();
@@ -1307,14 +1389,20 @@ describe('list reload', () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
it('For same-type list-item with different item-key, do an insert + remove so the SDK detects it.', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
const root = b.__element_root;
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
const s3 = __SNAPSHOT__(
@@ -1323,35 +1411,46 @@ describe('list reload', () => {
);
const d1 = new SnapshotInstance(s3); // a
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3); // b
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3); // c
+ d3.__slotIndex = 0;
const d4 = new SnapshotInstance(s3); // d
+ d4.__slotIndex = 0;
d1.setAttribute(0, { 'item-key': 'a' });
d2.setAttribute(0, { 'item-key': 'b' });
d3.setAttribute(0, { 'item-key': 'c' });
d4.setAttribute(0, { 'item-key': 'd' });
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
- b.insertBefore(d4);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
+ b1.insertBefore(d4);
__pendingListUpdates.flush();
const bb = new SnapshotInstance(s1);
{
+ const bb1 = new SnapshotInstance(s11);
+ bb1.__slotIndex = 0;
+ bb.insertBefore(bb1);
const d1 = new SnapshotInstance(s3); // a1
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3); // b1
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3); // c1
+ d3.__slotIndex = 0;
const d4 = new SnapshotInstance(s3); // d1
+ d4.__slotIndex = 0;
d1.setAttribute(0, { 'item-key': 'a1' });
d2.setAttribute(0, { 'item-key': 'b1' });
d3.setAttribute(0, { 'item-key': 'c1' });
d4.setAttribute(0, { 'item-key': 'd1' });
- bb.insertBefore(d1);
- bb.insertBefore(d2);
- bb.insertBefore(d3);
- bb.insertBefore(d4);
+ bb1.insertBefore(d1);
+ bb1.insertBefore(d2);
+ bb1.insertBefore(d3);
+ bb1.insertBefore(d4);
}
hydrate(b, bb);
@@ -1364,70 +1463,72 @@ describe('list reload', () => {
text="111"
/>
-
+
+
+
`);
});
@@ -1437,6 +1538,10 @@ describe('list reload', () => {
b.ensureElements();
const root = b.__element_root;
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
+
const s3 = __SNAPSHOT__(
World
@@ -1444,20 +1549,29 @@ describe('list reload', () => {
);
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ d3.__slotIndex = 0;
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
__pendingListUpdates.flush();
const bb = new SnapshotInstance(s1);
{
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ bb.insertBefore(b1);
+
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
- bb.insertBefore(d1);
- bb.insertBefore(d2);
+ d2.__slotIndex = 0;
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
}
hydrate(b, bb);
@@ -1470,38 +1584,40 @@ describe('list reload', () => {
text="111"
/>
-
+
+
+
`);
@@ -1515,48 +1631,50 @@ describe('list reload', () => {
text="111"
/>
-
+
+
+
`);
});
@@ -1566,6 +1684,11 @@ describe('list reload', () => {
b.ensureElements();
const root = b.__element_root;
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
+
const s3 = __SNAPSHOT__(
World
@@ -1579,35 +1702,46 @@ describe('list reload', () => {
);
const d1 = new SnapshotInstance(s3); // a
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3); // b
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s4); // c
+ d3.__slotIndex = 0;
const d4 = new SnapshotInstance(s3); // d
+ d4.__slotIndex = 0;
d1.setAttribute(0, { 'item-key': 'a' });
d2.setAttribute(0, { 'item-key': 'b' });
d3.setAttribute(0, { 'item-key': 'c' });
d4.setAttribute(0, { 'item-key': 'd' });
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
- b.insertBefore(d4);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
+ b1.insertBefore(d4);
__pendingListUpdates.flush();
const bb = new SnapshotInstance(s1);
+ const bb1 = new SnapshotInstance(s11);
+ bb1.__slotIndex = 0;
+ bb.insertBefore(bb1);
{
const d1 = new SnapshotInstance(s3); // a
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s4); // c
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3); // b
+ d3.__slotIndex = 0;
const d4 = new SnapshotInstance(s3); // d
+ d4.__slotIndex = 0;
d1.setAttribute(0, { 'item-key': 'a' });
d2.setAttribute(0, { 'item-key': 'c' });
d3.setAttribute(0, { 'item-key': 'b' });
d4.setAttribute(0, { 'item-key': 'd' });
- bb.insertBefore(d1);
- bb.insertBefore(d2);
- bb.insertBefore(d3);
- bb.insertBefore(d4);
+ bb1.insertBefore(d1);
+ bb1.insertBefore(d2);
+ bb1.insertBefore(d3);
+ bb1.insertBefore(d4);
}
hydrate(b, bb);
@@ -1620,52 +1754,54 @@ describe('list reload', () => {
text="111"
/>
-
+
+
+
`);
});
@@ -1673,8 +1809,11 @@ describe('list reload', () => {
it('list-item with same type - with one list-item rendered', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
const root = b.__elements[0];
- const listRef = b.__elements[3];
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -1683,23 +1822,33 @@ describe('list reload', () => {
);
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ d3.__slotIndex = 0;
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
__pendingListUpdates.flush();
elementTree.triggerComponentAtIndex(listRef, 0);
const bb = new SnapshotInstance(s1);
{
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ bb.insertBefore(b1);
+
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
- bb.insertBefore(d1);
- bb.insertBefore(d2);
- bb.insertBefore(d3);
+ d3.__slotIndex = 0;
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
}
hydrate(b, bb);
@@ -1713,44 +1862,46 @@ describe('list reload', () => {
text="111"
/>
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
`);
});
@@ -1758,8 +1909,13 @@ describe('list reload', () => {
it('list-item with same type - platformInfo change', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
+
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
+
const root = b.__elements[0];
- const listRef = b.__elements[3];
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -1768,28 +1924,38 @@ describe('list reload', () => {
);
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
+ d3.__slotIndex = 0;
d1.setAttribute(0, { 'item-key': '1', 'full-span': true });
d2.setAttribute(0, { 'item-key': '2', 'full-span': true });
d3.setAttribute(0, { 'item-key': '3', 'full-span': true });
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
__pendingListUpdates.flush();
const bb = new SnapshotInstance(s1);
{
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ bb.insertBefore(b1);
+
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
+ d3.__slotIndex = 0;
d1.setAttribute(0, { 'item-key': '1', 'full-span': true });
d2.setAttribute(0, { 'item-key': '2', 'full-span': false });
d3.setAttribute(0, { 'item-key': '3', 'full-span': true });
- bb.insertBefore(d1);
- bb.insertBefore(d2);
- bb.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
}
hydrate(b, bb);
@@ -1802,51 +1968,53 @@ describe('list reload', () => {
text="111"
/>
-
+
+
+
`);
});
@@ -1854,8 +2022,11 @@ describe('list reload', () => {
it('list-item with different type', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
const root = b.__elements[0];
- const listRef = b.__elements[3];
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -1870,13 +2041,17 @@ describe('list reload', () => {
);
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
+ d3.__slotIndex = 0;
const d4 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
- b.insertBefore(d4);
+ d4.__slotIndex = 0;
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
+ b1.insertBefore(d4);
__pendingListUpdates.flush();
const uiSign0 = elementTree.triggerComponentAtIndex(listRef, 0);
@@ -1890,99 +2065,108 @@ describe('list reload', () => {
const recycleSignMap = recycleMap.get(s3);
expect(signMap.get(__GetElementUniqueID(d1.__element_root))).toBe(d1);
- expect(signMap.get(__GetElementUniqueID(d2.__element_root))).toBe(d2);
- expect(signMap.get(__GetElementUniqueID(d3.__element_root))).toBe(d3);
- expect(recycleSignMap.get(__GetElementUniqueID(d3.__element_root))).toBe(d3);
-
- const bb = new SnapshotInstance(s1);
- const d1_ = new SnapshotInstance(s3_alt);
- const d2_ = new SnapshotInstance(s3);
- const d3_ = new SnapshotInstance(s3);
- const d4_ = new SnapshotInstance(s3);
- bb.insertBefore(d1_);
- bb.insertBefore(d2_);
- bb.insertBefore(d3_);
- bb.insertBefore(d4_);
-
- hydrate(b, bb);
- b.unRenderElements();
-
- // Should only update `list-item` in the recycling pool
- // Should not add the on-screen `list-item` to the recycling pool,
- expect([...recycleSignMap.keys()]).toStrictEqual([__GetElementUniqueID(d3.__element_root)]);
- expect(recycleSignMap.get(__GetElementUniqueID(d3.__element_root))).not.toBe(d3);
-
- // The one rendered should be removed
- expect(root).toMatchInlineSnapshot(`
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ expect(signMap.get(__GetElementUniqueID(d2.__element_root))).toBe(d2);
+ expect(signMap.get(__GetElementUniqueID(d3.__element_root))).toBe(d3);
+ expect(recycleSignMap.get(__GetElementUniqueID(d3.__element_root))).toBe(d3);
+
+ const bb = new SnapshotInstance(s1);
+ const bb1 = new SnapshotInstance(s11);
+ bb1.__slotIndex = 0;
+ bb.insertBefore(bb1);
+ const d1_ = new SnapshotInstance(s3_alt);
+ d1_.__slotIndex = 0;
+ const d2_ = new SnapshotInstance(s3);
+ d2_.__slotIndex = 0;
+ const d3_ = new SnapshotInstance(s3);
+ d3_.__slotIndex = 0;
+ const d4_ = new SnapshotInstance(s3);
+ d4_.__slotIndex = 0;
+ bb1.insertBefore(d1_);
+ bb1.insertBefore(d2_);
+ bb1.insertBefore(d3_);
+ bb1.insertBefore(d4_);
+
+ hydrate(b, bb);
+ b.unRenderElements();
+
+ // Should only update `list-item` in the recycling pool
+ // Should not add the on-screen `list-item` to the recycling pool,
+ expect([...recycleSignMap.keys()]).toStrictEqual([__GetElementUniqueID(d3.__element_root)]);
+ expect(recycleSignMap.get(__GetElementUniqueID(d3.__element_root))).not.toBe(d3);
+
+ // The one rendered should be removed
+ expect(root).toMatchInlineSnapshot(`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`);
@@ -2001,76 +2185,78 @@ describe('list reload', () => {
text="111"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`);
@@ -2136,9 +2322,12 @@ describe('list bug', () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s2 = __SNAPSHOT__(World);
const s3 = __SNAPSHOT__(
@@ -2150,6 +2339,10 @@ describe('list bug', () => {
a.ensureElements();
const b = new SnapshotInstance(s1);
+ const b1 = new SnapshotInstance(s11);
+
+ b.insertBefore(b1);
+
const c = new SnapshotInstance(s2);
a.insertBefore(b);
@@ -2158,28 +2351,28 @@ describe('list bug', () => {
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
- expect(b.childNodes.length).toMatchInlineSnapshot(`3`);
+ expect(b1.childNodes.length).toMatchInlineSnapshot(`3`);
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-5": [
+ "-7": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
{
"position": 1,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
{
"position": 2,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
],
"removeAction": [],
@@ -2188,19 +2381,19 @@ describe('list bug', () => {
"flush": false,
"from": 0,
"to": 0,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
{
"flush": false,
"from": 1,
"to": 1,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
{
"flush": false,
"from": 2,
"to": 2,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
],
},
@@ -2210,15 +2403,15 @@ describe('list bug', () => {
{
__pendingListUpdates.clearAttachedLists();
- b.insertBefore(d3); // move
+ b1.insertBefore(d3); // move
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-5": [
+ "-7": [
{
"insertAction": [
{
"position": 2,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
],
"removeAction": [
@@ -2229,19 +2422,19 @@ describe('list bug', () => {
"flush": false,
"from": 0,
"to": 0,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
{
"flush": false,
"from": 1,
"to": 1,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
{
"flush": false,
"from": 2,
"to": 2,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
],
},
@@ -2252,10 +2445,10 @@ describe('list bug', () => {
{
__pendingListUpdates.clearAttachedLists();
- b.removeChild(d3); // move
+ b1.removeChild(d3); // move
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-5": [
+ "-7": [
{
"insertAction": [],
"removeAction": [
@@ -2266,13 +2459,13 @@ describe('list bug', () => {
"flush": false,
"from": 0,
"to": 0,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
{
"flush": false,
"from": 1,
"to": 1,
- "type": "__snapshot_a94a8_test_47",
+ "type": "__snapshot_a94a8_test_55",
},
],
},
@@ -2289,15 +2482,23 @@ describe('list-item JSXSpread', () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
it('list-item with same type - platformInfo change', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
+
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
+
const root = b.__elements[0];
- const listRef = b.__elements[3];
+ const listRef = b1.__elements[0];
const s3 = __SNAPSHOT__(
@@ -2307,11 +2508,14 @@ describe('list-item JSXSpread', () => {
{
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ d3.__slotIndex = 0;
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
d1.setAttribute(0, { 'item-key': '1', 'full-span': true, 'recyclable': true });
d2.setAttribute(0, { 'item-key': '2', 'full-span': true, 'recyclable': true });
@@ -2322,12 +2526,19 @@ describe('list-item JSXSpread', () => {
const bb = new SnapshotInstance(s1);
+ const bb1 = new SnapshotInstance(s11);
+ bb1.__slotIndex = 0;
+ bb.insertBefore(bb1);
+
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
- bb.insertBefore(d1);
- bb.insertBefore(d2);
- bb.insertBefore(d3);
+ d3.__slotIndex = 0;
+ bb1.insertBefore(d1);
+ bb1.insertBefore(d2);
+ bb1.insertBefore(d3);
d1.setAttribute(0, { 'item-key': '1', 'full-span': true, 'recyclable': false });
d2.setAttribute(0, { 'item-key': '2', 'full-span': false, 'recyclable': false });
@@ -2343,73 +2554,75 @@ describe('list-item JSXSpread', () => {
text="111"
/>
-
+
+
+
`);
@@ -2422,85 +2635,87 @@ describe('list-item JSXSpread', () => {
text="111"
/>
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
`);
@@ -2512,85 +2727,87 @@ describe('list-item JSXSpread', () => {
text="111"
/>
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
`);
});
@@ -2600,9 +2817,12 @@ describe('list-item with platform info attributes', () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s3 = __SNAPSHOT__(
{
it('basic list-item with platform info attributes', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
+
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+
const root = b.__elements[0];
- const listRef = b.__elements[3];
+ const listRef = b1.__elements[0];
{
const d0 = new SnapshotInstance(s3);
const d1 = new SnapshotInstance(s3);
const d2 = new SnapshotInstance(s3);
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
d0.setAttribute(0, {
'item-key': 'list-item-0',
@@ -2678,58 +2902,60 @@ describe('list-item with platform info attributes', () => {
text="111"
/>
-
+
+
+
`);
@@ -2758,7 +2984,7 @@ describe('list-item with platform info attributes', () => {
"reuse-identifier": "A",
"sticky-bottom": false,
"sticky-top": true,
- "type": "__snapshot_a94a8_test_51",
+ "type": "__snapshot_a94a8_test_61",
},
{
"estimated-height": 100,
@@ -2771,7 +2997,7 @@ describe('list-item with platform info attributes', () => {
"reuse-identifier": "A",
"sticky-bottom": false,
"sticky-top": false,
- "type": "__snapshot_a94a8_test_51",
+ "type": "__snapshot_a94a8_test_61",
},
{
"estimated-height": 100,
@@ -2784,7 +3010,7 @@ describe('list-item with platform info attributes', () => {
"reuse-identifier": "A",
"sticky-bottom": true,
"sticky-top": false,
- "type": "__snapshot_a94a8_test_51",
+ "type": "__snapshot_a94a8_test_61",
},
],
"removeAction": [],
@@ -2847,9 +3073,12 @@ describe('list componentAtIndexes', () => {
const s0 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s01 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s1 = __SNAPSHOT__(
@@ -2860,7 +3089,9 @@ describe('list componentAtIndexes', () => {
it('basic componentAtIndexes with async flush', () => {
const b = new SnapshotInstance(s0);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s01);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const d0 = new SnapshotInstance(s1);
const d1 = new SnapshotInstance(s1);
@@ -2868,9 +3099,9 @@ describe('list componentAtIndexes', () => {
d0.setAttribute(0, { 'item-key': 'list-item-0' });
d1.setAttribute(0, { 'item-key': 'list-item-1' });
d2.setAttribute(0, { 'item-key': 'list-item-2' });
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
__pendingListUpdates.flush();
const fn = vi.fn();
@@ -2908,11 +3139,11 @@ describe('list componentAtIndexes', () => {
[
{
"elementIDs": [
- 4,
- 7,
- 10,
+ 5,
+ 8,
+ 11,
],
- "listID": 3,
+ "listID": 4,
"operationIDs": [
0,
1,
@@ -2938,7 +3169,9 @@ describe('list componentAtIndexes', () => {
it('basic componentAtIndexes with no async flush', () => {
const b = new SnapshotInstance(s0);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s01);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const d0 = new SnapshotInstance(s1);
const d1 = new SnapshotInstance(s1);
@@ -2946,9 +3179,9 @@ describe('list componentAtIndexes', () => {
d0.setAttribute(0, { 'item-key': 'list-item-0' });
d1.setAttribute(0, { 'item-key': 'list-item-1' });
d2.setAttribute(0, { 'item-key': 'list-item-2' });
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
__pendingListUpdates.flush();
const fn = vi.fn();
@@ -2970,11 +3203,11 @@ describe('list componentAtIndexes', () => {
[
{
"elementIDs": [
- 4,
- 7,
- 10,
+ 5,
+ 8,
+ 11,
],
- "listID": 3,
+ "listID": 4,
"operationIDs": [
11,
22,
@@ -2990,7 +3223,9 @@ describe('list componentAtIndexes', () => {
it('basic componentAtIndexes with async flush and `enableReuseNotification` is true', () => {
const b = new SnapshotInstance(s0);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s01);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const d0 = new SnapshotInstance(s1);
const d1 = new SnapshotInstance(s1);
const d2 = new SnapshotInstance(s1);
@@ -3003,12 +3238,12 @@ describe('list componentAtIndexes', () => {
d3.setAttribute(0, { 'item-key': 'list-item-3' });
d4.setAttribute(0, { 'item-key': 'list-item-4' });
d5.setAttribute(0, { 'item-key': 'list-item-5' });
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
- b.insertBefore(d4);
- b.insertBefore(d5);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
+ b1.insertBefore(d4);
+ b1.insertBefore(d5);
__pendingListUpdates.flush();
{
@@ -3072,11 +3307,11 @@ describe('list componentAtIndexes', () => {
[
{
"elementIDs": [
- 4,
- 7,
- 10,
+ 5,
+ 8,
+ 11,
],
- "listID": 3,
+ "listID": 4,
"operationIDs": [
3,
4,
@@ -3092,16 +3327,18 @@ describe('list componentAtIndexes', () => {
it('should handle continuous componentAtIndexes on same index - self reuse', () => {
const b = new SnapshotInstance(s0);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s01);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const d0 = new SnapshotInstance(s1);
const d1 = new SnapshotInstance(s1);
const d2 = new SnapshotInstance(s1);
d0.setAttribute(0, { 'item-key': 'list-item-0' });
d1.setAttribute(0, { 'item-key': 'list-item-1' });
d2.setAttribute(0, { 'item-key': 'list-item-2' });
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
__pendingListUpdates.flush();
{
@@ -3149,11 +3386,11 @@ describe('list componentAtIndexes', () => {
[
{
"elementIDs": [
- 4,
- 7,
- 10,
+ 5,
+ 8,
+ 11,
],
- "listID": 3,
+ "listID": 4,
"operationIDs": [
0,
1,
@@ -3169,16 +3406,18 @@ describe('list componentAtIndexes', () => {
it('should update signMap before __FlushElementTree', () => {
const b = new SnapshotInstance(s0);
b.ensureElements();
- const listRef = b.__elements[3];
+ const b1 = new SnapshotInstance(s01);
+ b.insertBefore(b1);
+ const listRef = b1.__elements[0];
const d0 = new SnapshotInstance(s1);
const d1 = new SnapshotInstance(s1);
const d2 = new SnapshotInstance(s1);
d0.setAttribute(0, { 'item-key': 'list-item-0' });
d1.setAttribute(0, { 'item-key': 'list-item-1' });
d2.setAttribute(0, { 'item-key': 'list-item-2' });
- b.insertBefore(d0);
- b.insertBefore(d1);
- b.insertBefore(d2);
+ b1.insertBefore(d0);
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
__pendingListUpdates.flush();
const listID = __GetElementUniqueID(listRef);
@@ -3259,7 +3498,7 @@ describe('list-item with "defer" attribute', () => {
{
"item-key": "1",
"position": 0,
- "type": "__snapshot_a94a8_test_55",
+ "type": "__snapshot_a94a8_test_66",
},
],
"removeAction": [],
@@ -3296,7 +3535,7 @@ describe('list-item with "defer" attribute', () => {
{
"item-key": "1",
"position": 0,
- "type": "__snapshot_a94a8_test_55",
+ "type": "__snapshot_a94a8_test_66",
},
],
"removeAction": [],
@@ -3389,17 +3628,17 @@ describe('list-item with "defer" attribute', () => {
{
"item-key": "0",
"position": 0,
- "type": "__snapshot_a94a8_test_60",
+ "type": "__snapshot_a94a8_test_71",
},
{
"item-key": "1",
"position": 1,
- "type": "__snapshot_a94a8_test_61",
+ "type": "__snapshot_a94a8_test_72",
},
{
"item-key": "2",
"position": 2,
- "type": "__snapshot_a94a8_test_62",
+ "type": "__snapshot_a94a8_test_73",
},
],
"removeAction": [],
@@ -3472,17 +3711,17 @@ describe('list-item with "defer" attribute', () => {
{
"item-key": "0",
"position": 0,
- "type": "__snapshot_a94a8_test_60",
+ "type": "__snapshot_a94a8_test_71",
},
{
"item-key": "1",
"position": 1,
- "type": "__snapshot_a94a8_test_61",
+ "type": "__snapshot_a94a8_test_72",
},
{
"item-key": "2",
"position": 2,
- "type": "__snapshot_a94a8_test_62",
+ "type": "__snapshot_a94a8_test_73",
},
],
"removeAction": [],
@@ -3553,17 +3792,17 @@ describe('list-item with "defer" attribute', () => {
{
"item-key": "0",
"position": 0,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
{
"item-key": "1",
"position": 1,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
{
"item-key": "2",
"position": 2,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
],
"removeAction": [],
@@ -3600,17 +3839,17 @@ describe('list-item with "defer" attribute', () => {
{
"item-key": "0",
"position": 0,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
{
"item-key": "1",
"position": 1,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
{
"item-key": "2",
"position": 2,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
],
"removeAction": [],
@@ -3659,17 +3898,17 @@ describe('list-item with "defer" attribute', () => {
{
"item-key": "0",
"position": 0,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
{
"item-key": "1",
"position": 1,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
{
"item-key": "2",
"position": 2,
- "type": "__snapshot_a94a8_test_65",
+ "type": "__snapshot_a94a8_test_76",
},
],
"removeAction": [],
@@ -3756,15 +3995,21 @@ describe('nested list', () => {
const s1 = __SNAPSHOT__(
s1
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s2 = __SNAPSHOT__(
s2
- {HOLE}
+ {HOLE}
,
);
+ const s21 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s3 = __SNAPSHOT__(
s3
@@ -3775,65 +4020,67 @@ describe('nested list', () => {
const b = new SnapshotInstance(s1);
a.insertBefore(b);
+
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
+
b.ensureElements();
- const parentListRef = b.__elements[3];
+ const parentListRef = b1.__elements[0];
const c1 = new SnapshotInstance(s2);
+ const c11 = new SnapshotInstance(s21);
const c2 = new SnapshotInstance(s2);
+ const c21 = new SnapshotInstance(s21);
const c3 = new SnapshotInstance(s2);
- b.insertBefore(c1);
- b.insertBefore(c2);
- b.insertBefore(c3);
+ const c31 = new SnapshotInstance(s21);
+ c1.insertBefore(c11);
+ c2.insertBefore(c21);
+ c3.insertBefore(c31);
+ b1.insertBefore(c1);
+ b1.insertBefore(c2);
+ b1.insertBefore(c3);
const d1 = new SnapshotInstance(s3);
- c1.insertBefore(d1);
+ c11.insertBefore(d1);
const d2 = new SnapshotInstance(s3);
- c2.insertBefore(d2);
+ c21.insertBefore(d2);
const d3 = new SnapshotInstance(s3);
- c3.insertBefore(d3);
+ c31.insertBefore(d3);
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-5": [
+ "-10": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_70",
- },
- {
- "position": 1,
- "type": "__snapshot_a94a8_test_70",
- },
- {
- "position": 2,
- "type": "__snapshot_a94a8_test_70",
+ "type": "__snapshot_a94a8_test_84",
},
],
"removeAction": [],
"updateAction": [],
},
],
- "-6": [
+ "-12": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_71",
+ "type": "__snapshot_a94a8_test_84",
},
],
"removeAction": [],
"updateAction": [],
},
],
- "-7": [
+ "-14": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_71",
+ "type": "__snapshot_a94a8_test_84",
},
],
"removeAction": [],
@@ -3845,7 +4092,15 @@ describe('nested list', () => {
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_71",
+ "type": "__snapshot_a94a8_test_82",
+ },
+ {
+ "position": 1,
+ "type": "__snapshot_a94a8_test_82",
+ },
+ {
+ "position": 2,
+ "type": "__snapshot_a94a8_test_82",
},
],
"removeAction": [],
@@ -3860,36 +4115,36 @@ describe('nested list', () => {
// children list should not be cleared
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-6": [
+ "-10": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_71",
+ "type": "__snapshot_a94a8_test_84",
},
],
"removeAction": [],
"updateAction": [],
},
],
- "-7": [
+ "-12": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_71",
+ "type": "__snapshot_a94a8_test_84",
},
],
"removeAction": [],
"updateAction": [],
},
],
- "-8": [
+ "-14": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_71",
+ "type": "__snapshot_a94a8_test_84",
},
],
"removeAction": [],
@@ -3899,20 +4154,20 @@ describe('nested list', () => {
}
`);
- expect(elementTree.triggerComponentAtIndex(parentListRef, 0)).toMatchInlineSnapshot(`4`);
- expect(elementTree.triggerComponentAtIndex(parentListRef, 1)).toMatchInlineSnapshot(`8`);
- expect(elementTree.triggerComponentAtIndex(parentListRef, 2)).toMatchInlineSnapshot(`12`);
+ expect(elementTree.triggerComponentAtIndex(parentListRef, 0)).toMatchInlineSnapshot(`5`);
+ expect(elementTree.triggerComponentAtIndex(parentListRef, 1)).toMatchInlineSnapshot(`10`);
+ expect(elementTree.triggerComponentAtIndex(parentListRef, 2)).toMatchInlineSnapshot(`15`);
__pendingListUpdates.flush();
// all lists should be cleared
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`{}`);
- const childListRef1 = c1.__elements[3];
- const childListRef2 = c2.__elements[3];
- const childListRef3 = c3.__elements[3];
- expect(elementTree.triggerComponentAtIndex(childListRef1, 0)).toMatchInlineSnapshot(`16`);
- expect(elementTree.triggerComponentAtIndex(childListRef2, 0)).toMatchInlineSnapshot(`19`);
- expect(elementTree.triggerComponentAtIndex(childListRef3, 0)).toMatchInlineSnapshot(`22`);
+ const childListRef1 = c11.__elements[0];
+ const childListRef2 = c21.__elements[0];
+ const childListRef3 = c31.__elements[0];
+ expect(elementTree.triggerComponentAtIndex(childListRef1, 0)).toMatchInlineSnapshot(`20`);
+ expect(elementTree.triggerComponentAtIndex(childListRef2, 0)).toMatchInlineSnapshot(`23`);
+ expect(elementTree.triggerComponentAtIndex(childListRef3, 0)).toMatchInlineSnapshot(`26`);
expect(elementTree).toMatchInlineSnapshot(`
"
@@ -3921,124 +4176,132 @@ describe('nested list', () => {
text="s1"
/>
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+ ]
+ }
+ >
+
+
+
+
+
+
+
+
+
+
"
`);
});
@@ -4047,15 +4310,21 @@ describe('nested list', () => {
const s1 = __SNAPSHOT__(
s1
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s2 = __SNAPSHOT__(
s2
- {HOLE}
+ {HOLE}
,
);
+ const s21 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s3 = __SNAPSHOT__(
s3
@@ -4063,62 +4332,68 @@ describe('nested list', () => {
);
const a = new SnapshotInstance(s);
-
const b = new SnapshotInstance(s1);
a.insertBefore(b);
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
b.ensureElements();
- const parentListRef = b.__elements[3];
+ const parentListRef = b1.__elements[0];
const c1 = new SnapshotInstance(s2);
+ const c11 = new SnapshotInstance(s21);
+ c1.insertBefore(c11);
const c2 = new SnapshotInstance(s2);
+ const c21 = new SnapshotInstance(s21);
+ c2.insertBefore(c21);
const c3 = new SnapshotInstance(s2);
-
- b.insertBefore(c1);
- b.insertBefore(c2);
- b.insertBefore(c3);
+ const c31 = new SnapshotInstance(s21);
+ c3.insertBefore(c31);
+ b1.insertBefore(c1);
+ b1.insertBefore(c2);
+ b1.insertBefore(c3);
const d1 = new SnapshotInstance(s3);
- c1.insertBefore(d1);
+ c11.insertBefore(d1);
const d2 = new SnapshotInstance(s3);
- c2.insertBefore(d2);
+ c21.insertBefore(d2);
const d3 = new SnapshotInstance(s3);
- c3.insertBefore(d3);
+ c31.insertBefore(d3);
__pendingListUpdates.flush();
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`
{
- "-6": [
+ "-10": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_74",
+ "type": "__snapshot_a94a8_test_89",
},
],
"removeAction": [],
"updateAction": [],
},
],
- "-7": [
+ "-12": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_74",
+ "type": "__snapshot_a94a8_test_89",
},
],
"removeAction": [],
"updateAction": [],
},
],
- "-8": [
+ "-14": [
{
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_74",
+ "type": "__snapshot_a94a8_test_89",
},
],
"removeAction": [],
@@ -4145,15 +4420,15 @@ describe('nested list', () => {
"insertAction": [
{
"position": 0,
- "type": "__snapshot_a94a8_test_73",
+ "type": "__snapshot_a94a8_test_87",
},
{
"position": 1,
- "type": "__snapshot_a94a8_test_73",
+ "type": "__snapshot_a94a8_test_87",
},
{
"position": 2,
- "type": "__snapshot_a94a8_test_73",
+ "type": "__snapshot_a94a8_test_87",
},
],
"removeAction": [],
@@ -4168,22 +4443,24 @@ describe('nested list', () => {
text="s2"
/>
-
+
+
+
@@ -4191,22 +4468,24 @@ describe('nested list', () => {
text="s2"
/>
-
+
+
+
@@ -4214,22 +4493,24 @@ describe('nested list', () => {
text="s2"
/>
-
+
+
+
@@ -4237,24 +4518,26 @@ describe('nested list', () => {
text="s2"
/>
-
+
+
+
`);
@@ -4264,15 +4547,21 @@ describe('nested list', () => {
const s1 = __SNAPSHOT__(
s1
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s2 = __SNAPSHOT__(
s2
- {HOLE}
+ {HOLE}
,
);
+ const s21 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const s3 = __SNAPSHOT__(
s3
@@ -4284,22 +4573,30 @@ describe('nested list', () => {
const b = new SnapshotInstance(s1);
a.insertBefore(b);
b.ensureElements();
+ const b1 = new SnapshotInstance(s11);
+ b.insertBefore(b1);
const c1 = new SnapshotInstance(s2);
+ const c11 = new SnapshotInstance(s21);
+ c1.insertBefore(c11);
const c2 = new SnapshotInstance(s2);
+ const c21 = new SnapshotInstance(s21);
+ c2.insertBefore(c21);
const c3 = new SnapshotInstance(s2);
- b.insertBefore(c1);
- b.insertBefore(c2);
- b.insertBefore(c3);
+ const c31 = new SnapshotInstance(s21);
+ c3.insertBefore(c31);
+ b1.insertBefore(c1);
+ b1.insertBefore(c2);
+ b1.insertBefore(c3);
const d1 = new SnapshotInstance(s3);
- c1.insertBefore(d1);
+ c11.insertBefore(d1);
const d2 = new SnapshotInstance(s3);
- c2.insertBefore(d2);
+ c21.insertBefore(d2);
const d3 = new SnapshotInstance(s3);
- c3.insertBefore(d3);
+ c31.insertBefore(d3);
expect(Object.keys(__pendingListUpdates.values).length).toBe(4);
@@ -4319,14 +4616,19 @@ describe('update-list-info profile', () => {
const s1 = __SNAPSHOT__(
111
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
it('flush & hydrate', () => {
const b = new SnapshotInstance(s1);
b.ensureElements();
- const root = b.__element_root;
+ const b1 = new SnapshotInstance(s11);
+ b1.__slotIndex = 0;
+ b.insertBefore(b1);
const s3 = __SNAPSHOT__(
@@ -4335,20 +4637,29 @@ describe('update-list-info profile', () => {
);
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
+ d2.__slotIndex = 0;
const d3 = new SnapshotInstance(s3);
- b.insertBefore(d1);
- b.insertBefore(d2);
- b.insertBefore(d3);
+ d3.__slotIndex = 0;
+
+ b1.insertBefore(d1);
+ b1.insertBefore(d2);
+ b1.insertBefore(d3);
__pendingListUpdates.flush();
const bb = new SnapshotInstance(s1);
+ const bb1 = new SnapshotInstance(s11);
+ bb1.__slotIndex = 0;
+ bb.insertBefore(bb1);
{
const d1 = new SnapshotInstance(s3);
+ d1.__slotIndex = 0;
const d2 = new SnapshotInstance(s3);
- bb.insertBefore(d1);
- bb.insertBefore(d2);
+ d2.__slotIndex = 0;
+ bb1.insertBefore(d1);
+ bb1.insertBefore(d2);
}
hydrate(b, bb);
@@ -4360,8 +4671,8 @@ describe('update-list-info profile', () => {
"ReactLynx::listFlush::updateListInfo",
{
"args": {
- "list id": "3",
- "update list info": "{"insertAction":[{"position":0,"type":"__snapshot_a94a8_test_79"},{"position":1,"type":"__snapshot_a94a8_test_79"},{"position":2,"type":"__snapshot_a94a8_test_79"}],"removeAction":[],"updateAction":[]}",
+ "list id": "4",
+ "update list info": "{"insertAction":[{"position":0,"type":"__snapshot_a94a8_test_97"},{"position":1,"type":"__snapshot_a94a8_test_97"},{"position":2,"type":"__snapshot_a94a8_test_97"}],"removeAction":[],"updateAction":[]}",
},
},
],
@@ -4369,7 +4680,7 @@ describe('update-list-info profile', () => {
"ReactLynx::listHydrate::updateListInfo",
{
"args": {
- "list id": "3",
+ "list id": "4",
"update list info": "{"insertAction":[],"removeAction":[2],"updateAction":[]}",
},
},
@@ -4384,19 +4695,25 @@ describe('clear __UpdateListCallbacks', () => {
const s1 = __SNAPSHOT__(
test
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const a = new SnapshotInstance(s1);
a.ensureElements();
+ const a1 = new SnapshotInstance(s11);
+ a1.__slotIndex = 0;
+ a.insertBefore(a1);
expect(lynx.getNative().addEventListener).toHaveBeenCalledWith(
'__DestroyLifetime',
expect.any(Function),
);
- const listElement = a.__elements[3];
+ const listElement = a1.__elements[0];
expect(listElement.componentAtIndex).not.toBeNull();
expect(listElement.enqueueComponent).not.toBeNull();
expect(listElement.componentAtIndexes).not.toBeNull();
@@ -4417,22 +4734,28 @@ describe('clear __UpdateListCallbacks', () => {
const s1 = __SNAPSHOT__(
test
- {HOLE}
+ {HOLE}
,
);
+ const s11 = __SNAPSHOT__(
+ {HOLE}
,
+ );
const root = new SnapshotInstance(s0);
root.ensureElements();
const a = new SnapshotInstance(s1);
root.insertBefore(a);
+ const a1 = new SnapshotInstance(s11);
+ a1.__slotIndex = 0;
+ a.insertBefore(a1);
expect(lynx.getNative().addEventListener).toHaveBeenCalledWith(
'__DestroyLifetime',
expect.any(Function),
);
- const listElement = a.__elements[3];
+ const listElement = a1.__elements[0];
expect(listElement.componentAtIndex).not.toBeNull();
expect(listElement.enqueueComponent).not.toBeNull();
expect(listElement.componentAtIndexes).not.toBeNull();
diff --git a/packages/react/runtime/__test__/lynx/suspense.test.jsx b/packages/react/runtime/__test__/lynx/suspense.test.jsx
index 0ec90aff46..2f777ceef5 100644
--- a/packages/react/runtime/__test__/lynx/suspense.test.jsx
+++ b/packages/react/runtime/__test__/lynx/suspense.test.jsx
@@ -277,12 +277,14 @@ describe('suspense', () => {
"childId": 3,
"op": "InsertBefore",
"parentId": 2,
+ "slotIndex": 0,
},
{
"beforeId": null,
"childId": 2,
"op": "InsertBefore",
"parentId": -1,
+ "slotIndex": 0,
},
{
"childId": -3,
@@ -299,12 +301,14 @@ describe('suspense', () => {
"childId": 7,
"op": "InsertBefore",
"parentId": 3,
+ "slotIndex": 0,
},
{
"beforeId": null,
"childId": 2,
"op": "InsertBefore",
"parentId": -1,
+ "slotIndex": 0,
},
]
`);
diff --git a/packages/react/runtime/__test__/lynx/timing.test.jsx b/packages/react/runtime/__test__/lynx/timing.test.jsx
index 0dcd9c5151..599a23b817 100644
--- a/packages/react/runtime/__test__/lynx/timing.test.jsx
+++ b/packages/react/runtime/__test__/lynx/timing.test.jsx
@@ -98,7 +98,7 @@ describe('setState timing api', () => {
expect(mtCallbacks[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":3,"snapshotPatch":[0,"__snapshot_a94a8_test_2",3,0,null,4,3,4,0,1,1,3,4,null,1,-2,3,null]}],"flushOptions":{"__lynx_timing_flag":"__lynx_timing_actual_fmp"}}",
+ "data": "{"patchList":[{"id":3,"snapshotPatch":[0,"__snapshot_a94a8_test_2",3,0,null,4,3,4,0,1,1,3,4,null,0,1,-2,3,null,0]}],"flushOptions":{"__lynx_timing_flag":"__lynx_timing_actual_fmp"}}",
"patchOptions": {
"flowIds": [
666,
@@ -180,7 +180,7 @@ describe('attribute timing api', () => {
await waitSchedule();
expect(mtCallbacks[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":6,"snapshotPatch":[0,"__snapshot_a94a8_test_4",3,4,3,[{"__ltf":"__lynx_timing_actual_fmp"}],0,null,4,3,4,0,1,1,3,4,null,1,-2,3,null]}]}",
+ "data": "{"patchList":[{"id":6,"snapshotPatch":[0,"__snapshot_a94a8_test_4",3,4,3,[{"__ltf":"__lynx_timing_actual_fmp"}],0,null,4,3,4,0,1,1,3,4,null,0,1,-2,3,null,0]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -372,7 +372,7 @@ describe('attribute timing api', () => {
`);
expect(mtCallbacks[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":9,"snapshotPatch":[0,"__snapshot_a94a8_test_6",3,4,3,[{"__ltf":"__lynx_timing_actual_fmp"}],0,null,4,3,4,0,1,1,3,4,null,1,-2,3,null]}]}",
+ "data": "{"patchList":[{"id":9,"snapshotPatch":[0,"__snapshot_a94a8_test_6",3,4,3,[{"__ltf":"__lynx_timing_actual_fmp"}],0,null,4,3,4,0,1,1,3,4,null,0,1,-2,3,null,0]}]}",
"patchOptions": {
"flowIds": [
666,
@@ -716,7 +716,7 @@ describe('attribute timing api', () => {
await waitSchedule();
expect(mtCallbacks[0][1]).toMatchInlineSnapshot(`
{
- "data": "{"patchList":[{"id":17,"snapshotPatch":[0,"__snapshot_a94a8_test_15",3,4,3,[{"xxx":333,"__lynx_timing_flag":"__lynx_timing_actual_fmp"}],0,null,4,3,4,0,1,1,3,4,null,1,-2,3,null]}]}",
+ "data": "{"patchList":[{"id":17,"snapshotPatch":[0,"__snapshot_a94a8_test_12",3,4,3,[{"xxx":333,"__lynx_timing_flag":"__lynx_timing_actual_fmp"}],0,null,4,3,4,0,1,1,3,4,null,0,1,-2,3,null,0]}]}",
"patchOptions": {
"flowIds": [
666,
diff --git a/packages/react/runtime/__test__/preact.test.jsx b/packages/react/runtime/__test__/preact.test.jsx
index f8641f9e83..4ffe5094a1 100644
--- a/packages/react/runtime/__test__/preact.test.jsx
+++ b/packages/react/runtime/__test__/preact.test.jsx
@@ -165,12 +165,8 @@ describe('document', () => {
expect(scratch).toMatchInlineSnapshot(`
<__snapshot_a94a8_test_2>
- <__snapshot_a94a8_test_3>
- "Hello"
-
- <__snapshot_a94a8_test_4>
- "World"
-
+ "Hello"
+ "World"
`);
@@ -180,8 +176,6 @@ describe('document', () => {
-6,
-7,
-8,
- -9,
- -10,
]
`);
});
@@ -348,11 +342,11 @@ describe('document - background', () => {
);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_14
+ <__snapshot_a94a8_test_10
0="world"
>
"Hello"
-
+
`);
@@ -374,14 +368,10 @@ describe('document - background', () => {
);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_15>
- <__snapshot_a94a8_test_16>
- "Hello"
-
- <__snapshot_a94a8_test_17>
- "World"
-
-
+ <__snapshot_a94a8_test_11>
+ "Hello"
+ "World"
+
`);
expect([...backgroundSnapshotInstanceManager.values.keys()]).toMatchInlineSnapshot(`
@@ -392,8 +382,6 @@ describe('document - background', () => {
4,
5,
6,
- 7,
- 8,
]
`);
expect(globalBackgroundSnapshotInstancesToRemove).toMatchInlineSnapshot(`
@@ -409,17 +397,17 @@ describe('document - background', () => {
render(jsx('Hello!'), scratch);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_18>
+ <__snapshot_a94a8_test_12>
"Hello!"
-
+
`);
render(jsx('Hello!!'), scratch);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_18>
+ <__snapshot_a94a8_test_12>
"Hello!!"
-
+
`);
});
@@ -476,7 +464,7 @@ describe('document - background', () => {
render(jsx('Hello'), scratch);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_25
+ <__snapshot_a94a8_test_17
0="Hello"
/>
@@ -484,7 +472,7 @@ describe('document - background', () => {
render(jsx(null), scratch);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_25
+ <__snapshot_a94a8_test_17
0={null}
/>
@@ -499,7 +487,7 @@ describe('document - background', () => {
render(jsx(vi.fn()), scratch);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_25
+ <__snapshot_a94a8_test_17
0={[MockFunction spy]}
/>
@@ -509,7 +497,7 @@ describe('document - background', () => {
render(jsx(vi.fn()), scratch);
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_25
+ <__snapshot_a94a8_test_17
0={[MockFunction spy]}
/>
@@ -594,16 +582,16 @@ describe('document - background', () => {
await Promise.resolve();
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_27>
+ <__snapshot_a94a8_test_19>
"foo"
-
+
`);
await Promise.resolve();
expect(scratch).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_26
+ <__snapshot_a94a8_test_18
0="bar"
/>
@@ -642,26 +630,26 @@ describe('document - dual-runtime', () => {
BackgroundSnapshotInstance.prototype.toJSON = backgroundSnapshotInstanceToJSON;
expect(backgroundRoot).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_29>
- <__snapshot_a94a8_test_30>
+ <__snapshot_a94a8_test_21>
+ <__snapshot_a94a8_test_22>
"W"
-
- <__snapshot_a94a8_test_30>
+
+ <__snapshot_a94a8_test_22>
"0"
-
- <__snapshot_a94a8_test_30>
+
+ <__snapshot_a94a8_test_22>
"r"
-
- <__snapshot_a94a8_test_30>
+
+ <__snapshot_a94a8_test_22>
"l"
-
- <__snapshot_a94a8_test_30>
+
+ <__snapshot_a94a8_test_22>
"d"
-
- <__snapshot_a94a8_test_30>
+
+ <__snapshot_a94a8_test_22>
"_"
-
-
+
+
`);
delete BackgroundSnapshotInstance.prototype.toJSON;
@@ -669,36 +657,38 @@ describe('document - dual-runtime', () => {
expect(hydrate(JSON.parse(JSON.stringify(root)), backgroundRoot)).toMatchInlineSnapshot(`
[
3,
- -88,
+ -64,
"k",
"0",
3,
- -89,
+ -65,
0,
"0",
0,
- "__snapshot_a94a8_test_30",
- 117,
+ "__snapshot_a94a8_test_22",
+ 91,
3,
- 117,
+ 91,
"k",
"_",
0,
null,
- 118,
+ 92,
4,
- 118,
+ 92,
[
"_",
],
1,
- 117,
- 118,
+ 91,
+ 92,
undefined,
+ 0,
1,
- -85,
- 117,
+ -61,
+ 91,
undefined,
+ 0,
]
`);
@@ -708,33 +698,35 @@ describe('document - dual-runtime', () => {
expect(takeGlobalSnapshotPatch()).toMatchInlineSnapshot(`
[
2,
- -85,
- -88,
+ -61,
+ -64,
2,
- -85,
- 117,
+ -61,
+ 91,
0,
- "__snapshot_a94a8_test_30",
- 119,
+ "__snapshot_a94a8_test_22",
+ 93,
3,
- 119,
+ 93,
"k",
"1",
0,
null,
- 120,
+ 94,
3,
- 120,
+ 94,
0,
"1",
1,
- 119,
- 120,
+ 93,
+ 94,
undefined,
+ 0,
1,
- -85,
- 119,
- -90,
+ -61,
+ 93,
+ -66,
+ 0,
]
`);
@@ -767,7 +759,7 @@ describe('document - dual-runtime', () => {
BackgroundSnapshotInstance.prototype.toJSON = backgroundSnapshotInstanceToJSON;
expect(backgroundRoot).toMatchInlineSnapshot(`
- <__snapshot_a94a8_test_31 />
+ <__snapshot_a94a8_test_23 />
`);
delete BackgroundSnapshotInstance.prototype.toJSON;
diff --git a/packages/react/runtime/__test__/renderToOpcodes.test.jsx b/packages/react/runtime/__test__/renderToOpcodes.test.jsx
index 7de60a1ace..4a616a5e63 100644
--- a/packages/react/runtime/__test__/renderToOpcodes.test.jsx
+++ b/packages/react/runtime/__test__/renderToOpcodes.test.jsx
@@ -51,8 +51,10 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -69,6 +71,7 @@ describe('renderToString', () => {
"a",
],
},
+ 0,
2,
"values",
[
@@ -77,6 +80,7 @@ describe('renderToString', () => {
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -87,6 +91,7 @@ describe('renderToString', () => {
},
"hello world",
],
+ 0,
1,
]
`);
@@ -112,10 +117,13 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -5,
@@ -137,9 +145,12 @@ describe('renderToString', () => {
"values": undefined,
},
0,
+ 0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -5,
@@ -154,9 +165,11 @@ describe('renderToString', () => {
"type": "__snapshot_a94a8_test_2",
"values": undefined,
},
+ 0,
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -5,
@@ -167,6 +180,7 @@ describe('renderToString', () => {
},
1000,
],
+ 0,
1,
1,
]
@@ -195,10 +209,13 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -220,9 +237,12 @@ describe('renderToString', () => {
"values": undefined,
},
0,
+ 0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -237,9 +257,11 @@ describe('renderToString', () => {
"type": "__snapshot_a94a8_test_4",
"values": undefined,
},
+ 0,
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -250,6 +272,7 @@ describe('renderToString', () => {
},
1,
],
+ 0,
1,
1,
]
@@ -272,6 +295,7 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -2,
@@ -281,6 +305,7 @@ describe('renderToString', () => {
"hello world",
],
},
+ 0,
2,
"values",
[
@@ -306,8 +331,10 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -3,
@@ -322,9 +349,11 @@ describe('renderToString', () => {
"type": "__snapshot_a94a8_test_7",
"values": undefined,
},
+ 0,
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -3,
@@ -335,6 +364,7 @@ describe('renderToString', () => {
},
"111",
],
+ 0,
1,
]
`);
@@ -356,8 +386,10 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -3,
@@ -372,9 +404,11 @@ describe('renderToString', () => {
"type": "__snapshot_a94a8_test_8",
"values": undefined,
},
+ 0,
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -3,
@@ -385,6 +419,7 @@ describe('renderToString', () => {
},
"111",
],
+ 0,
1,
]
`);
@@ -404,8 +439,10 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -3,
@@ -420,9 +457,11 @@ describe('renderToString', () => {
"type": "__snapshot_a94a8_test_9",
"values": undefined,
},
+ 0,
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -3,
@@ -433,6 +472,7 @@ describe('renderToString', () => {
},
"111",
],
+ 0,
1,
]
`);
@@ -451,10 +491,13 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -476,9 +519,12 @@ describe('renderToString', () => {
"values": undefined,
},
0,
+ 0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -493,9 +539,11 @@ describe('renderToString', () => {
"type": "__snapshot_a94a8_test_11",
"values": undefined,
},
+ 0,
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -4,
@@ -506,6 +554,7 @@ describe('renderToString', () => {
},
11111,
],
+ 0,
1,
1,
]
@@ -524,10 +573,13 @@ describe('renderToString', () => {
[
0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -7,
@@ -549,9 +601,12 @@ describe('renderToString', () => {
"values": undefined,
},
0,
+ 0,
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -7,
@@ -566,9 +621,11 @@ describe('renderToString', () => {
"type": "__snapshot_a94a8_test_13",
"values": undefined,
},
+ 0,
3,
[
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -7,
@@ -579,6 +636,7 @@ describe('renderToString', () => {
},
12345,
],
+ 0,
1,
1,
]
@@ -672,10 +730,12 @@ describe('renderToString', () => {
,
);
- expect(rendered.length).toBe(3);
+ expect(rendered.length).toBe(4);
expect(rendered[0]).toStrictEqual(0);
expect(rendered[1].type).toStrictEqual(fallbackJsx.type);
- expect(rendered[2]).toStrictEqual(1);
+ // slotIndex
+ expect(rendered[2]).toStrictEqual(0);
+ expect(rendered[3]).toStrictEqual(1);
});
it('should render fallback when suspended component is not a direct child', async () => {
@@ -693,10 +753,12 @@ describe('renderToString', () => {
,
);
- expect(rendered.length).toBe(3);
+ expect(rendered.length).toBe(4);
expect(rendered[0]).toStrictEqual(0);
expect(rendered[1].type).toStrictEqual(fallbackJsx.type);
- expect(rendered[2]).toStrictEqual(1);
+ // slotIndex
+ expect(rendered[2]).toStrictEqual(0);
+ expect(rendered[3]).toStrictEqual(1);
});
it('should render a fallback that is a Fragment', async () => {
@@ -723,7 +785,7 @@ describe('renderToString', () => {
);
expect(rendered[1].type).toStrictEqual(fallbackJsx1.type);
- expect(rendered[6].type).toStrictEqual(fallbackJsx2.type);
+ expect(rendered[8].type).toStrictEqual(fallbackJsx2.type);
});
it('should render outer fallback when nested child suspends', async () => {
@@ -748,10 +810,12 @@ describe('renderToString', () => {
,
);
- expect(rendered.length).toBe(3);
+ expect(rendered.length).toBe(4);
expect(rendered[0]).toStrictEqual(0);
expect(rendered[1].type).toStrictEqual(fallbackJsx1.type);
- expect(rendered[2]).toStrictEqual(1);
+ // slotIndex
+ expect(rendered[2]).toStrictEqual(0);
+ expect(rendered[3]).toStrictEqual(1);
});
it('should render inner fallback and resolved content when outer suspense is resolved', async () => {
@@ -781,10 +845,10 @@ describe('renderToString', () => {
,
);
- expect(rendered.length).toBe(9);
+ expect(rendered.length).toBe(12);
expect(rendered[1].type).toStrictEqual(resolvedJsx1.type);
- expect(rendered[4].type).toStrictEqual(fallbackJsx2.type);
- expect(rendered[7].type).toStrictEqual(resolvedJsx2.type);
+ expect(rendered[5].type).toStrictEqual(fallbackJsx2.type);
+ expect(rendered[9].type).toStrictEqual(resolvedJsx2.type);
});
it('should render text with resolved suspense', async () => {
@@ -802,10 +866,12 @@ describe('renderToString', () => {
,
);
- expect(rendered.length).toBe(3);
+ expect(rendered.length).toBe(4);
expect(rendered[0]).toStrictEqual(0);
expect(rendered[1].type).toStrictEqual(resolvedJsx.type);
- expect(rendered[2]).toStrictEqual(1);
+ // slotIndex
+ expect(rendered[2]).toStrictEqual(0);
+ expect(rendered[3]).toStrictEqual(1);
});
it('should render text with nested suspense', async () => {
@@ -845,12 +911,83 @@ describe('renderToString', () => {
,
);
- expect(rendered.length).toBe(18);
- expect(rendered[3].type).toStrictEqual(resolvedJsx1.type);
- expect(rendered[6].type).toStrictEqual(resolvedJsx2.type);
- expect(rendered[9].type).toStrictEqual(resolvedJsx3.type);
- expect(rendered[12].type).toStrictEqual(resolvedJsx4.type);
- expect(rendered[15].type).toStrictEqual(resolvedJsx5.type);
+ expect(rendered.length).toBe(24);
+ expect(rendered[4].type).toStrictEqual(resolvedJsx1.type);
+ expect(rendered[8].type).toStrictEqual(resolvedJsx2.type);
+ expect(rendered[12].type).toStrictEqual(resolvedJsx3.type);
+ expect(rendered[16].type).toStrictEqual(resolvedJsx4.type);
+ expect(rendered[20].type).toStrictEqual(resolvedJsx5.type);
+ });
+
+ it('should only render text when it is not empty', () => {
+ expect(renderToString(
+
+
+ {''}
+ Static Text
+ ,
+ )).toMatchInlineSnapshot(`
+ [
+ 0,
+ {
+ "__slotIndex": 0,
+ "children": undefined,
+ "extraProps": undefined,
+ "id": -2,
+ "type": "__snapshot_a94a8_test_47",
+ "values": undefined,
+ },
+ 0,
+ 1,
+ ]
+ `);
+ expect(renderToString(
+
+
+ {'Dynamic Text'}
+ Static Text
+ ,
+ )).toMatchInlineSnapshot(`
+ [
+ 0,
+ {
+ "__slotIndex": 0,
+ "children": [
+ {
+ "__slotIndex": 0,
+ "children": undefined,
+ "extraProps": undefined,
+ "id": -4,
+ "type": null,
+ "values": [
+ "Dynamic Text",
+ ],
+ },
+ ],
+ "extraProps": undefined,
+ "id": -3,
+ "type": "__snapshot_a94a8_test_48",
+ "values": undefined,
+ },
+ 0,
+ 3,
+ [
+ {
+ "__slotIndex": 0,
+ "children": undefined,
+ "extraProps": undefined,
+ "id": -4,
+ "type": null,
+ "values": [
+ "Dynamic Text",
+ ],
+ },
+ "Dynamic Text",
+ ],
+ 0,
+ 1,
+ ]
+ `);
});
});
@@ -1188,7 +1325,8 @@ describe('renderOpcodesInto', () => {
`);
- const [vnodeA, vnodeB, vnodeC, vnodeC2, vnodeD] = scratch.__firstChild.props.children;
+ debugger;
+ const [vnodeA, vnodeB, vnodeC, vnodeC2, vnodeD] = scratch.__firstChild.props.$0;
expect(vnodeA).not.toHaveProperty('__elements');
expect(vnodeA).not.toHaveProperty('__element_root');
@@ -1200,7 +1338,7 @@ describe('renderOpcodesInto', () => {
expect(vnodeD).not.toHaveProperty('__element_root');
{
- const componentVNodeC = vnodeC2.props.children;
+ const componentVNodeC = vnodeC2.props.$0;
expect(componentVNodeC.type).toBe(Fragment);
expect(componentVNodeC.props.children).toHaveLength(4);
// FIXME(hzy): there is still a cycle reference
@@ -1211,8 +1349,8 @@ describe('renderOpcodesInto', () => {
});
}
- expect(vnodeD.props.children).toHaveLength(4);
- vnodeD.props.children.forEach((vnode) => {
+ expect(vnodeD.props.$0).toHaveLength(4);
+ vnodeD.props.$0.forEach((vnode) => {
expect(vnode).not.toHaveProperty('__elements');
expect(vnode).not.toHaveProperty('__element_root');
});
@@ -1237,12 +1375,14 @@ describe('createElement', () => {
[
0,
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -41,
- "type": "__snapshot_a94a8_test_74",
+ "type": "__snapshot_a94a8_test_76",
"values": undefined,
},
+ 0,
1,
]
`);
@@ -1251,12 +1391,14 @@ describe('createElement', () => {
[
0,
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -42,
- "type": "__snapshot_a94a8_test_74",
+ "type": "__snapshot_a94a8_test_76",
"values": undefined,
},
+ 0,
1,
]
`);
@@ -1273,12 +1415,14 @@ describe('createElement', () => {
[
0,
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -43,
- "type": "__snapshot_a94a8_test_75",
+ "type": "__snapshot_a94a8_test_77",
"values": undefined,
},
+ 0,
1,
]
`);
@@ -1287,12 +1431,14 @@ describe('createElement', () => {
[
0,
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": -44,
- "type": "__snapshot_a94a8_test_75",
+ "type": "__snapshot_a94a8_test_77",
"values": undefined,
},
+ 0,
1,
]
`);
diff --git a/packages/react/runtime/__test__/snapshot/dynamicPartType.test.jsx b/packages/react/runtime/__test__/snapshot/dynamicPartType.test.jsx
new file mode 100644
index 0000000000..7702fe53fe
--- /dev/null
+++ b/packages/react/runtime/__test__/snapshot/dynamicPartType.test.jsx
@@ -0,0 +1,689 @@
+/** @jsxImportSource ../../lepus */
+
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+import * as ReactLynx from '../../src/internal';
+import { setupPage, SnapshotInstance, backgroundSnapshotInstanceManager } from '../../src/snapshot';
+import { hydrate } from '../../src/renderToOpcodes/hydrate';
+import { BackgroundSnapshotInstance, hydrate as backgroundHydrate } from '../../src/snapshot/backgroundSnapshot';
+import { __pendingListUpdates } from '../../src/list/pendingListUpdates';
+import { elementTree } from '../utils/nativeMethod';
+import { prettyFormatSnapshotPatch } from '../../src/debug/formatPatch';
+import renderToString from '../../src/renderToOpcodes';
+import { clearListGlobal, gRecycleMap, gSignMap } from '../../src/list/list';
+import { jsx } from '../../lepus/jsx-runtime';
+import { globalEnvManager } from '../utils/envManager';
+
+const HOLE = null;
+
+afterEach(() => {
+ elementTree.clear();
+ clearListGlobal();
+});
+
+describe('legacy DynamicPartType should work', () => {
+ it('DynamicPartType.Slot', () => {
+ // Input:
+ //
+ // Hello, ReactLynx, {hello1}
+ // {hello2}
+ //
+ const s0 = ReactLynx.createSnapshot(
+ 's0',
+ function() {
+ const pageId = ReactLynx.__pageId;
+ const el = __CreateView(pageId);
+ const el1 = __CreateText(pageId);
+ __AppendElement(el, el1);
+ const el2 = __CreateRawText('Hello, ReactLynx, ');
+ __AppendElement(el1, el2);
+ const el3 = __CreateWrapperElement(pageId);
+ __AppendElement(el1, el3);
+ const el4 = __CreateWrapperElement(pageId);
+ __AppendElement(el, el4);
+ return [
+ el,
+ el1,
+ el2,
+ el3,
+ el4,
+ ];
+ },
+ null,
+ [
+ [
+ ReactLynx.__DynamicPartSlot,
+ 3,
+ ],
+ [
+ ReactLynx.__DynamicPartSlot,
+ 4,
+ ],
+ ],
+ undefined,
+ globDynamicComponentEntry,
+ null,
+ );
+
+ const s1 = __SNAPSHOT__(hello1);
+ const s2 = __SNAPSHOT__(hello2);
+
+ const a = new SnapshotInstance(s0);
+ a.ensureElements();
+ const root = a.__element_root;
+
+ const b1 = new SnapshotInstance('wrapper');
+ const b2 = new SnapshotInstance(s1);
+ b1.insertBefore(b2);
+
+ const c1 = new SnapshotInstance('wrapper');
+ const c2 = new SnapshotInstance(s2);
+ c1.insertBefore(c2);
+
+ a.insertBefore(b1);
+ a.insertBefore(c1);
+
+ expect(root).toMatchInlineSnapshot(`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `);
+
+ const aa = new BackgroundSnapshotInstance(s0);
+ {
+ const s1 = __SNAPSHOT__(hello3);
+ const s2 = __SNAPSHOT__(hello4);
+
+ const b1 = new BackgroundSnapshotInstance('wrapper');
+ const b2 = new BackgroundSnapshotInstance(s1);
+ b1.insertBefore(b2);
+ const c1 = new BackgroundSnapshotInstance('wrapper');
+ const c2 = new BackgroundSnapshotInstance(s2);
+ c1.insertBefore(c2);
+
+ aa.insertBefore(b1);
+ aa.insertBefore(c1);
+
+ expect(prettyFormatSnapshotPatch(backgroundHydrate(JSON.parse(JSON.stringify(a)), aa))).toMatchInlineSnapshot(`
+ [
+ {
+ "childId": -11,
+ "op": "RemoveChild",
+ "parentId": -10,
+ },
+ {
+ "id": 3,
+ "op": "CreateElement",
+ "type": "__snapshot_a94a8_test_3",
+ },
+ {
+ "beforeId": undefined,
+ "childId": 3,
+ "op": "InsertBefore",
+ "parentId": -10,
+ "slotIndex": undefined,
+ },
+ {
+ "childId": -13,
+ "op": "RemoveChild",
+ "parentId": -12,
+ },
+ {
+ "id": 5,
+ "op": "CreateElement",
+ "type": "__snapshot_a94a8_test_4",
+ },
+ {
+ "beforeId": undefined,
+ "childId": 5,
+ "op": "InsertBefore",
+ "parentId": -12,
+ "slotIndex": undefined,
+ },
+ ]
+ `);
+ backgroundSnapshotInstanceManager.values.forEach((v, k) => {
+ expect(k).toEqual(v.__id);
+ });
+ }
+
+ {
+ const slotType = a.__snapshot_def.slot[0][0];
+ // some supported slot type
+ a.__snapshot_def.slot[0][0] = -1;
+ expect(() => backgroundHydrate(JSON.parse(JSON.stringify(a)), aa)).toThrowErrorMatchingInlineSnapshot(
+ `[Error: Unexpected slot type: -1]`,
+ );
+ a.__snapshot_def.slot[0][0] = slotType;
+ }
+
+ {
+ const slotType = aa.__snapshot_def.slot[0][0];
+ // some supported slot type
+ aa.__snapshot_def.slot[0][0] = -1;
+ expect(() => backgroundHydrate(JSON.parse(JSON.stringify(a)), aa)).toThrowErrorMatchingInlineSnapshot(
+ `[Error: Unexpected slot type: -1]`,
+ );
+ aa.__snapshot_def.slot[0][0] = slotType;
+ }
+ });
+ it('DynamicPartType.Slot with list-item hydrate', () => {
+ const s0 = __SNAPSHOT__({HOLE}
);
+ const b = new SnapshotInstance(s0);
+ b.ensureElements();
+ const listRef = b.__element_root;
+
+ // Input:
+ //
+ // {HOLE}!{HOLE}
+ //
+ const s1 = ReactLynx.createSnapshot(
+ 's1',
+ function() {
+ const pageId = ReactLynx.__pageId;
+ const el = __CreateElement('list-item', pageId);
+ const el1 = __CreateWrapperElement(pageId);
+ __AppendElement(el, el1);
+ const el2 = __CreateRawText('!');
+ __AppendElement(el, el2);
+ const el3 = __CreateWrapperElement(pageId);
+ __AppendElement(el, el3);
+ return [
+ el,
+ el1,
+ el2,
+ el3,
+ ];
+ },
+ [
+ (snapshot, index, oldValue) => ReactLynx.updateListItemPlatformInfo(snapshot, index, oldValue, 0),
+ ],
+ [
+ [
+ ReactLynx.__DynamicPartSlot,
+ 1,
+ ],
+ [
+ ReactLynx.__DynamicPartSlot,
+ 3,
+ ],
+ ],
+ void 0,
+ globDynamicComponentEntry,
+ null,
+ );
+
+ const slot = __SNAPSHOT__({HOLE});
+
+ const c0 = new SnapshotInstance(s1);
+ const c1 = new SnapshotInstance(s1);
+ b.insertBefore(c0);
+ b.insertBefore(c1);
+
+ const c0_d0 = new SnapshotInstance(slot);
+ const c0_d1 = new SnapshotInstance(slot);
+ c0.insertBefore(c0_d0);
+ c0.insertBefore(c0_d1);
+
+ const c1_d0 = new SnapshotInstance(slot);
+ const c1_d1 = new SnapshotInstance(slot);
+ c1.insertBefore(c1_d0);
+ c1.insertBefore(c1_d1);
+
+ __pendingListUpdates.flush();
+
+ const component = [];
+
+ {
+ component[0] = elementTree.triggerComponentAtIndex(listRef, 0);
+ elementTree.triggerEnqueueComponent(listRef, component[0]);
+ const slotType = c0.__snapshot_def.slot[0][0];
+ // some supported slot type
+ c0.__snapshot_def.slot[0][0] = -1;
+ expect(() => elementTree.triggerComponentAtIndex(listRef, 1)).toThrowErrorMatchingInlineSnapshot(
+ `[Error: Unexpected slot type: -1]`,
+ );
+ c0.__snapshot_def.slot[0][0] = slotType;
+ }
+
+ component[0] = elementTree.triggerComponentAtIndex(listRef, 0);
+ elementTree.triggerEnqueueComponent(listRef, component[0]);
+ component[1] = elementTree.triggerComponentAtIndex(listRef, 1);
+ expect(component[1]).toBe(component[0]);
+ elementTree.triggerEnqueueComponent(listRef, component[1]);
+ component[1] = elementTree.triggerComponentAtIndex(listRef, 0);
+ expect(component[0]).toBe(component[1]);
+
+ expect(listRef).toMatchInlineSnapshot(`
+
+
+
+
+
+
+
+
+
+
+
+
+ `);
+ });
+ describe('DynamicPartType.Children', () => {
+ // Input:
+ //
+ // {HOLE}
+ //
+ const s0 = ReactLynx.createSnapshot(
+ 's0',
+ function() {
+ const pageId = ReactLynx.__pageId;
+ const el = __CreateView(pageId);
+ const el1 = __CreateText(pageId);
+ __AppendElement(el, el1);
+ return [
+ el,
+ el1,
+ ];
+ },
+ null,
+ [
+ [
+ ReactLynx.__DynamicPartChildren,
+ 1,
+ ],
+ ],
+ undefined,
+ globDynamicComponentEntry,
+ null,
+ );
+ globalEnvManager.switchToMainThread();
+
+ it('with single text child', () => {
+ setupPage(__CreatePage('0', 0));
+ const scratch = document.createElement('root');
+ scratch.ensureElements();
+
+ const opcodes = renderToString(
+ jsx(s0, {
+ children: 'hello',
+ }),
+ null,
+ scratch,
+ );
+
+ expect(opcodes).toMatchInlineSnapshot(`
+ [
+ 0,
+ {
+ "__slotIndex": 0,
+ "children": [
+ {
+ "__slotIndex": 0,
+ "children": undefined,
+ "extraProps": undefined,
+ "id": -27,
+ "type": null,
+ "values": [
+ "hello",
+ ],
+ },
+ ],
+ "extraProps": undefined,
+ "id": -26,
+ "type": "__Card__:s0",
+ "values": undefined,
+ },
+ 0,
+ 3,
+ [
+ {
+ "__slotIndex": 0,
+ "children": undefined,
+ "extraProps": undefined,
+ "id": -27,
+ "type": null,
+ "values": [
+ "hello",
+ ],
+ },
+ "hello",
+ ],
+ 0,
+ 1,
+ ]
+ `);
+
+ expect(scratch.__element_root).toMatchInlineSnapshot(`
+
+
+
+
+
+
+
+
+
+ `);
+ });
+
+ it('with single children', () => {
+ setupPage(__CreatePage('0', 0));
+ const scratch = document.createElement('root');
+ scratch.ensureElements();
+
+ const opcodes = renderToString(
+ jsx(s0, {
+ children: children,
+ }),
+ null,
+ scratch,
+ );
+
+ expect(opcodes).toMatchInlineSnapshot(`
+ [
+ 0,
+ {
+ "__slotIndex": 0,
+ "children": [
+ {
+ "__slotIndex": 0,
+ "children": undefined,
+ "extraProps": undefined,
+ "id": -29,
+ "type": "__snapshot_a94a8_test_7",
+ "values": undefined,
+ },
+ ],
+ "extraProps": undefined,
+ "id": -30,
+ "type": "__Card__:s0",
+ "values": undefined,
+ },
+ 0,
+ 0,
+ {
+ "__slotIndex": 0,
+ "children": undefined,
+ "extraProps": undefined,
+ "id": -29,
+ "type": "__snapshot_a94a8_test_7",
+ "values": undefined,
+ },
+ 0,
+ 1,
+ 1,
+ ]
+ `);
+
+ expect(scratch.__element_root).toMatchInlineSnapshot(`
+
+
+
+
+
+
+
+
+
+
+
+ `);
+ });
+ });
+});
+
+describe('DynamicPartType v2 should work', () => {
+ const slotV2Host = ReactLynx.createSnapshot(
+ 'slot_v2_host',
+ function() {
+ const pageId = ReactLynx.__pageId;
+ const el = __CreateView(pageId);
+ return [el];
+ },
+ null,
+ [
+ [
+ ReactLynx.__DynamicPartSlotV2,
+ 0,
+ ],
+ ],
+ undefined,
+ globDynamicComponentEntry,
+ null,
+ );
+
+ const listSlotV2Host = ReactLynx.createSnapshot(
+ 'list_slot_v2_host',
+ function() {
+ const pageId = ReactLynx.__pageId;
+ const el = __CreateElement('list', pageId);
+ return [el];
+ },
+ null,
+ [
+ [
+ ReactLynx.__DynamicPartListSlotV2,
+ 0,
+ ],
+ ],
+ undefined,
+ globDynamicComponentEntry,
+ null,
+ );
+
+ const slotTextA = __SNAPSHOT__(A);
+ const slotTextB = __SNAPSHOT__(B);
+ const listItemA = __SNAPSHOT__(
+
+ A
+ ,
+ );
+ const listItemB = __SNAPSHOT__(
+
+ B
+ ,
+ );
+
+ it('renderToString should treat named children props as slot children', () => {
+ const scratch = document.createElement('root');
+ scratch.ensureElements();
+
+ const opcodes = renderToString(
+ jsx(slotV2Host, {
+ $0: named child,
+ }),
+ null,
+ scratch,
+ );
+
+ expect(opcodes).toEqual([
+ 0,
+ expect.objectContaining({
+ type: '__Card__:slot_v2_host',
+ }),
+ 0,
+ 0,
+ expect.objectContaining({
+ type: expect.stringMatching(/^__snapshot_/),
+ }),
+ 0,
+ 1,
+ 1,
+ ]);
+ });
+
+ it('hydrate should diff SlotV2 children by slot index', () => {
+ setupPage(__CreatePage('0', 0));
+
+ const before = new SnapshotInstance(slotV2Host);
+ before.ensureElements();
+
+ const beforeChild = new SnapshotInstance(slotTextA);
+ beforeChild.__slotIndex = 0;
+ before.insertBefore(beforeChild);
+
+ expect(before.__element_root).toMatchInlineSnapshot(`
+
+
+
+
+
+ `);
+
+ const after = new SnapshotInstance(slotV2Host);
+ const afterChild = new SnapshotInstance(slotTextB);
+ afterChild.__slotIndex = 0;
+ after.insertBefore(afterChild);
+
+ hydrate(before, after);
+
+ expect(before.__element_root).toMatchInlineSnapshot(`
+
+
+
+
+
+ `);
+ });
+
+ it('background hydrate should diff SlotV2 children by slot index', () => {
+ setupPage(__CreatePage('0', 0));
+
+ const before = new SnapshotInstance(slotV2Host);
+ const beforeChild = new SnapshotInstance(slotTextA);
+ beforeChild.__slotIndex = 0;
+ before.insertBefore(beforeChild);
+
+ const after = new BackgroundSnapshotInstance(slotV2Host);
+ const afterChild = new BackgroundSnapshotInstance(slotTextB);
+ afterChild.__slotIndex = 0;
+ after.insertBefore(afterChild);
+
+ const patch = prettyFormatSnapshotPatch(
+ backgroundHydrate(JSON.parse(JSON.stringify(before)), after),
+ );
+
+ expect(patch).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ op: 'RemoveChild',
+ parentId: before.__id,
+ childId: before.childNodes[0].__id,
+ }),
+ expect.objectContaining({
+ op: 'CreateElement',
+ type: slotTextB,
+ }),
+ expect.objectContaining({
+ op: 'InsertBefore',
+ parentId: before.__id,
+ beforeId: undefined,
+ slotIndex: 0,
+ }),
+ ]),
+ );
+ });
+
+ it('hydrate should diff ListSlotV2 children by slot index', () => {
+ setupPage(__CreatePage('0', 0));
+
+ const before = new SnapshotInstance(listSlotV2Host);
+ before.ensureElements();
+
+ const listID = __GetElementUniqueID(before.__element_root);
+ gSignMap[listID] = new Map();
+ gRecycleMap[listID] = new Map();
+
+ const beforeChild = new SnapshotInstance(listItemA);
+ beforeChild.__slotIndex = 0;
+ beforeChild.__listItemPlatformInfo = { 'item-key': 0 };
+ before.insertBefore(beforeChild);
+
+ const after = new SnapshotInstance(listSlotV2Host);
+ const afterChild = new SnapshotInstance(listItemB);
+ afterChild.__slotIndex = 0;
+ afterChild.__listItemPlatformInfo = { 'item-key': 0 };
+ after.insertBefore(afterChild);
+
+ hydrate(before, after);
+
+ expect(__GetAttributeByName(before.__element_root, 'update-list-info')).toEqual([
+ {
+ insertAction: [
+ {
+ position: 0,
+ type: listItemB,
+ 'item-key': 0,
+ },
+ ],
+ removeAction: [0],
+ updateAction: [],
+ },
+ ]);
+ });
+});
diff --git a/packages/react/runtime/__test__/snapshot/event.test.jsx b/packages/react/runtime/__test__/snapshot/event.test.jsx
index 2d0f9c3939..00b171250c 100644
--- a/packages/react/runtime/__test__/snapshot/event.test.jsx
+++ b/packages/react/runtime/__test__/snapshot/event.test.jsx
@@ -320,6 +320,7 @@ describe('eventUpdate', () => {
-2,
3,
undefined,
+ 0,
]
`);
globalEnvManager.switchToMainThread();
@@ -948,6 +949,7 @@ describe('event in spread', () => {
-2,
3,
undefined,
+ 0,
]
`);
globalEnvManager.switchToMainThread();
@@ -1154,7 +1156,7 @@ describe('event when firstScreenSyncTiming is jsReady', () => {
"-5": -8,
"-6": -9,
},
- "root": "{"id":-7,"type":"root","children":[{"id":-8,"type":"__snapshot_a94a8_test_12","children":[{"id":-9,"type":"__snapshot_a94a8_test_11","values":["-9:0:"]}]}]}",
+ "root": "{"id":-7,"type":"root","children":[{"id":-8,"type":"__snapshot_a94a8_test_12","children":[{"id":-9,"type":"__snapshot_a94a8_test_11","values":["-9:0:"],"__slotIndex":0}],"__slotIndex":0}]}",
},
],
]
@@ -1263,7 +1265,7 @@ describe('call `root.render()` async', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_14","children":[{"id":-3,"type":"__snapshot_a94a8_test_13","values":["-3:0:"]}]}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_14","children":[{"id":-3,"type":"__snapshot_a94a8_test_13","values":["-3:0:"],"__slotIndex":0}],"__slotIndex":0}]}",
},
],
]
diff --git a/packages/react/runtime/__test__/snapshot/ref.test.jsx b/packages/react/runtime/__test__/snapshot/ref.test.jsx
index b4027b873d..222fa622c7 100644
--- a/packages/react/runtime/__test__/snapshot/ref.test.jsx
+++ b/packages/react/runtime/__test__/snapshot/ref.test.jsx
@@ -117,7 +117,7 @@ describe('element ref', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_3","values":["react-ref--2-0","react-ref--2-1"]}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_3","values":["react-ref--2-0","react-ref--2-1"],"__slotIndex":0}]}",
},
],
]
@@ -202,7 +202,7 @@ describe('element ref', () => {
render(, __root);
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1].data).toMatchInlineSnapshot(
- `"{"patchList":[{"id":3,"snapshotPatch":[0,"__snapshot_a94a8_test_4",2,4,2,[1,1],1,-1,2,null]}]}"`,
+ `"{"patchList":[{"id":3,"snapshotPatch":[0,"__snapshot_a94a8_test_4",2,4,2,[1,1],1,-1,2,null,0]}]}"`,
);
}
@@ -496,7 +496,7 @@ describe('element ref', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_9","values":["react-ref--2-0","react-ref--2-1","react-ref--2-2"]}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_9","values":["react-ref--2-0","react-ref--2-1","react-ref--2-2"],"__slotIndex":0}]}",
},
],
]
@@ -903,7 +903,7 @@ describe('element ref', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_17"}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_17","__slotIndex":0}]}",
},
],
]
@@ -938,7 +938,7 @@ describe('element ref', () => {
lynxCoreInject.tt.OnLifecycleEvent(...globalThis.__OnLifecycleEvent.mock.calls[0]);
expect(lynx.getNativeApp().callLepusMethod).toHaveBeenCalledTimes(1);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1].data).toMatchInlineSnapshot(
- `"{"patchList":[{"snapshotPatch":[0,"__snapshot_a94a8_test_18",3,4,3,[1],1,-2,3,null],"id":2}]}"`,
+ `"{"patchList":[{"snapshotPatch":[0,"__snapshot_a94a8_test_18",3,4,3,[1],1,-2,3,null,0],"id":2}]}"`,
);
// rLynxChange
@@ -1015,7 +1015,7 @@ describe('element ref in spread', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_19","values":[{},{"ref":"react-ref--2-1"},{}]}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_a94a8_test_19","values":[{},{"ref":"react-ref--2-1"},{}],"__slotIndex":0}]}",
},
],
],
@@ -1960,7 +1960,7 @@ describe('ui operations', () => {
render(, __root);
expect(lynx.getNativeApp().callLepusMethod.mock.calls[0][1].data).toMatchInlineSnapshot(
- `"{"patchList":[{"id":3,"snapshotPatch":[0,"__snapshot_a94a8_test_30",3,4,3,[1],1,-2,3,null]}]}"`,
+ `"{"patchList":[{"id":3,"snapshotPatch":[0,"__snapshot_a94a8_test_30",3,4,3,[1],1,-2,3,null,0]}]}"`,
);
expect(lynx.createSelectorQuery().constructor.execLog.mock.calls).toMatchInlineSnapshot(`
[
diff --git a/packages/react/runtime/__test__/snapshotPatch.test.jsx b/packages/react/runtime/__test__/snapshotPatch.test.jsx
index c225cbe258..22b03bbb93 100644
--- a/packages/react/runtime/__test__/snapshotPatch.test.jsx
+++ b/packages/react/runtime/__test__/snapshotPatch.test.jsx
@@ -153,6 +153,7 @@ describe('insertBefore', () => {
2,
3,
undefined,
+ undefined,
]
`);
@@ -203,10 +204,12 @@ describe('insertBefore', () => {
2,
4,
undefined,
+ undefined,
1,
2,
3,
4,
+ undefined,
]
`);
@@ -252,14 +255,17 @@ describe('insertBefore', () => {
2,
100,
null,
+ 0,
SnapshotOperation.InsertBefore,
100,
2,
null,
+ 1,
SnapshotOperation.InsertBefore,
4,
100,
null,
+ 2,
);
expect(patch).toMatchInlineSnapshot(`
[
@@ -273,14 +279,17 @@ describe('insertBefore', () => {
2,
100,
null,
+ 0,
1,
100,
2,
null,
1,
+ 1,
4,
100,
null,
+ 2,
]
`);
@@ -1529,7 +1538,7 @@ describe('list', () => {
bsi2.setAttribute('values', ['test']);
bsi1.insertBefore(bsi2);
patch = takeGlobalSnapshotPatch();
- expect(patch.length).toMatchInlineSnapshot(`10`);
+ expect(patch.length).toMatchInlineSnapshot(`11`);
snapshotPatchApply(patch);
expect(si1.__element_root).toMatchInlineSnapshot(`
diff --git a/packages/react/runtime/__test__/ssr.test.jsx b/packages/react/runtime/__test__/ssr.test.jsx
index f43ace6235..07bbffcb2f 100644
--- a/packages/react/runtime/__test__/ssr.test.jsx
+++ b/packages/react/runtime/__test__/ssr.test.jsx
@@ -60,6 +60,7 @@ describe('ssr', () => {
},
],
],
+ 0,
1,
],
}
@@ -113,6 +114,7 @@ describe('ssr', () => {
],
],
0,
+ 0,
[
"__snapshot_a94a8_test_3",
-3,
@@ -132,6 +134,7 @@ describe('ssr', () => {
],
],
0,
+ 0,
[
"__snapshot_a94a8_test_4",
-4,
@@ -142,6 +145,7 @@ describe('ssr', () => {
],
],
0,
+ 0,
[
"__snapshot_a94a8_test_5",
-5,
@@ -163,6 +167,7 @@ describe('ssr', () => {
},
],
],
+ 0,
1,
1,
1,
@@ -203,6 +208,7 @@ describe('ssr', () => {
},
],
],
+ 0,
2,
"values",
[
@@ -254,6 +260,7 @@ describe('ssr', () => {
},
],
],
+ 0,
2,
"values",
[
@@ -314,6 +321,7 @@ describe('ssr', () => {
],
],
0,
+ 0,
[
"__snapshot_a94a8_test_9",
-3,
@@ -333,6 +341,7 @@ describe('ssr', () => {
],
],
0,
+ 0,
[
"__snapshot_a94a8_test_10",
-4,
@@ -342,6 +351,7 @@ describe('ssr', () => {
},
],
],
+ 0,
1,
1,
1,
diff --git a/packages/react/runtime/__test__/utils/debug.js b/packages/react/runtime/__test__/utils/debug.js
index 199ed81ae2..f8b4aa6125 100644
--- a/packages/react/runtime/__test__/utils/debug.js
+++ b/packages/react/runtime/__test__/utils/debug.js
@@ -30,6 +30,7 @@ function backgroundSnapshotInstanceToJSON() {
props: Object.fromEntries(
this.__values?.map((v, i) => [`${i}`, v]) ?? [],
),
+ __slotIndex: this.__slotIndex,
};
Object.defineProperty(json, '$$typeof', {
value: Symbol.for('react.test.json'),
diff --git a/packages/react/runtime/lazy/internal.js b/packages/react/runtime/lazy/internal.js
index 8093ba94c9..5d0d3b475c 100644
--- a/packages/react/runtime/lazy/internal.js
+++ b/packages/react/runtime/lazy/internal.js
@@ -19,7 +19,10 @@ export const {
__DynamicPartChildren,
__DynamicPartChildren_0,
__DynamicPartListChildren,
+ __DynamicPartListSlotV2,
__DynamicPartSlot,
+ __DynamicPartSlotV2,
+ __DynamicPartSlotV2_0,
__DynamicPartMultiChildren,
__dynamicImport,
__page,
diff --git a/packages/react/runtime/src/document.ts b/packages/react/runtime/src/document.ts
index 50ff8678c0..c0ed053b4c 100644
--- a/packages/react/runtime/src/document.ts
+++ b/packages/react/runtime/src/document.ts
@@ -33,14 +33,14 @@ const document: SnapshotDocumentAdapter = {} as SnapshotDocumentAdapter;
* Sets up the document interface for the background thread.
* All DOM operations are intercepted to create {@link BackgroundSnapshotInstance}.
*/
-function setupBackgroundDocument(): void {
- document.createElement = function(type: string) {
+function setupBackgroundDocument(_document: SnapshotDocumentAdapter = document): void {
+ _document.createElement = function(type: string) {
return new BackgroundSnapshotInstance(type);
};
- document.createElementNS = function(_ns: string, type: string) {
+ _document.createElementNS = function(_ns: string, type: string, _is?: string) {
return new BackgroundSnapshotInstance(type);
};
- document.createTextNode = function(text: string) {
+ _document.createTextNode = function(text: string) {
const i = new BackgroundSnapshotInstance(null as unknown as string);
i.setAttribute(0, text);
Object.defineProperty(i, 'data', {
@@ -56,14 +56,16 @@ function setupBackgroundDocument(): void {
* Sets up the document interface for the main thread.
* All DOM operations are intercepted to create {@link SnapshotInstance}.
*/
-function setupDocument(): void {
- document.createElement = function(type: string) {
- return new SnapshotInstance(type);
+function setupDocument(_document: SnapshotDocumentAdapter = document): void {
+ _document.createElement = function(type: string) {
+ const si = new SnapshotInstance(type);
+ return si;
};
- document.createElementNS = function(_ns: string, type: string) {
- return new SnapshotInstance(type);
+ _document.createElementNS = function(_ns: string, type: string, _is?: string) {
+ const si = new SnapshotInstance(type);
+ return si;
};
- document.createTextNode = function(text: string) {
+ _document.createTextNode = function(text: string) {
const i = new SnapshotInstance(null as unknown as string);
i.setAttribute(0, text);
Object.defineProperty(i, 'data', {
diff --git a/packages/react/runtime/src/internal.ts b/packages/react/runtime/src/internal.ts
index 043b77c151..7c4decbad4 100644
--- a/packages/react/runtime/src/internal.ts
+++ b/packages/react/runtime/src/internal.ts
@@ -36,6 +36,11 @@ export const __DynamicPartChildren: DynamicPartType = DynamicPartType.Children;
export const __DynamicPartListChildren: DynamicPartType = DynamicPartType.ListChildren;
export { __DynamicPartChildren_0 } from './snapshot/dynamicPartType.js';
+// v2 slot
+export const __DynamicPartSlotV2: DynamicPartType = DynamicPartType.SlotV2;
+export const __DynamicPartListSlotV2: DynamicPartType = DynamicPartType.ListSlotV2;
+export const __DynamicPartSlotV2_0: [DynamicPartType, number][] = [[DynamicPartType.SlotV2, 0]];
+
export { updateSpread } from './snapshot/spread.js';
export { updateEvent } from './snapshot/event.js';
export { updateRef, transformRef } from './snapshot/ref.js';
diff --git a/packages/react/runtime/src/lifecycle/patch/snapshotPatch.ts b/packages/react/runtime/src/lifecycle/patch/snapshotPatch.ts
index 00ac03e2b8..42081385bc 100644
--- a/packages/react/runtime/src/lifecycle/patch/snapshotPatch.ts
+++ b/packages/react/runtime/src/lifecycle/patch/snapshotPatch.ts
@@ -21,10 +21,18 @@ export const SnapshotOperation = {
} as const;
export const SnapshotOperationParams: Record = /* @__PURE__ */ {
- [SnapshotOperation.CreateElement]: { name: 'CreateElement', params: ['type', /* string */ 'id' /* number */] },
+ [SnapshotOperation.CreateElement]: {
+ name: 'CreateElement',
+ params: ['type', /* string */ 'id' /* number */],
+ },
[SnapshotOperation.InsertBefore]: {
name: 'InsertBefore',
- params: ['parentId', /* number */ 'childId', /* number */ 'beforeId' /* number | undefined */],
+ params: [
+ 'parentId',
+ /* number */ 'childId',
+ /* number */ 'beforeId',
+ /* number | undefined */ 'slotIndex', /* number | undefined */
+ ],
},
[SnapshotOperation.RemoveChild]: { name: 'RemoveChild', params: ['parentId', /* number */ 'childId' /* number */] },
[SnapshotOperation.SetAttribute]: {
diff --git a/packages/react/runtime/src/lifecycle/patch/snapshotPatchApply.ts b/packages/react/runtime/src/lifecycle/patch/snapshotPatchApply.ts
index 62565c47cc..ff205a6e0d 100644
--- a/packages/react/runtime/src/lifecycle/patch/snapshotPatchApply.ts
+++ b/packages/react/runtime/src/lifecycle/patch/snapshotPatchApply.ts
@@ -37,12 +37,14 @@ export function snapshotPatchApply(snapshotPatch: SnapshotPatch): void {
const parentId = snapshotPatch[++i] as number;
const childId = snapshotPatch[++i] as number;
const beforeId = snapshotPatch[++i] as number | undefined;
+ const __slotIndex = snapshotPatch[++i] as number | undefined;
const parent = snapshotInstanceManager.values.get(parentId);
const child = snapshotInstanceManager.values.get(childId);
const existingNode = snapshotInstanceManager.values.get(beforeId!);
if (!parent || !child) {
sendCtxNotFoundEventToBackground(parent ? childId : parentId);
} else {
+ child.__slotIndex = __slotIndex;
parent.insertBefore(child, existingNode);
}
break;
diff --git a/packages/react/runtime/src/lynx/suspense.ts b/packages/react/runtime/src/lynx/suspense.ts
index 49cf8ec111..69a34cac01 100644
--- a/packages/react/runtime/src/lynx/suspense.ts
+++ b/packages/react/runtime/src/lynx/suspense.ts
@@ -20,30 +20,38 @@ export const Suspense: FunctionComponent<{ children: VNode | VNode[]; fallback:
const newChildren = __createElement(
'wrapper',
- __MAIN_THREAD__ ? {} : {
- ref: (bsi: BackgroundSnapshotInstance) => {
- if (bsi) {
- childrenRef.current = bsi;
- }
+ __MAIN_THREAD__
+ ? {
+ $0: children,
+ }
+ : {
+ ref: (bsi: BackgroundSnapshotInstance) => {
+ if (bsi) {
+ childrenRef.current = bsi;
+ }
+ },
+ $0: children,
},
- },
- children,
);
const newFallback = __createElement(
'wrapper',
- __MAIN_THREAD__ ? {} : {
- ref: (bsi: BackgroundSnapshotInstance) => {
- if (bsi && childrenRef.current) {
- const i = globalBackgroundSnapshotInstancesToRemove.indexOf(childrenRef.current.__id);
- if (i !== -1) {
- globalBackgroundSnapshotInstancesToRemove.splice(i, 1);
+ __MAIN_THREAD__
+ ? {
+ $0: fallback,
+ }
+ : {
+ ref: (bsi: BackgroundSnapshotInstance) => {
+ if (bsi && childrenRef.current) {
+ const i = globalBackgroundSnapshotInstancesToRemove.indexOf(childrenRef.current.__id);
+ if (i !== -1) {
+ globalBackgroundSnapshotInstancesToRemove.splice(i, 1);
+ }
+ childrenRef.current = undefined;
}
- childrenRef.current = undefined;
- }
+ },
+ $0: fallback,
},
- },
- fallback,
);
return __createElement(PreactSuspense, { fallback: newFallback }, newChildren);
diff --git a/packages/react/runtime/src/renderToOpcodes/hydrate.ts b/packages/react/runtime/src/renderToOpcodes/hydrate.ts
index cee54eaabe..64a5e3403d 100644
--- a/packages/react/runtime/src/renderToOpcodes/hydrate.ts
+++ b/packages/react/runtime/src/renderToOpcodes/hydrate.ts
@@ -262,10 +262,18 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
hydrate(v1, v2, options);
break;
}
+ case DynamicPartType.SlotV2:
case DynamicPartType.Children: {
+ let filteredBeforeChildNodes = beforeChildNodes;
+ let filteredAfterChildNodes = afterChildNodes;
+ if (type === DynamicPartType.SlotV2) {
+ filteredBeforeChildNodes = beforeChildNodes.filter(v => v.__slotIndex === index);
+ filteredAfterChildNodes = afterChildNodes.filter(v => v.__slotIndex === index);
+ }
+
const diffResult = diffArrayLepus(
- beforeChildNodes,
- afterChildNodes,
+ filteredBeforeChildNodes,
+ filteredAfterChildNodes,
(a, b) => a.type === b.type,
(a, b) => {
hydrate(a, b, options);
@@ -273,7 +281,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
false,
);
diffArrayAction(
- beforeChildNodes,
+ filteredBeforeChildNodes,
diffResult,
(node, target) => {
node.ensureElements();
@@ -304,7 +312,15 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
);
break;
}
+ case DynamicPartType.ListSlotV2:
case DynamicPartType.ListChildren: {
+ let filteredBeforeChildNodes = beforeChildNodes;
+ let filteredAfterChildNodes = afterChildNodes;
+ if (type === DynamicPartType.ListSlotV2) {
+ filteredBeforeChildNodes = beforeChildNodes.filter(v => v.__slotIndex === index);
+ filteredAfterChildNodes = afterChildNodes.filter(v => v.__slotIndex === index);
+ }
+
const removals: number[] = [];
const insertions: number[] = [];
const updateAction: any[] = [];
@@ -314,8 +330,8 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
const recycleMap = gRecycleMap[listID]!;
const diffResult = diffArrayLepus(
- beforeChildNodes,
- afterChildNodes,
+ filteredBeforeChildNodes,
+ filteredAfterChildNodes,
(a, b) => a.type === b.type,
(a, b, _oldIndex, newIndex) => {
if (
@@ -406,7 +422,10 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
if (typeof __PROFILE__ !== 'undefined' && __PROFILE__) {
profileEnd();
}
+ break;
}
+ default:
+ throw new Error('Unexpected slot type: ' + type);
}
});
}
diff --git a/packages/react/runtime/src/renderToOpcodes/index.ts b/packages/react/runtime/src/renderToOpcodes/index.ts
index 4381d53586..451eb450bb 100644
--- a/packages/react/runtime/src/renderToOpcodes/index.ts
+++ b/packages/react/runtime/src/renderToOpcodes/index.ts
@@ -69,7 +69,7 @@ export function renderToString(vnode: any, context: any, into: SnapshotInstance)
_renderToString(
vnode,
context || EMPTY_OBJ,
- false,
+ 0,
undefined,
parent,
opcodes,
@@ -145,7 +145,7 @@ function renderClassComponent(vnode, context) {
* Recursively render VNodes to HTML.
* @param {VNode|any} vnode
* @param {any} context
- * @param {boolean} isSvgMode
+ * @param {number | true} slotIndex
* @param {any} selectValue
* @param {VNode} parent
* @param {any[]} opcodes
@@ -155,7 +155,7 @@ function renderClassComponent(vnode, context) {
function _renderToString(
vnode,
context,
- isSvgMode,
+ slotIndex,
selectValue,
parent,
opcodes,
@@ -171,7 +171,7 @@ function _renderToString(
// Text VNodes: escape as HTML
if (vnodeType !== 'object') {
if (vnodeType === 'function') return;
- renderToTextNode(into, vnode + '', opcodes);
+ renderToTextNode(into, vnode, opcodes, slotIndex);
return;
}
@@ -185,7 +185,7 @@ function _renderToString(
_renderToString(
child,
context,
- isSvgMode,
+ slotIndex === true ? i : slotIndex,
selectValue,
parent,
opcodes,
@@ -275,7 +275,7 @@ function _renderToString(
_renderToString(
rendered,
context,
- isSvgMode,
+ slotIndex,
selectValue,
vnode,
opcodes,
@@ -305,7 +305,7 @@ function _renderToString(
_renderToString(
rendered,
context,
- isSvgMode,
+ slotIndex,
selectValue,
vnode,
opcodes,
@@ -329,6 +329,7 @@ function _renderToString(
}
let children;
+ let hasNamedChildren = false;
// hack for runtime test
if (process.env['NODE_ENV'] === 'test' && isValidElement(vnode) && typeof vnode.type === 'string') {
@@ -339,8 +340,9 @@ function _renderToString(
vnode = new SnapshotInstance(type);
}
if (__ENABLE_SSR__) {
- opcodes.push(__OpBegin, vnode);
+ opcodes.push(__OpBegin, vnode, slotIndex);
}
+ vnode.__slotIndex = slotIndex;
into.insertBefore(vnode);
for (const name in props) {
@@ -359,7 +361,14 @@ function _renderToString(
case '__source':
continue;
- default: {}
+ default: {
+ if (name.startsWith('$')) {
+ children ??= [];
+ children[+name.slice(1)] = v;
+ hasNamedChildren = true;
+ continue;
+ }
+ }
}
// write this attribute to the buffer
@@ -374,13 +383,23 @@ function _renderToString(
let childrenType = typeof children;
if (childrenType === 'string' || childrenType === 'number') {
// single text child
- renderToTextNode(vnode, children, opcodes);
+ renderToTextNode(vnode, children, opcodes, slotIndex);
} else if (children != null && children !== false && children !== true) {
// recurse into this element VNode's children
+ let _slotIndex = slotIndex;
+ if (hasNamedChildren) {
+ // @ts-expect-error children must be an array
+ if (children.length === 1) {
+ children = children[0];
+ _slotIndex = 0;
+ } else {
+ _slotIndex = true;
+ }
+ }
_renderToString(
children,
context,
- false,
+ _slotIndex,
selectValue,
vnode,
opcodes,
@@ -408,14 +427,15 @@ function doRender(props, state, context) {
return this.constructor(props, context);
}
-function renderToTextNode(into: SnapshotInstance, text: string | number, opcodes: Opcode[]) {
+function renderToTextNode(into: SnapshotInstance, text: string | number, opcodes: Opcode[], slotIndex: number) {
const textNode = new SnapshotInstance(null);
+ textNode.__slotIndex = slotIndex;
textNode.setAttribute(0, text);
into.insertBefore(textNode);
if (__ENABLE_SSR__) {
// We need store the just created SnapshotInstance, or it will be lost when we leave the function
text = [textNode, text];
- opcodes.push(__OpText, text);
+ opcodes.push(__OpText, text, slotIndex);
}
}
diff --git a/packages/react/runtime/src/renderToOpcodes/opcodes.ts b/packages/react/runtime/src/renderToOpcodes/opcodes.ts
index 365e2fc191..2428922b49 100644
--- a/packages/react/runtime/src/renderToOpcodes/opcodes.ts
+++ b/packages/react/runtime/src/renderToOpcodes/opcodes.ts
@@ -31,10 +31,11 @@ export function ssrHydrateByOpcodes(
const [type, __id, elements] = opcodes[i + 1] as SSRSnapshotInstance;
top = new SnapshotInstance(type, __id);
top.__pendingElements = elements;
+ top.__slotIndex = opcodes[i + 2];
p.insertBefore(top);
stack.push(top);
- i += 2;
+ i += 3;
break;
}
case OpcodeEnd: {
@@ -84,11 +85,12 @@ export function ssrHydrateByOpcodes(
case OpcodeText: {
const [[type, __id, elements], text] = opcodes[i + 1] as [SSRSnapshotInstance, string];
const s = new SnapshotInstance(type, __id);
+ s.__slotIndex = opcodes[i + 2];
s.setAttribute(0, text);
top.insertBefore(s);
s.__elements = elements.map(({ ssrID }) => refMap![ssrID]!);
s.__element_root = s.__elements[0];
- i += 2;
+ i += 3;
break;
}
}
diff --git a/packages/react/runtime/src/snapshot/backgroundSnapshot.ts b/packages/react/runtime/src/snapshot/backgroundSnapshot.ts
index 7c08108f03..b106ca4156 100644
--- a/packages/react/runtime/src/snapshot/backgroundSnapshot.ts
+++ b/packages/react/runtime/src/snapshot/backgroundSnapshot.ts
@@ -125,6 +125,7 @@ export class BackgroundSnapshotInstance {
__values: any[] | undefined;
__snapshot_def: Snapshot;
__extraProps?: Record | undefined;
+ __slotIndex?: number | undefined;
private __parent: BackgroundSnapshotInstance | null = null;
private __firstChild: BackgroundSnapshotInstance | null = null;
@@ -169,6 +170,7 @@ export class BackgroundSnapshotInstance {
this.__id,
node.__id,
beforeNode?.__id,
+ node.__slotIndex,
);
}
@@ -588,11 +590,20 @@ export function hydrate(
helper(v1, v2);
break;
}
+ case DynamicPartType.SlotV2:
+ case DynamicPartType.ListSlotV2:
case DynamicPartType.Children:
case DynamicPartType.ListChildren: {
+ let filteredBeforeChildNodes = beforeChildNodes;
+ let filteredAfterChildNodes = afterChildNodes;
+ if (type === DynamicPartType.SlotV2 || type === DynamicPartType.ListSlotV2) {
+ filteredBeforeChildNodes = beforeChildNodes.filter(v => v.__slotIndex === index);
+ filteredAfterChildNodes = afterChildNodes.filter(v => v.__slotIndex === index);
+ }
+
const diffResult = diffArrayLepus(
- beforeChildNodes,
- afterChildNodes,
+ filteredBeforeChildNodes,
+ filteredAfterChildNodes,
(a, b) => a.type === b.type,
(a, b) => {
helper(a, b);
@@ -601,7 +612,7 @@ export function hydrate(
false,
);
diffArrayAction(
- beforeChildNodes,
+ filteredBeforeChildNodes,
diffResult,
(node, target) => {
if (shouldProfile) {
@@ -667,6 +678,7 @@ export function hydrate(
before.id,
node.id,
target?.id,
+ node.__slotIndex,
);
} finally {
profileEnd();
@@ -677,12 +689,15 @@ export function hydrate(
before.id,
node.id,
target?.id,
+ node.__slotIndex,
);
}
},
);
break;
}
+ default:
+ throw new Error('Unexpected slot type: ' + type);
}
});
};
@@ -712,6 +727,6 @@ function reconstructInstanceTree(afters: BackgroundSnapshotInstance[], parentId:
child.setAttribute(key, extraProps[key]);
}
reconstructInstanceTree(child.childNodes, id);
- __globalSnapshotPatch?.push(SnapshotOperation.InsertBefore, parentId, id, targetId);
+ __globalSnapshotPatch?.push(SnapshotOperation.InsertBefore, parentId, id, targetId, child.__slotIndex);
}
}
diff --git a/packages/react/runtime/src/snapshot/definition.ts b/packages/react/runtime/src/snapshot/definition.ts
index 3eb560a6cf..2d7dc694c1 100644
--- a/packages/react/runtime/src/snapshot/definition.ts
+++ b/packages/react/runtime/src/snapshot/definition.ts
@@ -33,6 +33,7 @@ export interface Snapshot {
slot: [DynamicPartType, number][];
isListHolder?: boolean;
+ isSlotV2?: boolean;
cssId?: number | undefined;
entryName?: string | undefined;
refAndSpreadIndexes?: number[] | null;
@@ -140,8 +141,11 @@ export function createSnapshot(
const s: Snapshot = { create, update, slot, cssId, entryName, refAndSpreadIndexes };
snapshotManager.values.set(uniqID, s);
- if (slot && slot[0] && slot[0][0] === DynamicPartType.ListChildren) {
- s.isListHolder = true;
+ if (slot && slot[0]) {
+ const v = slot[0][0];
+ if (v === DynamicPartType.ListChildren || v === DynamicPartType.ListSlotV2) {
+ s.isListHolder = true;
+ }
}
return uniqID;
}
diff --git a/packages/react/runtime/src/snapshot/dynamicPartType.ts b/packages/react/runtime/src/snapshot/dynamicPartType.ts
index dd4b296bd5..31dd068807 100644
--- a/packages/react/runtime/src/snapshot/dynamicPartType.ts
+++ b/packages/react/runtime/src/snapshot/dynamicPartType.ts
@@ -13,6 +13,8 @@ export const DynamicPartType = {
Children: 3, // Regular children updates
ListChildren: 4, // List/array children updates
MultiChildren: 5, // Multiple children updates (compat layer)
+ SlotV2: 6, // Slot for component children (Preact MultiSlots)
+ ListSlotV2: 7, // List/array children updates (Preact MultiSlots)
} as const;
export type DynamicPartType = (typeof DynamicPartType)[keyof typeof DynamicPartType];
diff --git a/packages/react/runtime/src/snapshot/snapshot.ts b/packages/react/runtime/src/snapshot/snapshot.ts
index e5b9722a64..1843ab3a2a 100644
--- a/packages/react/runtime/src/snapshot/snapshot.ts
+++ b/packages/react/runtime/src/snapshot/snapshot.ts
@@ -88,6 +88,7 @@ export class SnapshotInstance {
__worklet_ref_set?: Set | Worklet>;
__listItemPlatformInfo?: PlatformInfo;
__extraProps?: Record | undefined;
+ __slotIndex?: number | undefined;
constructor(public type: string, id?: number) {
// Suspense uses 'div'
@@ -161,7 +162,7 @@ export class SnapshotInstance {
while (child) {
child.ensureElements();
- const [type, elementIndex] = slot[index]!;
+ const [type, elementIndex] = slot[typeof child.__slotIndex === 'number' ? child.__slotIndex : index]!;
switch (type) {
case DynamicPartType.Slot: {
__ReplaceElement(child.__element_root!, elements[elementIndex]!);
@@ -181,10 +182,14 @@ export class SnapshotInstance {
}
/* v8 ignore end */
case DynamicPartType.Children:
- case DynamicPartType.ListChildren: {
+ case DynamicPartType.ListChildren:
+ case DynamicPartType.SlotV2:
+ case DynamicPartType.ListSlotV2: {
__AppendElement(elements[elementIndex]!, child.__element_root!);
break;
}
+ default:
+ throw new Error('Unexpected slot type: ' + type);
}
child = child.__nextSibling;
@@ -357,18 +362,27 @@ export class SnapshotInstance {
}
const count = __snapshot_def.slot.length;
- if (count === 1) {
- const [, elementIndex] = __snapshot_def.slot[0]!;
+ if (
+ count === 1
+ || (__snapshot_def.isSlotV2 ??= __snapshot_def.slot.every(([type]) =>
+ type === DynamicPartType.SlotV2 || type === DynamicPartType.ListSlotV2
+ ))
+ ) {
+ const [, elementIndex] = __snapshot_def.slot[typeof newNode.__slotIndex === 'number' ? newNode.__slotIndex : 0]!;
const parent = __elements[elementIndex]!;
if (shouldRemove) {
__RemoveElement(parent, newNode.__element_root!);
}
if (existingNode) {
- __InsertElementBefore(
- parent,
- newNode.__element_root!,
- existingNode.__element_root,
- );
+ if (__snapshot_def.isSlotV2 && newNode.__slotIndex! < existingNode.__slotIndex!) {
+ __AppendElement(parent, newNode.__element_root!);
+ } else {
+ __InsertElementBefore(
+ parent,
+ newNode.__element_root!,
+ existingNode.__element_root,
+ );
+ }
} else {
__AppendElement(parent, newNode.__element_root!);
}
@@ -412,7 +426,7 @@ export class SnapshotInstance {
unref(child, true);
if (this.__elements) {
- const [, elementIndex] = __snapshot_def.slot[0]!;
+ const [, elementIndex] = __snapshot_def.slot[typeof child.__slotIndex === 'number' ? child.__slotIndex : 0]!;
__RemoveElement(this.__elements[elementIndex]!, child.__element_root!);
}
@@ -475,6 +489,7 @@ export class SnapshotInstance {
values: this.__values,
extraProps: this.__extraProps,
children: this.__firstChild ? this.childNodes : undefined,
+ __slotIndex: this.__slotIndex,
};
}
diff --git a/packages/react/runtime/src/snapshot/types.ts b/packages/react/runtime/src/snapshot/types.ts
index 4cae2d1dc8..8e5bfa4a10 100644
--- a/packages/react/runtime/src/snapshot/types.ts
+++ b/packages/react/runtime/src/snapshot/types.ts
@@ -22,4 +22,5 @@ export interface SerializedSnapshotInstance {
values?: any[] | undefined;
extraProps?: Record | undefined;
children?: SerializedSnapshotInstance[] | undefined;
+ __slotIndex?: number | undefined;
}
diff --git a/packages/react/testing-library/src/__tests__/act.test.jsx b/packages/react/testing-library/src/__tests__/act.test.jsx
index 48706037d6..23cf0f7f5a 100644
--- a/packages/react/testing-library/src/__tests__/act.test.jsx
+++ b/packages/react/testing-library/src/__tests__/act.test.jsx
@@ -174,6 +174,7 @@ test('fireEvent triggers useEffect calls', async () => {
expect(snapshotInstanceManager.values).toMatchInlineSnapshot(`
Map {
-1 => {
+ "__slotIndex": undefined,
"children": undefined,
"extraProps": undefined,
"id": -1,
@@ -201,7 +202,7 @@ test('fireEvent triggers useEffect calls', async () => {
[
"rLynxChange",
{
- "data": "{"patchList":[{"snapshotPatch":[0,"__snapshot_268b9_test_4",2,4,2,[1],0,null,3,4,3,[0],1,2,3,null,1,-1,2,null],"id":2}]}",
+ "data": "{"patchList":[{"snapshotPatch":[0,"__snapshot_268b9_test_4",2,4,2,[1],0,null,3,4,3,[0],1,2,3,null,0,1,-1,2,null,0],"id":2}]}",
"patchOptions": {
"isHydration": true,
"pipelineOptions": {
@@ -221,10 +222,13 @@ test('fireEvent triggers useEffect calls', async () => {
expect(snapshotInstanceManager.values).toMatchInlineSnapshot(`
Map {
-1 => {
+ "__slotIndex": undefined,
"children": [
{
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": 3,
@@ -248,8 +252,10 @@ test('fireEvent triggers useEffect calls', async () => {
"values": undefined,
},
2 => {
+ "__slotIndex": 0,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": 3,
@@ -267,6 +273,7 @@ test('fireEvent triggers useEffect calls', async () => {
],
},
3 => {
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": 3,
@@ -285,7 +292,7 @@ test('fireEvent triggers useEffect calls', async () => {
[
"rLynxChange",
{
- "data": "{"patchList":[{"snapshotPatch":[0,"__snapshot_268b9_test_4",2,4,2,[1],0,null,3,4,3,[0],1,2,3,null,1,-1,2,null],"id":2}]}",
+ "data": "{"patchList":[{"snapshotPatch":[0,"__snapshot_268b9_test_4",2,4,2,[1],0,null,3,4,3,[0],1,2,3,null,0,1,-1,2,null,0],"id":2}]}",
"patchOptions": {
"isHydration": true,
"pipelineOptions": {
diff --git a/packages/react/testing-library/src/__tests__/alog.test.jsx b/packages/react/testing-library/src/__tests__/alog.test.jsx
index e4d1acce1a..0e3d0bebf0 100644
--- a/packages/react/testing-library/src/__tests__/alog.test.jsx
+++ b/packages/react/testing-library/src/__tests__/alog.test.jsx
@@ -100,52 +100,40 @@ describe('alog', () => {
"[ReactLynxDebug] FiberElement API call #16: __AddEvent(TEXT#2, "catchEvent", "focus", "-2:1:")",
],
[
- "[ReactLynxDebug] FiberElement API call #17: __CreateWrapperElement(0) => WRAPPER#6",
+ "[ReactLynxDebug] FiberElement API call #17: __CreateRawText("") => #text#6",
],
[
- "[ReactLynxDebug] FiberElement API call #18: __ReplaceElement(WRAPPER#6, WRAPPER#4)",
+ "[ReactLynxDebug] FiberElement API call #18: __SetAttribute(#text#6, "text", 0)",
],
[
- "[ReactLynxDebug] FiberElement API call #19: __CreateRawText("") => #text#7",
+ "[ReactLynxDebug] FiberElement API call #19: __AppendElement(WRAPPER#4, #text#6)",
],
[
- "[ReactLynxDebug] FiberElement API call #20: __SetAttribute(#text#7, "text", 0)",
+ "[ReactLynxDebug] FiberElement API call #20: __CreateView(0) => VIEW#7",
],
[
- "[ReactLynxDebug] FiberElement API call #21: __AppendElement(WRAPPER#6, #text#7)",
+ "[ReactLynxDebug] FiberElement API call #21: __CreateRawText("Class Component") => #text#8",
],
[
- "[ReactLynxDebug] FiberElement API call #22: __CreateWrapperElement(0) => WRAPPER#8",
+ "[ReactLynxDebug] FiberElement API call #22: __AppendElement(VIEW#7, #text#8)",
],
[
- "[ReactLynxDebug] FiberElement API call #23: __ReplaceElement(WRAPPER#8, WRAPPER#5)",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #24: __CreateView(0) => VIEW#9",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #25: __CreateRawText("Class Component") => #text#10",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #26: __AppendElement(VIEW#9, #text#10)",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #27: __AppendElement(WRAPPER#8, VIEW#9)",
+ "[ReactLynxDebug] FiberElement API call #23: __AppendElement(WRAPPER#5, VIEW#7)",
],
[
"[MainThread Component Render] name: ClassComponent",
],
[
- "[ReactLynxDebug] FiberElement API call #28: __CreateView(0) => VIEW#11",
+ "[ReactLynxDebug] FiberElement API call #24: __CreateView(0) => VIEW#9",
],
[
- "[ReactLynxDebug] FiberElement API call #29: __CreateRawText("Function Component") => #text#12",
+ "[ReactLynxDebug] FiberElement API call #25: __CreateRawText("Function Component") => #text#10",
],
[
- "[ReactLynxDebug] FiberElement API call #30: __AppendElement(VIEW#11, #text#12)",
+ "[ReactLynxDebug] FiberElement API call #26: __AppendElement(VIEW#9, #text#10)",
],
[
- "[ReactLynxDebug] FiberElement API call #31: __AppendElement(WRAPPER#8, VIEW#11)",
+ "[ReactLynxDebug] FiberElement API call #27: __AppendElement(WRAPPER#5, VIEW#9)",
],
[
"[MainThread Component Render] name: FunctionComponent",
@@ -154,13 +142,16 @@ describe('alog', () => {
"[MainThread Component Render] name: App",
],
[
- "[ReactLynxDebug] FiberElement API call #32: __OnLifecycleEvent(["rLynxFirstScreen", {"root":"{\\"id\\":-1,\\"type\\":\\"root\\",\\"children\\":[{\\"id\\":-2,\\"type\\":\\"__snapshot_d6fb6_test_1\\",\\"values\\":[\\"-2:0:\\",\\"-2:1:\\"],\\"children\\":[{\\"id\\":-3,\\"type\\":\\"wrapper\\",\\"children\\":[{\\"id\\":-4,\\"type\\":null,\\"values\\":[0]}]},{\\"id\\":-5,\\"type\\":\\"wrapper\\",\\"children\\":[{\\"id\\":-6,\\"type\\":\\"__snapshot_d6fb6_test_2\\"},{\\"id\\":-7,\\"type\\":\\"__snapshot_d6fb6_test_3\\"}]}]}]}","jsReadyEventIdSwap":{}}])",
+ "[ReactLynxDebug] FiberElement API call #28: __OnLifecycleEvent(["rLynxFirstScreen", {"root":"{\\"id\\":-1,\\"type\\":\\"root\\",\\"children\\":[{\\"id\\":-2,\\"type\\":\\"__snapshot_d6fb6_test_1\\",\\"values\\":[\\"-2:0:\\",\\"-2:1:\\"],\\"children\\":[{\\"id\\":-3,\\"type\\":null,\\"values\\":[0],\\"__slotIndex\\":0},{\\"id\\":-4,\\"type\\":\\"__snapshot_d6fb6_test_2\\",\\"__slotIndex\\":1},{\\"id\\":-5,\\"type\\":\\"__snapshot_d6fb6_test_3\\",\\"__slotIndex\\":1}],\\"__slotIndex\\":0}]}","jsReadyEventIdSwap":{}}])",
+ ],
+ [
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: 4",
],
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: 6",
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: 5",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: 7",
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: 4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: 2",
@@ -185,32 +176,24 @@ describe('alog', () => {
"children": [
{
"id": -3,
- "type": "wrapper",
- "children": [
- {
- "id": -4,
- "type": null,
- "values": [
- 0
- ]
- }
- ]
+ "type": null,
+ "values": [
+ 0
+ ],
+ "__slotIndex": 0
+ },
+ {
+ "id": -4,
+ "type": "__snapshot_d6fb6_test_2",
+ "__slotIndex": 1
},
{
"id": -5,
- "type": "wrapper",
- "children": [
- {
- "id": -6,
- "type": "__snapshot_d6fb6_test_2"
- },
- {
- "id": -7,
- "type": "__snapshot_d6fb6_test_3"
- }
- ]
+ "type": "__snapshot_d6fb6_test_3",
+ "__slotIndex": 1
}
- ]
+ ],
+ "__slotIndex": 0
}
]
},
@@ -221,31 +204,25 @@ describe('alog', () => {
"[ReactLynxDebug] SnapshotInstance tree for first screen hydration:
| -1(root): undefined
| -2(__snapshot_d6fb6_test_1): ["-2:0:","-2:1:"]
- | -3(wrapper): undefined
- | -4(null): [0]
- | -5(wrapper): undefined
- | -6(__snapshot_d6fb6_test_2): undefined
- | -7(__snapshot_d6fb6_test_3): undefined",
+ | -3(null): [0]
+ | -4(__snapshot_d6fb6_test_2): undefined
+ | -5(__snapshot_d6fb6_test_3): undefined",
],
[
"[ReactLynxDebug] BackgroundSnapshotInstance tree before hydration:
| 1(root): undefined
| 2(__snapshot_d6fb6_test_1): [null,null]
- | 3(wrapper): undefined
- | 4(null): [0]
- | 5(wrapper): undefined
- | 6(__snapshot_d6fb6_test_2): undefined
- | 7(__snapshot_d6fb6_test_3): undefined",
+ | 3(null): [0]
+ | 4(__snapshot_d6fb6_test_2): undefined
+ | 5(__snapshot_d6fb6_test_3): undefined",
],
[
"[ReactLynxDebug] BackgroundSnapshotInstance after hydration:
| -1(root): undefined
| -2(__snapshot_d6fb6_test_1): [null,null]
- | -3(wrapper): undefined
- | -4(null): [0]
- | -5(wrapper): undefined
- | -6(__snapshot_d6fb6_test_2): undefined
- | -7(__snapshot_d6fb6_test_3): undefined",
+ | -3(null): [0]
+ | -4(__snapshot_d6fb6_test_2): undefined
+ | -5(__snapshot_d6fb6_test_3): undefined",
],
[
"[ReactLynxDebug] BTS -> MTS updateMainThread:
@@ -272,7 +249,7 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #33: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #29: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
[
"[ReactLynxDebug] BTS received event:
@@ -293,10 +270,13 @@ describe('alog', () => {
}",
],
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -6",
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -7",
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -5",
+ ],
+ [
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: -2",
@@ -311,7 +291,7 @@ describe('alog', () => {
"snapshotPatch": [
{
"op": "SetAttribute",
- "id": -4,
+ "id": -3,
"dynamicPartIndex": 0,
"value": 1
}
@@ -332,10 +312,10 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #34: __SetAttribute(#text#7, "text", 1)",
+ "[ReactLynxDebug] FiberElement API call #30: __SetAttribute(#text#6, "text", 1)",
],
[
- "[ReactLynxDebug] FiberElement API call #35: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #31: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
]
`);
@@ -390,52 +370,40 @@ describe('alog', () => {
"[ReactLynxDebug] FiberElement API call #16: __AddEvent(TEXT#2, "catchEvent", "focus", "-2:1:")",
],
[
- "[ReactLynxDebug] FiberElement API call #17: __CreateWrapperElement(0) => WRAPPER#6",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #18: __ReplaceElement(WRAPPER#6, WRAPPER#4)",
+ "[ReactLynxDebug] FiberElement API call #17: __CreateRawText("") => #text#6",
],
[
- "[ReactLynxDebug] FiberElement API call #19: __CreateRawText("") => #text#7",
+ "[ReactLynxDebug] FiberElement API call #18: __SetAttribute(#text#6, "text", 0)",
],
[
- "[ReactLynxDebug] FiberElement API call #20: __SetAttribute(#text#7, "text", 0)",
+ "[ReactLynxDebug] FiberElement API call #19: __AppendElement(WRAPPER#4, #text#6)",
],
[
- "[ReactLynxDebug] FiberElement API call #21: __AppendElement(WRAPPER#6, #text#7)",
+ "[ReactLynxDebug] FiberElement API call #20: __CreateView(0) => VIEW#7",
],
[
- "[ReactLynxDebug] FiberElement API call #22: __CreateWrapperElement(0) => WRAPPER#8",
+ "[ReactLynxDebug] FiberElement API call #21: __CreateRawText("Class Component") => #text#8",
],
[
- "[ReactLynxDebug] FiberElement API call #23: __ReplaceElement(WRAPPER#8, WRAPPER#5)",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #24: __CreateView(0) => VIEW#9",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #25: __CreateRawText("Class Component") => #text#10",
- ],
- [
- "[ReactLynxDebug] FiberElement API call #26: __AppendElement(VIEW#9, #text#10)",
+ "[ReactLynxDebug] FiberElement API call #22: __AppendElement(VIEW#7, #text#8)",
],
[
- "[ReactLynxDebug] FiberElement API call #27: __AppendElement(WRAPPER#8, VIEW#9)",
+ "[ReactLynxDebug] FiberElement API call #23: __AppendElement(WRAPPER#5, VIEW#7)",
],
[
"[MainThread Component Render] name: ClassComponent",
],
[
- "[ReactLynxDebug] FiberElement API call #28: __CreateView(0) => VIEW#11",
+ "[ReactLynxDebug] FiberElement API call #24: __CreateView(0) => VIEW#9",
],
[
- "[ReactLynxDebug] FiberElement API call #29: __CreateRawText("Function Component") => #text#12",
+ "[ReactLynxDebug] FiberElement API call #25: __CreateRawText("Function Component") => #text#10",
],
[
- "[ReactLynxDebug] FiberElement API call #30: __AppendElement(VIEW#11, #text#12)",
+ "[ReactLynxDebug] FiberElement API call #26: __AppendElement(VIEW#9, #text#10)",
],
[
- "[ReactLynxDebug] FiberElement API call #31: __AppendElement(WRAPPER#8, VIEW#11)",
+ "[ReactLynxDebug] FiberElement API call #27: __AppendElement(WRAPPER#5, VIEW#9)",
],
[
"[MainThread Component Render] name: FunctionComponent",
@@ -444,13 +412,16 @@ describe('alog', () => {
"[MainThread Component Render] name: App",
],
[
- "[ReactLynxDebug] FiberElement API call #32: __OnLifecycleEvent(["rLynxFirstScreen", {"root":"{\\"id\\":-1,\\"type\\":\\"root\\",\\"children\\":[{\\"id\\":-2,\\"type\\":\\"__snapshot_d6fb6_test_1\\",\\"values\\":[\\"-2:0:\\",\\"-2:1:\\"],\\"children\\":[{\\"id\\":-3,\\"type\\":\\"wrapper\\",\\"children\\":[{\\"id\\":-4,\\"type\\":null,\\"values\\":[0]}]},{\\"id\\":-5,\\"type\\":\\"wrapper\\",\\"children\\":[{\\"id\\":-6,\\"type\\":\\"__snapshot_d6fb6_test_2\\"},{\\"id\\":-7,\\"type\\":\\"__snapshot_d6fb6_test_3\\"}]}]}]}","jsReadyEventIdSwap":{}}])",
+ "[ReactLynxDebug] FiberElement API call #28: __OnLifecycleEvent(["rLynxFirstScreen", {"root":"{\\"id\\":-1,\\"type\\":\\"root\\",\\"children\\":[{\\"id\\":-2,\\"type\\":\\"__snapshot_d6fb6_test_1\\",\\"values\\":[\\"-2:0:\\",\\"-2:1:\\"],\\"children\\":[{\\"id\\":-3,\\"type\\":null,\\"values\\":[0],\\"__slotIndex\\":0},{\\"id\\":-4,\\"type\\":\\"__snapshot_d6fb6_test_2\\",\\"__slotIndex\\":1},{\\"id\\":-5,\\"type\\":\\"__snapshot_d6fb6_test_3\\",\\"__slotIndex\\":1}],\\"__slotIndex\\":0}]}","jsReadyEventIdSwap":{}}])",
],
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: 6",
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: 4",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: 7",
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: 5",
+ ],
+ [
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: 4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: 2",
@@ -475,32 +446,24 @@ describe('alog', () => {
"children": [
{
"id": -3,
- "type": "wrapper",
- "children": [
- {
- "id": -4,
- "type": null,
- "values": [
- 0
- ]
- }
- ]
+ "type": null,
+ "values": [
+ 0
+ ],
+ "__slotIndex": 0
+ },
+ {
+ "id": -4,
+ "type": "__snapshot_d6fb6_test_2",
+ "__slotIndex": 1
},
{
"id": -5,
- "type": "wrapper",
- "children": [
- {
- "id": -6,
- "type": "__snapshot_d6fb6_test_2"
- },
- {
- "id": -7,
- "type": "__snapshot_d6fb6_test_3"
- }
- ]
+ "type": "__snapshot_d6fb6_test_3",
+ "__slotIndex": 1
}
- ]
+ ],
+ "__slotIndex": 0
}
]
},
@@ -511,31 +474,25 @@ describe('alog', () => {
"[ReactLynxDebug] SnapshotInstance tree for first screen hydration:
| -1(root): undefined
| -2(__snapshot_d6fb6_test_1): ["-2:0:","-2:1:"]
- | -3(wrapper): undefined
- | -4(null): [0]
- | -5(wrapper): undefined
- | -6(__snapshot_d6fb6_test_2): undefined
- | -7(__snapshot_d6fb6_test_3): undefined",
+ | -3(null): [0]
+ | -4(__snapshot_d6fb6_test_2): undefined
+ | -5(__snapshot_d6fb6_test_3): undefined",
],
[
"[ReactLynxDebug] BackgroundSnapshotInstance tree before hydration:
| 1(root): undefined
| 2(__snapshot_d6fb6_test_1): [null,null]
- | 3(wrapper): undefined
- | 4(null): [0]
- | 5(wrapper): undefined
- | 6(__snapshot_d6fb6_test_2): undefined
- | 7(__snapshot_d6fb6_test_3): undefined",
+ | 3(null): [0]
+ | 4(__snapshot_d6fb6_test_2): undefined
+ | 5(__snapshot_d6fb6_test_3): undefined",
],
[
"[ReactLynxDebug] BackgroundSnapshotInstance after hydration:
| -1(root): undefined
| -2(__snapshot_d6fb6_test_1): [null,null]
- | -3(wrapper): undefined
- | -4(null): [0]
- | -5(wrapper): undefined
- | -6(__snapshot_d6fb6_test_2): undefined
- | -7(__snapshot_d6fb6_test_3): undefined",
+ | -3(null): [0]
+ | -4(__snapshot_d6fb6_test_2): undefined
+ | -5(__snapshot_d6fb6_test_3): undefined",
],
[
"[ReactLynxDebug] BTS -> MTS updateMainThread:
@@ -562,7 +519,7 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #33: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #29: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
[
"[ReactLynxDebug] BTS received event:
@@ -583,10 +540,13 @@ describe('alog', () => {
}",
],
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -6",
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -4",
+ ],
+ [
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -5",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -7",
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: -2",
@@ -601,7 +561,7 @@ describe('alog', () => {
"snapshotPatch": [
{
"op": "SetAttribute",
- "id": -4,
+ "id": -3,
"dynamicPartIndex": 0,
"value": 1
}
@@ -622,10 +582,10 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #34: __SetAttribute(#text#7, "text", 1)",
+ "[ReactLynxDebug] FiberElement API call #30: __SetAttribute(#text#6, "text", 1)",
],
[
- "[ReactLynxDebug] FiberElement API call #35: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #31: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
]
`);
@@ -640,10 +600,13 @@ describe('alog', () => {
expect(lynxTestingEnv.mainThread.console.alog.mock.calls).toMatchInlineSnapshot(`
[
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -6",
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -4",
+ ],
+ [
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -5",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -7",
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: -2",
@@ -658,7 +621,7 @@ describe('alog', () => {
"snapshotPatch": [
{
"op": "SetAttribute",
- "id": -4,
+ "id": -3,
"dynamicPartIndex": 0,
"value": 0
}
@@ -679,20 +642,23 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #36: __SetAttribute(#text#7, "text", 0)",
+ "[ReactLynxDebug] FiberElement API call #32: __SetAttribute(#text#6, "text", 0)",
],
[
- "[ReactLynxDebug] FiberElement API call #37: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #33: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
]
`);
expect(lynxTestingEnv.backgroundThread.console.alog.mock.calls).toMatchInlineSnapshot(`
[
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -6",
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -7",
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -5",
+ ],
+ [
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: -2",
@@ -707,7 +673,7 @@ describe('alog', () => {
"snapshotPatch": [
{
"op": "SetAttribute",
- "id": -4,
+ "id": -3,
"dynamicPartIndex": 0,
"value": 0
}
@@ -728,10 +694,10 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #36: __SetAttribute(#text#7, "text", 0)",
+ "[ReactLynxDebug] FiberElement API call #32: __SetAttribute(#text#6, "text", 0)",
],
[
- "[ReactLynxDebug] FiberElement API call #37: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #33: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
]
`);
@@ -746,10 +712,13 @@ describe('alog', () => {
expect(lynxTestingEnv.mainThread.console.alog.mock.calls).toMatchInlineSnapshot(`
[
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -6",
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -4",
+ ],
+ [
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -5",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -7",
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: -2",
@@ -764,7 +733,7 @@ describe('alog', () => {
"snapshotPatch": [
{
"op": "SetAttribute",
- "id": -4,
+ "id": -3,
"dynamicPartIndex": 0,
"value": 1
}
@@ -785,20 +754,23 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #38: __SetAttribute(#text#7, "text", 1)",
+ "[ReactLynxDebug] FiberElement API call #34: __SetAttribute(#text#6, "text", 1)",
],
[
- "[ReactLynxDebug] FiberElement API call #39: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #35: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
]
`);
expect(lynxTestingEnv.backgroundThread.console.alog.mock.calls).toMatchInlineSnapshot(`
[
[
- "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -6",
+ "[BackgroundThread Component Render] name: ClassComponent, uniqID: __snapshot_d6fb6_test_2, __id: -4",
+ ],
+ [
+ "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -5",
],
[
- "[BackgroundThread Component Render] name: FunctionComponent, uniqID: __snapshot_d6fb6_test_3, __id: -7",
+ "[BackgroundThread Component Render] name: Fragment, uniqID: __snapshot_d6fb6_test_2, __id: -4",
],
[
"[BackgroundThread Component Render] name: App, uniqID: __snapshot_d6fb6_test_1, __id: -2",
@@ -813,7 +785,7 @@ describe('alog', () => {
"snapshotPatch": [
{
"op": "SetAttribute",
- "id": -4,
+ "id": -3,
"dynamicPartIndex": 0,
"value": 1
}
@@ -834,10 +806,10 @@ describe('alog', () => {
}",
],
[
- "[ReactLynxDebug] FiberElement API call #38: __SetAttribute(#text#7, "text", 1)",
+ "[ReactLynxDebug] FiberElement API call #34: __SetAttribute(#text#6, "text", 1)",
],
[
- "[ReactLynxDebug] FiberElement API call #39: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
+ "[ReactLynxDebug] FiberElement API call #35: __FlushElementTree(PAGE#0, {"pipelineOptions":{"pipelineID":"pipelineID","needTimestamps":true,"pipelineOrigin":"reactLynxHydrate","dsl":"reactLynx","stage":"hydrate"}})",
],
]
`);
diff --git a/packages/react/testing-library/src/__tests__/end-to-end.test.jsx b/packages/react/testing-library/src/__tests__/end-to-end.test.jsx
index dd263864a1..194690c048 100644
--- a/packages/react/testing-library/src/__tests__/end-to-end.test.jsx
+++ b/packages/react/testing-library/src/__tests__/end-to-end.test.jsx
@@ -42,6 +42,7 @@ test('state change will cause re-render', async () => {
expect(snapshotInstanceManager.values).toMatchInlineSnapshot(`
Map {
-1 => {
+ "__slotIndex": undefined,
"children": undefined,
"extraProps": undefined,
"id": -1,
@@ -62,8 +63,10 @@ test('state change will cause re-render', async () => {
expect(snapshotInstanceManager.values).toMatchInlineSnapshot(`
Map {
-1 => {
+ "__slotIndex": undefined,
"children": [
{
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": 2,
@@ -77,6 +80,7 @@ test('state change will cause re-render', async () => {
"values": undefined,
},
2 => {
+ "__slotIndex": 0,
"children": undefined,
"extraProps": undefined,
"id": 2,
@@ -100,7 +104,7 @@ test('state change will cause re-render', async () => {
[
"rLynxChange",
{
- "data": "{"patchList":[{"snapshotPatch":[0,"__snapshot_f46c5_test_1",2,1,-1,2,null],"id":2}]}",
+ "data": "{"patchList":[{"snapshotPatch":[0,"__snapshot_f46c5_test_1",2,1,-1,2,null,0],"id":2}]}",
"patchOptions": {
"isHydration": true,
"pipelineOptions": {
@@ -118,7 +122,7 @@ test('state change will cause re-render', async () => {
[
"rLynxChange",
{
- "data": "{"patchList":[{"id":3,"snapshotPatch":[2,-1,2,0,"__snapshot_f46c5_test_2",3,0,null,4,3,4,0,"Hello World",1,3,4,null,1,-1,3,null]}]}",
+ "data": "{"patchList":[{"id":3,"snapshotPatch":[2,-1,2,0,"__snapshot_f46c5_test_2",3,0,null,4,3,4,0,"Hello World",1,3,4,null,0,1,-1,3,null,0]}]}",
"patchOptions": {
"pipelineOptions": {
"dsl": "reactLynx",
@@ -159,6 +163,7 @@ test('it waits for the data to be loaded', async () => {
expect(snapshotInstanceManager.values).toMatchInlineSnapshot(`
Map {
-1 => {
+ "__slotIndex": undefined,
"children": undefined,
"extraProps": undefined,
"id": -1,
diff --git a/packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx b/packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx
index 3e7e8159a4..26f0323215 100644
--- a/packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx
+++ b/packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx
@@ -80,6 +80,80 @@ describe('lazy bundle', () => {
`);
}
});
+
+ it('should render multi-slots lazy component', async () => {
+ const InternalComponent = lazy(() => import('./LazyComponent'));
+
+ const App = () => {
+ return (
+
+ loading 1...}>
+
+
+ ---
+ loading 2...}>
+
+
+
+ );
+ };
+
+ const { container } = render(
+ ,
+ );
+
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+
+
+ loading 1...
+
+
+
+
+ ---
+
+
+
+
+ loading 2...
+
+
+
+
+
+ `);
+
+ await waitForElementToBeRemoved(() => screen.getByText('loading 1...'), {
+ timeout: 50_000,
+ });
+
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+
+
+ Hello from LazyComponent
+
+
+
+
+ ---
+
+
+
+
+ Hello from LazyComponent
+
+
+
+
+
+ `);
+ });
});
describe('Suspense', () => {
@@ -139,34 +213,34 @@ describe('Suspense', () => {
if (name === 'PreactSuspense') {
expect(container).toMatchInlineSnapshot(`
-
-
-
+
- loading...
-
-
-
- `);
- } else {
- expect(container).toMatchInlineSnapshot(`
-
-
-
loading...
-
-
-
- `);
+
+
+ `);
+ } else {
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+
+ loading...
+
+
+
+
+ `);
}
{
@@ -178,24 +252,26 @@ describe('Suspense', () => {
{
"id": 2,
"op": "CreateElement",
- "type": "__snapshot_50869_test_3",
+ "type": "__snapshot_50869_test_6",
},
{
- "id": 7,
+ "id": 5,
"op": "CreateElement",
- "type": "__snapshot_50869_test_4",
+ "type": "__snapshot_50869_test_7",
},
{
"beforeId": null,
- "childId": 7,
+ "childId": 5,
"op": "InsertBefore",
"parentId": 2,
+ "slotIndex": 0,
},
{
"beforeId": null,
"childId": 2,
"op": "InsertBefore",
"parentId": -1,
+ "slotIndex": 0,
},
]
`);
@@ -205,35 +281,38 @@ describe('Suspense', () => {
{
"id": 2,
"op": "CreateElement",
- "type": "__snapshot_50869_test_3",
+ "type": "__snapshot_50869_test_6",
},
{
- "id": 8,
+ "id": 6,
"op": "CreateElement",
"type": "wrapper",
},
{
- "id": 9,
+ "id": 7,
"op": "CreateElement",
- "type": "__snapshot_50869_test_4",
+ "type": "__snapshot_50869_test_7",
},
{
"beforeId": null,
- "childId": 9,
+ "childId": 7,
"op": "InsertBefore",
- "parentId": 8,
+ "parentId": 6,
+ "slotIndex": 0,
},
{
"beforeId": null,
- "childId": 8,
+ "childId": 6,
"op": "InsertBefore",
"parentId": 2,
+ "slotIndex": 0,
},
{
"beforeId": null,
"childId": 2,
"op": "InsertBefore",
"parentId": -1,
+ "slotIndex": 0,
},
]
`);
@@ -331,10 +410,10 @@ describe('Suspense', () => {
el4
];
}",
- "type": "__snapshot_50869_test_5",
+ "type": "__snapshot_50869_test_8",
},
{
- "__id": 7,
+ "__id": 5,
"create": "function() {
const pageId = __vite_ssr_import_1__.__pageId;
const el = __CreateText(pageId);
@@ -346,7 +425,7 @@ describe('Suspense', () => {
el1
];
}",
- "type": "__snapshot_50869_test_4",
+ "type": "__snapshot_50869_test_7",
},
]
`);
@@ -354,19 +433,19 @@ describe('Suspense', () => {
} else {
if (!process.env.RSTEST) {
expect(tearDownInstances).toMatchInlineSnapshot(`
- [
- {
- "__id": 8,
- "create": "create () {
- /* v8 ignore start */ if (__JS__ && !__DEV__) return [];
- /* v8 ignore stop */ return [
- __CreateWrapperElement(__pageId)
- ];
- }",
- "type": "wrapper",
- },
- ]
- `);
+ [
+ {
+ "__id": 6,
+ "create": "create () {
+ /* v8 ignore start */ if (__JS__ && !__DEV__) return [];
+ /* v8 ignore stop */ return [
+ __CreateWrapperElement(__pageId)
+ ];
+ }",
+ "type": "wrapper",
+ },
+ ]
+ `);
}
}
diff --git a/packages/react/testing-library/src/__tests__/list.test.jsx b/packages/react/testing-library/src/__tests__/list.test.jsx
index f8b3bfe6cf..27855a6d81 100644
--- a/packages/react/testing-library/src/__tests__/list.test.jsx
+++ b/packages/react/testing-library/src/__tests__/list.test.jsx
@@ -47,11 +47,9 @@ describe('list', () => {
-
-
- 0
-
-
+
+ 0
+
@@ -66,26 +64,22 @@ describe('list', () => {
-
-
- 0
-
-
+
+ 0
+
-
-
- 1
-
-
+
+ 1
+
`);
expect(uid0).toMatchInlineSnapshot(`2`);
- expect(uid1).toMatchInlineSnapshot(`6`);
+ expect(uid1).toMatchInlineSnapshot(`5`);
elementTree.leaveListItem(list, uid0);
expect(__pendingListUpdates.values).toMatchInlineSnapshot(`{}`);
expect(container).toMatchInlineSnapshot(`
@@ -96,20 +90,16 @@ describe('list', () => {
-
-
- 0
-
-
+
+ 0
+
-
-
- 1
-
-
+
+ 1
+
@@ -126,20 +116,16 @@ describe('list', () => {
-
-
- 2
-
-
+
+ 2
+
-
-
- 1
-
-
+
+ 1
+
@@ -203,7 +189,7 @@ describe('list', () => {
>
@@ -221,21 +207,19 @@ describe('list', () => {
full-span="true"
item-key="3"
>
-
-
-
- 3
-
-
- 3
-
-
-
-
- hello
-
-
-
+
+
+ 3
+
+
+ 3
+
+
+
+
+ hello
+
+
`);
@@ -278,21 +262,19 @@ describe('list', () => {
full-span="true"
item-key="1"
>
-
-
-
- 1
-
-
- 1
-
-
-
-
- hello
-
-
-
+
+
+ 1
+
+
+ 1
+
+
+
+
+ hello
+
+
`);
@@ -303,21 +285,19 @@ describe('list', () => {
full-span="true"
item-key="1"
>
-
-
-
- 1
-
-
- 1
-
-
-
-
- hello
-
-
-
+
+
+ 1
+
+
+ 1
+
+
+
+
+ hello
+
+
,
"item-key",
"1",
@@ -327,21 +307,19 @@ describe('list', () => {
full-span="true"
item-key="1"
>
-
-
-
- 1
-
-
- 1
-
-
-
-
- hello
-
-
-
+
+
+ 1
+
+
+ 1
+
+
+
+
+ hello
+
+
,
"full-span",
true,
@@ -365,21 +343,19 @@ describe('list', () => {
full-span="true"
item-key="1"
>
-
-
-
- 1
-
-
- 1
-
-
-
-
- hello
-
-
-
+
+
+ 1
+
+
+ 1
+
+
+
+
+ hello
+
+
`);
expect(flushInfo).toMatchObject({
@@ -392,87 +368,79 @@ describe('list', () => {
expect(list).toMatchInlineSnapshot(`
-
-
-
- 4
-
-
- 4
-
-
-
-
- hello
-
-
-
+
+
+ 4
+
+
+ 4
+
+
+
+
+ hello
+
+
-
-
-
- 5
-
-
- 5
-
-
-
-
- hello
-
-
-
+
+
+ 5
+
+
+ 5
+
+
+
+
+ hello
+
+
-
-
-
- 2
-
-
- 2
-
-
-
-
- hello
-
-
-
+
+
+ 2
+
+
+ 2
+
+
+
+
+ hello
+
+
-
-
-
- 1
-
-
- 1
-
-
-
-
- hello
-
-
-
+
+
+ 1
+
+
+ 1
+
+
+
+
+ hello
+
+
`);
@@ -480,87 +448,79 @@ describe('list', () => {
expect(list).toMatchInlineSnapshot(`
-
-
-
- 4
-
-
- 4
-
-
-
-
- hello
-
-
-
+
+
+ 4
+
+
+ 4
+
+
+
+
+ hello
+
+
-
-
-
- 5
-
-
- 5
-
-
-
-
- hello
-
-
-
+
+
+ 5
+
+
+ 5
+
+
+
+
+ hello
+
+
-
-
-
- 2
-
-
- 2
-
-
-
-
- hello
-
-
-
+
+
+ 2
+
+
+ 2
+
+
+
+
+ hello
+
+
-
-
-
- 1
-
-
- 1
-
-
-
-
- hello
-
-
-
+
+
+ 1
+
+
+ 1
+
+
+
+
+ hello
+
+
`);
@@ -646,7 +606,7 @@ describe('list - deferred should render as normal', () => {
`);
@@ -670,7 +630,7 @@ describe('list - deferred should render as normal', () => {
`);
@@ -682,7 +642,7 @@ describe('list - deferred should render as normal', () => {
should render as normal', () => {
`);
@@ -851,7 +811,7 @@ describe('list - deferred should render as normal', () => {
`);
@@ -871,7 +831,7 @@ describe('list - deferred should render as normal', () => {
`);
@@ -890,7 +850,7 @@ describe('list - deferred should render as normal', () => {
should render as normal', () => {
"rLynxFirstScreen",
{
"jsReadyEventIdSwap": {},
- "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_d0c07_test_30","children":[{"id":-3,"type":"__snapshot_d0c07_test_31","values":[{"item-key":0}],"children":[{"id":-4,"type":"__snapshot_d0c07_test_29","values":[{"style":{"backgroundColor":"red","margin":"12px"}}],"children":[{"id":-5,"type":"__snapshot_d0c07_test_32","children":[{"id":-6,"type":null,"values":[0]}]}]}]},{"id":-7,"type":"__snapshot_d0c07_test_31","values":[{"item-key":1}],"children":[{"id":-8,"type":"__snapshot_d0c07_test_29","values":[{"style":{"backgroundColor":"red","margin":"12px"}}],"children":[{"id":-9,"type":"__snapshot_d0c07_test_32","children":[{"id":-10,"type":null,"values":[1]}]}]}]},{"id":-11,"type":"__snapshot_d0c07_test_31","values":[{"item-key":2}],"children":[{"id":-12,"type":"__snapshot_d0c07_test_29","values":[{"style":{"backgroundColor":"red","margin":"12px"}}],"children":[{"id":-13,"type":"__snapshot_d0c07_test_32","children":[{"id":-14,"type":null,"values":[2]}]}]}]}]}]}",
+ "root": "{"id":-1,"type":"root","children":[{"id":-2,"type":"__snapshot_d0c07_test_26","children":[{"id":-3,"type":"__snapshot_d0c07_test_27","values":[{"item-key":0}],"children":[{"id":-4,"type":"__snapshot_d0c07_test_25","values":[{"style":{"backgroundColor":"red","margin":"12px"}}],"children":[{"id":-5,"type":"__snapshot_d0c07_test_28","children":[{"id":-6,"type":null,"values":[0],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0},{"id":-7,"type":"__snapshot_d0c07_test_27","values":[{"item-key":1}],"children":[{"id":-8,"type":"__snapshot_d0c07_test_25","values":[{"style":{"backgroundColor":"red","margin":"12px"}}],"children":[{"id":-9,"type":"__snapshot_d0c07_test_28","children":[{"id":-10,"type":null,"values":[1],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0},{"id":-11,"type":"__snapshot_d0c07_test_27","values":[{"item-key":2}],"children":[{"id":-12,"type":"__snapshot_d0c07_test_25","values":[{"style":{"backgroundColor":"red","margin":"12px"}}],"children":[{"id":-13,"type":"__snapshot_d0c07_test_28","children":[{"id":-14,"type":null,"values":[2],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0}],"__slotIndex":0}]}",
},
],
],
diff --git a/packages/react/testing-library/src/__tests__/lynx.test.jsx b/packages/react/testing-library/src/__tests__/lynx.test.jsx
index 392a35bb88..1495362095 100644
--- a/packages/react/testing-library/src/__tests__/lynx.test.jsx
+++ b/packages/react/testing-library/src/__tests__/lynx.test.jsx
@@ -41,6 +41,7 @@ describe('lynx global API', () => {
1e10,
1e10,
null,
+ 0,
);
args[1].data = JSON.stringify(data);
}
@@ -69,12 +70,14 @@ describe('lynx global API', () => {
"childId": 2,
"op": "InsertBefore",
"parentId": -1,
+ "slotIndex": 0,
},
{
"beforeId": null,
"childId": 10000000000,
"op": "InsertBefore",
"parentId": 10000000000,
+ "slotIndex": 0,
},
]
`);
diff --git a/packages/react/testing-library/src/__tests__/render.test.jsx b/packages/react/testing-library/src/__tests__/render.test.jsx
index 94acdb4552..8c0fd92c11 100644
--- a/packages/react/testing-library/src/__tests__/render.test.jsx
+++ b/packages/react/testing-library/src/__tests__/render.test.jsx
@@ -69,10 +69,10 @@ describe('dynamic key in snapshot', () => {
expect(container).toMatchInlineSnapshot(`
-
-
+
+
foo
@@ -83,8 +83,8 @@ describe('dynamic key in snapshot', () => {
bar
-
-
+
+
`);
@@ -114,10 +114,10 @@ describe('dynamic key in snapshot', () => {
Hello
-
-
+
+
foo
@@ -128,8 +128,8 @@ describe('dynamic key in snapshot', () => {
bar
-
-
+
+
`);
@@ -155,10 +155,10 @@ describe('dynamic key in snapshot', () => {
expect(container).toMatchInlineSnapshot(`
-
-
+
+
foo
@@ -169,8 +169,8 @@ describe('dynamic key in snapshot', () => {
bar
-
-
+
+
Hello
@@ -201,20 +201,18 @@ describe('dynamic key in snapshot', () => {
-
+
-
-
- foo
-
-
-
-
- bar
-
-
+
+ foo
+
-
+
+
+ bar
+
+
+
`);
@@ -239,22 +237,24 @@ describe('dynamic key in snapshot', () => {
expect(container).toMatchInlineSnapshot(`
-
-
+
+
foo
-
-
- bar
-
-
-
-
+
+
+
+ bar
+
+
+
+
+
`);
diff --git a/packages/react/testing-library/src/__tests__/renderComponent.test.jsx b/packages/react/testing-library/src/__tests__/renderComponent.test.jsx
new file mode 100644
index 0000000000..bbd16c3ecc
--- /dev/null
+++ b/packages/react/testing-library/src/__tests__/renderComponent.test.jsx
@@ -0,0 +1,347 @@
+import { expect } from 'vitest';
+import { Component, useState } from '@lynx-js/react';
+
+import { render, act } from '..';
+import { prettyFormatSnapshotPatch } from '../../../runtime/lib/debug/formatPatch';
+
+test('setState generates insertBefore operation', async () => {
+ vi.spyOn(lynxTestingEnv.backgroundThread.lynxCoreInject.tt, 'OnLifecycleEvent');
+ const onLifecycleEventCalls = lynxTestingEnv.backgroundThread.lynxCoreInject.tt.OnLifecycleEvent.mock.calls;
+ vi.spyOn(lynx.getNativeApp(), 'callLepusMethod');
+ const callLepusMethodCalls = lynx.getNativeApp().callLepusMethod.mock.calls;
+
+ let setList;
+ const App = () => {
+ const [list, _setList] = useState([1, 2, 3, 4]);
+ setList = _setList;
+ return (
+
+
+ {list.map(key => (
+
+ {key}
+
+ ))}
+
+ );
+ };
+
+ render(, {
+ enableMainThread: true,
+ enableBackgroundThread: true,
+ });
+
+ expect(callLepusMethodCalls[0]).toMatchInlineSnapshot(`
+ [
+ "rLynxChange",
+ {
+ "data": "{"patchList":[{"snapshotPatch":[],"id":2}]}",
+ "patchOptions": {
+ "isHydration": true,
+ "pipelineOptions": {
+ "dsl": "reactLynx",
+ "needTimestamps": true,
+ "pipelineID": "pipelineID",
+ "pipelineOrigin": "reactLynxHydrate",
+ "stage": "hydrate",
+ },
+ "reloadVersion": 0,
+ },
+ },
+ [Function],
+ ]
+ `);
+ {
+ const snapshotPatch = JSON.parse(callLepusMethodCalls[0][1]['data']).patchList[0].snapshotPatch;
+ const formattedSnapshotPatch = prettyFormatSnapshotPatch(snapshotPatch);
+ expect(formattedSnapshotPatch).toMatchInlineSnapshot(`[]`);
+ }
+
+ expect(elementTree).toMatchInlineSnapshot(`
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
+
+
+
+ `);
+
+ act(() => {
+ setList([1, 3, 2, 4]);
+ });
+
+ expect(callLepusMethodCalls[1]).toMatchInlineSnapshot(`
+ [
+ "rLynxChange",
+ {
+ "data": "{"patchList":[{"id":3,"snapshotPatch":[1,-2,-5,-9,0]}]}",
+ "patchOptions": {
+ "pipelineOptions": {
+ "dsl": "reactLynx",
+ "needTimestamps": true,
+ "pipelineID": "pipelineID",
+ "pipelineOrigin": "reactLynxHydrate",
+ "stage": "hydrate",
+ },
+ "reloadVersion": 0,
+ },
+ },
+ [Function],
+ ]
+ `);
+ const snapshotPatch = JSON.parse(callLepusMethodCalls[1][1]['data']).patchList[0].snapshotPatch;
+ const formattedSnapshotPatch = prettyFormatSnapshotPatch(snapshotPatch);
+ expect(formattedSnapshotPatch).toMatchInlineSnapshot(`
+ [
+ {
+ "beforeId": -9,
+ "childId": -5,
+ "op": "InsertBefore",
+ "parentId": -2,
+ "slotIndex": 0,
+ },
+ ]
+ `);
+
+ expect(elementTree).toMatchInlineSnapshot(`
+
+
+
+
+
+
+ 1
+
+
+
+
+ 3
+
+
+
+
+ 2
+
+
+
+
+ 4
+
+
+
+
+
+ `);
+});
+
+test('setState triggered renderComponent should have correct slotIndex', async () => {
+ vi.spyOn(lynxTestingEnv.backgroundThread.lynxCoreInject.tt, 'OnLifecycleEvent');
+ const onLifecycleEventCalls = lynxTestingEnv.backgroundThread.lynxCoreInject.tt.OnLifecycleEvent.mock.calls;
+ vi.spyOn(lynx.getNativeApp(), 'callLepusMethod');
+ const callLepusMethodCalls = lynx.getNativeApp().callLepusMethod.mock.calls;
+
+ const Parent = ({ children }) => {
+ const text = 'parent';
+ return (
+
+ {text}
+ Split
+ {children}
+
+ );
+ };
+ let setCount;
+ const Child = () => {
+ const [count, _setCount] = useState(0);
+ setCount = _setCount;
+ return (
+ count === 0
+ ? (
+
+ {count}
+
+ )
+ : (
+
+ {count}
+
+ )
+ );
+ };
+ const App = () => {
+ return (
+
+
+
+ );
+ };
+
+ render(, {
+ enableMainThread: true,
+ enableBackgroundThread: true,
+ });
+
+ expect(JSON.stringify(JSON.parse(onLifecycleEventCalls[0][0][1]['root']), null, 2)).toMatchInlineSnapshot(`
+ "{
+ "id": -1,
+ "type": "root",
+ "children": [
+ {
+ "id": -2,
+ "type": "__snapshot_289e0_test_3",
+ "children": [
+ {
+ "id": -3,
+ "type": null,
+ "values": [
+ "parent"
+ ],
+ "__slotIndex": 0
+ },
+ {
+ "id": -4,
+ "type": "__snapshot_289e0_test_4",
+ "children": [
+ {
+ "id": -5,
+ "type": null,
+ "values": [
+ 0
+ ],
+ "__slotIndex": 0
+ }
+ ],
+ "__slotIndex": 1
+ }
+ ],
+ "__slotIndex": 0
+ }
+ ]
+ }"
+ `);
+
+ expect(elementTree).toMatchInlineSnapshot(`
+
+
+
+ parent
+
+
+ Split
+
+
+
+
+ 0
+
+
+
+
+
+ `);
+
+ act(() => {
+ setCount(1);
+ });
+
+ expect(callLepusMethodCalls[1]).toMatchInlineSnapshot(`
+ [
+ "rLynxChange",
+ {
+ "data": "{"patchList":[{"id":3,"snapshotPatch":[2,-2,-4,0,"__snapshot_289e0_test_5",6,0,null,7,3,7,0,1,1,6,7,null,0,1,-2,6,null,1]}]}",
+ "patchOptions": {
+ "pipelineOptions": {
+ "dsl": "reactLynx",
+ "needTimestamps": true,
+ "pipelineID": "pipelineID",
+ "pipelineOrigin": "reactLynxHydrate",
+ "stage": "hydrate",
+ },
+ "reloadVersion": 0,
+ },
+ },
+ [Function],
+ ]
+ `);
+ const snapshotPatch = JSON.parse(callLepusMethodCalls[1][1]['data']).patchList[0].snapshotPatch;
+ const formattedSnapshotPatch = prettyFormatSnapshotPatch(snapshotPatch);
+ expect(formattedSnapshotPatch).toMatchInlineSnapshot(`
+ [
+ {
+ "childId": -4,
+ "op": "RemoveChild",
+ "parentId": -2,
+ },
+ {
+ "id": 6,
+ "op": "CreateElement",
+ "type": "__snapshot_289e0_test_5",
+ },
+ {
+ "id": 7,
+ "op": "CreateElement",
+ "type": null,
+ },
+ {
+ "dynamicPartIndex": 0,
+ "id": 7,
+ "op": "SetAttribute",
+ "value": 1,
+ },
+ {
+ "beforeId": null,
+ "childId": 7,
+ "op": "InsertBefore",
+ "parentId": 6,
+ "slotIndex": 0,
+ },
+ {
+ "beforeId": null,
+ "childId": 6,
+ "op": "InsertBefore",
+ "parentId": -2,
+ "slotIndex": 1,
+ },
+ ]
+ `);
+ expect(elementTree).toMatchInlineSnapshot(`
+
+
+
+ parent
+
+
+ Split
+
+
+
+
+ 1
+
+
+
+
+
+ `);
+});
diff --git a/packages/react/testing-library/src/__tests__/setState-jsx.test.jsx b/packages/react/testing-library/src/__tests__/setState-jsx.test.jsx
new file mode 100644
index 0000000000..d41ef78b82
--- /dev/null
+++ b/packages/react/testing-library/src/__tests__/setState-jsx.test.jsx
@@ -0,0 +1,276 @@
+import { expect } from 'vitest';
+import { Component, useState } from '@lynx-js/react';
+
+import { fireEvent, render, act } from '..';
+import { prettyFormatSnapshotPatch } from '../../../runtime/lib/debug/formatPatch';
+
+test('setState changes jsx', async () => {
+ vi.spyOn(lynxTestingEnv.backgroundThread.lynxCoreInject.tt, 'OnLifecycleEvent');
+ const onLifecycleEventCalls = lynxTestingEnv.backgroundThread.lynxCoreInject.tt.OnLifecycleEvent.mock.calls;
+ vi.spyOn(lynx.getNativeApp(), 'callLepusMethod');
+ const callLepusMethodCalls = lynx.getNativeApp().callLepusMethod.mock.calls;
+
+ const jsx0 = Hello 0;
+ const jsx1 = Hello 1;
+ const jsx2 = Hello 2;
+
+ const Comp = () => {
+ const [text0, setText0] = useState(jsx0);
+ const [text1, setText1] = useState(jsx1);
+ const handleTap = () => {
+ setText0(jsx1);
+ setText1(jsx0);
+ };
+ return (
+
+ {text0}
+ ---
+ {[0, 1, 2].map((i) => text1)}
+ ---
+ {jsx2}
+
+ );
+ };
+
+ const { container, findByTestId } = render();
+
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+
+ Hello 0
+
+
+
+ ---
+
+
+
+ Hello 1
+
+
+ Hello 1
+
+
+ Hello 1
+
+
+
+ ---
+
+
+
+ Hello 2
+
+
+
+
+ `);
+
+ const view = await findByTestId('view');
+ fireEvent.tap(view);
+
+ {
+ const snapshotPatch = JSON.parse(callLepusMethodCalls[0][1]['data']).patchList[0].snapshotPatch;
+ const formattedSnapshotPatch = prettyFormatSnapshotPatch(snapshotPatch);
+ expect(formattedSnapshotPatch).toMatchInlineSnapshot(`
+ [
+ {
+ "id": 2,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_4",
+ },
+ {
+ "id": 2,
+ "op": "SetAttributes",
+ "values": [
+ 1,
+ ],
+ },
+ {
+ "id": 3,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_1",
+ },
+ {
+ "beforeId": null,
+ "childId": 3,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 0,
+ },
+ {
+ "id": 4,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_2",
+ },
+ {
+ "beforeId": null,
+ "childId": 4,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 1,
+ },
+ {
+ "id": 5,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_2",
+ },
+ {
+ "beforeId": null,
+ "childId": 5,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 1,
+ },
+ {
+ "id": 6,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_2",
+ },
+ {
+ "beforeId": null,
+ "childId": 6,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 1,
+ },
+ {
+ "id": 7,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_3",
+ },
+ {
+ "beforeId": null,
+ "childId": 7,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 2,
+ },
+ {
+ "beforeId": null,
+ "childId": 2,
+ "op": "InsertBefore",
+ "parentId": -1,
+ "slotIndex": 0,
+ },
+ ]
+ `);
+ }
+
+ {
+ const snapshotPatch = JSON.parse(callLepusMethodCalls[1][1]['data']).patchList[0].snapshotPatch;
+ const formattedSnapshotPatch = prettyFormatSnapshotPatch(snapshotPatch);
+ expect(formattedSnapshotPatch).toMatchInlineSnapshot(`
+ [
+ {
+ "childId": 3,
+ "op": "RemoveChild",
+ "parentId": 2,
+ },
+ {
+ "id": 8,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_2",
+ },
+ {
+ "beforeId": null,
+ "childId": 8,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 0,
+ },
+ {
+ "childId": 4,
+ "op": "RemoveChild",
+ "parentId": 2,
+ },
+ {
+ "childId": 5,
+ "op": "RemoveChild",
+ "parentId": 2,
+ },
+ {
+ "childId": 6,
+ "op": "RemoveChild",
+ "parentId": 2,
+ },
+ {
+ "id": 9,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_1",
+ },
+ {
+ "beforeId": null,
+ "childId": 9,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 1,
+ },
+ {
+ "id": 10,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_1",
+ },
+ {
+ "beforeId": null,
+ "childId": 10,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 1,
+ },
+ {
+ "id": 11,
+ "op": "CreateElement",
+ "type": "__snapshot_c1928_test_1",
+ },
+ {
+ "beforeId": null,
+ "childId": 11,
+ "op": "InsertBefore",
+ "parentId": 2,
+ "slotIndex": 1,
+ },
+ ]
+ `);
+ }
+
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+
+ Hello 1
+
+
+
+ ---
+
+
+
+ Hello 0
+
+
+ Hello 0
+
+
+ Hello 0
+
+
+
+ ---
+
+
+
+ Hello 2
+
+
+
+
+ `);
+});
diff --git a/packages/react/testing-library/src/__tests__/text.test.jsx b/packages/react/testing-library/src/__tests__/text.test.jsx
new file mode 100644
index 0000000000..8caad62936
--- /dev/null
+++ b/packages/react/testing-library/src/__tests__/text.test.jsx
@@ -0,0 +1,133 @@
+import '@testing-library/jest-dom';
+import { vi } from 'vitest';
+import { render, fireEvent } from '..';
+import { expect } from 'vitest';
+import { useState } from 'preact/hooks';
+import { prettyFormatSnapshotPatch } from '../../../runtime/lib/debug/formatPatch';
+
+describe('should only render text when it is not empty', () => {
+ it('empty text should not be rendered', () => {
+ vi.spyOn(lynxTestingEnv.backgroundThread.lynxCoreInject.tt, 'OnLifecycleEvent');
+ const onLifecycleEventCalls = lynxTestingEnv.backgroundThread.lynxCoreInject.tt.OnLifecycleEvent.mock.calls;
+ vi.spyOn(lynx.getNativeApp(), 'callLepusMethod');
+ const callLepusMethodCalls = lynx.getNativeApp().callLepusMethod.mock.calls;
+
+ const { container } = render(
+
+
+ {''}
+ Static Text
+ ,
+ {
+ enableMainThread: true,
+ enableBackground: true,
+ },
+ );
+
+ expect(JSON.stringify(JSON.parse(onLifecycleEventCalls[0][0][1]['root']), null, 2)).toMatchInlineSnapshot(`
+ "{
+ "id": -1,
+ "type": "root",
+ "children": [
+ {
+ "id": -2,
+ "type": "__snapshot_89850_test_1",
+ "__slotIndex": 0
+ }
+ ]
+ }"
+ `);
+ expect(callLepusMethodCalls[0]).toMatchInlineSnapshot(`
+ [
+ "rLynxChange",
+ {
+ "data": "{"patchList":[{"snapshotPatch":[],"id":2}]}",
+ "patchOptions": {
+ "isHydration": true,
+ "pipelineOptions": {
+ "dsl": "reactLynx",
+ "needTimestamps": true,
+ "pipelineID": "pipelineID",
+ "pipelineOrigin": "reactLynxHydrate",
+ "stage": "hydrate",
+ },
+ "reloadVersion": 0,
+ },
+ },
+ [Function],
+ ]
+ `);
+ {
+ const snapshotPatch = JSON.parse(callLepusMethodCalls[0][1]['data']).patchList[0].snapshotPatch;
+ const formattedSnapshotPatch = prettyFormatSnapshotPatch(snapshotPatch);
+ expect(formattedSnapshotPatch.length).toBe(0);
+ }
+ });
+ it('non-empty text should be rendered', () => {
+ vi.spyOn(lynxTestingEnv.backgroundThread.lynxCoreInject.tt, 'OnLifecycleEvent');
+ const onLifecycleEventCalls = lynxTestingEnv.backgroundThread.lynxCoreInject.tt.OnLifecycleEvent.mock.calls;
+ vi.spyOn(lynx.getNativeApp(), 'callLepusMethod');
+ const callLepusMethodCalls = lynx.getNativeApp().callLepusMethod.mock.calls;
+
+ const { container } = render(
+
+
+ {'Dynamic Text'}
+ Static Text
+ ,
+ {
+ enableMainThread: true,
+ enableBackground: true,
+ },
+ );
+
+ expect(JSON.stringify(JSON.parse(onLifecycleEventCalls[0][0][1]['root']), null, 2)).toMatchInlineSnapshot(`
+ "{
+ "id": -1,
+ "type": "root",
+ "children": [
+ {
+ "id": -2,
+ "type": "__snapshot_89850_test_2",
+ "children": [
+ {
+ "id": -3,
+ "type": null,
+ "values": [
+ "Dynamic Text"
+ ],
+ "__slotIndex": 0
+ }
+ ],
+ "__slotIndex": 0
+ }
+ ]
+ }"
+ `);
+ expect(callLepusMethodCalls[0]).toMatchInlineSnapshot(`
+ [
+ "rLynxChange",
+ {
+ "data": "{"patchList":[{"snapshotPatch":[],"id":2}]}",
+ "patchOptions": {
+ "isHydration": true,
+ "pipelineOptions": {
+ "dsl": "reactLynx",
+ "needTimestamps": true,
+ "pipelineID": "pipelineID",
+ "pipelineOrigin": "reactLynxHydrate",
+ "stage": "hydrate",
+ },
+ "reloadVersion": 0,
+ },
+ },
+ [Function],
+ ]
+ `);
+ {
+ const snapshotPatch = JSON.parse(callLepusMethodCalls[0][1]['data']).patchList[0].snapshotPatch;
+ const formattedSnapshotPatch = prettyFormatSnapshotPatch(snapshotPatch);
+ expect(formattedSnapshotPatch.length).toBe(0);
+ }
+ });
+});
diff --git a/packages/react/testing-library/src/setupFiles/common/runtime-setup.js b/packages/react/testing-library/src/setupFiles/common/runtime-setup.js
index 778435c1de..42ac2c8450 100644
--- a/packages/react/testing-library/src/setupFiles/common/runtime-setup.js
+++ b/packages/react/testing-library/src/setupFiles/common/runtime-setup.js
@@ -19,6 +19,7 @@ import { destroyWorklet } from '../../../../runtime/lib/worklet/destroy.js';
import { initApiEnv } from '../../../../runtime/lib/worklet-runtime/api/lynxApi.js';
import { initEventListeners } from '../../../../runtime/lib/worklet-runtime/listeners.js';
import { initWorklet } from '../../../../runtime/lib/worklet-runtime/workletRuntime.js';
+import { setupDocument, setupBackgroundDocument } from '../../../../runtime/lib/document.js';
const {
onInjectMainThreadGlobals,
@@ -60,27 +61,8 @@ globalThis.onInjectMainThreadGlobals = (target) => {
snapshotInstanceManager.nextId = 0;
target.__root = new SnapshotInstance('root');
- function setupDocument(document) {
- document.createElement = function(type) {
- return new SnapshotInstance(type);
- };
- document.createElementNS = function(_ns, type) {
- return new SnapshotInstance(type);
- };
- document.createTextNode = function(text) {
- const i = new SnapshotInstance(null);
- i.setAttribute(0, text);
- Object.defineProperty(i, 'data', {
- set(v) {
- i.setAttribute(0, v);
- },
- });
- return i;
- };
- return document;
- }
-
- target._document = setupDocument({});
+ target._document = {};
+ setupDocument(target._document);
target.globalPipelineOptions = undefined;
@@ -101,27 +83,8 @@ globalThis.onInjectBackgroundThreadGlobals = (target) => {
backgroundSnapshotInstanceManager.nextId = 0;
target.__root = new BackgroundSnapshotInstance('root');
- function setupBackgroundDocument(document) {
- document.createElement = function(type) {
- return new BackgroundSnapshotInstance(type);
- };
- document.createElementNS = function(_ns, type) {
- return new BackgroundSnapshotInstance(type);
- };
- document.createTextNode = function(text) {
- const i = new BackgroundSnapshotInstance(null);
- i.setAttribute(0, text);
- Object.defineProperty(i, 'data', {
- set(v) {
- i.setAttribute(0, v);
- },
- });
- return i;
- };
- return document;
- }
-
- target._document = setupBackgroundDocument({});
+ target._document = {};
+ setupBackgroundDocument(target._document);
target.globalPipelineOptions = undefined;
// TODO: can we only inject to target(mainThread.globalThis) instead of globalThis?
diff --git a/packages/react/transform/__test__/fixture.spec.js b/packages/react/transform/__test__/fixture.spec.js
index 50188af9d5..d2deb4c94e 100644
--- a/packages/react/transform/__test__/fixture.spec.js
+++ b/packages/react/transform/__test__/fixture.spec.js
@@ -231,7 +231,7 @@ describe('jsx', () => {
];
}, [
(snapshot, index, oldValue)=>ReactLynx.updateListItemPlatformInfo(snapshot, index, oldValue, 0)
- ], ReactLynx.__DynamicPartChildren_0, undefined, globDynamicComponentEntry, null, true);
+ ], ReactLynx.__DynamicPartSlotV2_0, undefined, globDynamicComponentEntry, null, true);
const __snapshot_da39a_04d8c_1 = "__snapshot_da39a_04d8c_1";
ReactLynx.snapshotCreatorMap[__snapshot_da39a_04d8c_1] = (__snapshot_da39a_04d8c_1)=>ReactLynx.createSnapshot(__snapshot_da39a_04d8c_1, function(snapshotInstance) {
const pageId = ReactLynx.__pageId;
@@ -241,19 +241,19 @@ describe('jsx', () => {
];
}, null, [
[
- ReactLynx.__DynamicPartListChildren,
+ ReactLynx.__DynamicPartListSlotV2,
0
]
], undefined, globDynamicComponentEntry, null, true);
/*#__PURE__*/ _jsx(__snapshot_da39a_04d8c_1, {
- children: /*#__PURE__*/ _jsx(ReactLynxRuntimeComponents.DeferredListItem, {
+ $0: /*#__PURE__*/ _jsx(ReactLynxRuntimeComponents.DeferredListItem, {
renderListItem: (__c)=>_jsx(__snapshot_da39a_04d8c_2, {
values: [
{
"item-key": "1"
}
],
- children: __c
+ $0: __c
}),
renderChildren: ()=>[],
defer: true
@@ -459,7 +459,7 @@ Component, View
];
}, [
(snapshot, index, oldValue)=>ReactLynx.updateSpread(snapshot, index, oldValue, 0)
- ], ReactLynx.__DynamicPartChildren_0, undefined, globDynamicComponentEntry, [
+ ], ReactLynx.__DynamicPartSlotV2_0, undefined, globDynamicComponentEntry, [
0
], true);
/*#__PURE__*/ ReactLynx1.wrapWithLynxComponent((__c, __spread)=>_jsx(__snapshot_da39a_89b7f_1, {
@@ -469,7 +469,7 @@ Component, View
__spread: true
}
],
- children: __c
+ $0: __c
}), _jsx(Comp, {
...s
}));
diff --git a/packages/react/transform/crates/swc_plugin_list/lib.rs b/packages/react/transform/crates/swc_plugin_list/lib.rs
index b9217e91d7..ba15f376a7 100644
--- a/packages/react/transform/crates/swc_plugin_list/lib.rs
+++ b/packages/react/transform/crates/swc_plugin_list/lib.rs
@@ -8,7 +8,9 @@ use swc_core::{
quote,
};
-use swc_plugins_shared::jsx_helpers::{jsx_attr_value, jsx_children_to_expr, jsx_is_list_item};
+use swc_plugins_shared::jsx_helpers::{
+ jsx_attr_value, jsx_children_to_expr, jsx_is_list, jsx_is_list_item,
+};
pub struct ListVisitor
where
@@ -70,6 +72,13 @@ where
// renderChildren={() => <>...>}
// />
fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) {
+ if jsx_is_list(n) {
+ n.children = vec![JSXElementChild::JSXExprContainer(JSXExprContainer {
+ expr: JSXExpr::Expr(Box::new(jsx_children_to_expr(n.children.take()))),
+ span: DUMMY_SP,
+ })];
+ }
+
n.visit_mut_children_with(self);
if jsx_list_item_deferred(n) {
@@ -162,6 +171,21 @@ where
}
}
+ fn visit_mut_jsx_element_child(&mut self, node: &mut JSXElementChild) {
+ if let JSXElementChild::JSXElement(jsx_element) = node {
+ if jsx_is_list(jsx_element) {
+ jsx_element.visit_mut_with(self);
+ *node = JSXElementChild::JSXExprContainer(JSXExprContainer {
+ expr: JSXExpr::Expr(Box::new(Expr::JSXElement(Box::new(*jsx_element.take())))),
+ span: DUMMY_SP,
+ });
+ return;
+ }
+ }
+
+ node.visit_mut_children_with(self);
+ }
+
fn visit_mut_module_items(&mut self, n: &mut Vec) {
let mut new_items: Vec = vec![];
for item in n.iter_mut() {
@@ -193,6 +217,275 @@ mod tests {
use swc_plugin_snapshot::napi::{JSXTransformer, JSXTransformerConfig};
use swc_plugins_shared::{target_napi::TransformTarget, transform_mode_napi::TransformMode};
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| {
+ (
+ visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))),
+ visit_mut_pass(JSXTransformer::<&SingleThreadedComments>::new(
+ JSXTransformerConfig {
+ preserve_jsx: true,
+ ..Default::default()
+ },
+ None,
+ TransformMode::Test,
+ None,
+ )),
+ )
+ },
+ basic_list,
+ // Input codes
+ r#"
+
+
+
+
+
+ ;
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| {
+ (
+ visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))),
+ visit_mut_pass(JSXTransformer::<&SingleThreadedComments>::new(
+ JSXTransformerConfig {
+ preserve_jsx: true,
+ ..Default::default()
+ },
+ None,
+ TransformMode::Test,
+ None,
+ )),
+ )
+ },
+ basic_list_with_fragment,
+ // Input codes
+ r#"
+
+
+ <>
+
+
+ >
+
+
+ ;
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| {
+ (
+ visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))),
+ visit_mut_pass(JSXTransformer::<&SingleThreadedComments>::new(
+ JSXTransformerConfig {
+ preserve_jsx: true,
+ ..Default::default()
+ },
+ None,
+ TransformMode::Test,
+ None,
+ )),
+ )
+ },
+ basic_list_toplevel,
+ // Input codes
+ r#"
+
+ !!!
+ !!!
+
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))),
+ should_transform_list_in_view,
+ r#"
+
+
+
+
+
+ ;
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| {
+ (
+ visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))),
+ visit_mut_pass(JSXTransformer::<&SingleThreadedComments>::new(
+ JSXTransformerConfig {
+ preserve_jsx: false,
+ target: TransformTarget::MIXED,
+ ..Default::default()
+ },
+ None,
+ TransformMode::Development,
+ None,
+ )),
+ )
+ },
+ should_transform_list_in_view_with_snapshot,
+ r#"
+
+
+
+
+
+ ;
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| {
+ (
+ visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))),
+ visit_mut_pass(JSXTransformer::<&SingleThreadedComments>::new(
+ JSXTransformerConfig {
+ preserve_jsx: false,
+ target: TransformTarget::MIXED,
+ ..Default::default()
+ },
+ None,
+ TransformMode::Development,
+ None,
+ )),
+ )
+ },
+ should_transform_list_in_view_with_static_sibling_with_snapshot,
+ r#"
+
+
+
+
+
+
+ ;
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| { visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))) },
+ should_transform_list_in_view_with_static_sibling_nested,
+ r#"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| {
+ (
+ visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))),
+ visit_mut_pass(JSXTransformer::<&SingleThreadedComments>::new(
+ JSXTransformerConfig {
+ preserve_jsx: false,
+ target: TransformTarget::MIXED,
+ ..Default::default()
+ },
+ None,
+ TransformMode::Development,
+ None,
+ )),
+ )
+ },
+ should_transform_list_in_view_with_static_sibling_with_snapshot_nested,
+ r#"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+ "#
+ );
+
+ test!(
+ module,
+ Syntax::Es(EsSyntax {
+ jsx: true,
+ ..Default::default()
+ }),
+ |t| { visit_mut_pass(ListVisitor::new(Some(t.comments.clone()))) },
+ should_transform_list_in_view_with_static_sibling,
+ r#"
+
+
+
+
+
+
+ ;
+ "#
+ );
+
test!(
module,
Syntax::Es(EsSyntax {
diff --git a/packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list.js
similarity index 68%
rename from packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list.js
rename to packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list.js
index 285902f26a..4117eeaa77 100644
--- a/packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list.js
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list.js
@@ -18,25 +18,17 @@ ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_2] = (__snapshot_da39a_test_2
];
}, null, [
[
- ReactLynx.__DynamicPartListChildren,
+ ReactLynx.__DynamicPartListSlotV2,
0
]
], undefined, globDynamicComponentEntry, null, true);
-const __snapshot_da39a_test_4 = "__snapshot_da39a_test_4";
-ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_4] = (__snapshot_da39a_test_4)=>ReactLynx.createSnapshot(__snapshot_da39a_test_4, function() {
- const pageId = ReactLynx.__pageId;
- const el = __CreateView(pageId);
- return [
- el
- ];
- }, null, ReactLynx.__DynamicPartChildren_0, undefined, globDynamicComponentEntry, null, true);
const __snapshot_da39a_test_1 = "__snapshot_da39a_test_1";
ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1)=>ReactLynx.createSnapshot(__snapshot_da39a_test_1, function() {
const pageId = ReactLynx.__pageId;
const el = __CreateView(pageId);
const el1 = __CreateWrapperElement(pageId);
__AppendElement(el, el1);
- const el2 = __CreateWrapperElement(pageId);
+ const el2 = __CreateView(pageId);
__AppendElement(el, el2);
return [
el,
@@ -45,17 +37,17 @@ ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1
];
}, null, [
[
- ReactLynx.__DynamicPartSlot,
+ ReactLynx.__DynamicPartSlotV2,
1
],
[
- ReactLynx.__DynamicPartSlot,
+ ReactLynx.__DynamicPartSlotV2,
2
]
], undefined, globDynamicComponentEntry, null, true);
-<__snapshot_da39a_test_1><__snapshot_da39a_test_2><__snapshot_da39a_test_3 values={[
+<__snapshot_da39a_test_1 $0={<__snapshot_da39a_test_2 $0={<__snapshot_da39a_test_3 values={[
{
"full-span": true,
"reuse-identifier": x
}
-]}/><__snapshot_da39a_test_4>;
+]}/>}/>} $1={}/>;
diff --git a/packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list_toplevel.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list_toplevel.js
similarity index 93%
rename from packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list_toplevel.js
rename to packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list_toplevel.js
index 1ba71e9690..98fcab4f0d 100644
--- a/packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list_toplevel.js
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list_toplevel.js
@@ -30,11 +30,11 @@ ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1
];
}, null, [
[
- ReactLynx.__DynamicPartListChildren,
+ ReactLynx.__DynamicPartListSlotV2,
0
]
], undefined, globDynamicComponentEntry, null, true);
-<__snapshot_da39a_test_1>{[
+<__snapshot_da39a_test_1 $0={[
<__snapshot_da39a_test_2/>,
<__snapshot_da39a_test_3/>
-]};
+]}/>;
diff --git a/packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list_with_fragment.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list_with_fragment.js
similarity index 72%
rename from packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list_with_fragment.js
rename to packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list_with_fragment.js
index b2827a255c..9c5a79a67e 100644
--- a/packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/basic_list_with_fragment.js
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/basic_list_with_fragment.js
@@ -24,25 +24,17 @@ ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_2] = (__snapshot_da39a_test_2
];
}, null, [
[
- ReactLynx.__DynamicPartListChildren,
+ ReactLynx.__DynamicPartListSlotV2,
0
]
], undefined, globDynamicComponentEntry, null, true);
-const __snapshot_da39a_test_5 = "__snapshot_da39a_test_5";
-ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_5] = (__snapshot_da39a_test_5)=>ReactLynx.createSnapshot(__snapshot_da39a_test_5, function() {
- const pageId = ReactLynx.__pageId;
- const el = __CreateView(pageId);
- return [
- el
- ];
- }, null, ReactLynx.__DynamicPartChildren_0, undefined, globDynamicComponentEntry, null, true);
const __snapshot_da39a_test_1 = "__snapshot_da39a_test_1";
ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1)=>ReactLynx.createSnapshot(__snapshot_da39a_test_1, function() {
const pageId = ReactLynx.__pageId;
const el = __CreateView(pageId);
const el1 = __CreateWrapperElement(pageId);
__AppendElement(el, el1);
- const el2 = __CreateWrapperElement(pageId);
+ const el2 = __CreateView(pageId);
__AppendElement(el, el2);
return [
el,
@@ -51,15 +43,15 @@ ReactLynx.snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1
];
}, null, [
[
- ReactLynx.__DynamicPartSlot,
+ ReactLynx.__DynamicPartSlotV2,
1
],
[
- ReactLynx.__DynamicPartSlot,
+ ReactLynx.__DynamicPartSlotV2,
2
]
], undefined, globDynamicComponentEntry, null, true);
-<__snapshot_da39a_test_1><__snapshot_da39a_test_2>{<>
+<__snapshot_da39a_test_1 $0={<__snapshot_da39a_test_2 $0={<>
<__snapshot_da39a_test_3/>
<__snapshot_da39a_test_4/>
- >}<__snapshot_da39a_test_5>;
+ >}/>} $1={}/>;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view.js
new file mode 100644
index 0000000000..cdfa75aa5a
--- /dev/null
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view.js
@@ -0,0 +1,6 @@
+
+ {{[
+ ,
+
+]}
}
+ ;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_snapshot.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_snapshot.js
new file mode 100644
index 0000000000..bd292b254f
--- /dev/null
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_snapshot.js
@@ -0,0 +1,53 @@
+const __snapshot_da39a_test_3 = "__snapshot_da39a_test_3";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_3] = (__snapshot_da39a_test_3)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_3, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_4 = "__snapshot_da39a_test_4";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_4] = (__snapshot_da39a_test_4)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_4, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_2 = "__snapshot_da39a_test_2";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_2] = (__snapshot_da39a_test_2)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_2, function(snapshotInstance) {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = require('@lynx-js/react/internal').snapshotCreateList(pageId, snapshotInstance, 0);
+ return [
+ el
+ ];
+ }, null, [
+ [
+ require('@lynx-js/react/internal').__DynamicPartListSlotV2,
+ 0
+ ]
+ ], undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_1 = "__snapshot_da39a_test_1";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_1, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateView(pageId);
+ return [
+ el
+ ];
+ }, null, require('@lynx-js/react/internal').__DynamicPartSlotV2_0, undefined, globDynamicComponentEntry, null, true);
+<__snapshot_da39a_test_1 $0={<__snapshot_da39a_test_2 $0={[
+ <__snapshot_da39a_test_3 key="1" values={[
+ {
+ "item-key": "1"
+ }
+ ]}/>,
+ <__snapshot_da39a_test_4 key="2" values={[
+ {
+ "item-key": "2"
+ }
+ ]}/>
+]}/>}/>;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling.js
new file mode 100644
index 0000000000..e2c9e624f3
--- /dev/null
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling.js
@@ -0,0 +1,7 @@
+
+ {{[
+ ,
+
+]}
}
+
+ ;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_nested.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_nested.js
new file mode 100644
index 0000000000..233a18d4a5
--- /dev/null
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_nested.js
@@ -0,0 +1,16 @@
+
+ {{[
+ ,
+ ,
+
+
+ {{[
+ ,
+
+ ]}
}
+
+
+
+]}
}
+
+ ;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_with_snapshot.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_with_snapshot.js
new file mode 100644
index 0000000000..8f30faab26
--- /dev/null
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_with_snapshot.js
@@ -0,0 +1,64 @@
+const __snapshot_da39a_test_3 = "__snapshot_da39a_test_3";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_3] = (__snapshot_da39a_test_3)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_3, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_4 = "__snapshot_da39a_test_4";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_4] = (__snapshot_da39a_test_4)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_4, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_2 = "__snapshot_da39a_test_2";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_2] = (__snapshot_da39a_test_2)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_2, function(snapshotInstance) {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = require('@lynx-js/react/internal').snapshotCreateList(pageId, snapshotInstance, 0);
+ return [
+ el
+ ];
+ }, null, [
+ [
+ require('@lynx-js/react/internal').__DynamicPartListSlotV2,
+ 0
+ ]
+ ], undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_1 = "__snapshot_da39a_test_1";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_1, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateView(pageId);
+ const el1 = __CreateWrapperElement(pageId);
+ __AppendElement(el, el1);
+ const el2 = __CreateView(pageId);
+ __AppendElement(el, el2);
+ return [
+ el,
+ el1,
+ el2
+ ];
+ }, null, [
+ [
+ require('@lynx-js/react/internal').__DynamicPartSlotV2,
+ 1
+ ]
+ ], undefined, globDynamicComponentEntry, null, true);
+<__snapshot_da39a_test_1 $0={<__snapshot_da39a_test_2 $0={[
+ <__snapshot_da39a_test_3 key="1" values={[
+ {
+ "item-key": "1"
+ }
+ ]}/>,
+ <__snapshot_da39a_test_4 key="2" values={[
+ {
+ "item-key": "2"
+ }
+ ]}/>
+]}/>}/>;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_with_snapshot_nested.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_with_snapshot_nested.js
new file mode 100644
index 0000000000..797dc123b2
--- /dev/null
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_in_view_with_static_sibling_with_snapshot_nested.js
@@ -0,0 +1,137 @@
+const __snapshot_da39a_test_3 = "__snapshot_da39a_test_3";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_3] = (__snapshot_da39a_test_3)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_3, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_4 = "__snapshot_da39a_test_4";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_4] = (__snapshot_da39a_test_4)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_4, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_7 = "__snapshot_da39a_test_7";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_7] = (__snapshot_da39a_test_7)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_7, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_8 = "__snapshot_da39a_test_8";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_8] = (__snapshot_da39a_test_8)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_8, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ return [
+ el
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], null, undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_6 = "__snapshot_da39a_test_6";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_6] = (__snapshot_da39a_test_6)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_6, function(snapshotInstance) {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = require('@lynx-js/react/internal').snapshotCreateList(pageId, snapshotInstance, 0);
+ return [
+ el
+ ];
+ }, null, [
+ [
+ require('@lynx-js/react/internal').__DynamicPartListSlotV2,
+ 0
+ ]
+ ], undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_5 = "__snapshot_da39a_test_5";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_5] = (__snapshot_da39a_test_5)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_5, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateElement("list-item", pageId);
+ const el1 = __CreateView(pageId);
+ __AppendElement(el, el1);
+ const el2 = __CreateWrapperElement(pageId);
+ __AppendElement(el1, el2);
+ const el3 = __CreateView(pageId);
+ __AppendElement(el1, el3);
+ return [
+ el,
+ el1,
+ el2,
+ el3
+ ];
+ }, [
+ (snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0)
+ ], [
+ [
+ require('@lynx-js/react/internal').__DynamicPartSlotV2,
+ 2
+ ]
+ ], undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_2 = "__snapshot_da39a_test_2";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_2] = (__snapshot_da39a_test_2)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_2, function(snapshotInstance) {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = require('@lynx-js/react/internal').snapshotCreateList(pageId, snapshotInstance, 0);
+ return [
+ el
+ ];
+ }, null, [
+ [
+ require('@lynx-js/react/internal').__DynamicPartListSlotV2,
+ 0
+ ]
+ ], undefined, globDynamicComponentEntry, null, true);
+const __snapshot_da39a_test_1 = "__snapshot_da39a_test_1";
+require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_1] = (__snapshot_da39a_test_1)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_1, function() {
+ const pageId = require('@lynx-js/react/internal').__pageId;
+ const el = __CreateView(pageId);
+ const el1 = __CreateWrapperElement(pageId);
+ __AppendElement(el, el1);
+ const el2 = __CreateView(pageId);
+ __AppendElement(el, el2);
+ return [
+ el,
+ el1,
+ el2
+ ];
+ }, null, [
+ [
+ require('@lynx-js/react/internal').__DynamicPartSlotV2,
+ 1
+ ]
+ ], undefined, globDynamicComponentEntry, null, true);
+<__snapshot_da39a_test_1 $0={<__snapshot_da39a_test_2 $0={[
+ <__snapshot_da39a_test_3 key="1" values={[
+ {
+ "item-key": "1"
+ }
+ ]}/>,
+ <__snapshot_da39a_test_4 key="2" values={[
+ {
+ "item-key": "2"
+ }
+ ]}/>,
+ <__snapshot_da39a_test_5 key="3" values={[
+ {
+ "item-key": "3"
+ }
+ ]} $0={<__snapshot_da39a_test_6 $0={[
+ <__snapshot_da39a_test_7 key="1" values={[
+ {
+ "item-key": "1"
+ }
+ ]}/>,
+ <__snapshot_da39a_test_8 key="2" values={[
+ {
+ "item-key": "2"
+ }
+ ]}/>
+ ]}/>}/>
+]}/>}/>;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_in_list.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_in_list.js
index 1d861f3e9c..6eac078e92 100644
--- a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_in_list.js
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_in_list.js
@@ -1,5 +1,5 @@
import * as ReactLynxRuntimeComponents from '@lynx-js/react/runtime-components';
-
- {__c}} renderChildren={()=>[]} key="1" defer/>
- {__c}} renderChildren={()=>[]} key="2" defer/>
-
;
+{[
+ {__c}} renderChildren={()=>[]} key="1" defer/>,
+ {__c}} renderChildren={()=>[]} key="2" defer/>
+]}
;
diff --git a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_with_children_with_snapshot.js b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_with_children_with_snapshot.js
index cec749bc24..e02c5a6a6a 100644
--- a/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_with_children_with_snapshot.js
+++ b/packages/react/transform/crates/swc_plugin_list/tests/__swc_snapshots__/lib.rs/should_transform_list_item_deferred_with_children_with_snapshot.js
@@ -11,7 +11,7 @@ require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_1] =
}, [
(snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0),
(snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateEvent(snapshot, index, oldValue, 0, "bindEvent", "tap", '')
- ], require('@lynx-js/react/internal').__DynamicPartChildren_0, undefined, globDynamicComponentEntry, null, true);
+ ], require('@lynx-js/react/internal').__DynamicPartSlotV2_0, undefined, globDynamicComponentEntry, null, true);
const __snapshot_da39a_test_2 = "__snapshot_da39a_test_2";
require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_2] = (__snapshot_da39a_test_2)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_2, function() {
const pageId = require('@lynx-js/react/internal').__pageId;
@@ -41,7 +41,7 @@ require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_4] =
"item-key": "1"
},
noop
- ]}>{__c}} renderChildren={()=>[
+ ]} $0={__c}/>} renderChildren={()=>[
<__snapshot_da39a_test_2/>,
<__snapshot_da39a_test_3/>,
<__snapshot_da39a_test_4/>
@@ -58,7 +58,7 @@ require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_5] =
}, [
(snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0),
(snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateEvent(snapshot, index, oldValue, 0, "bindEvent", "tap", '')
- ], require('@lynx-js/react/internal').__DynamicPartChildren_0, undefined, globDynamicComponentEntry, null, true);
+ ], require('@lynx-js/react/internal').__DynamicPartSlotV2_0, undefined, globDynamicComponentEntry, null, true);
const __snapshot_da39a_test_6 = "__snapshot_da39a_test_6";
require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_6] = (__snapshot_da39a_test_6)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_6, function() {
const pageId = require('@lynx-js/react/internal').__pageId;
@@ -72,7 +72,7 @@ require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_6] =
"item-key": "1"
},
noop
- ]}>{__c}} renderChildren={()=><__snapshot_da39a_test_6/>} key="1" defer/>;
+ ]} $0={__c}/>} renderChildren={()=><__snapshot_da39a_test_6/>} key="1" defer/>;
const __snapshot_da39a_test_7 = "__snapshot_da39a_test_7";
require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_7] = (__snapshot_da39a_test_7)=>require('@lynx-js/react/internal').createSnapshot(__snapshot_da39a_test_7, function() {
const pageId = require('@lynx-js/react/internal').__pageId;
@@ -85,10 +85,10 @@ require('@lynx-js/react/internal').snapshotCreatorMap[__snapshot_da39a_test_7] =
}, [
(snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateListItemPlatformInfo(snapshot, index, oldValue, 0),
(snapshot, index, oldValue)=>require('@lynx-js/react/internal').updateEvent(snapshot, index, oldValue, 0, "bindEvent", "tap", '')
- ], require('@lynx-js/react/internal').__DynamicPartChildren_0, undefined, globDynamicComponentEntry, null, true);
+ ], require('@lynx-js/react/internal').__DynamicPartSlotV2_0, undefined, globDynamicComponentEntry, null, true);
<__snapshot_da39a_test_7 values={[
{
"item-key": "1"
},
noop
- ]}>{__c}} renderChildren={()=>} key="1" defer/>;
+ ]} $0={__c}/>} renderChildren={()=>} key="1" defer/>;
diff --git a/packages/react/transform/crates/swc_plugin_snapshot/lib.rs b/packages/react/transform/crates/swc_plugin_snapshot/lib.rs
index 3a0d93c40e..662eec1295 100644
--- a/packages/react/transform/crates/swc_plugin_snapshot/lib.rs
+++ b/packages/react/transform/crates/swc_plugin_snapshot/lib.rs
@@ -23,7 +23,6 @@ use swc_core::{
};
mod attr_name;
-mod slot_marker;
#[cfg(feature = "napi")]
pub mod napi;
@@ -31,7 +30,7 @@ pub mod napi;
use swc_plugins_shared::{
css::get_string_inline_style_from_literal,
jsx_helpers::{
- jsx_attr_name, jsx_attr_to_prop, jsx_attr_value, jsx_children_to_expr,
+ jsx_attr_name, jsx_attr_to_prop, jsx_attr_value, jsx_children_to_expr, jsx_has_dynamic_key,
jsx_is_children_full_dynamic, jsx_is_custom, jsx_is_list, jsx_is_list_item, jsx_name,
jsx_props_to_obj, jsx_text_to_str, transform_jsx_attr_str,
},
@@ -40,10 +39,7 @@ use swc_plugins_shared::{
utils::{calc_hash, calc_hash_number},
};
-use self::{
- attr_name::AttrName,
- slot_marker::{jsx_is_internal_slot, jsx_unwrap_internal_slot, WrapperMarker},
-};
+use self::attr_name::AttrName;
// impl From for Expr {
// fn from(value: i32) -> Self {
@@ -118,9 +114,8 @@ pub struct UISourceMapRecord {
pub enum DynamicPart {
Attr(Expr, i32, AttrName),
Spread(Expr, i32),
- Slot(JSXElement, i32),
- Children(Expr, i32),
- ListChildren(Expr, i32),
+ Slot(Expr, i32),
+ ListSlot(Expr, i32),
}
pub fn i32_to_expr(i: &i32) -> Expr {
@@ -246,8 +241,7 @@ impl DynamicPart {
element_index: Expr = i32_to_expr(element_index)
),
DynamicPart::Slot(_, _) => Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
- DynamicPart::Children(_, _) => Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
- DynamicPart::ListChildren(_, _) => Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
+ DynamicPart::ListSlot(_, _) => Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
},
TransformTarget::JS => Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
}
@@ -267,7 +261,6 @@ where
static_stmts: Vec>,
si_id: Lazy,
snapshot_creator: Option,
- dynamic_part_count: i32,
dynamic_parts: Vec,
dynamic_part_visitor: &'a mut V,
key: Option,
@@ -282,7 +275,6 @@ where
{
fn new(
runtime_id: Expr,
- dynamic_part_count: i32,
dynamic_part_visitor: &'a mut V,
enable_ui_source_map: bool,
node_index_fn: F,
@@ -296,7 +288,6 @@ where
static_stmts: vec![],
si_id: Lazy::new(|| private_ident!("snapshotInstance")),
snapshot_creator: None,
- dynamic_part_count,
dynamic_parts: vec![],
dynamic_part_visitor,
key: None,
@@ -450,20 +441,83 @@ where
V: VisitMut,
F: Fn(Span) -> Expr,
{
- fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) {
- if jsx_is_internal_slot(n) {
- if self.dynamic_part_count > 1 {
- n.visit_mut_children_with(self.dynamic_part_visitor);
- self.dynamic_parts.push(DynamicPart::Slot(
- jsx_unwrap_internal_slot(n.take()),
- self.element_index,
- ));
- *n = WRAPPER_NODE_2.clone();
+ fn visit_mut_jsx_element_childs(&mut self, n: &mut Vec) {
+ if n.is_empty() {
+ return;
+ }
+
+ // merge dynamic parts together to reduce wrapper node count
+
+ let mut merged_children: Vec = vec![];
+ let mut current_chunk: Vec = vec![];
+
+ for mut child in n.take() {
+ let should_merge: bool;
+ match child {
+ JSXElementChild::JSXText(ref text) => {
+ if jsx_text_to_str(&text.value).is_empty() {
+ should_merge = current_chunk.is_empty();
+ } else {
+ should_merge = true;
+ }
+ }
+ JSXElementChild::JSXElement(ref element) => {
+ should_merge = !jsx_is_custom(element);
+ }
+ JSXElementChild::JSXExprContainer(JSXExprContainer {
+ expr: JSXExpr::Expr(ref _expr),
+ ..
+ }) => {
+ should_merge = false;
+ }
+ JSXElementChild::JSXFragment(_)
+ | JSXElementChild::JSXExprContainer(JSXExprContainer {
+ expr: JSXExpr::JSXEmptyExpr(_),
+ ..
+ }) => {
+ should_merge = true;
+ }
+ JSXElementChild::JSXSpreadChild(_) => {
+ unreachable!("JSXSpreadChild is not supported yet");
+ }
+ }
+
+ if should_merge {
+ if !current_chunk.is_empty() {
+ current_chunk.visit_mut_with(self.dynamic_part_visitor);
+ self.dynamic_parts.push(DynamicPart::Slot(
+ jsx_children_to_expr(current_chunk.take()),
+ self.element_index,
+ ));
+
+ let mut child = JSXElementChild::JSXElement(Box::new(WRAPPER_NODE_2.clone()));
+ child.visit_mut_with(self);
+ merged_children.push(child);
+ }
+
+ child.visit_mut_with(self);
+ merged_children.push(child);
} else {
- *n = jsx_unwrap_internal_slot(n.take());
+ current_chunk.push(child);
}
}
+ if !current_chunk.is_empty() {
+ current_chunk.visit_mut_with(self.dynamic_part_visitor);
+ self.dynamic_parts.push(DynamicPart::Slot(
+ jsx_children_to_expr(current_chunk.take()),
+ self.element_index,
+ ));
+
+ let mut child = JSXElementChild::JSXElement(Box::new(WRAPPER_NODE_2.clone()));
+ child.visit_mut_with(self);
+ merged_children.push(child);
+ }
+
+ *n = merged_children;
+ }
+
+ fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) {
if !jsx_is_custom(n) {
match Lazy::::get(&self.page_id) {
Some(_) => {}
@@ -479,6 +533,23 @@ where
let el = private_ident!("el");
self.element_ids.insert(self.element_index, el.clone());
+ if (jsx_has_dynamic_key(n)) && self.parent_element.is_some() {
+ n.visit_mut_with(self.dynamic_part_visitor);
+ let expr = Expr::JSXElement(Box::new(n.take()));
+
+ if jsx_is_list(n) {
+ self
+ .dynamic_parts
+ .push(DynamicPart::ListSlot(expr, self.element_index));
+ } else {
+ self
+ .dynamic_parts
+ .push(DynamicPart::Slot(expr, self.element_index));
+ }
+
+ *n = WRAPPER_NODE_2.clone();
+ }
+
let static_stmt = self.static_stmt_from_jsx_element(n, el.clone());
let static_stmt = RefCell::new(static_stmt);
self.static_stmts.push(static_stmt.clone());
@@ -912,76 +983,26 @@ where
)));
};
- let is_list = jsx_is_list(n);
- let is_children_full_dynamic = is_list || jsx_is_children_full_dynamic(n);
+ let is_children_full_dynamic = jsx_is_children_full_dynamic(n);
if !is_children_full_dynamic {
self.element_index += 1;
let pre_parent_element = self.parent_element.take();
self.parent_element = Some(el.clone());
- // n.children.iter_mut().for_each(|child| match child {
- // JSXElementChild::JSXText(_) => {
- // child.visit_mut_children_with(self);
- // }
- // JSXElementChild::JSXElement(_) => {
- // child.visit_mut_children_with(self);
- // }
- // JSXElementChild::JSXFragment(_) => {
- // child.visit_mut_children_with(self);
- // }
- // JSXElementChild::JSXExprContainer(JSXExprContainer {
- // expr: JSXExpr::Expr(_expr),
- // ..
- // }) => {
- // unreachable!("should be handled by WrapDynamicPart");
- // }
- // JSXElementChild::JSXExprContainer(JSXExprContainer {
- // expr: JSXExpr::JSXEmptyExpr(_),
- // ..
- // }) => {
- // // comment, just ignore
- // }
- // JSXElementChild::JSXSpreadChild(_) => {
- // unreachable!("JSXSpreadChild is not supported yet");
- // }
- // });
-
n.visit_mut_children_with(self);
-
self.parent_element = pre_parent_element;
} else {
- if self.dynamic_part_count <= 1 {
- n.visit_mut_children_with(self.dynamic_part_visitor);
- let children_expr = jsx_children_to_expr(n.children.take());
- if is_list {
- self
- .dynamic_parts
- .push(DynamicPart::ListChildren(children_expr, self.element_index));
- } else {
- self
- .dynamic_parts
- .push(DynamicPart::Children(children_expr, self.element_index));
- }
+ n.visit_mut_children_with(self.dynamic_part_visitor);
+ let children_expr = jsx_children_to_expr(n.children.take());
+ if jsx_is_list(n) {
+ self
+ .dynamic_parts
+ .push(DynamicPart::ListSlot(children_expr, self.element_index));
} else {
- // static_stmt.replace_with(|_| {
- // let r = WRAPPER_NODE.clone();
- // let (static_stmt, _) =
- // self.static_stmt_from_jsx_element(&r, el.clone());
- // static_stmt
- // });
-
- // n.map_with_mut(|value| value.fold_with(self.dynamic_part_visitor));
- // if is_list {
- // // unreachable!()
- // self.dynamic_parts
- // .push(DynamicPart::Slot(n.take(), self.element_index));
- // } else {
- // self.dynamic_parts
- // .push(DynamicPart::Slot(n.take(), self.element_index));
- // }
-
- unreachable!("should be handled by WrapDynamicPart");
+ self
+ .dynamic_parts
+ .push(DynamicPart::Slot(children_expr, self.element_index));
}
self.element_index += 1;
@@ -1042,7 +1063,7 @@ where
n.visit_mut_children_with(self.dynamic_part_visitor);
if self.parent_element.is_some() {
- self.dynamic_parts.push(DynamicPart::Children(
+ self.dynamic_parts.push(DynamicPart::Slot(
Expr::JSXElement(Box::new(n.take())),
self.element_index,
));
@@ -1284,12 +1305,6 @@ where
SyntaxContext::default().apply_mark(Mark::fresh(Mark::root())),
);
- let mut wrap_dynamic_part = WrapperMarker {
- current_is_children_full_dynamic: false,
- dynamic_part_count: 0,
- };
- node.visit_mut_with(&mut wrap_dynamic_part);
-
let target = self.cfg.target;
let runtime_id = self.runtime_id.clone();
let filename_hash = self.filename_hash.clone();
@@ -1327,7 +1342,6 @@ where
let mut dynamic_part_extractor = DynamicPartExtractor::new(
self.runtime_id.clone(),
- wrap_dynamic_part.dynamic_part_count,
self,
self.cfg.enable_ui_source_map,
node_index_fn,
@@ -1338,7 +1352,7 @@ where
let mut snapshot_values: Vec