fix(reactivity): Array methods relying on identity should work with raw values
This commit is contained in:
parent
3919c7840d
commit
aefb7d282e
@ -44,6 +44,27 @@ describe('reactivity/reactive', () => {
|
|||||||
expect(clone[0]).toBe(observed[0])
|
expect(clone[0]).toBe(observed[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Array identity methods should work with raw values', () => {
|
||||||
|
const raw = {}
|
||||||
|
const arr = reactive([{}, {}])
|
||||||
|
arr.push(raw)
|
||||||
|
expect(arr.indexOf(raw)).toBe(2)
|
||||||
|
expect(arr.indexOf(raw, 3)).toBe(-1)
|
||||||
|
expect(arr.includes(raw)).toBe(true)
|
||||||
|
expect(arr.includes(raw, 3)).toBe(false)
|
||||||
|
expect(arr.lastIndexOf(raw)).toBe(2)
|
||||||
|
expect(arr.lastIndexOf(raw, 1)).toBe(-1)
|
||||||
|
|
||||||
|
// should work also for the observed version
|
||||||
|
const observed = arr[2]
|
||||||
|
expect(arr.indexOf(observed)).toBe(2)
|
||||||
|
expect(arr.indexOf(observed, 3)).toBe(-1)
|
||||||
|
expect(arr.includes(observed)).toBe(true)
|
||||||
|
expect(arr.includes(observed, 3)).toBe(false)
|
||||||
|
expect(arr.lastIndexOf(observed)).toBe(2)
|
||||||
|
expect(arr.lastIndexOf(observed, 1)).toBe(-1)
|
||||||
|
})
|
||||||
|
|
||||||
test('nested reactives', () => {
|
test('nested reactives', () => {
|
||||||
const original = {
|
const original = {
|
||||||
nested: {
|
nested: {
|
||||||
|
@ -2,7 +2,7 @@ import { reactive, readonly, toRaw } from './reactive'
|
|||||||
import { TrackOpTypes, TriggerOpTypes } from './operations'
|
import { TrackOpTypes, TriggerOpTypes } from './operations'
|
||||||
import { track, trigger, ITERATE_KEY } from './effect'
|
import { track, trigger, ITERATE_KEY } from './effect'
|
||||||
import { LOCKED } from './lock'
|
import { LOCKED } from './lock'
|
||||||
import { isObject, hasOwn, isSymbol, hasChanged } from '@vue/shared'
|
import { isObject, hasOwn, isSymbol, hasChanged, isArray } from '@vue/shared'
|
||||||
import { isRef } from './ref'
|
import { isRef } from './ref'
|
||||||
|
|
||||||
const builtInSymbols = new Set(
|
const builtInSymbols = new Set(
|
||||||
@ -15,8 +15,21 @@ const get = /*#__PURE__*/ createGetter()
|
|||||||
const readonlyGet = /*#__PURE__*/ createGetter(true)
|
const readonlyGet = /*#__PURE__*/ createGetter(true)
|
||||||
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true)
|
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true)
|
||||||
|
|
||||||
|
const arrayIdentityInstrumentations: Record<string, Function> = {}
|
||||||
|
;['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
|
||||||
|
arrayIdentityInstrumentations[key] = function(
|
||||||
|
value: unknown,
|
||||||
|
...args: any[]
|
||||||
|
): any {
|
||||||
|
return toRaw(this)[key](toRaw(value), ...args)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
function createGetter(isReadonly = false, shallow = false) {
|
function createGetter(isReadonly = false, shallow = false) {
|
||||||
return function get(target: object, key: string | symbol, receiver: object) {
|
return function get(target: object, key: string | symbol, receiver: object) {
|
||||||
|
if (isArray(target) && hasOwn(arrayIdentityInstrumentations, key)) {
|
||||||
|
return Reflect.get(arrayIdentityInstrumentations, key, receiver)
|
||||||
|
}
|
||||||
const res = Reflect.get(target, key, receiver)
|
const res = Reflect.get(target, key, receiver)
|
||||||
if (isSymbol(key) && builtInSymbols.has(key)) {
|
if (isSymbol(key) && builtInSymbols.has(key)) {
|
||||||
return res
|
return res
|
||||||
|
Loading…
x
Reference in New Issue
Block a user