From 22178613a2b0d37ff842e2a726b48b1c0d517fd2 Mon Sep 17 00:00:00 2001 From: LastLeaf Date: Wed, 20 Sep 2023 20:46:30 +0800 Subject: [PATCH] fix(core): list diff wrong when an item moved to list front (#98) --- glass-easel/src/tmpl/range_list_diff.ts | 8 ++-- glass-easel/tests/core/data_update.test.ts | 55 ++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/glass-easel/src/tmpl/range_list_diff.ts b/glass-easel/src/tmpl/range_list_diff.ts index 6e0ee02..6fa5f16 100644 --- a/glass-easel/src/tmpl/range_list_diff.ts +++ b/glass-easel/src/tmpl/range_list_diff.ts @@ -1,4 +1,4 @@ -import { Element, VirtualNode } from '..' +import { Element, VirtualNode, dumpElementToString } from '..' import { DataValue } from '../data_proxy' import { UpdatePathTreeNode, UpdatePathTreeRoot } from './proc_gen_wrapper' import { triggerWarning } from '../func_arr' @@ -327,12 +327,12 @@ export class RangeListManager { // decide what operation to be used with each item const enum OpKind { Stable = 0, - ForwardMove, - BackwardMove, + ForwardMove, // move towards the array end (index increasing direction) + BackwardMove, // move towards the array start (index decreasing direction) } const oldListOp = new Array(oldRawKeys.length) as (OpKind | undefined)[] const changedItems = new Array(newRawKeys.length) as (VirtualNode | undefined)[] - let prevLcsOldPos = lcsArr[curLcsArrIndex]! + let prevLcsOldPos = -1 for (let i = 0; i < oldPosList.length; i += 1) { const oldPos = oldPosList[i]! if (i === lcsArr[curLcsArrIndex]) { diff --git a/glass-easel/tests/core/data_update.test.ts b/glass-easel/tests/core/data_update.test.ts index 39c49b3..0b5b3f2 100644 --- a/glass-easel/tests/core/data_update.test.ts +++ b/glass-easel/tests/core/data_update.test.ts @@ -185,6 +185,61 @@ describe('partial update', () => { expect(execArr).toStrictEqual(['E']) }) + test('should be able to update list (full list update)', () => { + let execArr = [] as string[] + const childCompDef = componentSpace + .define() + .property('p', String) + .observer('p', function () { + execArr.push(this.data.p) + }) + .registerComponent() + const compDef = componentSpace + .define() + .usingComponents({ + child: childCompDef.general(), + }) + .template( + tmpl(` + + `), + ) + .data(() => ({ + list: [ + { k: 1, v: 'A' }, + { k: 2, v: 'B' }, + { k: 3, v: 'C' }, + { k: 4, v: 'D' }, + ], + })) + .registerComponent() + const comp = glassEasel.Component.createWithContext('root', compDef, domBackend) + glassEasel.Element.pretendAttached(comp) + const getP = () => { + const ret = [] as string[] + comp + .getShadowRoot()! + .childNodes[0]!.asElement()! + .childNodes.forEach((child) => { + ret.push(child.asElement()!.childNodes[0]!.asInstanceOf(childCompDef)!.data.p) + }) + return ret + } + expect(getP()).toStrictEqual(['A', 'B', 'C', 'D']) + expect(execArr).toStrictEqual(['A', 'B', 'C', 'D']) + execArr = [] + comp.setData({ + list: [ + { k: 3, v: 'C' }, + { k: 5, v: 'E' }, + { k: 1, v: 'A' }, + { k: 6, v: 'F' }, + ], + }) + expect(getP()).toStrictEqual(['C', 'E', 'A', 'F']) + expect(execArr).toStrictEqual(['E', 'F', 'C', 'A']) + }) + test('should be able to update list keys', () => { let execArr = [] as string[] const childCompDef = componentSpace