diff options
Diffstat (limited to 'extensions/web/02_structured_clone.js')
-rw-r--r-- | extensions/web/02_structured_clone.js | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/extensions/web/02_structured_clone.js b/extensions/web/02_structured_clone.js new file mode 100644 index 000000000..2170095d9 --- /dev/null +++ b/extensions/web/02_structured_clone.js @@ -0,0 +1,73 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +// @ts-check +/// <reference path="../../core/lib.deno_core.d.ts" /> +/// <reference path="../web/internal.d.ts" /> +/// <reference path="../web/lib.deno_web.d.ts" /> + +"use strict"; + +((window) => { + const core = window.Deno.core; + + const objectCloneMemo = new WeakMap(); + + function cloneArrayBuffer( + srcBuffer, + srcByteOffset, + srcLength, + _cloneConstructor, + ) { + // this function fudges the return type but SharedArrayBuffer is disabled for a while anyway + return srcBuffer.slice( + srcByteOffset, + srcByteOffset + srcLength, + ); + } + + /** Clone a value in a similar way to structured cloning. It is similar to a +* StructureDeserialize(StructuredSerialize(...)). */ + function structuredClone(value) { + // Performance optimization for buffers, otherwise + // `serialize/deserialize` will allocate new buffer. + if (value instanceof ArrayBuffer) { + const cloned = cloneArrayBuffer( + value, + 0, + value.byteLength, + ArrayBuffer, + ); + objectCloneMemo.set(value, cloned); + return cloned; + } + if (ArrayBuffer.isView(value)) { + const clonedBuffer = structuredClone(value.buffer); + // Use DataViewConstructor type purely for type-checking, can be a + // DataView or TypedArray. They use the same constructor signature, + // only DataView has a length in bytes and TypedArrays use a length in + // terms of elements, so we adjust for that. + let length; + if (value instanceof DataView) { + length = value.byteLength; + } else { + length = value.length; + } + return new (value.constructor)( + clonedBuffer, + value.byteOffset, + length, + ); + } + + try { + return core.deserialize(core.serialize(value)); + } catch (e) { + if (e instanceof TypeError) { + throw new DOMException("Uncloneable value", "DataCloneError"); + } + throw e; + } + } + + window.__bootstrap.structuredClone = structuredClone; +})(globalThis); |