{"version":3,"file":"clone.cjs","names":["purry"],"sources":["../src/clone.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types --\n * The state needed to compute the clone is passed by reference via mutable\n * arrays.\n */\n\nimport { purry } from \"./purry\";\n\n/**\n * Creates a deep copy of the value. Supported types: [plain objects](#isPlainObject),\n * `Array`, `number`, `string`, `boolean`, `Date`, and `RegExp`. Functions are\n * assigned by reference rather than copied. Class instances or any other\n * built-in type that isn't mentioned above are not supported (but might\n * work).\n *\n * @param data - The object to clone.\n * @signature\n *   clone(data)\n * @example\n *   clone({foo: 'bar'}) // {foo: 'bar'}\n * @dataFirst\n * @category Object\n */\nexport function clone<T>(data: T): T;\n\n/**\n * Creates a deep copy of the value. Supported types: [plain objects](#isPlainObject),\n * `Array`, `number`, `string`, `boolean`, `Date`, and `RegExp`. Functions are\n * assigned by reference rather than copied. Class instances or any other\n * built-in type that isn't mentioned above are not supported (but might\n * work).\n *\n * @signature\n *   clone()(data)\n * @example\n *   pipe({foo: 'bar'}, clone()) // {foo: 'bar'}\n * @dataLast\n * @category Object\n */\nexport function clone(): <T>(data: T) => T;\n\nexport function clone(...args: readonly unknown[]): unknown {\n  return purry(cloneImplementation, args);\n}\n\nfunction cloneImplementation<T>(\n  value: T,\n  refFrom: unknown[] = [],\n  refTo: unknown[] = [],\n): T {\n  if (typeof value === \"function\") {\n    // Functions aren't cloned, we return the same instance.\n    return value;\n  }\n\n  if (typeof value !== \"object\" || value === null) {\n    // Only objects are interesting when cloning, everything else can use\n    // whatever JS does by default.\n    return structuredClone(value);\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n  const prototype = Object.getPrototypeOf(value);\n  if (\n    !Array.isArray(value) &&\n    // Keep this check in sync with the same check in the impl of\n    // `isPlainObject`.\n    prototype !== null &&\n    prototype !== Object.prototype\n  ) {\n    // Our cloning logic is only designed for plain objects and arrays; other\n    // object types (like `Date`, `RegExp`, `File`, and user-defined classes)\n    // wouldn't clone properly. We fallback to the native cloning for them.\n    return structuredClone(value);\n  }\n\n  // In order to support cyclic/self-referential structures, and to support\n  // functions _within_ objects, we need to have our own cloning logic.\n\n  // First we check if we've already cloned this value.\n  const idx = refFrom.indexOf(value);\n  if (idx !== -1) {\n    return refTo[idx] as T;\n  }\n  // And if we haven't, we add it to our list of seen values so that it is kept\n  // and clone the deep structure.\n  refFrom.push(value);\n  return Array.isArray(value)\n    ? deepCloneArray(value, refFrom, refTo)\n    : deepCloneObject(value, refFrom, refTo);\n}\n\nfunction deepCloneObject<T extends object>(\n  value: T,\n  refFrom: unknown[],\n  refTo: unknown[],\n): T {\n  const copiedValue: Record<PropertyKey, unknown> = {};\n\n  // It's important to first push the cloned ref so that it's index is kept in\n  // sync with the ref to the original value in refFrom.\n  refTo.push(copiedValue);\n\n  for (const [k, v] of Object.entries(value)) {\n    copiedValue[k] = cloneImplementation(v, refFrom, refTo);\n  }\n\n  return copiedValue as T;\n}\n\nfunction deepCloneArray<T extends readonly unknown[]>(\n  value: T,\n  refFrom: unknown[],\n  refTo: unknown[],\n): T {\n  const copiedValue: unknown[] = [];\n\n  // It's important to first push the cloned ref so that it's index is kept in\n  // sync with the ref to the original value in refFrom.\n  refTo.push(copiedValue);\n\n  for (const [index, item] of value.entries()) {\n    copiedValue[index] = cloneImplementation(item, refFrom, refTo);\n  }\n\n  return copiedValue as unknown as T;\n}\n"],"mappings":"kGAwCA,SAAgB,EAAM,GAAG,EAAmC,CAC1D,OAAOA,EAAAA,MAAM,EAAqB,EAAK,CAGzC,SAAS,EACP,EACA,EAAqB,EAAE,CACvB,EAAmB,EAAE,CAClB,CACH,GAAI,OAAO,GAAU,WAEnB,OAAO,EAGT,GAAI,OAAO,GAAU,WAAY,EAG/B,OAAO,gBAAgB,EAAM,CAI/B,IAAM,EAAY,OAAO,eAAe,EAAM,CAC9C,GACE,CAAC,MAAM,QAAQ,EAAM,EAGrB,IAAc,MACd,IAAc,OAAO,UAKrB,OAAO,gBAAgB,EAAM,CAO/B,IAAM,EAAM,EAAQ,QAAQ,EAAM,CAOlC,OANI,IAAQ,IAKZ,EAAQ,KAAK,EAAM,CACZ,MAAM,QAAQ,EAAM,CACvB,EAAe,EAAO,EAAS,EAAM,CACrC,EAAgB,EAAO,EAAS,EAAM,EAPjC,EAAM,GAUjB,SAAS,EACP,EACA,EACA,EACG,CACH,IAAM,EAA4C,EAAE,CAIpD,EAAM,KAAK,EAAY,CAEvB,IAAK,GAAM,CAAC,EAAG,KAAM,OAAO,QAAQ,EAAM,CACxC,EAAY,GAAK,EAAoB,EAAG,EAAS,EAAM,CAGzD,OAAO,EAGT,SAAS,EACP,EACA,EACA,EACG,CACH,IAAM,EAAyB,EAAE,CAIjC,EAAM,KAAK,EAAY,CAEvB,IAAK,GAAM,CAAC,EAAO,KAAS,EAAM,SAAS,CACzC,EAAY,GAAS,EAAoB,EAAM,EAAS,EAAM,CAGhE,OAAO"}