diff --git a/src/node_util.cc b/src/node_util.cc index f2c008c797d61b..6d20f636f0d25e 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -8,6 +8,7 @@ namespace util { using v8::ALL_PROPERTIES; using v8::Array; +using v8::ArrayBufferView; using v8::Boolean; using v8::Context; using v8::Function; @@ -174,6 +175,11 @@ void WatchdogHasPendingSigint(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(ret); } +void ArrayBufferViewHasBuffer(const FunctionCallbackInfo& args) { + CHECK(args[0]->IsArrayBufferView()); + args.GetReturnValue().Set(args[0].As()->HasBuffer()); +} + void EnqueueMicrotask(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); Isolate* isolate = env->isolate(); @@ -254,6 +260,7 @@ void Initialize(Local target, env->SetMethodNoSideEffect(target, "watchdogHasPendingSigint", WatchdogHasPendingSigint); + env->SetMethod(target, "arrayBufferViewHasBuffer", ArrayBufferViewHasBuffer); env->SetMethod(target, "enqueueMicrotask", EnqueueMicrotask); env->SetMethod(target, "triggerFatalException", FatalException); Local constants = Object::New(env->isolate()); diff --git a/test/parallel/test-buffer-backing-arraybuffer.js b/test/parallel/test-buffer-backing-arraybuffer.js new file mode 100644 index 00000000000000..e7e15c079e6332 --- /dev/null +++ b/test/parallel/test-buffer-backing-arraybuffer.js @@ -0,0 +1,37 @@ +// Flags: --expose-internals +'use strict'; +require('../common'); +const assert = require('assert'); +const { internalBinding } = require('internal/test/binding'); +const { arrayBufferViewHasBuffer } = internalBinding('util'); + +const tests = [ + { length: 0, expectOnHeap: true }, + { length: 48, expectOnHeap: true }, + { length: 96, expectOnHeap: false }, + { length: 1024, expectOnHeap: false }, +]; + +for (const { length, expectOnHeap } of tests) { + const arrays = [ + new Uint8Array(length), + new Uint16Array(length / 2), + new Uint32Array(length / 4), + new Float32Array(length / 4), + new Float64Array(length / 8), + Buffer.alloc(length), + Buffer.allocUnsafeSlow(length) + // Buffer.allocUnsafe() is missing because it may use pooled allocations. + ]; + + for (const array of arrays) { + const isOnHeap = !arrayBufferViewHasBuffer(array); + assert.strictEqual(isOnHeap, expectOnHeap, + `mismatch: ${isOnHeap} vs ${expectOnHeap} ` + + `for ${array.constructor.name}, length = ${length}`); + + // Consistency check: Accessing .buffer should create it. + array.buffer; + assert(arrayBufferViewHasBuffer(array)); + } +}