Skip to content

Commit

Permalink
fix: getOwnPropertyDescriptors is not available in Internet Explore…
Browse files Browse the repository at this point in the history
…r and Hermes. Fixes #626
  • Loading branch information
mweststrate committed Jun 19, 2020
1 parent 91915cf commit c7a47e2
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
34 changes: 33 additions & 1 deletion __tests__/polyfills.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const {assign} = Object
const {assign, getOwnPropertyDescriptors} = Object
const {ownKeys} = Reflect
const SymbolConstructor = Symbol

const testSymbol = Symbol("test-symbol")

Symbol = undefined
Object.assign = undefined
Reflect.ownKeys = undefined
Object.getOwnPropertyDescriptors = undefined

jest.resetModules()
const common = require("../src/internal")
Expand All @@ -13,6 +16,7 @@ const common = require("../src/internal")
Symbol = SymbolConstructor
Object.assign = assign
Reflect.ownKeys = ownKeys
Object.getOwnPropertyDescriptors = getOwnPropertyDescriptors

if (!global.USES_BUILD)
describe("Symbol", () => {
Expand Down Expand Up @@ -49,6 +53,34 @@ if (!global.USES_BUILD)
})
})

if (!global.USES_BUILD)
describe("Object.getOwnPropertyDescriptors", () => {
const {getOwnPropertyDescriptors} = common

// Symbol keys are always last.
it("gets symbolic and nonsymbolic properties", () => {
expect(
Object.getOwnPropertyDescriptors({
x: 1,
[testSymbol]: 2
})
).toEqual({
x: {
value: 1,
enumerable: true,
configurable: true,
writable: true
},
[testSymbol]: {
value: 2,
enumerable: true,
configurable: true,
writable: true
}
})
})
})

test("suppress jest warning", () => {
expect(true).toBe(true)
})
5 changes: 3 additions & 2 deletions src/plugins/es5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
die,
markChanged,
objectTraps,
ownKeys
ownKeys,
getOwnPropertyDescriptors
} from "../internal"

type ES5State = ES5ArrayState | ES5ObjectState
Expand Down Expand Up @@ -46,7 +47,7 @@ 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 = Object.getOwnPropertyDescriptors(base)
const descriptors = getOwnPropertyDescriptors(base)
// Descriptors we want to skip:
if (isArray) delete descriptors.length
delete descriptors[DRAFT_STATE as any]
Expand Down
13 changes: 12 additions & 1 deletion src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ export const ownKeys: (target: AnyObject) => PropertyKey[] =
)
: /* istanbul ignore next */ Object.getOwnPropertyNames

export const getOwnPropertyDescriptors =
Object.getOwnPropertyDescriptors ||
function getOwnPropertyDescriptors(target: any) {
// Polyfill needed for Hermes and IE, see https://github.com/facebook/hermes/issues/274
const res: any = {}
ownKeys(target).forEach(key => {
res[key] = Object.getOwnPropertyDescriptor(target, key)
})
return res
}

export function each<T extends Objectish>(
obj: T,
iter: (key: string | number, value: any, source: T) => void,
Expand Down Expand Up @@ -144,7 +155,7 @@ export function latest(state: ImmerState): any {
/*#__PURE__*/
export function shallowCopy(base: any) {
if (Array.isArray(base)) return base.slice()
const descriptors = Object.getOwnPropertyDescriptors(base)
const descriptors = getOwnPropertyDescriptors(base)
delete descriptors[DRAFT_STATE as any]
let keys = ownKeys(descriptors)
for (let i = 0; i < keys.length; i++) {
Expand Down

0 comments on commit c7a47e2

Please sign in to comment.