diff --git a/lib/internal/util.js b/lib/internal/util.js index f4c08ecdddbdaf..7825172e66e2e1 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, @@ -560,6 +562,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, @@ -577,6 +587,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 256075d3a1cfaa..d816dfae51af42 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'); @@ -104,7 +105,6 @@ const { extractHighWaterMark, extractSizeAlgorithm, lazyTransfer, - isDetachedBuffer, isViewedArrayBufferDetached, isBrandCheck, resetQueue, @@ -669,7 +669,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'); } @@ -2643,7 +2643,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 1cf2d3a1874b10..827a8676f5a0b9 100644 --- a/lib/internal/webstreams/util.js +++ b/lib/internal/webstreams/util.js @@ -1,7 +1,6 @@ 'use strict'; const { - ArrayBufferPrototypeGetByteLength, ArrayBufferPrototypeSlice, ArrayPrototypePush, ArrayPrototypeShift, @@ -45,6 +44,7 @@ const { } = internalBinding('util'); const assert = require('internal/assert'); +const { isArrayBufferDetached } = require('internal/util'); const kState = Symbol('kState'); const kType = Symbol('kType'); @@ -135,23 +135,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)) ); } @@ -251,7 +238,6 @@ module.exports = { extractSizeAlgorithm, lazyTransfer, isBrandCheck, - isDetachedBuffer, isPromisePending, isViewedArrayBufferDetached, peekQueueValue, diff --git a/src/node_util.cc b/src/node_util.cc index e9028c3edc4d4f..6a6fc506f95c2a 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; @@ -342,6 +351,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); @@ -403,6 +413,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);