chore: workflow internals improvementss (#9455)

This commit is contained in:
Adrien de Peretti
2024-10-10 09:11:56 +02:00
committed by GitHub
parent 1b9379be62
commit 34d57870ad
26 changed files with 354 additions and 206 deletions

View File

@@ -1,36 +1,56 @@
import { isObject } from "./is-object"
import * as util from "node:util"
/**
* In most casees, JSON.parse(JSON.stringify(obj)) is enough to deep copy an object.
* But in some cases, it's not enough. For example, if the object contains a function or a proxy, it will be lost after JSON.parse(JSON.stringify(obj)).
*
* @param obj
* @param cache
*/
export function deepCopy<
T extends Record<any, any> | Record<any, any>[] = Record<any, any>,
TOutput = T extends [] ? T[] : T
>(obj: T): TOutput {
>(obj: T, cache = new WeakMap()): TOutput {
if (obj === null || typeof obj !== "object") {
return obj
return obj as TOutput
}
// Handle circular references with cache
if (cache.has(obj)) {
return cache.get(obj) as TOutput
}
let copy: TOutput
// Handle arrays
if (Array.isArray(obj)) {
const copy: any[] = []
for (let i = 0; i < obj.length; i++) {
copy[i] = deepCopy(obj[i])
}
return copy as TOutput
}
if (isObject(obj)) {
const copy: Record<any, any> = {}
for (let attr in obj) {
if (obj.hasOwnProperty(attr)) {
copy[attr] = deepCopy(obj[attr] as T)
}
}
copy = [] as unknown as TOutput
cache.set(obj, copy) // Add to cache before recursing
;(obj as Array<any>).forEach((item, index) => {
;(copy as Array<any>)[index] = deepCopy(item, cache)
})
return copy
}
return obj
// Handle objects
if (isObject(obj)) {
if (util.types.isProxy(obj)) {
return obj as unknown as TOutput
}
copy = {} as TOutput
cache.set(obj, copy) // Add to cache before recursing
Object.keys(obj).forEach((key) => {
;(copy as Record<any, any>)[key] = deepCopy(
(obj as Record<any, any>)[key],
cache
)
})
return copy
}
return obj as TOutput
}