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: {
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(
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