Skip to content

Commit e5f15df

Browse files
committed
fix(reactivity): ensure extended method arguments are not lost
1 parent bf33217 commit e5f15df

File tree

2 files changed

+95
-16
lines changed

2 files changed

+95
-16
lines changed

packages/reactivity/__tests__/reactiveArray.spec.ts

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -625,19 +625,97 @@ describe('reactivity/reactive/Array', () => {
625625

626626
test('extend methods', () => {
627627
class Collection extends Array {
628-
find(id: any) {
629-
return super.find(obj => obj.id === id)
628+
// @ts-expect-error
629+
every(foo: any, bar: any, baz: any) {
630+
expect(foo).toBe('foo')
631+
expect(bar).toBe('bar')
632+
expect(baz).toBe('baz')
633+
return super.every(obj => obj.id === foo)
634+
}
635+
636+
// @ts-expect-error
637+
filter(foo: any, bar: any, baz: any) {
638+
expect(foo).toBe('foo')
639+
expect(bar).toBe('bar')
640+
expect(baz).toBe('baz')
641+
return super.filter(obj => obj.id === foo)
642+
}
643+
644+
// @ts-expect-error
645+
find(foo: any, bar: any, baz: any) {
646+
expect(foo).toBe('foo')
647+
expect(bar).toBe('bar')
648+
expect(baz).toBe('baz')
649+
return super.find(obj => obj.id === foo)
650+
}
651+
652+
// @ts-expect-error
653+
findIndex(foo: any, bar: any, baz: any) {
654+
expect(foo).toBe('foo')
655+
expect(bar).toBe('bar')
656+
expect(baz).toBe('baz')
657+
return super.findIndex(obj => obj.id === bar)
658+
}
659+
660+
findLast(foo: any, bar: any, baz: any) {
661+
expect(foo).toBe('foo')
662+
expect(bar).toBe('bar')
663+
expect(baz).toBe('baz')
664+
// @ts-expect-error our code is limited to es2016 but user code is not
665+
return super.findLast(obj => obj.id === bar)
666+
}
667+
668+
findLastIndex(foo: any, bar: any, baz: any) {
669+
expect(foo).toBe('foo')
670+
expect(bar).toBe('bar')
671+
expect(baz).toBe('baz')
672+
return super.findIndex(obj => obj.id === bar)
673+
}
674+
675+
// @ts-expect-error
676+
forEach(foo: any, bar: any, baz: any) {
677+
expect(foo).toBe('foo')
678+
expect(bar).toBe('bar')
679+
expect(baz).toBe('baz')
680+
}
681+
682+
// @ts-expect-error
683+
map(foo: any, bar: any, baz: any) {
684+
expect(foo).toBe('foo')
685+
expect(bar).toBe('bar')
686+
expect(baz).toBe('baz')
687+
return super.map(obj => obj.value)
688+
}
689+
690+
// @ts-expect-error
691+
some(foo: any, bar: any, baz: any) {
692+
expect(foo).toBe('foo')
693+
expect(bar).toBe('bar')
694+
expect(baz).toBe('baz')
695+
return super.some(obj => obj.id === baz)
630696
}
631697
}
632698

633699
const state = reactive({
634700
things: new Collection(),
635701
})
636702

637-
const val = { id: 'foo', value: 'bar' }
638-
state.things.push(val)
639-
640-
expect(state.things.find('foo')).toBe(val)
703+
const foo = { id: 'foo', value: '1' }
704+
const bar = { id: 'bar', value: '2' }
705+
const baz = { id: 'baz', value: '3' }
706+
state.things.push(foo)
707+
state.things.push(bar)
708+
state.things.push(baz)
709+
710+
expect(state.things.every('foo', 'bar', 'baz')).toBe(false)
711+
expect(state.things.filter('foo', 'bar', 'baz')).toEqual([foo])
712+
expect(state.things.find('foo', 'bar', 'baz')).toBe(foo)
713+
expect(state.things.findIndex('foo', 'bar', 'baz')).toBe(1)
714+
expect(state.things.findLast('foo', 'bar', 'baz')).toBe(bar)
715+
expect(state.things.findLastIndex('foo', 'bar', 'baz')).toBe(1)
716+
expect(state.things.forEach('foo', 'bar', 'baz')).toBeUndefined()
717+
expect(state.things.map('foo', 'bar', 'baz')).toEqual(['1', '2', '3'])
718+
expect(state.things.some('foo', 'bar', 'baz')).toBe(true)
641719
})
642720
})
643721
})

