Initial commit, demo program, wraps a C++ double in a JS object
[node_zettair.git] / zetjs.cpp
1 #include <node.h>
2 #include <node_object_wrap.h>
3
4 namespace zetjs {
5
6 using v8::Context;
7 using v8::Function;
8 using v8::FunctionCallbackInfo;
9 using v8::FunctionTemplate;
10 using v8::Isolate;
11 using v8::Local;
12 using v8::Number;
13 using v8::Object;
14 using v8::Persistent;
15 using v8::String;
16 using v8::Value;
17
18 class MyObject : public node::ObjectWrap {
19  public:
20   static void Init(v8::Local<v8::Object> exports);
21
22  private:
23   explicit MyObject(double value = 0);
24   ~MyObject();
25
26   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
27   static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
28   static v8::Persistent<v8::Function> constructor;
29   double value_;
30 };
31
32 Persistent<Function> MyObject::constructor;
33
34 MyObject::MyObject(double value) : value_(value) {
35 }
36
37 MyObject::~MyObject() {
38 }
39
40 void MyObject::Init(Local<Object> exports) {
41   Isolate* isolate = exports->GetIsolate();
42
43   // Prepare constructor template
44   Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
45   tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
46   tpl->InstanceTemplate()->SetInternalFieldCount(1);
47
48   // Prototype
49   NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
50
51   constructor.Reset(isolate, tpl->GetFunction());
52   exports->Set(String::NewFromUtf8(isolate, "MyObject"),
53                tpl->GetFunction());
54 }
55
56 void MyObject::New(const FunctionCallbackInfo<Value>& args) {
57   Isolate* isolate = args.GetIsolate();
58
59   if (args.IsConstructCall()) {
60     // Invoked as constructor: `new MyObject(...)`
61     double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
62     MyObject* obj = new MyObject(value);
63     obj->Wrap(args.This());
64     args.GetReturnValue().Set(args.This());
65   } else {
66     // Invoked as plain function `MyObject(...)`, turn into construct call.
67     const int argc = 1;
68     Local<Value> argv[argc] = { args[0] };
69     Local<Context> context = isolate->GetCurrentContext();
70     Local<Function> cons = Local<Function>::New(isolate, constructor);
71     Local<Object> result =
72         cons->NewInstance(context, argc, argv).ToLocalChecked();
73     args.GetReturnValue().Set(result);
74   }
75 }
76
77 void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
78   Isolate* isolate = args.GetIsolate();
79
80   MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.Holder());
81   obj->value_ += 1;
82
83   args.GetReturnValue().Set(Number::New(isolate, obj->value_));
84 }
85
86 void InitAll(Local<Object> exports) {
87   MyObject::Init(exports);
88 }
89
90 NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
91
92 }