diff --git a/packages/runtime-core/__tests__/helpers/withMemo.spec.ts b/packages/runtime-core/__tests__/helpers/withMemo.spec.ts
index 93aac0d8..5d6590bd 100644
--- a/packages/runtime-core/__tests__/helpers/withMemo.spec.ts
+++ b/packages/runtime-core/__tests__/helpers/withMemo.spec.ts
@@ -10,6 +10,47 @@ describe('v-memo', () => {
return [el, vm]
}
+ test('on with external array', async () => {
+ const [el, vm] = mount({
+ template: `
{{ arr[0] }} {{ arr[1] }} {{arr[2] ?? '_' }} ({{c}})
{{c}}`,
+ data: () => ({ arr: [0, 0], c: 0 })
+ })
+ expect(el.innerHTML).toBe(`0 0 _ (0)
0`)
+
+ let [x, y, z] = [0, 1, 2]
+
+ // change at index x - should update
+ vm.arr[x]++
+ vm.c++
+ await nextTick()
+ expect(el.innerHTML).toBe(`1 0 _ (1)
1`)
+
+ // change at index y - should update
+ vm.arr[y]++
+ vm.c++
+ await nextTick()
+ expect(el.innerHTML).toBe(`1 1 _ (2)
2`)
+
+ // noop change - should NOT update
+ vm.arr[x] = vm.arr[0]
+ vm.arr[y] = vm.arr[1]
+ vm.c++
+ await nextTick()
+ expect(el.innerHTML).toBe(`1 1 _ (2)
3`)
+
+ // add item 3rd item - should update
+ vm.arr[z] = 0
+ vm.c++
+ await nextTick()
+ expect(el.innerHTML).toBe(`1 1 0 (4)
4`)
+
+ // remove 3rd item - should update
+ vm.arr = vm.arr.slice(0, vm.arr.length - 1)
+ vm.c++
+ await nextTick()
+ expect(el.innerHTML).toBe(`1 1 _ (5)
5`)
+ })
+
test('on normal element', async () => {
const [el, vm] = mount({
template: `{{ x }} {{ y }}
`,
diff --git a/packages/runtime-core/src/helpers/withMemo.ts b/packages/runtime-core/src/helpers/withMemo.ts
index 43b1fc28..3e40365e 100644
--- a/packages/runtime-core/src/helpers/withMemo.ts
+++ b/packages/runtime-core/src/helpers/withMemo.ts
@@ -11,12 +11,17 @@ export function withMemo(
return cached
}
const ret = render()
- ret.memo = memo
+
+ // shallow clone
+ ret.memo = memo.slice()
return (cache[index] = ret)
}
export function isMemoSame(cached: VNode, memo: any[]) {
const prev: any[] = cached.memo!
+ if (prev.length != memo.length) {
+ return false
+ }
for (let i = 0; i < prev.length; i++) {
if (prev[i] !== memo[i]) {
return false