diff options
author | Kenta Moriuchi <moriken@kimamass.com> | 2023-01-29 23:15:01 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-29 15:15:01 +0100 |
commit | 266915d5ce354fde12b20f8f5ceb5ffdfacb7983 (patch) | |
tree | 8787d5b36ede178cd691492c5fdaab6b686b9f5f /ext | |
parent | 04ba709b6ec994fd084e0d09ff9edc9df3a1eefc (diff) |
fix(ext): internal `structuredClone` for `ArrayBuffer` and `TypedArray` subclasses (#17431)
Diffstat (limited to 'ext')
-rw-r--r-- | ext/console/02_console.js | 6 | ||||
-rw-r--r-- | ext/web/02_structured_clone.js | 94 | ||||
-rw-r--r-- | ext/webidl/00_webidl.js | 8 |
3 files changed, 84 insertions, 24 deletions
diff --git a/ext/console/02_console.js b/ext/console/02_console.js index 9b898a040..1720fe7e2 100644 --- a/ext/console/02_console.js +++ b/ext/console/02_console.js @@ -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 = { diff --git a/ext/web/02_structured_clone.js b/ext/web/02_structured_clone.js index f8a88a7ef..793cb1c75 100644 --- a/ext/web/02_structured_clone.js +++ b/ext/web/02_structured_clone.js @@ -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), + ); + } + // 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 (value.constructor)( - clonedBuffer, - value.byteOffset, - length, + return new Constructor( + structuredClone(TypedArrayPrototypeGetBuffer(value)), + TypedArrayPrototypeGetByteOffset(value), + TypedArrayPrototypeGetLength(value), ); } diff --git a/ext/webidl/00_webidl.js b/ext/webidl/00_webidl.js index 4127d24bf..bb90d973e 100644 --- a/ext/webidl/00_webidl.js +++ b/ext/webidl/00_webidl.js @@ -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); } |