diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 9f2e79ed..804d442c 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -71,9 +71,15 @@ export const isMap = (val: unknown): val is Map => export const isSet = (val: unknown): val is Set => toTypeString(val) === '[object Set]' +const MAX_VALID_ARRAY_LENGTH = 4294967295 // Math.pow(2, 32) - 1 export function isValidArrayIndex(val: any): boolean { const n = parseFloat(String(val)) - return n >= 0 && Math.floor(n) === n && isFinite(val) + return ( + n >= 0 && + Math.floor(n) === n && + isFinite(val) && + n <= MAX_VALID_ARRAY_LENGTH + ) } export function isObject(val: unknown): val is Record { diff --git a/test/v3/reactivity/del.spec.ts b/test/v3/reactivity/del.spec.ts index e7cf07ad..f590034e 100644 --- a/test/v3/reactivity/del.spec.ts +++ b/test/v3/reactivity/del.spec.ts @@ -1,4 +1,4 @@ -import { del, reactive, ref, watch } from '../../../src' +import { del, reactive, ref, watch, set, watchEffect } from '../../../src' // Vue.delete workaround for triggering view updates on object property/array index deletion describe('reactivity/del', () => { @@ -41,4 +41,21 @@ describe('reactivity/del', () => { expect(spy).toBeCalledTimes(1) expect(arr.value).toEqual([1, 3]) }) + + it('should trigger reactivity when using del on array to delete index out of valid array length', () => { + const arr = ref([]) + const MAX_VALID_ARRAY_LENGTH = Math.pow(2, 32) - 1 + const NON_VALIDD_INDEX = MAX_VALID_ARRAY_LENGTH + 1 + set(arr.value, NON_VALIDD_INDEX, 0) + const spy = jest.fn() + watchEffect( + () => { + spy(arr.value) + }, + { flush: 'sync' } + ) + expect(spy).toBeCalledTimes(1) + del(arr.value, NON_VALIDD_INDEX) + expect(spy).toBeCalledTimes(2) + }) })