From 3c05f8bbd6cd0e01bbc5830730852f9a93d8de8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=9C=C9=B4=D0=B2=CA=8F=D1=82=E1=B4=87?= Date: Sat, 22 Aug 2020 01:36:41 +0800 Subject: [PATCH] fix(reactivity): unwrap non-index accessed refs on reactive arrays (#1859) close #1846 --- packages/reactivity/__tests__/ref.spec.ts | 13 +++++++++++++ packages/reactivity/src/baseHandlers.ts | 13 +++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/reactivity/__tests__/ref.spec.ts b/packages/reactivity/__tests__/ref.spec.ts index bae4ec35a31..9ef6c4e4b15 100644 --- a/packages/reactivity/__tests__/ref.spec.ts +++ b/packages/reactivity/__tests__/ref.spec.ts @@ -115,6 +115,19 @@ describe('reactivity/ref', () => { expect((arr[1] as Ref).value).toBe(3) }) + it('should unwrap ref types as props of arrays', () => { + const arr = [ref(0)] + const symbolKey = Symbol('') + arr['' as any] = ref(1) + arr[symbolKey as any] = ref(2) + const arrRef = ref(arr).value + expect(isRef(arrRef[0])).toBe(true) + expect(isRef(arrRef['' as any])).toBe(false) + expect(isRef(arrRef[symbolKey as any])).toBe(false) + expect(arrRef['' as any]).toBe(1) + expect(arrRef[symbolKey as any]).toBe(2) + }) + it('should keep tuple types', () => { const tuple: [number, string, { a: number }, () => number, Ref] = [ 0, diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index 11a7b1cc04e..8d8112e926a 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -63,9 +63,10 @@ function createGetter(isReadonly = false, shallow = false) { const res = Reflect.get(target, key, receiver) + const keyIsSymbol = isSymbol(key) if ( - isSymbol(key) - ? builtInSymbols.has(key) + keyIsSymbol + ? builtInSymbols.has(key as symbol) : key === `__proto__` || key === `__v_isRef` ) { return res @@ -80,8 +81,12 @@ function createGetter(isReadonly = false, shallow = false) { } if (isRef(res)) { - // ref unwrapping, only for Objects, not for Arrays. - return targetIsArray ? res : res.value + // ref unwrapping - does not apply for Array + integer key. + const shouldUnwrap = + !targetIsArray || + keyIsSymbol || + '' + parseInt(key as string, 10) !== key + return shouldUnwrap ? res.value : res } if (isObject(res)) {