deepCyclicCopy.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = deepCyclicCopy;
  6. /**
  7. * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  8. *
  9. * This source code is licensed under the MIT license found in the
  10. * LICENSE file in the root directory of this source tree.
  11. */
  12. const EMPTY = new Set();
  13. function deepCyclicCopy(
  14. value,
  15. options = {
  16. blacklist: EMPTY,
  17. keepPrototype: false
  18. },
  19. cycles = new WeakMap()
  20. ) {
  21. if (typeof value !== 'object' || value === null) {
  22. return value;
  23. } else if (cycles.has(value)) {
  24. return cycles.get(value);
  25. } else if (Array.isArray(value)) {
  26. return deepCyclicCopyArray(value, options, cycles);
  27. } else {
  28. return deepCyclicCopyObject(value, options, cycles);
  29. }
  30. }
  31. function deepCyclicCopyObject(object, options, cycles) {
  32. const newObject = options.keepPrototype
  33. ? Object.create(Object.getPrototypeOf(object))
  34. : {};
  35. const descriptors = Object.getOwnPropertyDescriptors(object);
  36. cycles.set(object, newObject);
  37. Object.keys(descriptors).forEach(key => {
  38. if (options.blacklist && options.blacklist.has(key)) {
  39. delete descriptors[key];
  40. return;
  41. }
  42. const descriptor = descriptors[key];
  43. if (typeof descriptor.value !== 'undefined') {
  44. descriptor.value = deepCyclicCopy(
  45. descriptor.value,
  46. {
  47. blacklist: EMPTY,
  48. keepPrototype: options.keepPrototype
  49. },
  50. cycles
  51. );
  52. }
  53. descriptor.configurable = true;
  54. });
  55. return Object.defineProperties(newObject, descriptors);
  56. }
  57. function deepCyclicCopyArray(array, options, cycles) {
  58. const newArray = options.keepPrototype
  59. ? new (Object.getPrototypeOf(array).constructor)(array.length)
  60. : [];
  61. const length = array.length;
  62. cycles.set(array, newArray);
  63. for (let i = 0; i < length; i++) {
  64. newArray[i] = deepCyclicCopy(
  65. array[i],
  66. {
  67. blacklist: EMPTY,
  68. keepPrototype: options.keepPrototype
  69. },
  70. cycles
  71. );
  72. }
  73. return newArray;
  74. }