wip: check duplicate keys
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details

This commit is contained in:
daiwei 2025-07-17 21:44:32 +08:00
parent 3913f9df43
commit 0e427d39ef
2 changed files with 34 additions and 1 deletions

View File

@ -1287,7 +1287,22 @@ describe('createFor', () => {
expect(updatedChild).toBe(firstChild) expect(updatedChild).toBe(firstChild)
}) })
test.todo('should warn with duplicate keys', async () => {}) test('should warn with duplicate keys', async () => {
const arr = ref<number[]>([1, 2, 3])
const { host, html } = render(arr)
expect(host.children.length).toBe(3)
expect(html()).toBe(
`<span>1</span><span>2</span><span>3</span><!--for-->`,
)
arr.value = [1, 2, 2]
await nextTick()
expect(host.children.length).toBe(3)
expect(html()).toBe(
`<span>1</span><span>2</span><span>2</span><!--for-->`,
)
expect(`Duplicate keys`).toHaveBeenWarned()
})
}) })
describe.todo('renderer: unkeyed children', () => {}) describe.todo('renderer: unkeyed children', () => {})

View File

@ -150,6 +150,24 @@ export const createFor = (
unmount(oldBlocks[i]) unmount(oldBlocks[i])
} }
} else { } else {
if (__DEV__) {
const keyToIndexMap: Map<any, number> = 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 sharedBlockCount = Math.min(oldLength, newLength)
const previousKeyIndexPairs: [any, number][] = new Array(oldLength) const previousKeyIndexPairs: [any, number][] = new Array(oldLength)
const queuedBlocks: [ const queuedBlocks: [