source: frontend/node_modules/immer/src/utils/common.ts

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.9 KB
RevLine 
[9af201e]1import {
2 DRAFT_STATE,
3 DRAFTABLE,
4 hasSet,
5 Objectish,
6 Drafted,
7 AnyObject,
8 AnyMap,
9 AnySet,
10 ImmerState,
11 hasMap,
12 Archtype,
13 die
14} from "../internal"
15
16/** Returns true if the given value is an Immer draft */
17/*#__PURE__*/
18export function isDraft(value: any): boolean {
19 return !!value && !!value[DRAFT_STATE]
20}
21
22/** Returns true if the given value can be drafted by Immer */
23/*#__PURE__*/
24export function isDraftable(value: any): boolean {
25 if (!value) return false
26 return (
27 isPlainObject(value) ||
28 Array.isArray(value) ||
29 !!value[DRAFTABLE] ||
30 !!value.constructor?.[DRAFTABLE] ||
31 isMap(value) ||
32 isSet(value)
33 )
34}
35
36const objectCtorString = Object.prototype.constructor.toString()
37/*#__PURE__*/
38export function isPlainObject(value: any): boolean {
39 if (!value || typeof value !== "object") return false
40 const proto = Object.getPrototypeOf(value)
41 if (proto === null) {
42 return true
43 }
44 const Ctor =
45 Object.hasOwnProperty.call(proto, "constructor") && proto.constructor
46
47 if (Ctor === Object) return true
48
49 return (
50 typeof Ctor == "function" &&
51 Function.toString.call(Ctor) === objectCtorString
52 )
53}
54
55/** Get the underlying object that is represented by the given draft */
56/*#__PURE__*/
57export function original<T>(value: T): T | undefined
58export function original(value: Drafted<any>): any {
59 if (!isDraft(value)) die(23, value)
60 return value[DRAFT_STATE].base_
61}
62
63/*#__PURE__*/
64export const ownKeys: (target: AnyObject) => PropertyKey[] =
65 typeof Reflect !== "undefined" && Reflect.ownKeys
66 ? Reflect.ownKeys
67 : typeof Object.getOwnPropertySymbols !== "undefined"
68 ? obj =>
69 Object.getOwnPropertyNames(obj).concat(
70 Object.getOwnPropertySymbols(obj) as any
71 )
72 : /* istanbul ignore next */ Object.getOwnPropertyNames
73
74export const getOwnPropertyDescriptors =
75 Object.getOwnPropertyDescriptors ||
76 function getOwnPropertyDescriptors(target: any) {
77 // Polyfill needed for Hermes and IE, see https://github.com/facebook/hermes/issues/274
78 const res: any = {}
79 ownKeys(target).forEach(key => {
80 res[key] = Object.getOwnPropertyDescriptor(target, key)
81 })
82 return res
83 }
84
85export function each<T extends Objectish>(
86 obj: T,
87 iter: (key: string | number, value: any, source: T) => void,
88 enumerableOnly?: boolean
89): void
90export function each(obj: any, iter: any, enumerableOnly = false) {
91 if (getArchtype(obj) === Archtype.Object) {
92 ;(enumerableOnly ? Object.keys : ownKeys)(obj).forEach(key => {
93 if (!enumerableOnly || typeof key !== "symbol") iter(key, obj[key], obj)
94 })
95 } else {
96 obj.forEach((entry: any, index: any) => iter(index, entry, obj))
97 }
98}
99
100/*#__PURE__*/
101export function getArchtype(thing: any): Archtype {
102 /* istanbul ignore next */
103 const state: undefined | ImmerState = thing[DRAFT_STATE]
104 return state
105 ? state.type_ > 3
106 ? state.type_ - 4 // cause Object and Array map back from 4 and 5
107 : (state.type_ as any) // others are the same
108 : Array.isArray(thing)
109 ? Archtype.Array
110 : isMap(thing)
111 ? Archtype.Map
112 : isSet(thing)
113 ? Archtype.Set
114 : Archtype.Object
115}
116
117/*#__PURE__*/
118export function has(thing: any, prop: PropertyKey): boolean {
119 return getArchtype(thing) === Archtype.Map
120 ? thing.has(prop)
121 : Object.prototype.hasOwnProperty.call(thing, prop)
122}
123
124/*#__PURE__*/
125export function get(thing: AnyMap | AnyObject, prop: PropertyKey): any {
126 // @ts-ignore
127 return getArchtype(thing) === Archtype.Map ? thing.get(prop) : thing[prop]
128}
129
130/*#__PURE__*/
131export function set(thing: any, propOrOldValue: PropertyKey, value: any) {
132 const t = getArchtype(thing)
133 if (t === Archtype.Map) thing.set(propOrOldValue, value)
134 else if (t === Archtype.Set) {
135 thing.add(value)
136 } else thing[propOrOldValue] = value
137}
138
139/*#__PURE__*/
140export function is(x: any, y: any): boolean {
141 // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js
142 if (x === y) {
143 return x !== 0 || 1 / x === 1 / y
144 } else {
145 return x !== x && y !== y
146 }
147}
148
149/*#__PURE__*/
150export function isMap(target: any): target is AnyMap {
151 return hasMap && target instanceof Map
152}
153
154/*#__PURE__*/
155export function isSet(target: any): target is AnySet {
156 return hasSet && target instanceof Set
157}
158/*#__PURE__*/
159export function latest(state: ImmerState): any {
160 return state.copy_ || state.base_
161}
162
163/*#__PURE__*/
164export function shallowCopy(base: any) {
165 if (Array.isArray(base)) return Array.prototype.slice.call(base)
166 const descriptors = getOwnPropertyDescriptors(base)
167 delete descriptors[DRAFT_STATE as any]
168 let keys = ownKeys(descriptors)
169 for (let i = 0; i < keys.length; i++) {
170 const key: any = keys[i]
171 const desc = descriptors[key]
172 if (desc.writable === false) {
173 desc.writable = true
174 desc.configurable = true
175 }
176 // like object.assign, we will read any _own_, get/set accessors. This helps in dealing
177 // with libraries that trap values, like mobx or vue
178 // unlike object.assign, non-enumerables will be copied as well
179 if (desc.get || desc.set)
180 descriptors[key] = {
181 configurable: true,
182 writable: true, // could live with !!desc.set as well here...
183 enumerable: desc.enumerable,
184 value: base[key]
185 }
186 }
187 return Object.create(Object.getPrototypeOf(base), descriptors)
188}
189
190/**
191 * Freezes draftable objects. Returns the original object.
192 * By default freezes shallowly, but if the second argument is `true` it will freeze recursively.
193 *
194 * @param obj
195 * @param deep
196 */
197export function freeze<T>(obj: T, deep?: boolean): T
198export function freeze<T>(obj: any, deep: boolean = false): T {
199 if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj)) return obj
200 if (getArchtype(obj) > 1 /* Map or Set */) {
201 obj.set = obj.add = obj.clear = obj.delete = dontMutateFrozenCollections as any
202 }
203 Object.freeze(obj)
204 if (deep) each(obj, (key, value) => freeze(value, true), true)
205 return obj
206}
207
208function dontMutateFrozenCollections() {
209 die(2)
210}
211
212export function isFrozen(obj: any): boolean {
213 if (obj == null || typeof obj !== "object") return true
214 // See #600, IE dies on non-objects in Object.isFrozen
215 return Object.isFrozen(obj)
216}
Note: See TracBrowser for help on using the repository browser.