Skip to content

Commit 61d1f11

Browse files
committed
WIP, start of example 6 for abi stable api
Not working yet but much of the scafolding is in place Key issue now is that object is not be constructed correctly, instead we are getting a base object instead of a MyObject when we do new MyObject(10) in the addon.js
1 parent f169334 commit 61d1f11

6 files changed

Lines changed: 188 additions & 0 deletions

File tree

6_object_wrap/abi/addon.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "myobject.h"
2+
3+
void new_init(node::js::env env, node::js::value exports, node::js::value module) {
4+
MyObject::Init(env, exports);
5+
}
6+
7+
// NODE_MODULE's init callback's signature uses v8 type for its parameter
8+
// // which complicates our effort to create a VM neutral and ABI stable API.
9+
// // For not I am working around the issue by assuming v8 and thunking into
10+
// // an init callback with a VM neutral signature.
11+
void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {
12+
node::js::legacy::WorkaroundNewModuleInit(exports, module, new_init);
13+
}
14+
15+
NODE_MODULE(addon, Init)

6_object_wrap/abi/addon.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
var addon = require('bindings')('addon');
2+
var util = require('util');
3+
console.log(util.inspect(addon.MyObject), {showHidden: true, depth: null });
4+
console.log(util.inspect(addon.MyObject.prototype), {showHidden: true, depth: null });
5+
addon.MyObject.prototype.test = function() {
6+
}
7+
8+
var obj = new addon.MyObject(10);
9+
console.log(obj);
10+
11+
obj.test();
12+
13+
console.log( obj.plusOne() ); // 11
14+
console.log( obj.plusOne() ); // 12
15+
console.log( obj.plusOne() ); // 13
16+
17+
console.log( obj.multiply().value() ); // 13
18+
console.log( obj.multiply(10).value() ); // 130
19+
20+
var newobj = obj.multiply(-1);
21+
console.log( newobj.value() ); // -13
22+
console.log( obj === newobj ); // false

6_object_wrap/abi/binding.gyp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "addon",
5+
"sources": [ "addon.cc", "myobject.cc" ]
6+
}
7+
]
8+
}

