fix(reactivity): call array subclass methods (#3624)
fix #2314, close #2315
This commit is contained in:
parent
299f7c08c7
commit
1cfe290352
@ -171,4 +171,45 @@ describe('reactivity/reactive/Array', () => {
|
|||||||
expect(original.indexOf(ref)).toBe(1)
|
expect(original.indexOf(ref)).toBe(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Array subclasses', () => {
|
||||||
|
class SubArray<T> extends Array<T> {
|
||||||
|
lastPushed: undefined | T
|
||||||
|
lastSearched: undefined | T
|
||||||
|
|
||||||
|
push(item: T) {
|
||||||
|
this.lastPushed = item
|
||||||
|
return super.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
indexOf(searchElement: T, fromIndex?: number | undefined): number {
|
||||||
|
this.lastSearched = searchElement
|
||||||
|
return super.indexOf(searchElement, fromIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('calls correct mutation method on Array subclass', () => {
|
||||||
|
const subArray = new SubArray(4, 5, 6)
|
||||||
|
const observed = reactive(subArray)
|
||||||
|
|
||||||
|
subArray.push(7)
|
||||||
|
expect(subArray.lastPushed).toBe(7)
|
||||||
|
observed.push(9)
|
||||||
|
expect(observed.lastPushed).toBe(9)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('calls correct identity-sensitive method on Array subclass', () => {
|
||||||
|
const subArray = new SubArray(4, 5, 6)
|
||||||
|
const observed = reactive(subArray)
|
||||||
|
let index
|
||||||
|
|
||||||
|
index = subArray.indexOf(4)
|
||||||
|
expect(index).toBe(0)
|
||||||
|
expect(subArray.lastSearched).toBe(4)
|
||||||
|
|
||||||
|
index = observed.indexOf(6)
|
||||||
|
expect(index).toBe(2)
|
||||||
|
expect(observed.lastSearched).toBe(6)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -49,17 +49,16 @@ function createArrayInstrumentations() {
|
|||||||
// instrument identity-sensitive Array methods to account for possible reactive
|
// instrument identity-sensitive Array methods to account for possible reactive
|
||||||
// values
|
// values
|
||||||
;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
|
;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
|
||||||
const method = Array.prototype[key] as any
|
|
||||||
instrumentations[key] = function(this: unknown[], ...args: unknown[]) {
|
instrumentations[key] = function(this: unknown[], ...args: unknown[]) {
|
||||||
const arr = toRaw(this)
|
const arr = toRaw(this) as any
|
||||||
for (let i = 0, l = this.length; i < l; i++) {
|
for (let i = 0, l = this.length; i < l; i++) {
|
||||||
track(arr, TrackOpTypes.GET, i + '')
|
track(arr, TrackOpTypes.GET, i + '')
|
||||||
}
|
}
|
||||||
// we run the method using the original args first (which may be reactive)
|
// we run the method using the original args first (which may be reactive)
|
||||||
const res = method.apply(arr, args)
|
const res = arr[key](...args)
|
||||||
if (res === -1 || res === false) {
|
if (res === -1 || res === false) {
|
||||||
// if that didn't work, run it again using raw values.
|
// if that didn't work, run it again using raw values.
|
||||||
return method.apply(arr, args.map(toRaw))
|
return arr[key](...args.map(toRaw))
|
||||||
} else {
|
} else {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -68,10 +67,9 @@ function createArrayInstrumentations() {
|
|||||||
// instrument length-altering mutation methods to avoid length being tracked
|
// instrument length-altering mutation methods to avoid length being tracked
|
||||||
// which leads to infinite loops in some cases (#2137)
|
// which leads to infinite loops in some cases (#2137)
|
||||||
;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => {
|
;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => {
|
||||||
const method = Array.prototype[key] as any
|
|
||||||
instrumentations[key] = function(this: unknown[], ...args: unknown[]) {
|
instrumentations[key] = function(this: unknown[], ...args: unknown[]) {
|
||||||
pauseTracking()
|
pauseTracking()
|
||||||
const res = method.apply(this, args)
|
const res = (toRaw(this) as any)[key].apply(this, args)
|
||||||
resetTracking()
|
resetTracking()
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user