From 0e427d39ef91c23a25f963a91c4eb4c0183c03f6 Mon Sep 17 00:00:00 2001 From: daiwei Date: Thu, 17 Jul 2025 21:44:32 +0800 Subject: [PATCH] wip: check duplicate keys --- packages/runtime-vapor/__tests__/for.spec.ts | 17 ++++++++++++++++- packages/runtime-vapor/src/apiCreateFor.ts | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/runtime-vapor/__tests__/for.spec.ts b/packages/runtime-vapor/__tests__/for.spec.ts index 73a217aed..01e5c9d41 100644 --- a/packages/runtime-vapor/__tests__/for.spec.ts +++ b/packages/runtime-vapor/__tests__/for.spec.ts @@ -1287,7 +1287,22 @@ describe('createFor', () => { expect(updatedChild).toBe(firstChild) }) - test.todo('should warn with duplicate keys', async () => {}) + test('should warn with duplicate keys', async () => { + const arr = ref([1, 2, 3]) + const { host, html } = render(arr) + expect(host.children.length).toBe(3) + expect(html()).toBe( + `123`, + ) + + arr.value = [1, 2, 2] + await nextTick() + expect(host.children.length).toBe(3) + expect(html()).toBe( + `122`, + ) + expect(`Duplicate keys`).toHaveBeenWarned() + }) }) describe.todo('renderer: unkeyed children', () => {}) diff --git a/packages/runtime-vapor/src/apiCreateFor.ts b/packages/runtime-vapor/src/apiCreateFor.ts index 426a5c56b..18f564072 100644 --- a/packages/runtime-vapor/src/apiCreateFor.ts +++ b/packages/runtime-vapor/src/apiCreateFor.ts @@ -150,6 +150,24 @@ export const createFor = ( unmount(oldBlocks[i]) } } else { + if (__DEV__) { + const keyToIndexMap: Map = new Map() + for (let i = 0; i < newLength; i++) { + const item = getItem(source, i) + const key = getKey(...item) + if (key != null) { + if (keyToIndexMap.has(key)) { + warn( + `Duplicate keys found during update:`, + JSON.stringify(key), + `Make sure keys are unique.`, + ) + } + keyToIndexMap.set(key, i) + } + } + } + const sharedBlockCount = Math.min(oldLength, newLength) const previousKeyIndexPairs: [any, number][] = new Array(oldLength) const queuedBlocks: [