Skip to content

Commit

Permalink
fix(reactivity): Array methods relying on identity should work with r…
Browse files Browse the repository at this point in the history
…aw values
  • Loading branch information
yyx990803 committed Jan 23, 2020
1 parent 3919c78 commit aefb7d2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
21 changes: 21 additions & 0 deletions packages/reactivity/__tests__/reactive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@ describe('reactivity/reactive', () => {
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', () => {
const original = {
nested: {
Expand Down
15 changes: 14 additions & 1 deletion packages/reactivity/src/baseHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { reactive, readonly, toRaw } from './reactive'
import { TrackOpTypes, TriggerOpTypes } from './operations'
import { track, trigger, ITERATE_KEY } from './effect'
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'

const builtInSymbols = new Set(
Expand All @@ -15,8 +15,21 @@ const get = /*#__PURE__*/ createGetter()
const readonlyGet = /*#__PURE__*/ createGetter(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) {
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)
if (isSymbol(key) && builtInSymbols.has(key)) {
return res
Expand Down

0 comments on commit aefb7d2

Please sign in to comment.