Skip to content

Commit

Permalink
Fix to check whether buffers are detached or not
Browse files Browse the repository at this point in the history
  • Loading branch information
petamoriken committed Oct 29, 2021
1 parent e113ee8 commit eab3453
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 15 deletions.
50 changes: 38 additions & 12 deletions src/Float16Array.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
OFFSET_IS_OUT_OF_BOUNDS,
REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE,
SPECIESCONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY,
THIS_BUFFER_HAS_ALREADY_BEEN_DETACHED,
THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY,
THIS_IS_NOT_A_FLOAT16ARRAY,
} from "./_util/messages.mjs";
Expand Down Expand Up @@ -73,6 +74,7 @@ import {
WeakMapPrototypeSet,
} from "./_util/primordials.mjs";
import {
IsDetachedBuffer,
LengthOfArrayLike,
SpeciesConstructor,
ToIntegerOrInfinity,
Expand All @@ -84,7 +86,7 @@ const BYTES_PER_ELEMENT = 2;
const brand = SymbolFor("__Float16Array__");

/** @type {WeakMap<Float16Array, Uint16Array & { __float16bits: never }>} */
const targets = new NativeWeakMap();
const float16bitsArrays = new NativeWeakMap();

/**
* @param {unknown} target
Expand Down Expand Up @@ -171,9 +173,18 @@ function assertSpeciesTypedArray(target, count) {
* @returns {Uint16Array & { __float16bits: never }}
*/
function getFloat16BitsArray(float16) {
const target = WeakMapPrototypeGet(targets, float16);
if (target !== undefined) {
return target;
const float16bitsArray = WeakMapPrototypeGet(float16bitsArrays, float16);
if (float16bitsArray !== undefined) {
const buffer = TypedArrayPrototypeGetBuffer(float16bitsArray);
if (IsDetachedBuffer(buffer)) {
throw NativeTypeError(THIS_BUFFER_HAS_ALREADY_BEEN_DETACHED);
}
return float16bitsArray;
}

// @ts-ignore
if (IsDetachedBuffer(float16.buffer)) {
throw NativeTypeError(THIS_BUFFER_HAS_ALREADY_BEEN_DETACHED);
}

// from another Float16Array instance (a different version?)
Expand All @@ -185,7 +196,7 @@ function getFloat16BitsArray(float16) {
// @ts-ignore
float16.length,
], float16.constructor);
return WeakMapPrototypeGet(targets, cloned);
return WeakMapPrototypeGet(float16bitsArrays, cloned);
}

/**
Expand Down Expand Up @@ -256,12 +267,6 @@ export class Float16Array {
let length;

if (isTypedArray(input)) { // TypedArray
if (isBigIntTypedArray(input)) {
throw NativeTypeError(
CANNOT_MIX_BIGINT_AND_OTHER_TYPES
);
}

list = input;
length = TypedArrayPrototypeGetLength(input);

Expand All @@ -272,6 +277,15 @@ export class Float16Array {
NativeArrayBuffer
))
: NativeArrayBuffer;

if (IsDetachedBuffer(buffer)) {
throw NativeTypeError(THIS_BUFFER_HAS_ALREADY_BEEN_DETACHED);
}

if (isBigIntTypedArray(input)) {
throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES);
}

const data = new BufferConstructor(
length * BYTES_PER_ELEMENT
);
Expand Down Expand Up @@ -304,7 +318,7 @@ export class Float16Array {
const proxy = new NativeProxy(/** @type {any} */ (float16bitsArray), handler);

// proxy private storage
WeakMapPrototypeSet(targets, proxy, float16bitsArray);
WeakMapPrototypeSet(float16bitsArrays, proxy, float16bitsArray);

return proxy;
}
Expand Down Expand Up @@ -775,6 +789,13 @@ export class Float16Array {
);
}

if (isTypedArray(input)) {
const buffer = TypedArrayPrototypeGetBuffer(input);
if (IsDetachedBuffer(buffer)) {
throw NativeTypeError(THIS_BUFFER_HAS_ALREADY_BEEN_DETACHED);
}
}

const targetLength = TypedArrayPrototypeGetLength(float16bitsArray);

const src = NativeObject(input);
Expand Down Expand Up @@ -887,6 +908,11 @@ export class Float16Array {
return array;
}

const buffer = TypedArrayPrototypeGetBuffer(float16bitsArray);
if (IsDetachedBuffer(buffer)) {
throw NativeTypeError(THIS_BUFFER_HAS_ALREADY_BEEN_DETACHED);
}

