deepCyclicCopyReplaceable.js 3.1 KB

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