diff options
Diffstat (limited to 'ext/mixed/js')
| -rw-r--r-- | ext/mixed/js/core.js | 67 | 
1 files changed, 67 insertions, 0 deletions
| diff --git a/ext/mixed/js/core.js b/ext/mixed/js/core.js index 21b7bf5e..9b3ea3e2 100644 --- a/ext/mixed/js/core.js +++ b/ext/mixed/js/core.js @@ -157,6 +157,73 @@ function getSetDifference(set1, set2) {      );  } +const clone = (() => { +    // eslint-disable-next-line no-shadow +    function clone(value) { +        if (value === null) { return null; } +        switch (typeof value) { +            case 'boolean': +            case 'number': +            case 'string': +            case 'bigint': +            case 'symbol': +            case 'undefined': +                return value; +            default: +                return cloneInternal(value, new Set()); +        } +    } + +    function cloneInternal(value, visited) { +        if (value === null) { return null; } +        switch (typeof value) { +            case 'boolean': +            case 'number': +            case 'string': +            case 'bigint': +            case 'symbol': +            case 'undefined': +                return value; +            case 'function': +                return cloneObject(value, visited); +            case 'object': +                return Array.isArray(value) ? cloneArray(value, visited) : cloneObject(value, visited); +        } +    } + +    function cloneArray(value, visited) { +        if (visited.has(value)) { throw new Error('Circular'); } +        try { +            visited.add(value); +            const result = []; +            for (const item of value) { +                result.push(cloneInternal(item, visited)); +            } +            return result; +        } finally { +            visited.delete(value); +        } +    } + +    function cloneObject(value, visited) { +        if (visited.has(value)) { throw new Error('Circular'); } +        try { +            visited.add(value); +            const result = {}; +            for (const key in value) { +                if (Object.prototype.hasOwnProperty.call(value, key)) { +                    result[key] = cloneInternal(value[key], visited); +                } +            } +            return result; +        } finally { +            visited.delete(value); +        } +    } + +    return clone; +})(); +  /*   * Async utilities |