let n = 0;
while (k < final) {
array[n] = convertToNumber(float16bitsArray[k]);
Expand Down
22 changes: 19 additions & 3 deletions src/_util/is.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
ArrayBufferPrototypeGetByteLength,
ArrayIsArray,
MathTrunc,
NativeNumber,
NativeSharedArrayBuffer,
NumberIsFinite,
SharedArrayBufferPrototypeGetByteLength,
SymbolIterator,
SymbolToStringTag,
TypedArrayPrototypeGetSymbolToStringTag,
Expand Down Expand Up @@ -51,16 +54,29 @@ export function isBigIntTypedArray(value) {
* @returns {value is ArrayBuffer}
*/
export function isArrayBuffer(value) {
return isObjectLike(value) && value[SymbolToStringTag] === "ArrayBuffer";
try {
ArrayBufferPrototypeGetByteLength(/** @type {any} */ (value));
return true;
} catch (e) {
return false;
}
}

/**
* @param {unknown} value
* @returns {value is SharedArrayBuffer}
*/
export function isSharedArrayBuffer(value) {
return isObjectLike(value) &&
value[SymbolToStringTag] === "SharedArrayBuffer";
if (NativeSharedArrayBuffer === null) {
return false;
}

try {
SharedArrayBufferPrototypeGetByteLength(/** @type {any} */ (value));
return true;
} catch (e) {
return false;
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/_util/messages.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const SPECIESCONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY =
"SpeciesConstructor didn't return TypedArray";
export const DERIVED_TYPEDARRAY_CONSTRUCTOR_CREATED_AN_ARRAY_WHICH_WAS_TOO_SMALL =
"Derived TypedArray constructor created an array which was too small";
export const THIS_BUFFER_HAS_ALREADY_BEEN_DETACHED = "This buffer has already been detached";
export const CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT =
"Cannot convert undefined or null to object";
export const CANNOT_CONVERT_A_BIGINT_VALUE_TO_A_NUMBER =
Expand Down
14 changes: 14 additions & 0 deletions src/_util/primordials.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-restricted-globals */
/* global SharedArrayBuffer */

const { bind, call } = Function.prototype;

Expand Down Expand Up @@ -76,6 +77,19 @@ export const MathTrunc = Math.trunc;

// ArrayBuffer
export const NativeArrayBuffer = ArrayBuffer;
/** @type {(buffer: ArrayBuffer, begin: number, end?: number) => number} */
export const ArrayBufferPrototypeSlice = uncurryThis(NativeArrayBuffer.prototype.slice);
/** @type {(buffer: ArrayBuffer) => ArrayBuffer} */
export const ArrayBufferPrototypeGetByteLength = uncurryThisGetter(NativeArrayBuffer.prototype, "byteLength");

// SharedArrayBuffer
export const NativeSharedArrayBuffer = typeof SharedArrayBuffer !== "undefined" ? SharedArrayBuffer : null;
/** @type {(buffer: SharedArrayBuffer, begin: number, end?: number) => number} */
export const SharedArrayBufferPrototypeSlice = NativeSharedArrayBuffer
&& uncurryThis(NativeSharedArrayBuffer.prototype.slice);
/** @type {(buffer: SharedArrayBuffer) => SharedArrayBuffer} */
export const SharedArrayBufferPrototypeGetByteLength = NativeSharedArrayBuffer
&& uncurryThisGetter(NativeSharedArrayBuffer.prototype, "byteLength");

// TypedArray
/** @typedef {Uint8Array|Uint8ClampedArray|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array|BigUint64Array|BigInt64Array} TypedArray */
Expand Down
24 changes: 24 additions & 0 deletions src/_util/spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import {
THIS_IS_NOT_A_OBJECT,
} from "./messages.mjs";
import {
ArrayBufferPrototypeSlice,
MathTrunc,
NativeNumber,
NativeSharedArrayBuffer,
NativeTypeError,
NumberIsNaN,
ObjectIs,
SharedArrayBufferPrototypeSlice,
SymbolSpecies,
} from "./primordials.mjs";

Expand Down Expand Up @@ -88,6 +91,27 @@ export function SpeciesConstructor(target, defaultConstructor) {
return species;
}

/**
* @see https://tc39.es/ecma262/#sec-isdetachedbuffer
* @param {ArrayBuffer | SharedArrayBuffer} buffer
* @returns {boolean}
*/
export function IsDetachedBuffer(buffer) {
try {
ArrayBufferPrototypeSlice(buffer, 0, 0);
return false;
} catch (e) {/* empty */}

if (NativeSharedArrayBuffer !== null) {
try {
SharedArrayBufferPrototypeSlice(/** @type {SharedArrayBuffer} */ (buffer), 0, 0);
return false;
} catch (e) {/* empty */}
}

return true;
}

/**
* bigint comparisons are not supported
*
Expand Down

0 comments on commit eab3453

Please sign in to comment.