UNPKG

3.14 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', {
4 value: true
5});
6exports.default = deepCyclicCopyReplaceable;
7
8var _prettyFormat = require('pretty-format');
9
10/**
11 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
12 *
13 * This source code is licensed under the MIT license found in the
14 * LICENSE file in the root directory of this source tree.
15 */
16const builtInObject = [
17 Array,
18 Date,
19 Float32Array,
20 Float64Array,
21 Int16Array,
22 Int32Array,
23 Int8Array,
24 Map,
25 Set,
26 RegExp,
27 Uint16Array,
28 Uint32Array,
29 Uint8Array,
30 Uint8ClampedArray
31];
32
33if (typeof Buffer !== 'undefined') {
34 builtInObject.push(Buffer);
35}
36
37const isBuiltInObject = object => builtInObject.includes(object.constructor);
38
39const isMap = value => value.constructor === Map;
40
41function deepCyclicCopyReplaceable(value, cycles = new WeakMap()) {
42 if (typeof value !== 'object' || value === null) {
43 return value;
44 } else if (cycles.has(value)) {
45 return cycles.get(value);
46 } else if (Array.isArray(value)) {
47 return deepCyclicCopyArray(value, cycles);
48 } else if (isMap(value)) {
49 return deepCyclicCopyMap(value, cycles);
50 } else if (isBuiltInObject(value)) {
51 return value;
52 } else if (_prettyFormat.plugins.DOMElement.test(value)) {
53 return value.cloneNode(true);
54 } else {
55 return deepCyclicCopyObject(value, cycles);
56 }
57}
58
59function deepCyclicCopyObject(object, cycles) {
60 const newObject = Object.create(Object.getPrototypeOf(object));
61 const descriptors = Object.getOwnPropertyDescriptors(object);
62 cycles.set(object, newObject);
63 const newDescriptors = [
64 ...Object.keys(descriptors),
65 ...Object.getOwnPropertySymbols(descriptors)
66 ].reduce(
67 //@ts-expect-error because typescript do not support symbol key in object
68 //https://github.com/microsoft/TypeScript/issues/1863
69 (newDescriptors, key) => {
70 const enumerable = descriptors[key].enumerable;
71 newDescriptors[key] = {
72 configurable: true,
73 enumerable,
74 value: deepCyclicCopyReplaceable(
75 // this accesses the value or getter, depending. We just care about the value anyways, and this allows us to not mess with accessors
76 // it has the side effect of invoking the getter here though, rather than copying it over
77 object[key],
78 cycles
79 ),
80 writable: true
81 };
82 return newDescriptors;
83 },
84 {}
85 ); //@ts-expect-error because typescript do not support symbol key in object
86 //https://github.com/microsoft/TypeScript/issues/1863
87
88 return Object.defineProperties(newObject, newDescriptors);
89}
90
91function deepCyclicCopyArray(array, cycles) {
92 const newArray = new (Object.getPrototypeOf(array).constructor)(array.length);
93 const length = array.length;
94 cycles.set(array, newArray);
95
96 for (let i = 0; i < length; i++) {
97 newArray[i] = deepCyclicCopyReplaceable(array[i], cycles);
98 }
99
100 return newArray;
101}
102
103function deepCyclicCopyMap(map, cycles) {
104 const newMap = new Map();
105 cycles.set(map, newMap);
106 map.forEach((value, key) => {
107 newMap.set(key, deepCyclicCopyReplaceable(value, cycles));
108 });
109 return newMap;
110}