Skip to content

Commit e79e0a3

Browse files
committed
First rough draft of adding support for promises.
1 parent 20d0f1f commit e79e0a3

6 files changed

Lines changed: 79 additions & 0 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
},
3333
"devDependencies": {
3434
"async": "~0.1.22",
35+
"bluebird": "^2.6.0",
3536
"nodeunit": "0.9.0"
3637
},
3738
"scripts": {

src/java.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ NAN_METHOD(Java::New) {
7979
NanObjectWrapHandle(self)->Set(NanNew<v8::String>("classpath"), NanNew<v8::Array>());
8080
NanObjectWrapHandle(self)->Set(NanNew<v8::String>("options"), NanNew<v8::Array>());
8181
NanObjectWrapHandle(self)->Set(NanNew<v8::String>("nativeBindingLocation"), NanNew<v8::String>("Not Set"));
82+
NanObjectWrapHandle(self)->Set(NanNew<v8::String>("asyncOptions"), NanNull());
8283

8384
NanReturnValue(args.This());
8485
}
@@ -104,6 +105,21 @@ v8::Local<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
104105
JavaVM* jvmTemp;
105106
JavaVMInitArgs args;
106107

108+
v8::Local<v8::Value> asyncOptions = NanObjectWrapHandle(this)->Get(NanNew<v8::String>("asyncOptions"));
109+
if (asyncOptions->IsObject()) {
110+
v8::Local<v8::Object> asyncOptionsObj = asyncOptions->ToObject();
111+
v8::Local<v8::Value> promisify = asyncOptionsObj->Get(NanNew<v8::String>("promisify"));
112+
if (!promisify->IsFunction()) {
113+
return NanTypeError("asyncOptions.promisify must be a function");
114+
}
115+
v8::Local<v8::Value> suffix = asyncOptionsObj->Get(NanNew<v8::String>("suffix"));
116+
if (!suffix->IsString()) {
117+
return NanTypeError("asyncOptions.suffix must be a string");
118+
}
119+
v8::Handle<v8::Object> asyncOptionsObjTemp = v8::Handle<v8::Object>::Cast(asyncOptionsObj);
120+
NanAssignPersistent(m_asyncOptions, asyncOptionsObjTemp);
121+
}
122+
107123
// setup classpath
108124
std::ostringstream classPath;
109125
classPath << "-Djava.class.path=";

src/java.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class Java : public node::ObjectWrap {
5959
static std::string s_nativeBindingLocation;
6060
v8::Persistent<v8::Array> m_classPathArray;
6161
v8::Persistent<v8::Array> m_optionsArray;
62+
v8::Persistent<v8::Object> m_asyncOptions;
6263
};
6364

6465
#endif

src/javaObject.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@
2727
std::replace(className.begin(), className.end(), '[', 'a');
2828
className = "nodeJava_" + className;
2929

30+
// Set up promisification
31+
v8::Local<v8::Object> asyncOptions = NanObjectWrapHandle(java)->Get(NanNew<v8::String>("asyncOptions"))->ToObject();
32+
v8::Local<v8::Function> promisify;
33+
std::string promiseSuffix;
34+
bool promisifying = asyncOptions->IsObject();
35+
if(promisifying) {
36+
v8::Local<v8::Value> promisifyValue = asyncOptions->Get(NanNew<v8::String>("promisify"));
37+
promisify = v8::Function::Cast(*promisifyValue);
38+
v8::Local<v8::String> suffix = asyncOptions->Get(NanNew<v8::String>("suffix"))->ToString();
39+
v8::String::Utf8Value utf8(suffix);
40+
promiseSuffix.assign(*utf8);
41+
}
42+
3043
v8::Local<v8::FunctionTemplate> funcTemplate;
3144
if(sFunctionTemplates.find(className) != sFunctionTemplates.end()) {
3245
//printf("existing className: %s\n", className.c_str());
@@ -54,6 +67,18 @@
5467
v8::Handle<v8::String> methodNameSync = NanNew<v8::String>((methodNameStr + "Sync").c_str());
5568
v8::Local<v8::FunctionTemplate> methodCallSyncTemplate = NanNew<v8::FunctionTemplate>(methodCallSync, methodName);
5669
funcTemplate->PrototypeTemplate()->Set(methodNameSync, methodCallSyncTemplate->GetFunction());
70+
71+
if (promisifying) {
72+
v8::Local<v8::Object> recv = asyncOptions; // just a dummy receiver
73+
v8::Local<v8::Value> argv[] = { methodCallTemplate->GetFunction() };
74+
v8::Local<v8::Value> result = promisify->Call(recv, 1, argv);
75+
if (!result->IsFunction()) {
76+
printf("Promisified result is not a function.\n");
77+
}
78+
v8::Local<v8::Function> promFunction = v8::Function::Cast(*result);
79+
v8::Handle<v8::String> methodNamePromise = NanNew<v8::String>((methodNameStr + promiseSuffix).c_str());\
80+
funcTemplate->PrototypeTemplate()->Set(methodNamePromise, promFunction);
81+
}
5782
}
5883

5984
std::list<jobject> fields;

test/promises-test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
var java = require("../testHelpers").java;
2+
3+
var nodeunit = require("nodeunit");
4+
var util = require("util");
5+
6+
exports['Promises'] = nodeunit.testCase({
7+
"create an instance of a class and call methods (getClassPromise & getNamePromise)": function(test) {
8+
java.newInstance("java.util.ArrayList", function(err, list) {
9+
if (err) {
10+
console.log(err);
11+
return;
12+
}
13+
test.ok(list);
14+
if (list) {
15+
list.getClassPromise()
16+
.then(function(clazz) { return clazz.getNamePromise(); })
17+
.then(function(name) {
18+
test.equal(name, "java.util.ArrayList");
19+
})
20+
.catch(function(err) {
21+
test.ifError(err);
22+
})
23+
.then(function() {
24+
test.expect(2);
25+
test.done();
26+
})
27+
}
28+
});
29+
},
30+
});
31+

testHelpers.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,9 @@ java.classpath.push("test/");
77
java.classpath.push("test/commons-lang3-3.1.jar");
88
java.classpath.push("test8/");
99

10+
java.asyncOptions = {
11+
suffix: 'Promise',
12+
promisify: require('bluebird').promisify
13+
};
14+
1015
module.exports.java = java;

0 commit comments

Comments
 (0)