diff --git a/lib/internal/util.js b/lib/internal/util.js index 5eb6598d6a0db6..b6fab1187960ec 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -1,6 +1,7 @@ 'use strict'; const { + ArrayBufferPrototypeGetByteLength, ArrayFrom, ArrayIsArray, ArrayPrototypePush, @@ -42,6 +43,7 @@ const { } = require('internal/errors'); const { signals } = internalBinding('constants').os; const { + isArrayBufferDetached: _isArrayBufferDetached, privateSymbols: { arrow_message_private_symbol, decorated_private_symbol, @@ -557,6 +559,14 @@ function SideEffectFreeRegExpPrototypeExec(regex, string) { return FunctionPrototypeCall(RegExpFromAnotherRealm.prototype.exec, regex, string); } +function isArrayBufferDetached(value) { + if (ArrayBufferPrototypeGetByteLength(value) === 0) { + return _isArrayBufferDetached(value); + } + + return false; +} + module.exports = { assertCrypto, cachedResult, @@ -574,6 +584,7 @@ module.exports = { getInternalGlobal, getSystemErrorMap, getSystemErrorName, + isArrayBufferDetached, isError, isInsideNodeModules, join, diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 2dfcf90bce34b4..50b2cf0e487064 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -51,6 +51,7 @@ const { const { createDeferredPromise, customInspectSymbol: kInspect, + isArrayBufferDetached, kEmptyObject, kEnumerableProperty, } = require('internal/util'); @@ -103,7 +104,6 @@ const { extractHighWaterMark, extractSizeAlgorithm, lazyTransfer, - isDetachedBuffer, isViewedArrayBufferDetached, isBrandCheck, resetQueue, @@ -668,7 +668,7 @@ class ReadableStreamBYOBRequest { const viewBuffer = ArrayBufferViewGetBuffer(view); const viewBufferByteLength = ArrayBufferPrototypeGetByteLength(viewBuffer); - if (isDetachedBuffer(viewBuffer)) { + if (isArrayBufferDetached(viewBuffer)) { throw new ERR_INVALID_STATE.TypeError('Viewed ArrayBuffer is detached'); } @@ -2641,7 +2641,7 @@ function readableByteStreamControllerEnqueue(controller, chunk) { if (pendingPullIntos.length) { const firstPendingPullInto = pendingPullIntos[0]; - if (isDetachedBuffer(firstPendingPullInto.buffer)) { + if (isArrayBufferDetached(firstPendingPullInto.buffer)) { throw new ERR_INVALID_STATE.TypeError( 'Destination ArrayBuffer is detached', ); diff --git a/lib/internal/webstreams/util.js b/lib/internal/webstreams/util.js index 5e0a75d2b30265..9f978ef3ec50ca 100644 --- a/lib/internal/webstreams/util.js +++ b/lib/internal/webstreams/util.js @@ -1,7 +1,6 @@ 'use strict'; const { - ArrayBufferPrototypeGetByteLength, ArrayBufferPrototypeSlice, ArrayPrototypePush, ArrayPrototypeShift, @@ -47,6 +46,7 @@ const { } = internalBinding('util'); const assert = require('internal/assert'); +const { isArrayBufferDetached } = require('internal/util'); const kState = Symbol('kState'); const kType = Symbol('kType'); @@ -137,23 +137,10 @@ function transferArrayBuffer(buffer) { return res; } -function isDetachedBuffer(buffer) { - if (ArrayBufferPrototypeGetByteLength(buffer) === 0) { - // TODO(daeyeon): Consider using C++ builtin to improve performance. - try { - new Uint8Array(buffer); - } catch (error) { - assert(error.name === 'TypeError'); - return true; - } - } - return false; -} - function isViewedArrayBufferDetached(view) { return ( ArrayBufferViewGetByteLength(view) === 0 && - isDetachedBuffer(ArrayBufferViewGetBuffer(view)) + isArrayBufferDetached(ArrayBufferViewGetBuffer(view)) ); } @@ -253,7 +240,6 @@ module.exports = { extractSizeAlgorithm, lazyTransfer, isBrandCheck, - isDetachedBuffer, isPromisePending, isViewedArrayBufferDetached, peekQueueValue, diff --git a/src/node_util.cc b/src/node_util.cc index ecb591698a4e82..46346a4b0f3181 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -137,6 +137,15 @@ static void GetProxyDetails(const FunctionCallbackInfo& args) { } } +static void IsArrayBufferDetached(const FunctionCallbackInfo& args) { + if (args[0]->IsArrayBuffer()) { + auto buffer = args[0].As(); + args.GetReturnValue().Set(buffer->WasDetached()); + return; + } + args.GetReturnValue().Set(false); +} + static void PreviewEntries(const FunctionCallbackInfo& args) { if (!args[0]->IsObject()) return; @@ -349,6 +358,7 @@ static void ToUSVString(const FunctionCallbackInfo& args) { void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(GetPromiseDetails); registry->Register(GetProxyDetails); + registry->Register(IsArrayBufferDetached); registry->Register(PreviewEntries); registry->Register(GetOwnNonIndexProperties); registry->Register(GetConstructorName); @@ -422,6 +432,8 @@ void Initialize(Local target, SetMethodNoSideEffect( context, target, "getPromiseDetails", GetPromiseDetails); SetMethodNoSideEffect(context, target, "getProxyDetails", GetProxyDetails); + SetMethodNoSideEffect( + context, target, "isArrayBufferDetached", IsArrayBufferDetached); SetMethodNoSideEffect(context, target, "previewEntries", PreviewEntries); SetMethodNoSideEffect( context, target, "getOwnNonIndexProperties", GetOwnNonIndexProperties);