deepCyclicCopyReplaceable.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. Buffer,
  16. Date,
  17. Float32Array,
  18. Float64Array,
  19. Int16Array,
  20. Int32Array,
  21. Int8Array,
  22. Map,
  23. Set,
  24. RegExp,
  25. Uint16Array,
  26. Uint32Array,
  27. Uint8Array,
  28. Uint8ClampedArray
  29. ];
  30. const isBuiltInObject = object => builtInObject.includes(object.constructor);
  31. const isMap = value => value.constructor === Map;
  32. function deepCyclicCopyReplaceable(value, cycles = new WeakMap()) {
  33. if (typeof value !== 'object' || value === null) {
  34. return value;
  35. } else if (cycles.has(value)) {
  36. return cycles.get(value);
  37. } else if (Array.isArray(value)) {
  38. return deepCyclicCopyArray(value, cycles);
  39. } else if (isMap(value)) {
  40. return deepCyclicCopyMap(value, cycles);
  41. } else if (isBuiltInObject(value)) {
  42. return value;
  43. } else if (_prettyFormat.plugins.DOMElement.test(value)) {
  44. return value.cloneNode(true);
  45. } else {
  46. return deepCyclicCopyObject(value, cycles);
  47. }
  48. }
  49. function deepCyclicCopyObject(object, cycles) {
  50. const newObject = Object.create(Object.getPrototypeOf(object));
  51. const descriptors = Object.getOwnPropertyDescriptors(object);
  52. cycles.set(object, newObject);
  53. const newDescriptors = [
  54. ...Object.keys(descriptors),
  55. ...Object.getOwnPropertySymbols(descriptors)
  56. ].reduce(
  57. //@ts-expect-error because typescript do not support symbol key in object
  58. //https://github.com/microsoft/TypeScript/issues/1863
  59. (newDescriptors, key) => {
  60. const enumerable = descriptors[key].enumerable;
  61. newDescriptors[key] = {
  62. configurable: true,
  63. enumerable,
  64. value: deepCyclicCopyReplaceable(
  65. // this accesses the value or getter, depending. We just care about the value anyways, and this allows us to not mess with accessors
  66. // it has the side effect of invoking the getter here though, rather than copying it over
  67. object[key],
  68. cycles
  69. ),
  70. writable: true
  71. };
  72. return newDescriptors;
  73. },
  74. {}
  75. ); //@ts-expect-error because typescript do not support symbol key in object
  76. //https://github.com/microsoft/TypeScript/issues/1863
  77. return Object.defineProperties(newObject, newDescriptors);
  78. }
  79. function deepCyclicCopyArray(array, cycles) {
  80. const newArray = new (Object.getPrototypeOf(array).constructor)(array.length);
  81. const length = array.length;
  82. cycles.set(array, newArray);
  83. for (let i = 0; i < length; i++) {
  84. newArray[i] = deepCyclicCopyReplaceable(array[i], cycles);
  85. }
  86. return newArray;
  87. }
  88. function deepCyclicCopyMap(map, cycles) {
  89. const newMap = new Map();
  90. cycles.set(map, newMap);
  91. map.forEach((value, key) => {
  92. newMap.set(key, deepCyclicCopyReplaceable(value, cycles));
  93. });
  94. return newMap;
  95. }