This commit is contained in:
216
node_modules/immer/src/utils/common.ts
generated
vendored
Normal file
216
node_modules/immer/src/utils/common.ts
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
import {
|
||||
DRAFT_STATE,
|
||||
DRAFTABLE,
|
||||
hasSet,
|
||||
Objectish,
|
||||
Drafted,
|
||||
AnyObject,
|
||||
AnyMap,
|
||||
AnySet,
|
||||
ImmerState,
|
||||
hasMap,
|
||||
Archtype,
|
||||
die
|
||||
} from "../internal"
|
||||
|
||||
/** Returns true if the given value is an Immer draft */
|
||||
/*#__PURE__*/
|
||||
export function isDraft(value: any): boolean {
|
||||
return !!value && !!value[DRAFT_STATE]
|
||||
}
|
||||
|
||||
/** Returns true if the given value can be drafted by Immer */
|
||||
/*#__PURE__*/
|
||||
export function isDraftable(value: any): boolean {
|
||||
if (!value) return false
|
||||
return (
|
||||
isPlainObject(value) ||
|
||||
Array.isArray(value) ||
|
||||
!!value[DRAFTABLE] ||
|
||||
!!value.constructor?.[DRAFTABLE] ||
|
||||
isMap(value) ||
|
||||
isSet(value)
|
||||
)
|
||||
}
|
||||
|
||||
const objectCtorString = Object.prototype.constructor.toString()
|
||||
/*#__PURE__*/
|
||||
export function isPlainObject(value: any): boolean {
|
||||
if (!value || typeof value !== "object") return false
|
||||
const proto = Object.getPrototypeOf(value)
|
||||
if (proto === null) {
|
||||
return true
|
||||
}
|
||||
const Ctor =
|
||||
Object.hasOwnProperty.call(proto, "constructor") && proto.constructor
|
||||
|
||||
if (Ctor === Object) return true
|
||||
|
||||
return (
|
||||
typeof Ctor == "function" &&
|
||||
Function.toString.call(Ctor) === objectCtorString
|
||||
)
|
||||
}
|
||||
|
||||
/** Get the underlying object that is represented by the given draft */
|
||||
/*#__PURE__*/
|
||||
export function original<T>(value: T): T | undefined
|
||||
export function original(value: Drafted<any>): any {
|
||||
if (!isDraft(value)) die(23, value)
|
||||
return value[DRAFT_STATE].base_
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export const ownKeys: (target: AnyObject) => PropertyKey[] =
|
||||
typeof Reflect !== "undefined" && Reflect.ownKeys
|
||||
? Reflect.ownKeys
|
||||
: typeof Object.getOwnPropertySymbols !== "undefined"
|
||||
? obj =>
|
||||
Object.getOwnPropertyNames(obj).concat(
|
||||
Object.getOwnPropertySymbols(obj) as any
|
||||
)
|
||||
: /* 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,
|
||||
enumerableOnly?: boolean
|
||||
): void
|
||||
export function each(obj: any, iter: any, enumerableOnly = false) {
|
||||
if (getArchtype(obj) === Archtype.Object) {
|
||||
;(enumerableOnly ? Object.keys : ownKeys)(obj).forEach(key => {
|
||||
if (!enumerableOnly || typeof key !== "symbol") iter(key, obj[key], obj)
|
||||
})
|
||||
} else {
|
||||
obj.forEach((entry: any, index: any) => iter(index, entry, obj))
|
||||
}
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function getArchtype(thing: any): Archtype {
|
||||
/* istanbul ignore next */
|
||||
const state: undefined | ImmerState = thing[DRAFT_STATE]
|
||||
return state
|
||||
? state.type_ > 3
|
||||
? state.type_ - 4 // cause Object and Array map back from 4 and 5
|
||||
: (state.type_ as any) // others are the same
|
||||
: Array.isArray(thing)
|
||||
? Archtype.Array
|
||||
: isMap(thing)
|
||||
? Archtype.Map
|
||||
: isSet(thing)
|
||||
? Archtype.Set
|
||||
: Archtype.Object
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function has(thing: any, prop: PropertyKey): boolean {
|
||||
return getArchtype(thing) === Archtype.Map
|
||||
? thing.has(prop)
|
||||
: Object.prototype.hasOwnProperty.call(thing, prop)
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function get(thing: AnyMap | AnyObject, prop: PropertyKey): any {
|
||||
// @ts-ignore
|
||||
return getArchtype(thing) === Archtype.Map ? thing.get(prop) : thing[prop]
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function set(thing: any, propOrOldValue: PropertyKey, value: any) {
|
||||
const t = getArchtype(thing)
|
||||
if (t === Archtype.Map) thing.set(propOrOldValue, value)
|
||||
else if (t === Archtype.Set) {
|
||||
thing.add(value)
|
||||
} else thing[propOrOldValue] = value
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function is(x: any, y: any): boolean {
|
||||
// From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js
|
||||
if (x === y) {
|
||||
return x !== 0 || 1 / x === 1 / y
|
||||
} else {
|
||||
return x !== x && y !== y
|
||||
}
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function isMap(target: any): target is AnyMap {
|
||||
return hasMap && target instanceof Map
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function isSet(target: any): target is AnySet {
|
||||
return hasSet && target instanceof Set
|
||||
}
|
||||
/*#__PURE__*/
|
||||
export function latest(state: ImmerState): any {
|
||||
return state.copy_ || state.base_
|
||||
}
|
||||
|
||||
/*#__PURE__*/
|
||||
export function shallowCopy(base: any) {
|
||||
if (Array.isArray(base)) return Array.prototype.slice.call(base)
|
||||
const descriptors = getOwnPropertyDescriptors(base)
|
||||
delete descriptors[DRAFT_STATE as any]
|
||||
let keys = ownKeys(descriptors)
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key: any = keys[i]
|
||||
const desc = descriptors[key]
|
||||
if (desc.writable === false) {
|
||||
desc.writable = true
|
||||
desc.configurable = true
|
||||
}
|
||||
// like object.assign, we will read any _own_, get/set accessors. This helps in dealing
|
||||
// with libraries that trap values, like mobx or vue
|
||||
// unlike object.assign, non-enumerables will be copied as well
|
||||
if (desc.get || desc.set)
|
||||
descriptors[key] = {
|
||||
configurable: true,
|
||||
writable: true, // could live with !!desc.set as well here...
|
||||
enumerable: desc.enumerable,
|
||||
value: base[key]
|
||||
}
|
||||
}
|
||||
return Object.create(Object.getPrototypeOf(base), descriptors)
|
||||
}
|
||||
|
||||
/**
|
||||
* Freezes draftable objects. Returns the original object.
|
||||
* By default freezes shallowly, but if the second argument is `true` it will freeze recursively.
|
||||
*
|
||||
* @param obj
|
||||
* @param deep
|
||||
*/
|
||||
export function freeze<T>(obj: T, deep?: boolean): T
|
||||
export function freeze<T>(obj: any, deep: boolean = false): T {
|
||||
if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj)) return obj
|
||||
if (getArchtype(obj) > 1 /* Map or Set */) {
|
||||
obj.set = obj.add = obj.clear = obj.delete = dontMutateFrozenCollections as any
|
||||
}
|
||||
Object.freeze(obj)
|
||||
if (deep) each(obj, (key, value) => freeze(value, true), true)
|
||||
return obj
|
||||
}
|
||||
|
||||
function dontMutateFrozenCollections() {
|
||||
die(2)
|
||||
}
|
||||
|
||||
export function isFrozen(obj: any): boolean {
|
||||
if (obj == null || typeof obj !== "object") return true
|
||||
// See #600, IE dies on non-objects in Object.isFrozen
|
||||
return Object.isFrozen(obj)
|
||||
}
|
||||
47
node_modules/immer/src/utils/env.ts
generated
vendored
Normal file
47
node_modules/immer/src/utils/env.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// Should be no imports here!
|
||||
|
||||
// Some things that should be evaluated before all else...
|
||||
|
||||
// We only want to know if non-polyfilled symbols are available
|
||||
const hasSymbol =
|
||||
typeof Symbol !== "undefined" && typeof Symbol("x") === "symbol"
|
||||
export const hasMap = typeof Map !== "undefined"
|
||||
export const hasSet = typeof Set !== "undefined"
|
||||
export const hasProxies =
|
||||
typeof Proxy !== "undefined" &&
|
||||
typeof Proxy.revocable !== "undefined" &&
|
||||
typeof Reflect !== "undefined"
|
||||
|
||||
/**
|
||||
* The sentinel value returned by producers to replace the draft with undefined.
|
||||
*/
|
||||
export const NOTHING: Nothing = hasSymbol
|
||||
? Symbol.for("immer-nothing")
|
||||
: ({["immer-nothing"]: true} as any)
|
||||
|
||||
/**
|
||||
* To let Immer treat your class instances as plain immutable objects
|
||||
* (albeit with a custom prototype), you must define either an instance property
|
||||
* or a static property on each of your custom classes.
|
||||
*
|
||||
* Otherwise, your class instance will never be drafted, which means it won't be
|
||||
* safe to mutate in a produce callback.
|
||||
*/
|
||||
export const DRAFTABLE: unique symbol = hasSymbol
|
||||
? Symbol.for("immer-draftable")
|
||||
: ("__$immer_draftable" as any)
|
||||
|
||||
export const DRAFT_STATE: unique symbol = hasSymbol
|
||||
? Symbol.for("immer-state")
|
||||
: ("__$immer_state" as any)
|
||||
|
||||
// Even a polyfilled Symbol might provide Symbol.iterator
|
||||
export const iteratorSymbol: typeof Symbol.iterator =
|
||||
(typeof Symbol != "undefined" && Symbol.iterator) || ("@@iterator" as any)
|
||||
|
||||
/** Use a class type for `nothing` so its type is unique */
|
||||
export class Nothing {
|
||||
// This lets us do `Exclude<T, Nothing>`
|
||||
// @ts-ignore
|
||||
private _!: unique symbol
|
||||
}
|
||||
60
node_modules/immer/src/utils/errors.ts
generated
vendored
Normal file
60
node_modules/immer/src/utils/errors.ts
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
const errors = {
|
||||
0: "Illegal state",
|
||||
1: "Immer drafts cannot have computed properties",
|
||||
2: "This object has been frozen and should not be mutated",
|
||||
3(data: any) {
|
||||
return (
|
||||
"Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " +
|
||||
data
|
||||
)
|
||||
},
|
||||
4: "An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.",
|
||||
5: "Immer forbids circular references",
|
||||
6: "The first or second argument to `produce` must be a function",
|
||||
7: "The third argument to `produce` must be a function or undefined",
|
||||
8: "First argument to `createDraft` must be a plain object, an array, or an immerable object",
|
||||
9: "First argument to `finishDraft` must be a draft returned by `createDraft`",
|
||||
10: "The given draft is already finalized",
|
||||
11: "Object.defineProperty() cannot be used on an Immer draft",
|
||||
12: "Object.setPrototypeOf() cannot be used on an Immer draft",
|
||||
13: "Immer only supports deleting array indices",
|
||||
14: "Immer only supports setting array indices and the 'length' property",
|
||||
15(path: string) {
|
||||
return "Cannot apply patch, path doesn't resolve: " + path
|
||||
},
|
||||
16: 'Sets cannot have "replace" patches.',
|
||||
17(op: string) {
|
||||
return "Unsupported patch operation: " + op
|
||||
},
|
||||
18(plugin: string) {
|
||||
return `The plugin for '${plugin}' has not been loaded into Immer. To enable the plugin, import and call \`enable${plugin}()\` when initializing your application.`
|
||||
},
|
||||
20: "Cannot use proxies if Proxy, Proxy.revocable or Reflect are not available",
|
||||
21(thing: string) {
|
||||
return `produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got '${thing}'`
|
||||
},
|
||||
22(thing: string) {
|
||||
return `'current' expects a draft, got: ${thing}`
|
||||
},
|
||||
23(thing: string) {
|
||||
return `'original' expects a draft, got: ${thing}`
|
||||
},
|
||||
24: "Patching reserved attributes like __proto__, prototype and constructor is not allowed"
|
||||
} as const
|
||||
|
||||
export function die(error: keyof typeof errors, ...args: any[]): never {
|
||||
if (__DEV__) {
|
||||
const e = errors[error]
|
||||
const msg = !e
|
||||
? "unknown error nr: " + error
|
||||
: typeof e === "function"
|
||||
? e.apply(null, args as any)
|
||||
: e
|
||||
throw new Error(`[Immer] ${msg}`)
|
||||
}
|
||||
throw new Error(
|
||||
`[Immer] minified error nr: ${error}${
|
||||
args.length ? " " + args.map(s => `'${s}'`).join(",") : ""
|
||||
}. Find the full error at: https://bit.ly/3cXEKWf`
|
||||
)
|
||||
}
|
||||
109
node_modules/immer/src/utils/plugins.ts
generated
vendored
Normal file
109
node_modules/immer/src/utils/plugins.ts
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
import {
|
||||
ImmerState,
|
||||
Patch,
|
||||
ImmerScope,
|
||||
Drafted,
|
||||
AnyObject,
|
||||
ImmerBaseState,
|
||||
AnyMap,
|
||||
AnySet,
|
||||
ProxyType,
|
||||
die
|
||||
} from "../internal"
|
||||
|
||||
/** Plugin utilities */
|
||||
const plugins: {
|
||||
Patches?: {
|
||||
generatePatches_(
|
||||
state: ImmerState,
|
||||
basePath: PatchPath,
|
||||
patches: Patch[],
|
||||
inversePatches: Patch[]
|
||||
): void
|
||||
generateReplacementPatches_(
|
||||
base: any,
|
||||
replacement: any,
|
||||
patches: Patch[],
|
||||
inversePatches: Patch[]
|
||||
): void
|
||||
applyPatches_<T>(draft: T, patches: Patch[]): T
|
||||
}
|
||||
ES5?: {
|
||||
willFinalizeES5_(scope: ImmerScope, result: any, isReplaced: boolean): void
|
||||
createES5Proxy_<T>(
|
||||
base: T,
|
||||
parent?: ImmerState
|
||||
): Drafted<T, ES5ObjectState | ES5ArrayState>
|
||||
hasChanges_(state: ES5ArrayState | ES5ObjectState): boolean
|
||||
}
|
||||
MapSet?: {
|
||||
proxyMap_<T extends AnyMap>(target: T, parent?: ImmerState): T
|
||||
proxySet_<T extends AnySet>(target: T, parent?: ImmerState): T
|
||||
}
|
||||
} = {}
|
||||
|
||||
type Plugins = typeof plugins
|
||||
|
||||
export function getPlugin<K extends keyof Plugins>(
|
||||
pluginKey: K
|
||||
): Exclude<Plugins[K], undefined> {
|
||||
const plugin = plugins[pluginKey]
|
||||
if (!plugin) {
|
||||
die(18, pluginKey)
|
||||
}
|
||||
// @ts-ignore
|
||||
return plugin
|
||||
}
|
||||
|
||||
export function loadPlugin<K extends keyof Plugins>(
|
||||
pluginKey: K,
|
||||
implementation: Plugins[K]
|
||||
): void {
|
||||
if (!plugins[pluginKey]) plugins[pluginKey] = implementation
|
||||
}
|
||||
|
||||
/** ES5 Plugin */
|
||||
|
||||
interface ES5BaseState extends ImmerBaseState {
|
||||
assigned_: {[key: string]: any}
|
||||
parent_?: ImmerState
|
||||
revoked_: boolean
|
||||
}
|
||||
|
||||
export interface ES5ObjectState extends ES5BaseState {
|
||||
type_: ProxyType.ES5Object
|
||||
draft_: Drafted<AnyObject, ES5ObjectState>
|
||||
base_: AnyObject
|
||||
copy_: AnyObject | null
|
||||
}
|
||||
|
||||
export interface ES5ArrayState extends ES5BaseState {
|
||||
type_: ProxyType.ES5Array
|
||||
draft_: Drafted<AnyObject, ES5ArrayState>
|
||||
base_: any
|
||||
copy_: any
|
||||
}
|
||||
|
||||
/** Map / Set plugin */
|
||||
|
||||
export interface MapState extends ImmerBaseState {
|
||||
type_: ProxyType.Map
|
||||
copy_: AnyMap | undefined
|
||||
assigned_: Map<any, boolean> | undefined
|
||||
base_: AnyMap
|
||||
revoked_: boolean
|
||||
draft_: Drafted<AnyMap, MapState>
|
||||
}
|
||||
|
||||
export interface SetState extends ImmerBaseState {
|
||||
type_: ProxyType.Set
|
||||
copy_: AnySet | undefined
|
||||
base_: AnySet
|
||||
drafts_: Map<any, Drafted> // maps the original value to the draft value in the new set
|
||||
revoked_: boolean
|
||||
draft_: Drafted<AnySet, SetState>
|
||||
}
|
||||
|
||||
/** Patches plugin */
|
||||
|
||||
export type PatchPath = (string | number)[]
|
||||
Reference in New Issue
Block a user