/**
 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */ import { plugins } from '../pretty-format' ; const builtInObject = [ Array , Date , Float32Array , Float64Array , Int16Array , Int32Array , Int8Array , Map , Set , RegExp , Uint16Array , Uint32Array , Uint8Array , Uint8ClampedArray , ] ; if ( typeof Buffer !== 'undefined' ) { builtInObject . push ( Buffer ) ; } const isBuiltInObject = ( object ) => builtInObject . includes ( object . constructor ) ; const isMap = ( value ) : value is Map < unknown , unknown > => value . constructor === Map ; export default function deepCyclicCopyReplaceable < T > ( value , cycles = new WeakMap ( ) ) { if ( typeof value !== 'object' || value === null ) { return value ; } else if ( cycles . has ( value ) ) { return cycles . get ( value ) ; } else if ( Array . isArray ( value ) ) { return deepCyclicCopyArray ( value , cycles ) ; } else if ( isMap ( value ) ) { return deepCyclicCopyMap ( value , cycles ) ; } else if ( isBuiltInObject ( value ) ) { return value ; } else if ( plugins . DOMElement . test ( value ) ) { return ( value as unknown as Element ) . cloneNode ( true ) as unknown as T ; } else { return deepCyclicCopyObject ( value , cycles ) ; } } function deepCyclicCopyObject < T > ( object , cycles ) { const newObject = Object . create ( Object . getPrototypeOf ( object ) ) ; const descriptors = Object . getOwnPropertyDescriptors ( object ) ; cycles . set ( object , newObject ) ; const newDescriptors = [ ... Object . keys ( descriptors ) , ... Object . getOwnPropertySymbols ( descriptors ) , ] . reduce ( ( newDescriptors , key ) => { const enumerable = descriptors [ key ] . enumerable ; newDescriptors [ key ] = { configurable : true , enumerable , value : deepCyclicCopyReplaceable ( ( object as Record < string | symbol , unknown > ) [ key ] , cycles ) , writable : true , } ; return newDescriptors ; } , { } ) ; return Object . defineProperties ( newObject , newDescriptors ) ; } function deepCyclicCopyArray < T > ( array , cycles ) { const newArray = new ( Object . getPrototypeOf ( array ) . constructor ) ( array . length ) ; const length = array . length ; cycles . set ( array , newArray ) ; for ( let i = 0 ; i < length ; i ++ ) { newArray [ i ] = deepCyclicCopyReplaceable ( array [ i ] , cycles ) ; } return newArray ; } function deepCyclicCopyMap < T > ( map , cycles ) { const newMap = new Map ( ) ; cycles . set ( map , newMap ) ; map . forEach ( ( value , key ) => { newMap . set ( key , deepCyclicCopyReplaceable ( value , cycles ) ) ; } ) ; return newMap as any ; }