Skip to content

Commit b22ba10

Browse files
author
John Haley
committed
Added ability for callbacks to poll promises for fulfillment value
1 parent 8d81b73 commit b22ba10

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

generate/partials/field_accessors.cc

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,22 @@ void {{ cppClassName }}::{{ field.name }}_asyncAfter(uv_work_t* req, int status)
132132

133133
TryCatch tryCatch;
134134
Handle<Value> result = instance->{{ field.name }}->Call({{ field.args|jsArgsCount }}, argv);
135+
136+
if (result->IsObject()) {
137+
const char* constructorName = **(new NanUtf8String(result->ToObject()->GetConstructorName()));
138+
string promiseConName ("Promise");
139+
140+
if (promiseConName.compare(constructorName) == 0) {
141+
// we can be reasonbly certain that the result is a promise
142+
Local<Object> promise = result->ToObject();
143+
144+
NanAssignPersistent(baton->promise, promise);
145+
146+
uv_queue_work(uv_default_loop(), &baton->req, {{ field.name }}_asyncWork, {{ field.name }}_asyncPromisePolling);
147+
return;
148+
}
149+
}
150+
135151
{{ field.returnType }} resultStatus;
136152

137153
{%each field|returnsInfo true false as _return%}
@@ -151,6 +167,52 @@ void {{ cppClassName }}::{{ field.name }}_asyncAfter(uv_work_t* req, int status)
151167
{%endeach%}
152168
baton->done = true;
153169
}
170+
171+
void {{ cppClassName }}::{{ field.name }}_asyncPromisePolling(uv_work_t* req, int status) {
172+
NanScope();
173+
174+
{{ field.name|titleCase }}Baton* baton = static_cast<{{ field.name|titleCase }}Baton*>(req->data);
175+
Local<Object> promise = NanNew<Object>(baton->promise);
176+
NanCallback* isPendingFn = new NanCallback(promise->Get(NanNew("isPending")).As<Function>());
177+
Local<Value> argv[0];
178+
Local<Boolean> isPending = isPendingFn->Call(0, argv)->ToBoolean();
179+
180+
if (isPending->Value()) {
181+
uv_queue_work(uv_default_loop(), &baton->req, {{ field.name }}_asyncWork, {{ field.name }}_asyncPromisePolling);
182+
return;
183+
}
184+
185+
NanCallback* isFulfilledFn = new NanCallback(promise->Get(NanNew("isFulfilled")).As<Function>());
186+
Local<Boolean> isFulfilled = isFulfilledFn->Call(0, argv)->ToBoolean();
187+
188+
if (isFulfilled->Value()) {
189+
NanCallback* resultFn = new NanCallback(promise->Get(NanNew("value")).As<Function>());
190+
Handle<Value> result = resultFn->Call(0, argv);
191+
{{ field.returnType }} resultStatus;
192+
193+
{%each field|returnsInfo true false as _return%}
194+
if (result.IsEmpty() || result->IsNativeError()) {
195+
baton->result = {{ field.returnError }};
196+
}
197+
else if (!result->IsNull() && !result->IsUndefined()) {
198+
{{ _return.cppClassName }}* wrapper = ObjectWrap::Unwrap<{{ _return.cppClassName }}>(result->ToObject());
199+
wrapper->selfFreeing = false;
200+
201+
baton->{{ _return.name }} = wrapper->GetRefValue();
202+
baton->result = {{ field.returnSuccess }};
203+
}
204+
else {
205+
baton->result = {{ field.returnNoResults }};
206+
}
207+
{%endeach%}
208+
baton->done = true;
209+
}
210+
else {
211+
// promise was rejected
212+
baton->result = {{ field.returnError }};
213+
baton->done = false;
214+
}
215+
}
154216
{%endif%}
155217
{%endif%}
156218
{%endeach%}

generate/templates/struct_header.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ class {{ cppClassName }} : public ObjectWrap {
4141
);
4242
static void {{ field.name }}_asyncWork(uv_work_t* req);
4343
static void {{ field.name }}_asyncAfter(uv_work_t* req, int status);
44+
static void {{ field.name }}_asyncPromisePolling(uv_work_t* req, int status);
4445
struct {{ field.name|titleCase }}Baton {
4546
{%each field.args|argsInfo as arg %}
4647
{{ arg.cType }} {{ arg.name}};
4748
{%endeach%}
4849
uv_work_t req;
4950
{{ field.returnType }} result;
51+
Persistent<Object> promise;
5052
bool done;
5153
};
5254
{%endif%}

0 commit comments

Comments
 (0)