| 530 | |
| 531 | // recurse this function so we don't reset allParents and allChildren |
| 532 | function _clone(parent, depth) { |
| 533 | // cloning null always returns null |
| 534 | if (parent === null) |
| 535 | return null; |
| 536 | |
| 537 | if (depth === 0) |
| 538 | return parent; |
| 539 | |
| 540 | let child; |
| 541 | if (typeof parent != 'object') { |
| 542 | return parent; |
| 543 | } |
| 544 | |
| 545 | if (Array.isArray(parent)) { |
| 546 | child = []; |
| 547 | } else if (parent instanceof RegExp) { |
| 548 | child = new RegExp(parent.source, util.getRegExpFlags(parent)); |
| 549 | if (parent.lastIndex) child.lastIndex = parent.lastIndex; |
| 550 | } else if (parent instanceof Date) { |
| 551 | child = new Date(parent.getTime()); |
| 552 | } else if (Buffer.isBuffer(parent)) { |
| 553 | child = Buffer.alloc(parent.length); |
| 554 | parent.copy(child); |
| 555 | return child; |
| 556 | } else if (parent instanceof RawConfig) { |
| 557 | child = parent; |
| 558 | } else { |
| 559 | if (typeof prototype === 'undefined') child = Object.create(Object.getPrototypeOf(parent)); |
| 560 | else child = Object.create(prototype); |
| 561 | } |
| 562 | |
| 563 | if (circular) { |
| 564 | const index = allParents.indexOf(parent); |
| 565 | |
| 566 | if (index !== -1) { |
| 567 | return allChildren[index]; |
| 568 | } |
| 569 | allParents.push(parent); |
| 570 | allChildren.push(child); |
| 571 | } |
| 572 | |
| 573 | for (const i in parent) { |
| 574 | const propDescriptor = Object.getOwnPropertyDescriptor(parent, i); |
| 575 | const hasGetter = ((typeof propDescriptor !== 'undefined') && (typeof propDescriptor.get !== 'undefined')); |
| 576 | |
| 577 | if (hasGetter) { |
| 578 | Object.defineProperty(child, i, propDescriptor); |
| 579 | } else if (util.isPromise(parent[i])) { |
| 580 | child[i] = parent[i]; |
| 581 | } else { |
| 582 | child[i] = _clone(parent[i], depth - 1); |
| 583 | } |
| 584 | } |
| 585 | |
| 586 | return child; |
| 587 | } |
| 588 | |
| 589 | return _clone(parent, depth); |