2024-01-01 19:58:21 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2021-06-07 12:19:33 +00:00
|
|
|
|
|
|
|
// @ts-check
|
|
|
|
/// <reference path="../../core/lib.deno_core.d.ts" />
|
2021-07-06 12:38:12 +00:00
|
|
|
/// <reference path="../../core/internal.d.ts" />
|
2021-06-07 12:19:33 +00:00
|
|
|
/// <reference path="../web/internal.d.ts" />
|
|
|
|
/// <reference path="../web/lib.deno_web.d.ts" />
|
|
|
|
|
2023-12-07 13:21:01 +00:00
|
|
|
import { core, primordials } from "ext:core/mod.js";
|
2024-01-10 22:37:25 +00:00
|
|
|
const {
|
|
|
|
isArrayBuffer,
|
|
|
|
} = core;
|
2023-02-07 19:22:46 +00:00
|
|
|
const {
|
|
|
|
ArrayBuffer,
|
|
|
|
ArrayBufferPrototypeGetByteLength,
|
|
|
|
ArrayBufferPrototypeSlice,
|
|
|
|
ArrayBufferIsView,
|
|
|
|
DataView,
|
|
|
|
DataViewPrototypeGetBuffer,
|
|
|
|
DataViewPrototypeGetByteLength,
|
|
|
|
DataViewPrototypeGetByteOffset,
|
|
|
|
ObjectPrototypeIsPrototypeOf,
|
2023-04-14 20:23:28 +00:00
|
|
|
SafeWeakMap,
|
2023-02-07 19:22:46 +00:00
|
|
|
TypedArrayPrototypeGetBuffer,
|
|
|
|
TypedArrayPrototypeGetByteOffset,
|
|
|
|
TypedArrayPrototypeGetLength,
|
|
|
|
TypedArrayPrototypeGetSymbolToStringTag,
|
|
|
|
TypeErrorPrototype,
|
|
|
|
WeakMapPrototypeSet,
|
|
|
|
Int8Array,
|
|
|
|
Int16Array,
|
|
|
|
Int32Array,
|
|
|
|
BigInt64Array,
|
|
|
|
Uint8Array,
|
|
|
|
Uint8ClampedArray,
|
|
|
|
Uint16Array,
|
|
|
|
Uint32Array,
|
|
|
|
BigUint64Array,
|
|
|
|
Float32Array,
|
|
|
|
Float64Array,
|
|
|
|
} = primordials;
|
2024-01-10 22:37:25 +00:00
|
|
|
|
|
|
|
import { DOMException } from "ext:deno_web/01_dom_exception.js";
|
2021-06-07 12:19:33 +00:00
|
|
|
|
2023-04-14 20:23:28 +00:00
|
|
|
const objectCloneMemo = new SafeWeakMap();
|
2021-06-07 12:19:33 +00:00
|
|
|
|
2023-02-07 19:22:46 +00:00
|
|
|
function cloneArrayBuffer(
|
|
|
|
srcBuffer,
|
|
|
|
srcByteOffset,
|
|
|
|
srcLength,
|
|
|
|
_cloneConstructor,
|
|
|
|
) {
|
|
|
|
// this function fudges the return type but SharedArrayBuffer is disabled for a while anyway
|
|
|
|
return ArrayBufferPrototypeSlice(
|
2021-06-07 12:19:33 +00:00
|
|
|
srcBuffer,
|
|
|
|
srcByteOffset,
|
2023-02-07 19:22:46 +00:00
|
|
|
srcByteOffset + srcLength,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(petamoriken): Resizable ArrayBuffer support in the future
|
|
|
|
/** 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.
|
2024-01-04 04:12:38 +00:00
|
|
|
if (isArrayBuffer(value)) {
|
2023-02-07 19:22:46 +00:00
|
|
|
const cloned = cloneArrayBuffer(
|
|
|
|
value,
|
|
|
|
0,
|
|
|
|
ArrayBufferPrototypeGetByteLength(value),
|
|
|
|
ArrayBuffer,
|
2021-06-07 12:19:33 +00:00
|
|
|
);
|
2023-02-07 19:22:46 +00:00
|
|
|
WeakMapPrototypeSet(objectCloneMemo, value, cloned);
|
|
|
|
return cloned;
|
2021-06-07 12:19:33 +00:00
|
|
|
}
|
|
|
|
|
2023-02-07 19:22:46 +00:00
|
|
|
if (ArrayBufferIsView(value)) {
|
|
|
|
const tag = TypedArrayPrototypeGetSymbolToStringTag(value);
|
|
|
|
// DataView
|
|
|
|
if (tag === undefined) {
|
|
|
|
return new DataView(
|
|
|
|
structuredClone(DataViewPrototypeGetBuffer(value)),
|
|
|
|
DataViewPrototypeGetByteOffset(value),
|
|
|
|
DataViewPrototypeGetByteLength(value),
|
2021-06-07 12:19:33 +00:00
|
|
|
);
|
|
|
|
}
|
2023-02-07 19:22:46 +00:00
|
|
|
// TypedArray
|
|
|
|
let Constructor;
|
|
|
|
switch (tag) {
|
|
|
|
case "Int8Array":
|
|
|
|
Constructor = Int8Array;
|
|
|
|
break;
|
|
|
|
case "Int16Array":
|
|
|
|
Constructor = Int16Array;
|
|
|
|
break;
|
|
|
|
case "Int32Array":
|
|
|
|
Constructor = Int32Array;
|
|
|
|
break;
|
|
|
|
case "BigInt64Array":
|
|
|
|
Constructor = BigInt64Array;
|
|
|
|
break;
|
|
|
|
case "Uint8Array":
|
|
|
|
Constructor = Uint8Array;
|
|
|
|
break;
|
|
|
|
case "Uint8ClampedArray":
|
|
|
|
Constructor = Uint8ClampedArray;
|
|
|
|
break;
|
|
|
|
case "Uint16Array":
|
|
|
|
Constructor = Uint16Array;
|
|
|
|
break;
|
|
|
|
case "Uint32Array":
|
|
|
|
Constructor = Uint32Array;
|
|
|
|
break;
|
|
|
|
case "BigUint64Array":
|
|
|
|
Constructor = BigUint64Array;
|
|
|
|
break;
|
|
|
|
case "Float32Array":
|
|
|
|
Constructor = Float32Array;
|
|
|
|
break;
|
|
|
|
case "Float64Array":
|
|
|
|
Constructor = Float64Array;
|
|
|
|
break;
|
2021-06-07 12:19:33 +00:00
|
|
|
}
|
2023-02-07 19:22:46 +00:00
|
|
|
return new Constructor(
|
|
|
|
structuredClone(TypedArrayPrototypeGetBuffer(value)),
|
|
|
|
TypedArrayPrototypeGetByteOffset(value),
|
|
|
|
TypedArrayPrototypeGetLength(value),
|
|
|
|
);
|
|
|
|
}
|
2021-06-07 12:19:33 +00:00
|
|
|
|
2023-02-07 19:22:46 +00:00
|
|
|
try {
|
|
|
|
return core.deserialize(core.serialize(value));
|
|
|
|
} catch (e) {
|
|
|
|
if (ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e)) {
|
|
|
|
throw new DOMException(e.message, "DataCloneError");
|
2021-06-07 12:19:33 +00:00
|
|
|
}
|
2023-02-07 19:22:46 +00:00
|
|
|
throw e;
|
2021-06-07 12:19:33 +00:00
|
|
|
}
|
2023-02-07 19:22:46 +00:00
|
|
|
}
|
2021-06-07 12:19:33 +00:00
|
|
|
|
2023-02-07 19:22:46 +00:00
|
|
|
export { structuredClone };
|