Skip to content

Commit 255977c

Browse files
committed
util: add isArrayBufferDetached method
1 parent c74dbd2 commit 255977c

File tree

6 files changed

+53
-19
lines changed

6 files changed

+53
-19
lines changed

Diff for: doc/api/util.md

+17
Original file line numberDiff line numberDiff line change
@@ -2024,6 +2024,23 @@ util.types.isAnyArrayBuffer(new ArrayBuffer()); // Returns true
20242024
util.types.isAnyArrayBuffer(new SharedArrayBuffer()); // Returns true
20252025
```
20262026
2027+
### `util.types.isArrayBufferDetached(value)`
2028+
2029+
<!-- YAML
2030+
added: REPLACEME
2031+
-->
2032+
2033+
* `value` {any}
2034+
* Returns: {boolean}
2035+
2036+
Returns `true` if the value is a built-in [`ArrayBuffer`][] and
2037+
is detached.
2038+
2039+
```js
2040+
util.types.isArrayBufferDetached(null); // Returns false
2041+
util.types.isArrayBufferDetached(new ArrayBuffer()); // Returns false
2042+
```
2043+
20272044
### `util.types.isArrayBufferView(value)`
20282045
20292046
<!-- YAML

Diff for: lib/internal/util/types.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@
22

33
const {
44
ArrayBufferIsView,
5+
ArrayBufferPrototype,
56
ObjectDefineProperties,
7+
ReflectGet,
68
TypedArrayPrototypeGetSymbolToStringTag,
79
} = primordials;
810

11+
const { isArrayBufferDetached: _isArrayBufferDetached, ...internalTypes } = internalBinding('types');
12+
13+
function ArrayBufferGetByteLength(view) {
14+
return ReflectGet(ArrayBufferPrototype, 'byteLength', view);
15+
}
16+
917
function isTypedArray(value) {
1018
return TypedArrayPrototypeGetSymbolToStringTag(value) !== undefined;
1119
}
@@ -54,8 +62,16 @@ function isBigUint64Array(value) {
5462
return TypedArrayPrototypeGetSymbolToStringTag(value) === 'BigUint64Array';
5563
}
5664

65+
function isArrayBufferDetached(value) {
66+
if (ArrayBufferGetByteLength(value) === 0) {
67+
return _isArrayBufferDetached(value);
68+
}
69+
return false;
70+
}
71+
5772
module.exports = {
58-
...internalBinding('types'),
73+
...internalTypes,
74+
isArrayBufferDetached,
5975
isArrayBufferView: ArrayBufferIsView,
6076
isTypedArray,
6177
isUint8Array,

Diff for: lib/internal/webstreams/readablestream.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const {
4343
} = internalBinding('messaging');
4444

4545
const {
46+
isArrayBufferDetached,
4647
isArrayBufferView,
4748
isDataView,
4849
} = require('internal/util/types');
@@ -104,7 +105,6 @@ const {
104105
extractHighWaterMark,
105106
extractSizeAlgorithm,
106107
lazyTransfer,
107-
isDetachedBuffer,
108108
isViewedArrayBufferDetached,
109109
isBrandCheck,
110110
resetQueue,
@@ -669,7 +669,7 @@ class ReadableStreamBYOBRequest {
669669
const viewBuffer = ArrayBufferViewGetBuffer(view);
670670
const viewBufferByteLength = ArrayBufferGetByteLength(viewBuffer);
671671

672-
if (isDetachedBuffer(viewBuffer)) {
672+
if (isArrayBufferDetached(viewBuffer)) {
673673
throw new ERR_INVALID_STATE.TypeError('Viewed ArrayBuffer is detached');
674674
}
675675

@@ -2643,7 +2643,7 @@ function readableByteStreamControllerEnqueue(controller, chunk) {
26432643
if (pendingPullIntos.length) {
26442644
const firstPendingPullInto = pendingPullIntos[0];
26452645

2646-
if (isDetachedBuffer(firstPendingPullInto.buffer)) {
2646+
if (isArrayBufferDetached(firstPendingPullInto.buffer)) {
26472647
throw new ERR_INVALID_STATE.TypeError(
26482648
'Destination ArrayBuffer is detached',
26492649
);

Diff for: lib/internal/webstreams/util.js

+2-15
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const {
3232
} = internalBinding('buffer');
3333

3434
const {
35+
isArrayBufferDetached,
3536
isPromise,
3637
} = require('internal/util/types');
3738

@@ -139,23 +140,10 @@ function transferArrayBuffer(buffer) {
139140
return res;
140141
}
141142

142-
function isDetachedBuffer(buffer) {
143-
if (ArrayBufferGetByteLength(buffer) === 0) {
144-
// TODO(daeyeon): Consider using C++ builtin to improve performance.
145-
try {
146-
new Uint8Array(buffer);
147-
} catch (error) {
148-
assert(error.name === 'TypeError');
149-
return true;
150-
}
151-
}
152-
return false;
153-
}
154-
155143
function isViewedArrayBufferDetached(view) {
156144
return (
157145
ArrayBufferViewGetByteLength(view) === 0 &&
158-
isDetachedBuffer(ArrayBufferViewGetBuffer(view))
146+
isArrayBufferDetached(ArrayBufferViewGetBuffer(view))
159147
);
160148
}
161149

@@ -256,7 +244,6 @@ module.exports = {
256244
extractSizeAlgorithm,
257245
lazyTransfer,
258246
isBrandCheck,
259-
isDetachedBuffer,
260247
isPromisePending,
261248
isViewedArrayBufferDetached,
262249
peekQueueValue,

Diff for: src/node_types.cc

+13
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ static void IsBoxedPrimitive(const FunctionCallbackInfo<Value>& args) {
6161
args[0]->IsSymbolObject());
6262
}
6363

64+
static void IsArrayBufferDetached(const FunctionCallbackInfo<Value>& args) {
65+
if (args[0]->IsArrayBuffer()) {
66+
auto buffer = args[0].As<v8::ArrayBuffer>();
67+
args.GetReturnValue().Set(buffer->WasDetached());
68+
return;
69+
}
70+
71+
args.GetReturnValue().Set(false);
72+
}
73+
6474
void InitializeTypes(Local<Object> target,
6575
Local<Value> unused,
6676
Local<Context> context,
@@ -71,6 +81,8 @@ void InitializeTypes(Local<Object> target,
7181

7282
SetMethodNoSideEffect(context, target, "isAnyArrayBuffer", IsAnyArrayBuffer);
7383
SetMethodNoSideEffect(context, target, "isBoxedPrimitive", IsBoxedPrimitive);
84+
SetMethodNoSideEffect(
85+
context, target, "isArrayBufferDetached", IsArrayBufferDetached);
7486
}
7587

7688
} // anonymous namespace
@@ -82,6 +94,7 @@ void RegisterTypesExternalReferences(ExternalReferenceRegistry* registry) {
8294

8395
registry->Register(IsAnyArrayBuffer);
8496
registry->Register(IsBoxedPrimitive);
97+
registry->Register(IsArrayBufferDetached);
8598
}
8699
} // namespace node
87100

Diff for: typings/internalBinding/types.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ declare function InternalBinding(binding: 'types'): {
55
isArrayBuffer(value: unknown): value is ArrayBuffer;
66
isArgumentsObject(value: unknown): value is ArrayLike<unknown>;
77
isBoxedPrimitive(value: unknown): value is (BigInt | Boolean | Number | String | Symbol);
8+
isArrayBufferDetached(value: unknown): boolean;
89
isDataView(value: unknown): value is DataView;
910
isExternal(value: unknown): value is Object;
1011
isMap(value: unknown): value is Map<unknown, unknown>;

0 commit comments

Comments
 (0)