1#include <v8.h>
2#include <node.h>
3#include <assert.h>
4
5using v8::Array;
6using v8::ArrayBuffer;
7using v8::ArrayBufferView;
8using v8::BackingStore;
9using v8::Context;
10using v8::FunctionCallbackInfo;
11using v8::Isolate;
12using v8::Local;
13using v8::MaybeLocal;
14using v8::Number;
15using v8::Object;
16using v8::String;
17using v8::Uint32;
18using v8::Value;
19
20void CallWithString(const FunctionCallbackInfo<Value>& args) {
21  assert(args.Length() == 1 && args[0]->IsString());
22  if (args.Length() == 1 && args[0]->IsString()) {
23    Local<String> str = args[0].As<String>();
24    const int32_t length = str->Utf8Length(args.GetIsolate()) + 1;
25    char* buf = new char[length];
26    str->WriteUtf8(args.GetIsolate(), buf, length);
27    delete[] buf;
28  }
29}
30
31void CallWithArray(const FunctionCallbackInfo<Value>& args) {
32  assert(args.Length() == 1 && args[0]->IsArray());
33  if (args.Length() == 1 && args[0]->IsArray()) {
34    const Local<Array> array = args[0].As<Array>();
35    uint32_t length = array->Length();
36    for (uint32_t i = 0; i < length; i++) {
37      Local<Value> v;
38      v = array->Get(args.GetIsolate()->GetCurrentContext(),
39                     i).ToLocalChecked();
40    }
41  }
42}
43
44void CallWithNumber(const FunctionCallbackInfo<Value>& args) {
45  assert(args.Length() == 1 && args[0]->IsNumber());
46  if (args.Length() == 1 && args[0]->IsNumber()) {
47    args[0].As<Number>()->Value();
48  }
49}
50
51void CallWithObject(const FunctionCallbackInfo<Value>& args) {
52  Isolate* isolate = args.GetIsolate();
53  Local<Context> context = isolate->GetCurrentContext();
54
55  assert(args.Length() == 1 && args[0]->IsObject());
56  if (args.Length() == 1 && args[0]->IsObject()) {
57    Local<Object> obj = args[0].As<Object>();
58
59    MaybeLocal<String> map_key = String::NewFromUtf8(isolate,
60        "map", v8::NewStringType::kNormal);
61    assert(!map_key.IsEmpty());
62    MaybeLocal<Value> map_maybe = obj->Get(context,
63        map_key.ToLocalChecked());
64    assert(!map_maybe.IsEmpty());
65    Local<Value> map;
66    map = map_maybe.ToLocalChecked();
67
68    MaybeLocal<String> operand_key = String::NewFromUtf8(isolate,
69        "operand", v8::NewStringType::kNormal);
70    assert(!operand_key.IsEmpty());
71    MaybeLocal<Value> operand_maybe = obj->Get(context,
72        operand_key.ToLocalChecked());
73    assert(!operand_maybe.IsEmpty());
74    Local<Value> operand;
75    operand = operand_maybe.ToLocalChecked();
76
77    MaybeLocal<String> data_key = String::NewFromUtf8(isolate,
78        "data", v8::NewStringType::kNormal);
79    assert(!data_key.IsEmpty());
80    MaybeLocal<Value> data_maybe = obj->Get(context,
81        data_key.ToLocalChecked());
82    assert(!data_maybe.IsEmpty());
83    Local<Value> data;
84    data = data_maybe.ToLocalChecked();
85
86    MaybeLocal<String> reduce_key = String::NewFromUtf8(isolate,
87        "reduce", v8::NewStringType::kNormal);
88    assert(!reduce_key.IsEmpty());
89    MaybeLocal<Value> reduce_maybe = obj->Get(context,
90        reduce_key.ToLocalChecked());
91    assert(!reduce_maybe.IsEmpty());
92    Local<Value> reduce;
93    reduce = reduce_maybe.ToLocalChecked();
94  }
95}
96
97void CallWithTypedarray(const FunctionCallbackInfo<Value>& args) {
98  assert(args.Length() == 1 && args[0]->IsArrayBufferView());
99  if (args.Length() == 1 && args[0]->IsArrayBufferView()) {
100    assert(args[0]->IsArrayBufferView());
101    Local<ArrayBufferView> view = args[0].As<ArrayBufferView>();
102    const size_t byte_offset = view->ByteOffset();
103    const size_t byte_length = view->ByteLength();
104    assert(byte_length > 0);
105    assert(view->HasBuffer());
106    Local<ArrayBuffer> buffer = view->Buffer();
107    std::shared_ptr<BackingStore> bs = buffer->GetBackingStore();
108    const uint32_t* data = reinterpret_cast<uint32_t*>(
109        static_cast<uint8_t*>(bs->Data()) + byte_offset);
110    assert(data);
111  }
112}
113
114void CallWithArguments(const FunctionCallbackInfo<Value>& args) {
115  assert(args.Length() > 1 && args[0]->IsNumber());
116  if (args.Length() > 1 && args[0]->IsNumber()) {
117    int32_t loop = args[0].As<Uint32>()->Value();
118    for (int32_t i = 1; i < loop; ++i) {
119      assert(i < args.Length());
120      assert(args[i]->IsUint32());
121      args[i].As<Uint32>()->Value();
122    }
123  }
124}
125
126void Initialize(Local<Object> target,
127                Local<Value> module,
128                void* data) {
129  NODE_SET_METHOD(target, "callWithString", CallWithString);
130  NODE_SET_METHOD(target, "callWithLongString", CallWithString);
131
132  NODE_SET_METHOD(target, "callWithArray", CallWithArray);
133  NODE_SET_METHOD(target, "callWithLargeArray", CallWithArray);
134  NODE_SET_METHOD(target, "callWithHugeArray", CallWithArray);
135
136  NODE_SET_METHOD(target, "callWithNumber", CallWithNumber);
137  NODE_SET_METHOD(target, "callWithObject", CallWithObject);
138  NODE_SET_METHOD(target, "callWithTypedarray", CallWithTypedarray);
139
140  NODE_SET_METHOD(target, "callWith10Numbers", CallWithArguments);
141  NODE_SET_METHOD(target, "callWith100Numbers", CallWithArguments);
142  NODE_SET_METHOD(target, "callWith1000Numbers", CallWithArguments);
143}
144
145NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
146