Skip to content

Commit

Permalink
fix: out of range assignments were broken in ES5 mode. Fixes #638
Browse files Browse the repository at this point in the history
  • Loading branch information
mweststrate committed Jul 24, 2020
1 parent 5521527 commit 0fe9132
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 15 deletions.
20 changes: 19 additions & 1 deletion __tests__/regressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"])
})
})
}
26 changes: 12 additions & 14 deletions src/plugins/es5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down

0 comments on commit 0fe9132

Please sign in to comment.