Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Commit

Permalink
Provide a way to create ArrayBuffer from external source
Browse files Browse the repository at this point in the history
  • Loading branch information
zcbenz committed Aug 21, 2015
1 parent 9c27152 commit 205b013
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 64 deletions.
102 changes: 38 additions & 64 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,28 @@ using v8::Uint8Array;
using v8::Value;
using v8::WeakCallbackData;

namespace {

v8::Local<v8::ArrayBuffer> DefaultArrayBufferCreate(
v8::Isolate* isolate, size_t size) {
return v8::ArrayBuffer::New(isolate, size);
}

v8::Local<v8::Uint8Array> DefaultUint8ArrayCreate(
v8::Local<v8::ArrayBuffer> ab, size_t offset, size_t size) {
return v8::Uint8Array::New(ab, offset, size);
}

ArrayBufferCreator g_array_buffer_create = &DefaultArrayBufferCreate;
Uint8ArrayCreator g_uint8_array_create = &DefaultUint8ArrayCreate;

} // namespace

void SetArrayBufferCreator(ArrayBufferCreator array_buffer_create,
Uint8ArrayCreator uint8_array_create) {
g_array_buffer_create = array_buffer_create;
g_uint8_array_create = uint8_array_create;
}

class CallbackInfo {
public:
Expand Down Expand Up @@ -251,28 +273,13 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
return Local<Object>();
}

void* data;
if (length > 0) {
data = malloc(length);
if (data == nullptr)
return Local<Object>();
} else {
data = nullptr;
}

Local<ArrayBuffer> ab =
ArrayBuffer::New(env->isolate(),
data,
length,
ArrayBufferCreationMode::kInternalized);
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
Local<ArrayBuffer> ab = g_array_buffer_create(env->isolate(), length);
Local<Uint8Array> ui = g_uint8_array_create(ab, 0, length);
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());
if (mb.FromMaybe(false))
return scope.Escape(ui);

// Object failed to be created. Clean up resources.
free(data);
return Local<Object>();
}

Expand All @@ -295,30 +302,14 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
return Local<Object>();
}

void* new_data;
if (length > 0) {
CHECK_NE(data, nullptr);
new_data = malloc(length);
if (new_data == nullptr)
return Local<Object>();
memcpy(new_data, data, length);
} else {
new_data = nullptr;
}

Local<ArrayBuffer> ab =
ArrayBuffer::New(env->isolate(),
new_data,
length,
ArrayBufferCreationMode::kInternalized);
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
Local<ArrayBuffer> ab = g_array_buffer_create(env->isolate(), length);
memcpy(ab->GetContents().Data(), data, length);
Local<Uint8Array> ui = g_uint8_array_create(ab, 0, length);
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());
if (mb.FromMaybe(false))
return scope.Escape(ui);

// Object failed to be created. Clean up resources.
free(new_data);
return Local<Object>();
}

Expand Down Expand Up @@ -348,15 +339,16 @@ MaybeLocal<Object> New(Environment* env,
return Local<Object>();
}

Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), data, length);
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
Local<ArrayBuffer> ab = g_array_buffer_create(env->isolate(), length);
memcpy(ab->GetContents().Data(), data, length);
callback(data, hint);
Local<Uint8Array> ui = g_uint8_array_create(ab, 0, length);
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());

if (!mb.FromMaybe(false))
return Local<Object>();

CallbackInfo::New(env->isolate(), ui, callback, hint);
return scope.Escape(ui);
}

Expand All @@ -379,12 +371,9 @@ MaybeLocal<Object> New(Environment* env, char* data, size_t length) {
CHECK(length <= kMaxLength);
}

Local<ArrayBuffer> ab =
ArrayBuffer::New(env->isolate(),
data,
length,
ArrayBufferCreationMode::kInternalized);
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
Local<ArrayBuffer> ab = g_array_buffer_create(env->isolate(), length);
memcpy(ab->GetContents().Data(), data, length);
Local<Uint8Array> ui = g_uint8_array_create(ab, 0, length);
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());
if (mb.FromMaybe(false))
Expand All @@ -405,23 +394,8 @@ void Create(const FunctionCallbackInfo<Value>& args) {
return env->ThrowRangeError("invalid Buffer length");
}

void* data;
if (length > 0) {
data = malloc(length);
if (data == nullptr) {
return env->ThrowRangeError(
"Buffer allocation failed - process out of memory");
}
} else {
data = nullptr;
}

Local<ArrayBuffer> ab =
ArrayBuffer::New(isolate,
data,
length,
ArrayBufferCreationMode::kInternalized);
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
Local<ArrayBuffer> ab = g_array_buffer_create(env->isolate(), length);
Local<Uint8Array> ui = g_uint8_array_create(ab, 0, length);
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());
if (!mb.FromMaybe(false))
Expand All @@ -448,7 +422,7 @@ void CreateFromArrayBuffer(const FunctionCallbackInfo<Value>& args) {
if (!args[0]->IsArrayBuffer())
return env->ThrowTypeError("argument is not an ArrayBuffer");
Local<ArrayBuffer> ab = args[0].As<ArrayBuffer>();
Local<Uint8Array> ui = Uint8Array::New(ab, 0, ab->ByteLength());
Local<Uint8Array> ui = g_uint8_array_create(ab, 0, ab->ByteLength());
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());
if (!mb.FromMaybe(false))
Expand All @@ -471,7 +445,7 @@ void Slice(const FunctionCallbackInfo<Value>& args) {
CHECK_GE(end, start);
size_t size = end - start;
CHECK_GE(ab_c.ByteLength(), start + size);
Local<Uint8Array> ui = Uint8Array::New(ab, start, size);
Local<Uint8Array> ui = g_uint8_array_create(ab, start, size);
Maybe<bool> mb =
ui->SetPrototype(env->context(), env->buffer_prototype_object());
if (!mb.FromMaybe(false))
Expand Down
7 changes: 7 additions & 0 deletions src/node_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ namespace Buffer {
static const unsigned int kMaxLength =
sizeof(int32_t) == sizeof(intptr_t) ? 0x3fffffff : 0x7fffffff;

// Allow creating custom ArrayBuffer objets.
typedef v8::Local<v8::ArrayBuffer> (*ArrayBufferCreator)(
v8::Isolate* isolate, size_t size);
typedef v8::Local<v8::Uint8Array> (*Uint8ArrayCreator)(
v8::Local<v8::ArrayBuffer> ab, size_t offset, size_t size);
NODE_EXTERN void SetArrayBufferCreator(ArrayBufferCreator, Uint8ArrayCreator);

NODE_EXTERN typedef void (*FreeCallback)(char* data, void* hint);

NODE_EXTERN bool HasInstance(v8::Handle<v8::Value> val);
Expand Down

0 comments on commit 205b013

Please sign in to comment.