packages/reactivity/src/arrayInstrumentations.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,42 +47,42 @@ export const arrayInstrumentations: Record<string | symbol, Function> = <any>{
4747
fn: (item: unknown, index: number, array: unknown[]) => unknown,
4848
thisArg?: unknown,
4949
) {
50-
return apply(this, 'every', fn, thisArg)
50+
return apply(this, 'every', fn, thisArg, undefined, arguments)
5151
},
5252

5353
filter(
5454
fn: (item: unknown, index: number, array: unknown[]) => unknown,
5555
thisArg?: unknown,
5656
) {
57-
return apply(this, 'filter', fn, thisArg, v => v.map(toReactive))
57+
return apply(this, 'filter', fn, thisArg, v => v.map(toReactive), arguments)
5858
},
5959

6060
find(
6161
fn: (item: unknown, index: number, array: unknown[]) => boolean,
6262
thisArg?: unknown,
6363
) {
64-
return apply(this, 'find', fn, thisArg, toReactive)
64+
return apply(this, 'find', fn, thisArg, toReactive, arguments)
6565
},
6666

6767
findIndex(
6868
fn: (item: unknown, index: number, array: unknown[]) => boolean,
6969
thisArg?: unknown,
7070
) {
71-
return apply(this, 'findIndex', fn, thisArg)
71+
return apply(this, 'findIndex', fn, thisArg, undefined, arguments)
7272
},
7373

7474
findLast(
7575
fn: (item: unknown, index: number, array: unknown[]) => boolean,
7676
thisArg?: unknown,
7777
) {
78-
return apply(this, 'findLast', fn, thisArg, toReactive)
78+
return apply(this, 'findLast', fn, thisArg, toReactive, arguments)
7979
},
8080

8181
findLastIndex(
8282
fn: (item: unknown, index: number, array: unknown[]) => boolean,
8383
thisArg?: unknown,
8484
) {
85-
return apply(this, 'findLastIndex', fn, thisArg)
85+
return apply(this, 'findLastIndex', fn, thisArg, undefined, arguments)
8686
},
8787

8888
// flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement
@@ -91,7 +91,7 @@ export const arrayInstrumentations: Record<string | symbol, Function> = <any>{
9191
fn: (item: unknown, index: number, array: unknown[]) => unknown,
9292
thisArg?: unknown,
9393
) {
94-
return apply(this, 'forEach', fn, thisArg)
94+
return apply(this, 'forEach', fn, thisArg, undefined, arguments)
9595
},
9696

9797
includes(...args: unknown[]) {
@@ -116,7 +116,7 @@ export const arrayInstrumentations: Record<string | symbol, Function> = <any>{
116116
fn: (item: unknown, index: number, array: unknown[]) => unknown,
117117
thisArg?: unknown,
118118
) {
119-
return apply(this, 'map', fn, thisArg)
119+
return apply(this, 'map', fn, thisArg, undefined, arguments)
120120
},
121121

122122
pop() {
@@ -161,7 +161,7 @@ export const arrayInstrumentations: Record<string | symbol, Function> = <any>{
161161
fn: (item: unknown, index: number, array: unknown[]) => unknown,
162162
thisArg?: unknown,
163163
) {
164-
return apply(this, 'some', fn, thisArg)
164+
return apply(this, 'some', fn, thisArg, undefined, arguments)
165165
},
166166

167167
splice(...args: unknown[]) {
@@ -236,12 +236,13 @@ function apply(
236236
fn: (item: unknown, index: number, array: unknown[]) => unknown,
237237
thisArg?: unknown,
238238
wrappedRetFn?: (result: any) => unknown,
239+
args?: IArguments,
239240
) {
240241
const arr = shallowReadArray(self)
241242
let methodFn
242243
// @ts-expect-error our code is limited to es2016 but user code is not
243244
if ((methodFn = arr[method]) !== arrayProto[method]) {
244-
return methodFn.apply(arr, arrayProto.slice.call(arguments, 2))
245+
return methodFn.apply(arr, args)
245246
}
246247

247248
let needsWrap = false

0 commit comments

Comments
 (0)