1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-27 16:10:57 -05:00
denoland-deno/ext/web/02_structured_clone.js
2021-08-11 12:27:05 +02:00

85 lines
2.4 KiB
JavaScript

// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
// @ts-check
/// <reference path="../../core/lib.deno_core.d.ts" />
/// <reference path="../../core/internal.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 { DOMException } = window.__bootstrap.domException;
const {
ArrayBuffer,
ArrayBufferIsView,
DataView,
TypedArrayPrototypeSlice,
TypeError,
WeakMap,
WeakMapPrototypeSet,
} = window.__bootstrap.primordials;
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 TypedArrayPrototypeSlice(
srcBuffer,
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,
);
WeakMapPrototypeSet(objectCloneMemo, value, cloned);
return cloned;
}
if (ArrayBufferIsView(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);