Commit 3e357c57 authored by John Haley's avatar John Haley

Callbacks in classes build now

parent 107f023f
......@@ -6,7 +6,7 @@ module.exports = function(args) {
for(cArg = 0, jsArg = 0; cArg < args.length; cArg++) {
var arg = args[cArg];
if (!arg.isReturn && !arg.isSelf && !arg.isPayload) {
if (!arg.isReturn && !arg.isSelf) {
arg.isJsArg = true;
arg.jsArg = jsArg;
......@@ -23,6 +23,17 @@ module.exports = function(args) {
arg.cArg = cArg;
arg.isCppClassStringOrArray = ~["String", "Array"].indexOf(arg.cppClassName);
// if we have a callback then we also need the corresponding payload for that callback
if (arg.isCallbackFunction) {
var payload = args.filter(function(payload) {
return payload.payloadFor == arg.name || payload.payloadFor == '*';
})[0];
if (payload) {
arg.payload = payload;
}
}
result.push(arg);
}
......
......@@ -19,6 +19,7 @@ module.exports = function(fn, argReturnsOnly, isAsync) {
});
if (!result.length
&& !fn.isCallbackFunction
&& !argReturnsOnly
&& fn.return
&& !fn.return.isErrorCode
......
......@@ -11,7 +11,7 @@ using namespace node;
struct CallbackWrapper {
NanCallback* jsCallback;
void * payload;
Persistent<Value> payload;
};
#endif
......@@ -9,9 +9,9 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
{%each args|argsInfo as arg %}
{%if arg.isCallbackFunction %}
CallbackWrapper* {{ arg.name }}_cbWrapper = malloc(sizeof(CallbackWrapper));
{{ arg.name }}_cbWrapper->jsCallback = args[{{ arg.jsArg }}];
{{ arg.name }}_cbWrapper->payload = {{ args|payloadFor arg.name }};
CallbackWrapper* {{ arg.name }}_cbWrapper = (CallbackWrapper *)malloc(sizeof(CallbackWrapper));
{{ arg.name }}_cbWrapper->jsCallback = new NanCallback(args[{{ arg.jsArg }}].As<Function>());
NanAssignPersistent({{ arg.name }}_cbWrapper->payload, args[{{ arg.payload.jsArg }}]);
{%endif%}
{%endeach%}
......@@ -25,9 +25,10 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
{%if arg.isSelf %}
baton->{{ arg.name }} = ObjectWrap::Unwrap<{{ arg.cppClassName }}>(args.This())->GetValue();
{%elsif arg.isCallbackFunction %}
baton->{{ arg.name}} = {{ cppFunctionName }}_{{ arg.name }}_cppCallback
baton->{{ arg.name}} = {{ cppFunctionName }}_{{ arg.name }}_cppCallback;
baton->{{ arg.payload.name }} = {{ arg.name }}_cbWrapper;
{%elsif arg.payloadFor %}
baton->{{ arg.name }} = {{ arg.payloadFor }}_cbWrapper
{%-- payloads are handled inside of the callback condition --%}
{%elsif arg.name %}
{%partial convertFromV8 arg%}
{%if not arg.isPayload %}
......@@ -159,8 +160,10 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() {
baton->{{ arg.name}}NeedsFree = false;
free((void *)baton->{{ arg.name }});
}
{%elsif arg.payloadFor%}
free(baton->{{ arg.name }});
{%elsif arg.isCallbackFunction%}
CallbackWrapper* cbWrapper = (CallbackWrapper *)baton->{{ arg.payload.name }};
NanDisposePersistent(cbWrapper->payload);
free(baton->{{ arg.payload.name }});
{%endif%}
{%endeach%}
......
{%each args as cbArg %}
{%if cbArg.isCallbackFunction %}
{%each args as cbFunction %}
{%if cbFunction.isCallbackFunction %}
{{ cbArg.returnType }} {{ cppClassName }}::{{ cppFunctionName }}_{{ cbArg.name }}_cppCallback (
{% each cbArg.args|argsInfo as arg %}
{{ cbFunction.return.type }} {{ cppClassName }}::{{ cppFunctionName }}_{{ cbFunction.name }}_cppCallback (
{% each cbFunction.args|argsInfo as arg %}
{{ arg.cType }} {{ arg.name}}{% if not arg.lastArg %},{% endif %}
{% endeach %}
) {
{{ cppFunctionName }}_{{ cbArg.name|titleCase }}Baton* baton = new {{ cppFunctionName }}_{{ cbArg.name|titleCase }}Baton();
{{ cppFunctionName }}_{{ cbFunction.name|titleCase }}Baton* baton = new {{ cppFunctionName }}_{{ cbFunction.name|titleCase }}Baton();
{% each cbArg.args|argsInfo as arg %}
{% each cbFunction.args|argsInfo as arg %}
baton->{{ arg.name }} = {{ arg.name }};
{% endeach %}
baton->req.data = baton;
baton->done = false;
uv_queue_work(uv_default_loop(), &baton->req, {{ cppFunctionName }}_{{ cbArg.name }}_asyncWork, {{ cppFunctionName }}_{{ cbArg.name }}_asyncAfter);
uv_queue_work(uv_default_loop(), &baton->req, {{ cppFunctionName }}_{{ cbFunction.name }}_asyncWork, {{ cppFunctionName }}_{{ cbFunction.name }}_asyncAfter);
while(!baton->done) {
this_thread::sleep_for(chrono::milliseconds(1));
}
{% each cbArg|returnsInfo true false as _return %}
{% each cbFunction|returnsInfo true false as _return %}
*{{ _return.name }} = *baton->{{ _return.name }};
{% endeach %}
return baton->result;
}
void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbArg.name }}_asyncWork(uv_work_t* req) {
void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbFunction.name }}_asyncWork(uv_work_t* req) {
// We aren't doing any work on a seperate thread, just need to
// access the main node thread in the async after method.
// However, this worker method is still needed
}
void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbArg.name }}_asyncAfter(uv_work_t* req, int status) {
void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbFunction.name }}_asyncAfter(uv_work_t* req, int status) {
NanScope();
{{ cppFunctionName }}_{{ cbArg.name|titleCase }}Baton* baton = static_cast<{{ cppFunctionName }}_{{ cbArg.name|titleCase }}Baton*>(req->data);
{{ cppClassName }}* instance = static_cast<{{ cppClassName }}*>(baton->payload);
{{ cppFunctionName }}_{{ cbFunction.name|titleCase }}Baton* baton = static_cast<{{ cppFunctionName }}_{{ cbFunction.name|titleCase }}Baton*>(req->data);
if (instance->{{ cbArg.name }}->IsEmpty()) {
{% if cbArg.returnType == "int" %}
baton->result = {{ cbArg.returnNoResults }}; // no results acquired
{% endif %}
CallbackWrapper* cbWrapper = (CallbackWrapper *)baton->payload;
baton->done = true;
return;
}
CallbackWrapper* cbWrapper = baton->payload;
Local<Value> argv[{{ cbArg.args|jsArgsCount }}] = {
{% each cbArg.args|argsInfo as arg %}
Local<Value> argv[{{ cbFunction.args|jsArgsCount }}] = {
{% each cbFunction.args|argsInfo as arg %}
{% if arg.name == "payload" %}
{%-- payload is always the last arg --%}
NanNew(cbWrapper->payload)
......@@ -72,7 +62,7 @@ void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbArg.name }}_asyncAfter(uv_wo
};
TryCatch tryCatch;
Handle<Value> result = cbWrapper->jsFunction->Call({{ cbArg.args|jsArgsCount }}, argv);
Handle<Value> result = cbWrapper->jsCallback->Call({{ cbFunction.args|jsArgsCount }}, argv);
if (result->IsObject() && result->ToObject()->Has(NanNew("then"))) {
Handle<Value> thenProp = result->ToObject()->Get(NanNew("then"));
......@@ -83,42 +73,42 @@ void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbArg.name }}_asyncAfter(uv_wo
NanAssignPersistent(baton->promise, promise);
uv_queue_work(uv_default_loop(), &baton->req, {{ cppFunctionName }}_{{ cbArg.name }}_asyncWork, {{ cppFunctionName }}_{{ cbArg.name }}_asyncPromisePolling);
uv_queue_work(uv_default_loop(), &baton->req, {{ cppFunctionName }}_{{ cbFunction.name }}_asyncWork, {{ cppFunctionName }}_{{ cbFunction.name }}_asyncPromisePolling);
return;
}
}
{{ cbArg.returnType }} resultStatus;
{{ cbFunction.return.type }} resultStatus;
{% each cbArg|returnsInfo true false as _return %}
{% each cbFunction|returnsInfo true false as _return %}
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = {{ cbArg.returnError }};
baton->result = {{ cbFunction.return.error }};
}
else if (!result->IsNull() && !result->IsUndefined()) {
{{ _return.cppClassName }}* wrapper = ObjectWrap::Unwrap<{{ _return.cppClassName }}>(result->ToObject());
wrapper->selfFreeing = false;
baton->{{ _return.name }} = wrapper->GetRefValue();
baton->result = {{ cbArg.returnSuccess }};
baton->result = {{ cbFunction.return.success }};
}
else {
baton->result = {{ cbArg.returnNoResults }};
baton->result = {{ cbFunction.return.noResults }};
}
{% endeach %}
baton->done = true;
}
void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbArg.name }}_asyncPromisePolling(uv_work_t* req, int status) {
void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbFunction.name }}_asyncPromisePolling(uv_work_t* req, int status) {
NanScope();
{{ cppFunctionName }}_{{ cbArg.name|titleCase }}Baton* baton = static_cast<{{ cppFunctionName }}_{{ cbArg.name|titleCase }}Baton*>(req->data);
{{ cppFunctionName }}_{{ cbFunction.name|titleCase }}Baton* baton = static_cast<{{ cppFunctionName }}_{{ cbFunction.name|titleCase }}Baton*>(req->data);
Local<Object> promise = NanNew<Object>(baton->promise);
NanCallback* isPendingFn = new NanCallback(promise->Get(NanNew("isPending")).As<Function>());
Local<Value> argv[1]; // MSBUILD won't assign an array of length 0
Local<Boolean> isPending = isPendingFn->Call(0, argv)->ToBoolean();
if (isPending->Value()) {
uv_queue_work(uv_default_loop(), &baton->req, {{ cppFunctionName }}_{{ cbArg.name }}_asyncWork, {{ cppFunctionName }}_{{ cbArg.name }}_asyncPromisePolling);
uv_queue_work(uv_default_loop(), &baton->req, {{ cppFunctionName }}_{{ cbFunction.name }}_asyncWork, {{ cppFunctionName }}_{{ cbFunction.name }}_asyncPromisePolling);
return;
}
......@@ -128,28 +118,28 @@ void {{ cppClassName }}::{{ cppFunctionName }}_{{ cbArg.name }}_asyncPromisePoll
if (isFulfilled->Value()) {
NanCallback* resultFn = new NanCallback(promise->Get(NanNew("value")).As<Function>());
Handle<Value> result = resultFn->Call(0, argv);
{{ cbArg.returnType }} resultStatus;
{{ cbFunction.return.type }} resultStatus;
{% each cbArg|returnsInfo true false as _return %}
{% each cbFunction|returnsInfo true false as _return %}
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = {{ cbArg.returnError }};
baton->result = {{ cbFunction.return.error }};
}
else if (!result->IsNull() && !result->IsUndefined()) {
{{ _return.cppClassName }}* wrapper = ObjectWrap::Unwrap<{{ _return.cppClassName }}>(result->ToObject());
wrapper->selfFreeing = false;
baton->{{ _return.name }} = wrapper->GetRefValue();
baton->result = {{ cbArg.returnSuccess }};
baton->result = {{ cbFunction.return.success }};
}
else {
baton->result = {{ cbArg.returnNoResults }};
baton->result = {{ cbFunction.return.noResults }};
}
{% endeach %}
baton->done = true;
}
else {
// promise was rejected
baton->result = {{ cbArg.returnError }};
baton->result = {{ cbFunction.return.error }};
baton->done = false;
}
}
......
......@@ -69,7 +69,7 @@
}
{% if field.isCallbackFunction %}
{{ field.returnType }} {{ cppClassName }}::{{ field.name }}_cppCallback (
{{ field.return.type }} {{ cppClassName }}::{{ field.name }}_cppCallback (
{% each field.args|argsInfo as arg %}
{{ arg.cType }} {{ arg.name}}{% if not arg.lastArg %},{% endif %}
{% endeach %}
......@@ -109,8 +109,8 @@
{{ cppClassName }}* instance = static_cast<{{ cppClassName }}*>(baton->payload);
if (instance->{{ field.name }}->IsEmpty()) {
{% if field.returnType == "int" %}
baton->result = {{ field.returnNoResults }}; // no results acquired
{% if field.return.type == "int" %}
baton->result = {{ field.return.noResults }}; // no results acquired
{% endif %}
baton->done = true;
......@@ -154,21 +154,21 @@
}
}
{{ field.returnType }} resultStatus;
{{ field.return.type }} resultStatus;
{% each field|returnsInfo true false as _return %}
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = {{ field.returnError }};
baton->result = {{ field.return.error }};
}
else if (!result->IsNull() && !result->IsUndefined()) {
{{ _return.cppClassName }}* wrapper = ObjectWrap::Unwrap<{{ _return.cppClassName }}>(result->ToObject());
wrapper->selfFreeing = false;
baton->{{ _return.name }} = wrapper->GetRefValue();
baton->result = {{ field.returnSuccess }};
baton->result = {{ field.return.success }};
}
else {
baton->result = {{ field.returnNoResults }};
baton->result = {{ field.return.noResults }};
}
{% endeach %}
baton->done = true;
......@@ -194,28 +194,28 @@
if (isFulfilled->Value()) {
NanCallback* resultFn = new NanCallback(promise->Get(NanNew("value")).As<Function>());
Handle<Value> result = resultFn->Call(0, argv);
{{ field.returnType }} resultStatus;
{{ field.return.type }} resultStatus;
{% each field|returnsInfo true false as _return %}
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = {{ field.returnError }};
baton->result = {{ field.return.error }};
}
else if (!result->IsNull() && !result->IsUndefined()) {
{{ _return.cppClassName }}* wrapper = ObjectWrap::Unwrap<{{ _return.cppClassName }}>(result->ToObject());
wrapper->selfFreeing = false;
baton->{{ _return.name }} = wrapper->GetRefValue();
baton->result = {{ field.returnSuccess }};
baton->result = {{ field.return.success }};
}
else {
baton->result = {{ field.returnNoResults }};
baton->result = {{ field.return.noResults }};
}
{% endeach %}
baton->done = true;
}
else {
// promise was rejected
baton->result = {{ field.returnError }};
baton->result = {{ field.return.error }};
baton->done = false;
}
}
......
......@@ -26,9 +26,9 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
{%each args|argsInfo as arg %}
{%if arg.isCallbackFunction %}
CallbackWrapper* {{ arg.name }}_cbWrapper = malloc(sizeof(CallbackWrapper));
{{ arg.name }}_cbWrapper->jsCallback = args[{{ arg.jsArg }}];
{{ arg.name }}_cbWrapper->payload = {{ args|payloadFor arg.name }};
CallbackWrapper* {{ arg.name }}_cbWrapper = (CallbackWrapper *)malloc(sizeof(CallbackWrapper));
{{ arg.name }}_cbWrapper->jsCallback = new NanCallback(args[{{ arg.jsArg }}].As<Function>());
NanAssignPersistent({{ arg.name }}_cbWrapper->payload, args[{{ arg.payload.jsArg }}]);
{%endif%}
{%endeach%}
{%if .|hasReturns %}
......@@ -42,9 +42,10 @@ ObjectWrap::Unwrap<{{ arg.cppClassName }}>(args.This())->GetValue()
{%elsif arg.isReturn %}
{{ arg.name }}
{%elsif arg.isCallbackFunction %}
{{ cppFunctionName }}_{{ arg.name }}_cppCallback
{{ cppFunctionName }}_{{ arg.name }}_cppCallback,
{{ arg.name }}_cbWrapper
{%elsif arg.payloadFor %}
{{ arg.payloadFor }}_cbWrapper
{%-- payloads are handled inside of the callback condition --%}
{%else%}
from_{{ arg.name }}
{%endif%}
......
// This is a generated file, modify: generate/templates/class_content.cc.
#include <nan.h>
#include <string.h>
#include <chrono>
#include <thread>
extern "C" {
#include <git2.h>
......
......@@ -49,7 +49,7 @@ class {{ cppClassName }} : public ObjectWrap {
{% if not function.ignore %}
{%each function.args as arg %}
{%if arg.isCallbackFunction %}
static {{ arg.returnType }} {{ function.cppFunctionName }}_{{ arg.name }}_cppCallback (
static {{ arg.return.type }} {{ function.cppFunctionName }}_{{ arg.name }}_cppCallback (
{% each arg.args|argsInfo as cbArg %}
{{ cbArg.cType }} {{ cbArg.name }}
{% if not cbArg.lastArg %}
......@@ -66,8 +66,8 @@ class {{ cppClassName }} : public ObjectWrap {
{{ cbArg.cType }} {{ cbArg.name }};
{% endeach %}
uv_work_t* req;
{{ arg.returnType }} result;
uv_work_t req;
{{ arg.return.type }} result;
Persistent<Object> promise;
bool done;
};
......
......@@ -34,7 +34,7 @@ class {{ cppClassName }} : public ObjectWrap {
{% each fields as field %}
{% if not field.ignore %}
{% if field.isCallbackFunction %}
static {{ field.returnType }} {{ field.name }}_cppCallback (
static {{ field.return.type }} {{ field.name }}_cppCallback (
{% each field.args|argsInfo as arg %}
{{ arg.cType }} {{ arg.name}}
{% if not arg.lastArg %}
......@@ -52,7 +52,7 @@ class {{ cppClassName }} : public ObjectWrap {
{% endeach %}
uv_work_t req;
{{ field.returnType }} result;
{{ field.return.type }} result;
Persistent<Object> promise;
bool done;
};
......
......@@ -26,10 +26,12 @@
"cType": "void *"
}
],
"returnType": "int",
"returnNoResults": 1,
"returnSuccess": 0,
"returnError": -1
"return": {
"type": "int",
"noResults": 1,
"success": 0,
"error": -1
}
},
"git_checkout_progress_cb": {
"args": [
......@@ -50,10 +52,12 @@
"cType": "void *"
}
],
"returnType": "int",
"returnNoResults": 1,
"returnSuccess": 0,
"returnError": -1
"return": {
"type": "int",
"noResults": 1,
"success": 0,
"error": -1
}
},
"git_cred_acquire_cb": {
"args": [
......@@ -79,10 +83,12 @@
"cType": "void *"
}
],
"returnType": "int",
"returnNoResults": 1,
"returnSuccess": 0,
"returnError": -1
"return": {
"type": "int",
"noResults": 1,
"success": 0,
"error": -1
}
},
"git_diff_notify_cb": {
"args": [
......@@ -103,10 +109,12 @@
"cType": "void *"
}
],
"returnType": "int",
"returnNoResults": 1,
"returnSuccess": 0,
"returnError": -1
"return": {
"type": "int",
"noResults": 1,
"success": 0,
"error": -1
}
},
"git_diff_file_cb": {
"args": [
......@@ -123,16 +131,18 @@
"cType": "void *"
}
],
"returnType": "int",
"returnNoResults": 1,
"returnSuccess": 0,
"returnError": -1
"return": {
"type": "int",
"noResults": 1,
"success": 0,
"error": -1
}
},
"git_status_cb": {
"args": [
{
"name": "path",
"cType": "const char"
"cType": "const char *"
},
{
"name": "status_flags",
......@@ -143,9 +153,11 @@
"cType": "void *"
}
],
"returnType": "int",
"returnNoResults": 1,
"returnSuccess": 0,
"returnError": -1
"return": {
"type": "int",
"noResults": 1,
"success": 0,
"error": -1
}
}
}
......@@ -1282,10 +1282,16 @@
"ignore": true
},
"git_status_foreach": {
"isAsync": true
"isAsync": true,
"return": {
"isErrorCode": true
}
},
"git_status_foreach_ext": {
"isAsync": true
"isAsync": true,
"return": {
"isErrorCode": true
}
},
"git_status_init_options": {
"ignore": true
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment