Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Callbacks in classes build now
  • Loading branch information
John Haley committed Feb 3, 2015
commit 3e357c572b16979c4905b92f351cb210d98e1953
13 changes: 12 additions & 1 deletion generate/combyne/filters/args_info.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}

Expand Down
1 change: 1 addition & 0 deletions generate/combyne/filters/returns_info.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = function(fn, argReturnsOnly, isAsync) {
});

if (!result.length
&& !fn.isCallbackFunction
&& !argReturnsOnly
&& fn.return
&& !fn.return.isErrorCode
Expand Down
2 changes: 1 addition & 1 deletion generate/combyne/manual/include/callbackWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ using namespace node;

struct CallbackWrapper {
NanCallback* jsCallback;
void * payload;
Persistent<Value> payload;
};

#endif
17 changes: 10 additions & 7 deletions generate/combyne/partials/async_function.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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%}

Expand All @@ -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 %}
Expand Down Expand Up @@ -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%}

Expand Down
70 changes: 30 additions & 40 deletions generate/combyne/partials/callback_helpers.cc
Original file line number Diff line number Diff line change
@@ -1,58 +1,48 @@
{%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)
Expand All @@ -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"));
Expand All @@ -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;
}

Expand All @@ -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;
}
}
Expand Down
24 changes: 12 additions & 12 deletions generate/combyne/partials/field_accessors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
}
Expand Down
11 changes: 6 additions & 5 deletions generate/combyne/partials/sync_function.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand All @@ -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%}
Expand Down
2 changes: 2 additions & 0 deletions generate/combyne/templates/class_content.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// 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>
Expand Down
6 changes: 3 additions & 3 deletions generate/combyne/templates/class_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand All @@ -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;
};
Expand Down
Loading