-
-
Notifications
You must be signed in to change notification settings - Fork 850
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
When a class instance has the new `immerable` symbol in its own properties, its prototype, or on its constructor, the class instance can be drafted. When drafted, class instances are basically plain objects, just with a different prototype. No magic here. OTHER CHANGES: - Allow symbols as property names in drafts - Add non-enumerable property support to drafts - Improved error messages - Fixed issue where ES5 drafts were not being marked as `finalizing` before being shallow cloned, which resulted in unnecessary draft creation
- Loading branch information
1 parent
d5d07e8
commit 9877d64
Showing
7 changed files
with
217 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,11 @@ export const NOTHING = | |
? Symbol("immer-nothing") | ||
: {["immer-nothing"]: true} | ||
|
||
export const DRAFTABLE = | ||
typeof Symbol !== "undefined" | ||
? Symbol("immer-draftable") | ||
: "__$immer_draftable" | ||
|
||
export const DRAFT_STATE = | ||
typeof Symbol !== "undefined" ? Symbol("immer-state") : "__$immer_state" | ||
|
||
|
@@ -11,11 +16,11 @@ export function isDraft(value) { | |
} | ||
|
||
export function isDraftable(value) { | ||
if (!value) return false | ||
if (typeof value !== "object") return false | ||
if (!value || typeof value !== "object") return false | ||
if (Array.isArray(value)) return true | ||
const proto = Object.getPrototypeOf(value) | ||
return proto === null || proto === Object.prototype | ||
if (!proto || proto === Object.prototype) return true | ||
return !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE] | ||
} | ||
|
||
export function original(value) { | ||
|
@@ -36,10 +41,39 @@ export const assign = | |
return target | ||
} | ||
|
||
export function shallowCopy(value) { | ||
if (Array.isArray(value)) return value.slice() | ||
const target = value.__proto__ === undefined ? Object.create(null) : {} | ||
return assign(target, value) | ||
export const ownKeys = | ||
typeof Reflect !== "undefined" | ||
? Reflect.ownKeys | ||
: obj => | ||
Object.getOwnPropertyNames(obj).concat( | ||
Object.getOwnPropertySymbols(obj) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
aleclarson
Author
Member
|
||
) | ||
|
||
export function shallowCopy(base, invokeGetters = false) { | ||
if (Array.isArray(base)) return base.slice() | ||
const clone = Object.create(Object.getPrototypeOf(base)) | ||
ownKeys(base).forEach(key => { | ||
if (key === DRAFT_STATE) { | ||
return // Never copy over draft state. | ||
} | ||
const desc = Object.getOwnPropertyDescriptor(base, key) | ||
if (desc.get) { | ||
if (!invokeGetters) { | ||
throw new Error("Immer drafts cannot have computed properties") | ||
} | ||
desc.value = desc.get.call(base) | ||
} | ||
if (desc.enumerable) { | ||
clone[key] = desc.value | ||
} else { | ||
Object.defineProperty(clone, key, { | ||
value: desc.value, | ||
writable: true, | ||
configurable: true | ||
}) | ||
} | ||
}) | ||
return clone | ||
} | ||
|
||
export function each(value, cb) { | ||
|
@@ -50,6 +84,18 @@ export function each(value, cb) { | |
} | ||
} | ||
|
||
export function eachOwn(value, cb) { | ||
if (Array.isArray(value)) { | ||
for (let i = 0; i < value.length; i++) cb(i, value[i], value) | ||
} else { | ||
ownKeys(value).forEach(key => cb(key, value[key], value)) | ||
} | ||
} | ||
|
||
export function isEnumerable(base, prop) { | ||
return Object.getOwnPropertyDescriptor(base, prop).enumerable | ||
} | ||
|
||
export function has(thing, prop) { | ||
return Object.prototype.hasOwnProperty.call(thing, prop) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
It makes error on React-Native projects that uses redux-starter-kit.
Error:
undefined is not a function (evaluating 'Object.getOwnPropertySymbols(obj)')