From 5bc66a4e69c7de3c2ca53025c234f86275466d4a Mon Sep 17 00:00:00 2001 From: * <8> Date: Tue, 6 Sep 2022 21:50:47 +0800 Subject: [PATCH 1/4] Match-id-78aab772cb8e654ef883d9b69084d2c4da273119 --- .../src/renderer/diff/nodeDiffComparator.ts | 5 +- .../ComponentTest/DiffAlgorithm.test.js | 48 +++++++++++++++++++ .../ComponentTest/HookTest/UseEffect.test.js | 2 +- 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 scripts/__tests__/ComponentTest/DiffAlgorithm.test.js diff --git a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts index 8e029fb6..9334116f 100644 --- a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts +++ b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts @@ -294,8 +294,9 @@ function diffArrayNodesHandler( if (rightOldIndex < 0 || rightOldNode === null) { break; } - - canBeReuse = checkCanReuseNode(rightOldNode, newChildren[rightIdx - 1]); + // 新旧节点的index应该相同才能复用,null会影响位置 + const samePosition = rightOldNode.eIndex === rightIdx - 1; + canBeReuse = checkCanReuseNode(rightOldNode, newChildren[rightIdx - 1]) && samePosition; // 不能复用,break if (!canBeReuse) { break; diff --git a/scripts/__tests__/ComponentTest/DiffAlgorithm.test.js b/scripts/__tests__/ComponentTest/DiffAlgorithm.test.js new file mode 100644 index 00000000..0f5ab14d --- /dev/null +++ b/scripts/__tests__/ComponentTest/DiffAlgorithm.test.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + */ + +import * as Horizon from '@cloudsop/horizon/index.ts'; + +describe('Diff Algorithm', () => { + it('null should diff correctly', () => { + const fn = jest.fn(); + + class C extends Horizon.Component { + constructor() { + super(); + fn(); + } + + render() { + return 1; + } + } + + let update; + + function App() { + const [current, setCurrent] = Horizon.useState(1); + update = setCurrent; + return ( + <> + {current === 1 ? : null} + {current === 2 ? : null} + {current === 3 ? : null} + + ); + } + + Horizon.render(, container); + expect(fn).toHaveBeenCalledTimes(1); + + update(2); + expect(fn).toHaveBeenCalledTimes(2); + + update(3); + expect(fn).toHaveBeenCalledTimes(3); + + update(1); + expect(fn).toHaveBeenCalledTimes(4); + }); +}); diff --git a/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js b/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js index a88cb813..443894a5 100644 --- a/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js +++ b/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js @@ -81,7 +81,7 @@ describe('useEffect Hook Test', () => { expect(LogUtils.getAndClear()).toEqual([]); // 在执行新的render前,会执行完上一次render的useEffect,所以LogUtils会加入'NewApp effect'。 Horizon.render([na], container); - expect(LogUtils.getAndClear()).toEqual(['NewApp effect']); + expect(LogUtils.getAndClear()).toEqual(['NewApp effect', 'NewApp']); expect(container.textContent).toBe('NewApp'); expect(LogUtils.getAndClear()).toEqual([]); }); From ec83aff5e62f1887f415093f3816bf458229ce79 Mon Sep 17 00:00:00 2001 From: * <8> Date: Wed, 7 Sep 2022 11:27:22 +0800 Subject: [PATCH 2/4] Match-id-91b148af957f0c2f4043f45a93a8a6e8929a0507 --- .../src/renderer/diff/nodeDiffComparator.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts index 9334116f..183e6dd9 100644 --- a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts +++ b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts @@ -55,7 +55,7 @@ function deleteVNodes(parentVNode: VNode, startDelVNode: VNode | null, endVNode? } } -function checkCanReuseNode(oldNode: VNode | null, newChild: any): boolean { +function checkCanReuseNode(oldNode: VNode | null, newChild: any, newNodeIdx: number): boolean { if (newChild === null) { return false; } @@ -70,7 +70,12 @@ function checkCanReuseNode(oldNode: VNode | null, newChild: any): boolean { return oldKey === null; } if (newChild.vtype === TYPE_COMMON_ELEMENT || newChild.vtype === TYPE_PORTAL) { - return oldKey === newChild.key; + if(oldKey || newChild.key) { + return oldKey === newChild.key; + } else { + // 新旧节点的index应该相同才能复用,null会影响位置 + return oldNode?.eIndex === newNodeIdx; + } } } @@ -254,7 +259,7 @@ function diffArrayNodesHandler( nextOldNode = oldNode.next; } - canBeReuse = checkCanReuseNode(oldNode, newChildren[leftIdx]); + canBeReuse = checkCanReuseNode(oldNode, newChildren[leftIdx], leftIdx); // 不能复用,break if (!canBeReuse) { oldNode = oldNode ?? nextOldNode; @@ -294,9 +299,8 @@ function diffArrayNodesHandler( if (rightOldIndex < 0 || rightOldNode === null) { break; } - // 新旧节点的index应该相同才能复用,null会影响位置 - const samePosition = rightOldNode.eIndex === rightIdx - 1; - canBeReuse = checkCanReuseNode(rightOldNode, newChildren[rightIdx - 1]) && samePosition; + + canBeReuse = checkCanReuseNode(rightOldNode, newChildren[rightIdx - 1], rightIdx - 1); // 不能复用,break if (!canBeReuse) { break; From b55f7c4f22c07490693682b50d9e5a70140a6e6d Mon Sep 17 00:00:00 2001 From: * <8> Date: Wed, 7 Sep 2022 17:42:28 +0800 Subject: [PATCH 3/4] Match-id-e4196e9fd763be3e06cc2c404f9780e4664daff7 --- libs/horizon/src/renderer/diff/nodeDiffComparator.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts index 183e6dd9..84462e0e 100644 --- a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts +++ b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts @@ -70,7 +70,8 @@ function checkCanReuseNode(oldNode: VNode | null, newChild: any, newNodeIdx: num return oldKey === null; } if (newChild.vtype === TYPE_COMMON_ELEMENT || newChild.vtype === TYPE_PORTAL) { - if(oldKey || newChild.key) { + // key存在时用key判断复用 + if (oldKey != null || newChild.key != null) { return oldKey === newChild.key; } else { // 新旧节点的index应该相同才能复用,null会影响位置 From 4b62e8ee48b902f628827b895a5a8cf9f90a4a25 Mon Sep 17 00:00:00 2001 From: * <8> Date: Wed, 7 Sep 2022 17:52:26 +0800 Subject: [PATCH 4/4] Match-id-999bd213135d2e503b18dc8b65ad7e4c7f627294 --- libs/horizon/src/renderer/diff/nodeDiffComparator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts index 84462e0e..686b0692 100644 --- a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts +++ b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts @@ -71,7 +71,7 @@ function checkCanReuseNode(oldNode: VNode | null, newChild: any, newNodeIdx: num } if (newChild.vtype === TYPE_COMMON_ELEMENT || newChild.vtype === TYPE_PORTAL) { // key存在时用key判断复用 - if (oldKey != null || newChild.key != null) { + if (oldKey !== null || newChild.key !== null) { return oldKey === newChild.key; } else { // 新旧节点的index应该相同才能复用,null会影响位置