From 792c8f476eec69beb08ed85d2bd0bff83997cbbb Mon Sep 17 00:00:00 2001 From: tycho Date: Tue, 3 Sep 2024 23:26:12 +0800 Subject: [PATCH 1/2] fix(reactivity): handle non-array arguments in reactive `concat` method --- .../__tests__/reactiveArray.spec.ts | 26 +++++++++++++++---- .../reactivity/src/arrayInstrumentations.ts | 8 ++++-- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/reactivity/__tests__/reactiveArray.spec.ts b/packages/reactivity/__tests__/reactiveArray.spec.ts index 3d97660e428..5d54f33f000 100644 --- a/packages/reactivity/__tests__/reactiveArray.spec.ts +++ b/packages/reactivity/__tests__/reactiveArray.spec.ts @@ -303,19 +303,35 @@ describe('reactivity/reactive/Array', () => { const a2 = reactive([{ val: 3 }]) const a3 = [4, 5] - let result = computed(() => a1.concat(a2, a3)) - expect(result.value).toStrictEqual([1, { val: 2 }, { val: 3 }, 4, 5]) + let result = computed(() => a1.concat(a2, a3, 6, { val: 7 })) + expect(result.value).toStrictEqual([ + 1, + { val: 2 }, + { val: 3 }, + 4, + 5, + 6, + { val: 7 }, + ]) expect(isReactive(result.value[1])).toBe(false) expect(isReactive(result.value[2])).toBe(true) + expect(isReactive(result.value[6])).toBe(true) a1.shift() - expect(result.value).toStrictEqual([{ val: 2 }, { val: 3 }, 4, 5]) + expect(result.value).toStrictEqual([ + { val: 2 }, + { val: 3 }, + 4, + 5, + 6, + { val: 7 }, + ]) a2.pop() - expect(result.value).toStrictEqual([{ val: 2 }, 4, 5]) + expect(result.value).toStrictEqual([{ val: 2 }, 4, 5, 6, { val: 7 }]) a3.pop() - expect(result.value).toStrictEqual([{ val: 2 }, 4, 5]) + expect(result.value).toStrictEqual([{ val: 2 }, 4, 5, 6, { val: 7 }]) }) test('entries', () => { diff --git a/packages/reactivity/src/arrayInstrumentations.ts b/packages/reactivity/src/arrayInstrumentations.ts index 6a15e2a184a..75e8078158b 100644 --- a/packages/reactivity/src/arrayInstrumentations.ts +++ b/packages/reactivity/src/arrayInstrumentations.ts @@ -2,6 +2,7 @@ import { TrackOpTypes } from './constants' import { endBatch, pauseTracking, resetTracking, startBatch } from './effect' import { isProxy, isShallow, toRaw, toReactive } from './reactive' import { ARRAY_ITERATE_KEY, track } from './dep' +import { isArray } from '@vue/shared' /** * Track array iteration and return: @@ -30,9 +31,12 @@ export const arrayInstrumentations: Record = { return iterator(this, Symbol.iterator, toReactive) }, - concat(...args: unknown[][]) { + concat(...args: unknown[]) { + const needsWrap = isShallow(this) return reactiveReadArray(this).concat( - ...args.map(x => reactiveReadArray(x)), + ...args.map(x => + isArray(x) ? reactiveReadArray(x) : needsWrap ? toReactive(x) : x, + ), ) }, From c747cdbd1572165bd56a43c0bb284441c6fc3941 Mon Sep 17 00:00:00 2001 From: tycho Date: Tue, 3 Sep 2024 23:33:11 +0800 Subject: [PATCH 2/2] fix: remove toReactive wrap --- packages/reactivity/__tests__/reactiveArray.spec.ts | 2 +- packages/reactivity/src/arrayInstrumentations.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/reactivity/__tests__/reactiveArray.spec.ts b/packages/reactivity/__tests__/reactiveArray.spec.ts index 5d54f33f000..ebb4a926acd 100644 --- a/packages/reactivity/__tests__/reactiveArray.spec.ts +++ b/packages/reactivity/__tests__/reactiveArray.spec.ts @@ -315,7 +315,7 @@ describe('reactivity/reactive/Array', () => { ]) expect(isReactive(result.value[1])).toBe(false) expect(isReactive(result.value[2])).toBe(true) - expect(isReactive(result.value[6])).toBe(true) + expect(isReactive(result.value[6])).toBe(false) a1.shift() expect(result.value).toStrictEqual([ diff --git a/packages/reactivity/src/arrayInstrumentations.ts b/packages/reactivity/src/arrayInstrumentations.ts index 75e8078158b..e031df4fe10 100644 --- a/packages/reactivity/src/arrayInstrumentations.ts +++ b/packages/reactivity/src/arrayInstrumentations.ts @@ -32,11 +32,8 @@ export const arrayInstrumentations: Record = { }, concat(...args: unknown[]) { - const needsWrap = isShallow(this) return reactiveReadArray(this).concat( - ...args.map(x => - isArray(x) ? reactiveReadArray(x) : needsWrap ? toReactive(x) : x, - ), + ...args.map(x => (isArray(x) ? reactiveReadArray(x) : x)), ) },