summaryrefslogtreecommitdiff
path: root/extensions/web/02_structured_clone.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/web/02_structured_clone.js')
-rw-r--r--extensions/web/02_structured_clone.js73
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);