6_object_wrap/abi/myobject.cc

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#include "myobject.h"
2+
3+
node::js::persistent constructor;
4+
5+
MyObject::MyObject(double value) : value_(value) {
6+
}
7+
8+
MyObject::~MyObject() {
9+
}
10+
11+
void MyObject::Init(node::js::value env, node::js::value exports) {
12+
/*
13+
Nan::HandleScope scope;
14+
15+
// Prepare constructor template
16+
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
17+
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
18+
tpl->InstanceTemplate()->SetInternalFieldCount(1);
19+
20+
// Prototype
21+
Nan::SetPrototypeMethod(tpl, "value", GetValue);
22+
Nan::SetPrototypeMethod(tpl, "plusOne", PlusOne);
23+
Nan::SetPrototypeMethod(tpl, "multiply", Multiply);
24+
25+
constructor.Reset(tpl->GetFunction());
26+
exports->Set(Nan::New("MyObject").ToLocalChecked(), tpl->GetFunction());
27+
*/
28+
node::js::value function = node::js::CreateFunction(env, New);
29+
node::js::SetFunctionName(env, function, node::js::CreateString(env, "MyObject"));
30+
node::js::value prototype =
31+
node::js::GetProperty(env, function, node::js::PropertyName(env, "prototype"));
32+
33+
node::js::SetProperty(env, prototype, node::js::PropertyName(env, "value"),
34+
node::js::CreateFunction(env, GetValue));
35+
36+
node::js::value plusOneFunction = node::js::CreateFunction(env, PlusOne);
37+
node::js::SetFunctionName(env, plusOneFunction, node::js::CreateString(env, "plusOne"));
38+
node::js::SetProperty(env, prototype, node::js::PropertyName(env, "plusOne"),
39+
plusOneFunction);
40+
node::js::SetProperty(env, prototype, node::js::PropertyName(env, "Multiply"),
41+
node::js::CreateFunction(env, Multiply));
42+
43+
constructor = node::js::CreatePersistent(env, function);
44+
45+
node::js::SetProperty(env, exports, node::js::PropertyName(env, "MyObject"),
46+
function);
47+
}
48+
49+
void MyObject::New(node::js::value env, node::js::FunctionCallbackInfo info) {
50+
/*
51+
if (info.IsConstructCall()) {
52+
// Invoked as constructor: `new MyObject(...)`
53+
double value = info[0]->IsUndefined() ? 0 : info[0]->NumberValue();
54+
MyObject* obj = new MyObject(value);
55+
obj->Wrap(info.This());
56+
info.GetReturnValue().Set(info.This());
57+
} else {
58+
// Invoked as plain function `MyObject(...)`, turn into construct call.
59+
const int argc = 1;
60+
v8::Local<v8::Value> argv[argc] = { info[0] };
61+
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
62+
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
63+
}
64+
*/
65+
66+
printf("Called \n");
67+
68+
// assumes its a constructor call
69+
node::js::value args[1];
70+
node::js::GetCallbackArgs(info, args, 1);
71+
double value = 0;
72+
if (node::js::GetUndefined(env) != args[0]) {
73+
value = node::js::GetNumberFromValue(args[0]);
74+
}
75+
MyObject* obj = new MyObject(value);
76+
node::js::value jsobj = node::js::GetCallbackObject(env, info);
77+
node::js::SetProperty(env, jsobj, node::js::PropertyName(env, "test2"),
78+
node::js::CreateString(env, "test string"));
79+
node::js::Wrap(env, jsobj, (void*) obj);
80+
// node::js::SetReturnValue(env, info, jsobj);
81+
}
82+
83+
void MyObject::GetValue(node::js::value env, node::js::FunctionCallbackInfo info) {
84+
/*
85+
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
86+
info.GetReturnValue().Set(Nan::New(obj->value_));
87+
*/
88+
}
89+
90+
void MyObject::PlusOne(node::js::value env, node::js::FunctionCallbackInfo info) {
91+
/*
92+
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
93+
obj->value_ += 1;
94+
info.GetReturnValue().Set(Nan::New(obj->value_));
95+
*/
96+
}
97+
98+
void MyObject::Multiply(node::js::value env, node::js::FunctionCallbackInfo info) {
99+
/*
100+
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
101+
double multiple = info[0]->IsUndefined() ? 1 : info[0]->NumberValue();
102+
103+
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
104+
105+
const int argc = 1;
106+
v8::Local<v8::Value> argv[argc] = { Nan::New(obj->value_ * multiple) };
107+
108+
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
109+
*/
110+
}

6_object_wrap/abi/myobject.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef MYOBJECT_H
2+
#define MYOBJECT_H
3+
4+
#include <node_jsvmapi.h>
5+
6+
class MyObject {
7+
public:
8+
static void Init(node::js::value env, node::js::value exports);
9+
10+
private:
11+
explicit MyObject(double value = 0);
12+
~MyObject();
13+
14+
static void New(node::js::value env, node::js::FunctionCallbackInfo info);
15+
static void GetValue(node::js::value env, node::js::FunctionCallbackInfo info);
16+
static void PlusOne(node::js::value env, node::js::FunctionCallbackInfo info);
17+
static void Multiply(node::js::value env, node::js::FunctionCallbackInfo info);
18+
double value_;
19+
};
20+
21+
#endif

6_object_wrap/abi/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "object_wrap",
3+
"version": "0.0.0",
4+
"description": "Node.js Addons Example #6",
5+
"main": "addon.js",
6+
"private": true,
7+
"gypfile": true,
8+
"dependencies": {
9+
"bindings": "~1.2.1",
10+
"nan": "^2.0.0"
11+
}
12+
}

0 commit comments

Comments
 (0)