diff --git a/__tests__/regressions.js b/__tests__/regressions.js index e0fc30b1..e997f3e3 100644 --- a/__tests__/regressions.js +++ b/__tests__/regressions.js @@ -89,7 +89,7 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) { expect(foo2).toBe(foo) }) - test("#646 -2 setting undefined field to undefined should not create new result", () => { + test("#646 - 2 setting undefined field to undefined should not create new result", () => { const foo = {} const foo2 = produce(foo, draft => { draft.bar = undefined @@ -98,5 +98,23 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) { expect(foo).toEqual({}) expect(foo2).toEqual({bar: undefined}) }) + + test("#638 - out of range assignments", () => { + const state = [] + + const state1 = produce(state, draft => { + draft[2] = "v2" + }) + + expect(state1.length).toBe(3) + expect(state1).toEqual([undefined, undefined, "v2"]) + + const state2 = produce(state1, draft => { + draft[1] = "v1" + }) + + expect(state2.length).toBe(3) + expect(state2).toEqual([undefined, "v1", "v2"]) + }) }) } diff --git a/src/plugins/es5.ts b/src/plugins/es5.ts index c1f4f3ef..d0c3e02d 100644 --- a/src/plugins/es5.ts +++ b/src/plugins/es5.ts @@ -46,24 +46,22 @@ export function enableES5() { } function createES5Draft(isArray: boolean, base: any) { - // Create a new object / array, where each own property is trapped with an accessor - const descriptors = getOwnPropertyDescriptors(base) - // Descriptors we want to skip: - if (isArray) delete descriptors.length - delete descriptors[DRAFT_STATE as any] - const keys = ownKeys(descriptors) - for (let i = 0; i < keys.length; i++) { - const key: any = keys[i] - descriptors[key] = proxyProperty( - key, - isArray || !!descriptors[key].enumerable - ) - } if (isArray) { const draft = new Array(base.length) - Object.defineProperties(draft, descriptors) + for (let i = 0; i < base.length; i++) + Object.defineProperty(draft, "" + i, proxyProperty(i, true)) return draft } else { + const descriptors = getOwnPropertyDescriptors(base) + delete descriptors[DRAFT_STATE as any] + const keys = ownKeys(descriptors) + for (let i = 0; i < keys.length; i++) { + const key: any = keys[i] + descriptors[key] = proxyProperty( + key, + isArray || !!descriptors[key].enumerable + ) + } return Object.create(Object.getPrototypeOf(base), descriptors) } }