mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 16:49:18 -05:00
fix(ext): internal structuredClone
for ArrayBuffer
and TypedArray
subclasses (#17431)
This commit is contained in:
parent
04ba709b6e
commit
266915d5ce
6 changed files with 133 additions and 25 deletions
|
@ -2,6 +2,7 @@
|
|||
import {
|
||||
assert,
|
||||
assertEquals,
|
||||
assertNotStrictEquals,
|
||||
assertStringIncludes,
|
||||
assertThrows,
|
||||
deferred,
|
||||
|
@ -50,6 +51,31 @@ Deno.test(function performanceMark() {
|
|||
assert(markEntries[markEntries.length - 1] === mark);
|
||||
});
|
||||
|
||||
Deno.test(function performanceMarkDetail() {
|
||||
const detail = { foo: "foo" };
|
||||
const mark = performance.mark("test", { detail });
|
||||
assert(mark instanceof PerformanceMark);
|
||||
assertEquals(mark.detail, { foo: "foo" });
|
||||
assertNotStrictEquals(mark.detail, detail);
|
||||
});
|
||||
|
||||
Deno.test(function performanceMarkDetailArrayBuffer() {
|
||||
const detail = new ArrayBuffer(10);
|
||||
const mark = performance.mark("test", { detail });
|
||||
assert(mark instanceof PerformanceMark);
|
||||
assertEquals(mark.detail, new ArrayBuffer(10));
|
||||
assertNotStrictEquals(mark.detail, detail);
|
||||
});
|
||||
|
||||
Deno.test(function performanceMarkDetailSubTypedArray() {
|
||||
class SubUint8Array extends Uint8Array {}
|
||||
const detail = new SubUint8Array([1, 2]);
|
||||
const mark = performance.mark("test", { detail });
|
||||
assert(mark instanceof PerformanceMark);
|
||||
assertEquals(mark.detail, new Uint8Array([1, 2]));
|
||||
assertNotStrictEquals(mark.detail, detail);
|
||||
});
|
||||
|
||||
Deno.test(function performanceMeasure() {
|
||||
const markName1 = "mark1";
|
||||
const measureName1 = "measure1";
|
||||
|
|
|
@ -9,6 +9,7 @@ export {
|
|||
assertFalse,
|
||||
assertMatch,
|
||||
assertNotEquals,
|
||||
assertNotStrictEquals,
|
||||
assertRejects,
|
||||
assertStrictEquals,
|
||||
assertStringIncludes,
|
||||
|
|
23
core/internal.d.ts
vendored
23
core/internal.d.ts
vendored
|
@ -255,8 +255,11 @@ declare namespace __bootstrap {
|
|||
export const ArrayBuffer: typeof globalThis.ArrayBuffer;
|
||||
export const ArrayBufferLength: typeof ArrayBuffer.length;
|
||||
export const ArrayBufferName: typeof ArrayBuffer.name;
|
||||
export const ArrayBufferPrototype: typeof ArrayBuffer.prototype;
|
||||
export const ArrayBufferIsView: typeof ArrayBuffer.isView;
|
||||
export const ArrayBufferPrototype: typeof ArrayBuffer.prototype;
|
||||
export const ArrayBufferPrototypeGetByteLength: (
|
||||
buffer: ArrayBuffer,
|
||||
) => number;
|
||||
export const ArrayBufferPrototypeSlice: UncurryThis<
|
||||
typeof ArrayBuffer.prototype.slice
|
||||
>;
|
||||
|
@ -301,6 +304,11 @@ declare namespace __bootstrap {
|
|||
export const DataViewLength: typeof DataView.length;
|
||||
export const DataViewName: typeof DataView.name;
|
||||
export const DataViewPrototype: typeof DataView.prototype;
|
||||
export const DataViewPrototypeGetBuffer: (
|
||||
view: DataView,
|
||||
) => ArrayBuffer | SharedArrayBuffer;
|
||||
export const DataViewPrototypeGetByteLength: (view: DataView) => number;
|
||||
export const DataViewPrototypeGetByteOffset: (view: DataView) => number;
|
||||
export const DataViewPrototypeGetInt8: UncurryThis<
|
||||
typeof DataView.prototype.getInt8
|
||||
>;
|
||||
|
@ -979,6 +987,19 @@ declare namespace __bootstrap {
|
|||
constructor: Uint8ArrayConstructor,
|
||||
arrayLike: ArrayLike<number>,
|
||||
) => Uint8Array;
|
||||
export const TypedArrayPrototypeGetBuffer: (
|
||||
array: Uint8Array,
|
||||
) => ArrayBuffer | SharedArrayBuffer;
|
||||
export const TypedArrayPrototypeGetByteLength: (
|
||||
array: Uint8Array,
|
||||
) => number;
|
||||
export const TypedArrayPrototypeGetByteOffset: (
|
||||
array: Uint8Array,
|
||||
) => number;
|
||||
export const TypedArrayPrototypeGetLength: (array: Uint8Array) => number;
|
||||
export const TypedArrayPrototypeGetSymbolToStringTag: (
|
||||
v: unknown,
|
||||
) => string | undefined;
|
||||
export const TypedArrayPrototypeCopyWithin: UncurryThis<
|
||||
typeof Uint8Array.prototype.copyWithin
|
||||
>;
|
||||
|
|
|
@ -8,11 +8,9 @@
|
|||
const core = window.Deno.core;
|
||||
const colors = window.__bootstrap.colors;
|
||||
const {
|
||||
ArrayBufferIsView,
|
||||
AggregateErrorPrototype,
|
||||
ArrayPrototypeUnshift,
|
||||
isNaN,
|
||||
DataViewPrototype,
|
||||
DatePrototype,
|
||||
DateNow,
|
||||
DatePrototypeGetTime,
|
||||
|
@ -114,6 +112,7 @@
|
|||
ReflectGetPrototypeOf,
|
||||
ReflectHas,
|
||||
TypedArrayPrototypeGetLength,
|
||||
TypedArrayPrototypeGetSymbolToStringTag,
|
||||
WeakMapPrototype,
|
||||
WeakSetPrototype,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
@ -144,8 +143,7 @@
|
|||
// Forked from Node's lib/internal/cli_table.js
|
||||
|
||||
function isTypedArray(x) {
|
||||
return ArrayBufferIsView(x) &&
|
||||
!ObjectPrototypeIsPrototypeOf(DataViewPrototype, x);
|
||||
return TypedArrayPrototypeGetSymbolToStringTag(x) !== undefined;
|
||||
}
|
||||
|
||||
const tableChars = {
|
||||
|
|
|
@ -14,13 +14,32 @@
|
|||
const {
|
||||
ArrayBuffer,
|
||||
ArrayBufferPrototype,
|
||||
ArrayBufferPrototypeGetByteLength,
|
||||
ArrayBufferPrototypeSlice,
|
||||
ArrayBufferIsView,
|
||||
DataViewPrototype,
|
||||
DataView,
|
||||
DataViewPrototypeGetBuffer,
|
||||
DataViewPrototypeGetByteLength,
|
||||
DataViewPrototypeGetByteOffset,
|
||||
ObjectPrototypeIsPrototypeOf,
|
||||
TypedArrayPrototypeSlice,
|
||||
TypedArrayPrototypeGetBuffer,
|
||||
TypedArrayPrototypeGetByteOffset,
|
||||
TypedArrayPrototypeGetLength,
|
||||
TypedArrayPrototypeGetSymbolToStringTag,
|
||||
TypeErrorPrototype,
|
||||
WeakMap,
|
||||
WeakMapPrototypeSet,
|
||||
Int8Array,
|
||||
Int16Array,
|
||||
Int32Array,
|
||||
BigInt64Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Uint16Array,
|
||||
Uint32Array,
|
||||
BigUint64Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
||||
const objectCloneMemo = new WeakMap();
|
||||
|
@ -32,14 +51,15 @@
|
|||
_cloneConstructor,
|
||||
) {
|
||||
// this function fudges the return type but SharedArrayBuffer is disabled for a while anyway
|
||||
return TypedArrayPrototypeSlice(
|
||||
return ArrayBufferPrototypeSlice(
|
||||
srcBuffer,
|
||||
srcByteOffset,
|
||||
srcByteOffset + srcLength,
|
||||
);
|
||||
}
|
||||
|
||||
/** Clone a value in a similar way to structured cloning. It is similar to a
|
||||
// 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
|
||||
|
@ -48,28 +68,64 @@
|
|||
const cloned = cloneArrayBuffer(
|
||||
value,
|
||||
0,
|
||||
value.byteLength,
|
||||
ArrayBufferPrototypeGetByteLength(value),
|
||||
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 (ObjectPrototypeIsPrototypeOf(DataViewPrototype, view)) {
|
||||
length = value.byteLength;
|
||||
} else {
|
||||
length = value.length;
|
||||
const tag = TypedArrayPrototypeGetSymbolToStringTag(value);
|
||||
// DataView
|
||||
if (tag === undefined) {
|
||||
return new DataView(
|
||||
structuredClone(DataViewPrototypeGetBuffer(value)),
|
||||
DataViewPrototypeGetByteOffset(value),
|
||||
DataViewPrototypeGetByteLength(value),
|
||||
);
|
||||
}
|
||||
return new (value.constructor)(
|
||||
clonedBuffer,
|
||||
value.byteOffset,
|
||||
length,
|
||||
// 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;
|
||||
}
|
||||
return new Constructor(
|
||||
structuredClone(TypedArrayPrototypeGetBuffer(value)),
|
||||
TypedArrayPrototypeGetByteOffset(value),
|
||||
TypedArrayPrototypeGetLength(value),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
Symbol,
|
||||
SymbolIterator,
|
||||
SymbolToStringTag,
|
||||
TypedArrayPrototypeGetSymbolToStringTag,
|
||||
TypeError,
|
||||
Uint16Array,
|
||||
Uint32Array,
|
||||
|
@ -442,6 +443,11 @@
|
|||
return V;
|
||||
}
|
||||
|
||||
function isDataView(V) {
|
||||
return ArrayBufferIsView(V) &&
|
||||
TypedArrayPrototypeGetSymbolToStringTag(V) === undefined;
|
||||
}
|
||||
|
||||
function isNonSharedArrayBuffer(V) {
|
||||
return ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V);
|
||||
}
|
||||
|
@ -467,7 +473,7 @@
|
|||
};
|
||||
|
||||
converters.DataView = (V, opts = {}) => {
|
||||
if (!(ObjectPrototypeIsPrototypeOf(DataViewPrototype, V))) {
|
||||
if (!isDataView(V)) {
|
||||
throw makeException(TypeError, "is not a DataView", opts);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue