diff --git a/include/v8-version.h b/include/v8-version.h index ab9e6b484db..19729b09b6a 100644 --- a/include/v8-version.h +++ b/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 4 #define V8_MINOR_VERSION 3 #define V8_BUILD_NUMBER 61 -#define V8_PATCH_LEVEL 16 +#define V8_PATCH_LEVEL 17 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/include/v8.h b/include/v8.h index 0c320fb64c6..19de92fa8c4 100644 --- a/include/v8.h +++ b/include/v8.h @@ -3294,6 +3294,10 @@ class V8_EXPORT Promise : public Object { #define V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT 2 #endif + +enum class ArrayBufferCreationMode { kInternalized, kExternalized }; + + /** * An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5). * This API is experimental and may change significantly. @@ -3369,12 +3373,13 @@ class V8_EXPORT ArrayBuffer : public Object { /** * Create a new ArrayBuffer over an existing memory block. - * The created array buffer is immediately in externalized state. + * The created array buffer is by default immediately in externalized state. * The memory block will not be reclaimed when a created ArrayBuffer * is garbage-collected. */ - static Local New(Isolate* isolate, void* data, - size_t byte_length); + static Local New( + Isolate* isolate, void* data, size_t byte_length, + ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized); /** * Returns true if ArrayBuffer is extrenalized, that is, does not @@ -3406,6 +3411,18 @@ class V8_EXPORT ArrayBuffer : public Object { */ Contents Externalize(); + /** + * Get a pointer to the ArrayBuffer's underlying memory block without + * externalizing it. If the ArrayBuffer is not externalized, this pointer + * will become invalid as soon as the ArrayBuffer became garbage collected. + * + * The embedder should make sure to hold a strong reference to the + * ArrayBuffer while accessing this pointer. + * + * The memory block is guaranteed to be allocated with |Allocator::Allocate|. + */ + Contents GetContents(); + V8_INLINE static ArrayBuffer* Cast(Value* obj); static const int kInternalFieldCount = V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT; diff --git a/src/api.cc b/src/api.cc index 4afe5c40d8d..382ed132efc 100644 --- a/src/api.cc +++ b/src/api.cc @@ -6362,14 +6362,19 @@ bool v8::ArrayBuffer::IsNeuterable() const { v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() { - i::Handle obj = Utils::OpenHandle(this); - Utils::ApiCheck(!obj->is_external(), - "v8::ArrayBuffer::Externalize", + i::Handle self = Utils::OpenHandle(this); + Utils::ApiCheck(!self->is_external(), "v8::ArrayBuffer::Externalize", "ArrayBuffer already externalized"); - obj->set_is_external(true); - size_t byte_length = static_cast(obj->byte_length()->Number()); + self->set_is_external(true); + return GetContents(); +} + + +v8::ArrayBuffer::Contents v8::ArrayBuffer::GetContents() { + i::Handle self = Utils::OpenHandle(this); + size_t byte_length = static_cast(self->byte_length()->Number()); Contents contents; - contents.data_ = obj->backing_store(); + contents.data_ = self->backing_store(); contents.byte_length_ = byte_length; return contents; } @@ -6407,13 +6412,16 @@ Local v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) { Local v8::ArrayBuffer::New(Isolate* isolate, void* data, - size_t byte_length) { + size_t byte_length, + ArrayBufferCreationMode mode) { i::Isolate* i_isolate = reinterpret_cast(isolate); LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)"); ENTER_V8(i_isolate); i::Handle obj = i_isolate->factory()->NewJSArrayBuffer(); - i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length); + i::Runtime::SetupArrayBuffer(i_isolate, obj, + mode == ArrayBufferCreationMode::kExternalized, + data, byte_length); return Utils::ToLocal(obj); } diff --git a/test/cctest/test-typedarrays.cc b/test/cctest/test-typedarrays.cc index 966edb720ee..d031048caeb 100644 --- a/test/cctest/test-typedarrays.cc +++ b/test/cctest/test-typedarrays.cc @@ -10,6 +10,7 @@ #include "src/api.h" #include "src/heap/heap.h" #include "src/objects.h" +#include "src/v8.h" using namespace v8::internal; @@ -66,3 +67,15 @@ TEST(CopyContentsView) { "var a = new DataView(b, 2);"); TestArrayBufferViewContents(env, true); } + + +TEST(AllocateNotExternal) { + LocalContext env; + v8::HandleScope scope(env->GetIsolate()); + void* memory = V8::ArrayBufferAllocator()->Allocate(1024); + v8::Local buffer = + v8::ArrayBuffer::New(env->GetIsolate(), memory, 1024, + v8::ArrayBufferCreationMode::kInternalized); + CHECK(!buffer->IsExternal()); + CHECK_EQ(memory, buffer->GetContents().Data()); +}