]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): correctly handle method calls on user-extended arrays (#11760)
authorTycho <jh.leong@outlook.com>
Tue, 3 Sep 2024 09:32:13 +0000 (17:32 +0800)
committerGitHub <noreply@github.com>
Tue, 3 Sep 2024 09:32:13 +0000 (17:32 +0800)
close #11759

packages/reactivity/__tests__/reactiveArray.spec.ts
packages/reactivity/src/arrayInstrumentations.ts

index fabafc21e2523fcb5e6301639772f8d669ca1f15..3d97660e4284f85d507d93d9d674b7bfee686cca 100644 (file)
@@ -724,6 +724,27 @@ describe('reactivity/reactive/Array', () => {
       expect(state.things.forEach('foo', 'bar', 'baz')).toBeUndefined()
       expect(state.things.map('foo', 'bar', 'baz')).toEqual(['1', '2', '3'])
       expect(state.things.some('foo', 'bar', 'baz')).toBe(true)
+
+      {
+        class Collection extends Array {
+          find(matcher: any) {
+            return super.find(matcher)
+          }
+        }
+
+        const state = reactive({
+          // @ts-expect-error
+          things: new Collection({ foo: '' }),
+        })
+
+        const bar = computed(() => {
+          return state.things.find((obj: any) => obj.foo === 'bar')
+        })
+        bar.value
+        state.things[0].foo = 'bar'
+
+        expect(bar.value).toEqual({ foo: 'bar' })
+      }
     })
   })
 })
index 6cf7602eca5900b13a1d00aaa4d152d2bcd68dd1..6a15e2a184a546b1aa7bb3cd8f0e98e3ff7538dc 100644 (file)
@@ -242,9 +242,13 @@ function apply(
   const needsWrap = arr !== self && !isShallow(self)
   // @ts-expect-error our code is limited to es2016 but user code is not
   const methodFn = arr[method]
-  // @ts-expect-error
-  if (methodFn !== arrayProto[method]) {
-    const result = methodFn.apply(arr, args)
+
+  // #11759
+  // If the method being called is from a user-extended Array, the arguments will be unknown
+  // (unknown order and unknown parameter types). In this case, we skip the shallowReadArray
+  // handling and directly call apply with self.
+  if (methodFn !== arrayProto[method as any]) {
+    const result = methodFn.apply(self, args)
     return needsWrap ? toReactive(result) : result
   }