import { ObjectDefineProperty as define, ReflectApply as apply, SymbolIterator, TypeError, } from "ext:core/primordials"; import { clone } from "ext:core/structured_clone"; import { array, dictionary, isObject, required } from "ext:web/idl.js"; import { classify, setStructuredClone, transferCallbacks, } from "ext:web/serialization.js"; import { dataCloneError } from "ext:web/events.js"; const structuredClone = { structuredClone(value: unknown, options: unknown = undefined): unknown { required(arguments.length, 1); const raw = dictionary(options).transfer, transfer = array(); if (raw !== undefined) { if (!isObject(raw)) { throw new TypeError("Transfer list must be a sequence"); } const method = raw[SymbolIterator]; if (typeof method !== "function") { throw new TypeError("Transfer list must be iterable"); } const iterator = apply(method, raw, []); if (!isObject(iterator)) throw new TypeError("Invalid transfer iterator"); const next = iterator.next; if (typeof next !== "function") { throw new TypeError("Invalid transfer iterator next method"); } while (true) { const step = apply(next, iterator, []); if (!isObject(step)) { throw new TypeError("Invalid transfer iterator result"); } if (step.done) break; const item = step.value; if (!isObject(item)) { throw new TypeError("Transfer entries must be objects"); } transfer[transfer.length] = item; } } const callbacks = transferCallbacks(transfer, dataCloneError); try { return clone( value, transfer, classify, callbacks.cloneHost, dataCloneError, callbacks.prepare, callbacks.validate, callbacks.commit, ); } finally { callbacks.clear(); } }, }.structuredClone; define(globalThis, "structuredClone", { value: structuredClone, writable: true, configurable: true, enumerable: true, }); setStructuredClone(structuredClone); export { structuredClone };