From: KevinXi <1317205072@qq.com> Date: Fri, 11 Oct 2024 03:24:03 +0000 (+0800) Subject: test(reactivity): test for verifying no unnecessary calls of reactive array identity... X-Git-Tag: v3.5.12~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d96883cf7d9917df13f1f7cd97733287518b7026;p=thirdparty%2Fvuejs%2Fcore.git test(reactivity): test for verifying no unnecessary calls of reactive array identity methods (#11328) related: #9511 --- diff --git a/packages/reactivity/__tests__/reactiveArray.spec.ts b/packages/reactivity/__tests__/reactiveArray.spec.ts index ebb4a926ac..2760eb8a1a 100644 --- a/packages/reactivity/__tests__/reactiveArray.spec.ts +++ b/packages/reactivity/__tests__/reactiveArray.spec.ts @@ -89,6 +89,80 @@ describe('reactivity/reactive/Array', () => { expect(index).toBe(1) }) + // only non-existent reactive will try to search by using its raw value + describe('Array identity methods have been called times', () => { + const identityMethods = ['includes', 'indexOf', 'lastIndexOf'] as const + function instrumentArr(rawTarget: any[]) { + identityMethods.forEach(key => { + const spy = vi.fn(rawTarget[key] as any) + rawTarget[key] = spy + }) + } + function searchValue(target: any[], ...args: unknown[]) { + return identityMethods.map(key => (target[key] as any)(...args)) + } + function unInstrumentArr(rawTarget: any[]) { + identityMethods.forEach(key => { + ;(rawTarget[key] as any).mockClear() + // relink to prototype method + rawTarget[key] = Array.prototype[key] as any + }) + } + function expectHaveBeenCalledTimes(rawTarget: any[], times: number) { + identityMethods.forEach(key => { + expect(rawTarget[key]).toHaveBeenCalledTimes(times) + }) + } + + test('should be called once with a non-existent raw value', () => { + const reactiveArr = reactive([]) + instrumentArr(toRaw(reactiveArr)) + const searchResult = searchValue(reactiveArr, {}) + + expectHaveBeenCalledTimes(toRaw(reactiveArr), 1) + expect(searchResult).toStrictEqual([false, -1, -1]) + + unInstrumentArr(toRaw(reactiveArr)) + }) + + test('should be called once with an existent reactive value', () => { + const existReactiveValue = reactive({}) + const reactiveArr = reactive([existReactiveValue, existReactiveValue]) + + instrumentArr(toRaw(reactiveArr)) + const searchResult = searchValue(reactiveArr, existReactiveValue) + + expectHaveBeenCalledTimes(toRaw(reactiveArr), 1) + expect(searchResult).toStrictEqual([true, 0, 1]) + + unInstrumentArr(toRaw(reactiveArr)) + }) + + test('should be called twice with a non-existent reactive value', () => { + const reactiveArr = reactive([]) + instrumentArr(toRaw(reactiveArr)) + const searchResult = searchValue(reactiveArr, reactive({})) + + expectHaveBeenCalledTimes(toRaw(reactiveArr), 2) + expect(searchResult).toStrictEqual([false, -1, -1]) + + unInstrumentArr(toRaw(reactiveArr)) + }) + + test('should be called twice with a non-existent reactive value, but the raw value exists', () => { + const existRaw = {} + const reactiveArr = reactive([existRaw, existRaw]) + + instrumentArr(toRaw(reactiveArr)) + const searchResult = searchValue(reactiveArr, reactive(existRaw)) + + expectHaveBeenCalledTimes(toRaw(reactiveArr), 2) + expect(searchResult).toStrictEqual([true, 0, 1]) + + unInstrumentArr(toRaw(reactiveArr)) + }) + }) + test('delete on Array should not trigger length dependency', () => { const arr = reactive([1, 2, 3]) const fn = vi.fn()