Skip to content

Commit 9f4da15

Browse files
committed
util: add isArrayBufferDetached method
1 parent c74dbd2 commit 9f4da15

File tree

5 files changed

+37
-18
lines changed

5 files changed

+37
-18
lines changed

doc/api/util.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,23 @@ useful for addon developers who prefer to do type checking in JavaScript.
20042004
20052005
The API is accessible via `require('node:util').types` or `require('node:util/types')`.
20062006
2007+
### `util.types.isArrayBufferDetached(value)`
2008+
2009+
<!-- YAML
2010+
added: REPLACEME
2011+
-->
2012+
2013+
* `value` {any}
2014+
* Returns: {boolean}
2015+
2016+
Returns `true` if the value is a built-in [`ArrayBuffer`][] and
2017+
is detached.
2018+
2019+
```js
2020+
util.types.isArrayBufferDetached(null); // Returns false
2021+
util.types.isArrayBufferDetached(new ArrayBuffer()); // Returns false
2022+
```
2023+
20072024
### `util.types.isAnyArrayBuffer(value)`
20082025
20092026
<!-- YAML

lib/internal/webstreams/readablestream.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ const {
104104
extractHighWaterMark,
105105
extractSizeAlgorithm,
106106
lazyTransfer,
107-
isDetachedBuffer,
108107
isViewedArrayBufferDetached,
109108
isBrandCheck,
110109
resetQueue,
@@ -117,6 +116,8 @@ const {
117116
kState,
118117
} = require('internal/webstreams/util');
119118

119+
const { isArrayBufferDetached } = require('internal/util/types')
120+
120121
const {
121122
WritableStreamDefaultWriter,
122123

@@ -669,7 +670,7 @@ class ReadableStreamBYOBRequest {
669670
const viewBuffer = ArrayBufferViewGetBuffer(view);
670671
const viewBufferByteLength = ArrayBufferGetByteLength(viewBuffer);
671672

672-
if (isDetachedBuffer(viewBuffer)) {
673+
if (isArrayBufferDetached(viewBuffer)) {
673674
throw new ERR_INVALID_STATE.TypeError('Viewed ArrayBuffer is detached');
674675
}
675676

@@ -2643,7 +2644,7 @@ function readableByteStreamControllerEnqueue(controller, chunk) {
26432644
if (pendingPullIntos.length) {
26442645
const firstPendingPullInto = pendingPullIntos[0];
26452646

2646-
if (isDetachedBuffer(firstPendingPullInto.buffer)) {
2647+
if (isArrayBufferDetached(firstPendingPullInto.buffer)) {
26472648
throw new ERR_INVALID_STATE.TypeError(
26482649
'Destination ArrayBuffer is detached',
26492650
);

lib/internal/webstreams/util.js

Lines changed: 2 additions & 15 deletions
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,

src/node_types.cc

Lines changed: 13 additions & 0 deletions
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

typings/internalBinding/types.d.ts

Lines changed: 1 addition & 0 deletions
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)