How to check in an node.js C++ addon, if a promise is resolved

Multi tool use
The Task:
I call a callback from C++ that return a v8::Promise (so an async function).
Now I want to find out if the promise was resolved.
For this example here, I want to check from JS if the promise is resolved.
But "just beeing informed in the C++ addon" would be fine.
The Problem:
I failed to create a persistent Promise object in C++.
I works while I am still in the event loop. But when I get into the event loop again later on, the object is empty.
The code:
JS test code
// create an object in the addon
var OB = require('./build/Debug/objectwraphandle.node')
var obj = new OB.MyObject(42)
// just an async wait function
async function asyncFunc1(y) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('asyncFunc1: DONE'), 2000);
});
}
// pass the async function as callback to the addon and call it
obj.callAsyncFunction(asyncFunc1);
// ask the object, it the promise is already resolved.
// this should switch from 1 (Pending) to 0 (Resolved) after 2 seconds
console.log(" resolved? : " + obj.isPromiseResolved());
// but this core-dumps with:
// "FATAL ERROR: v8::Promise::Cast Could not convert to promise"
Now the C++ side (by the way - no need to say I am neither C++ nor JS guru)
(original taken from NAN - Native Abstractions for Node.js).
For reproducing, I put the full code here. Important are the functions CallAsyncFunction and IsPromiseResolved.
/*********************************************************************
* NAN - Native Abstractions for Node.js
* Copyright (c) 2018 NAN contributors
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
*
* and now here: used as test basis by Gerrit Prange
********************************************************************/
#include <iostream>
#include <nan.h>
using namespace Nan;
class MyObject : public ObjectWrap {
public:
static NAN_MODULE_INIT(Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// these are the two functions in question
SetPrototypeMethod(tpl, "callAsyncFunction", CallAsyncFunction);
SetPrototypeMethod(tpl, "isPromiseResolved", IsPromiseResolved);
constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
Set(target, Nan::New("MyObject").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
private:
explicit MyObject(double value = 0) : value_(value) {}
~MyObject() {}
// here: the promise is stored as persistent object
Nan::Persistent<v8::Promise> *persistentPromise;
static NAN_METHOD(New) {
if (info.IsConstructCall()) {
double value = info[0]->IsUndefined() ? 0 : Nan::To<double>(info[0]).FromJust();
MyObject *obj = new MyObject(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = {info[0]};
v8::Local<v8::Function> cons = Nan::New(constructor());
info.GetReturnValue().Set(
Nan::NewInstance(cons, argc, argv).ToLocalChecked());
}
}
/* we get a callback function (async function),
* call this callback and get a promise returned
*/
static NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
const unsigned argc = 1;
v8::Local<v8::Value> argv[argc] = { Nan::New("hello world").ToLocalChecked() };
Callback cb(To<v8::Function>(info[0]).ToLocalChecked());
// call the callback - and get a Promise
Nan::MaybeLocal<v8::Value> promiseReturnValue = (*cb)->Call(GetCurrentContext()->Global(), argc, argv);
// check if the promise is already resolved. (should not be in this example!)
v8::Handle<v8::Promise> promiseReturnObject = v8::Handle<v8::Promise>::Cast ( promiseReturnValue.ToLocalChecked() );
v8::Promise::PromiseState promiseState = promiseReturnObject->State();
std::cout << " state: " << promiseState << std::endl;
// make the callback persistent
Nan::Persistent<v8::Promise> persistentPromiseReturnObject(promiseReturnObject);
obj->persistentPromise = &persistentPromiseReturnObject;
}
/* check if the callback is already resolved and return the state
*/
static NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
// get the persistent callback and convert it into a local object
v8::Local<v8::Object> objectToCheckPromise = Nan::New ( *obj->persistentPromise );
// THE LINE BELOW IS THE PROBLEM! actually, persiting does not seem to work.
v8::Local<v8::Promise> promiseObject = v8::Local<v8::Promise>::Cast ( objectToCheckPromise );
// get the promises state
v8::Promise::PromiseState promiseState = promiseObject->State();
// and return the state
std::cout << " in IsPromiseResolved state: " << promiseState << std::endl;
info.GetReturnValue().Set(Nan::New(promiseState));
}
static inline Persistent<v8::Function> & constructor() {
static Persistent<v8::Function> my_constructor;
return my_constructor;
}
double value_;
};
NODE_MODULE(objectwraphandle, MyObject::Init)
The actual error I get is:
FATAL ERROR: v8::Promise::Cast Could not convert to promise
1: node::Abort() [node]
2: 0x121a2cc [node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
4: v8::Promise::Cast(v8::Value*) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
5: v8::Local<v8::Promise> v8::Local<v8::Promise>::Cast<v8::Object>(v8::Local<v8::Object>) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
6: MyObject::IsPromiseResolved(Nan::FunctionCallbackInfo<v8::Value> const&) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
7: 0x7fb4dd8889dc [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
8: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [node]
9: 0xb9043c [node]
10: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
Sorry, this is a long post. (But I wanted to put the code here - if anyone wants to try this out.)
node.js v8 node.js-addon node-nan
add a comment |
The Task:
I call a callback from C++ that return a v8::Promise (so an async function).
Now I want to find out if the promise was resolved.
For this example here, I want to check from JS if the promise is resolved.
But "just beeing informed in the C++ addon" would be fine.
The Problem:
I failed to create a persistent Promise object in C++.
I works while I am still in the event loop. But when I get into the event loop again later on, the object is empty.
The code:
JS test code
// create an object in the addon
var OB = require('./build/Debug/objectwraphandle.node')
var obj = new OB.MyObject(42)
// just an async wait function
async function asyncFunc1(y) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('asyncFunc1: DONE'), 2000);
});
}
// pass the async function as callback to the addon and call it
obj.callAsyncFunction(asyncFunc1);
// ask the object, it the promise is already resolved.
// this should switch from 1 (Pending) to 0 (Resolved) after 2 seconds
console.log(" resolved? : " + obj.isPromiseResolved());
// but this core-dumps with:
// "FATAL ERROR: v8::Promise::Cast Could not convert to promise"
Now the C++ side (by the way - no need to say I am neither C++ nor JS guru)
(original taken from NAN - Native Abstractions for Node.js).
For reproducing, I put the full code here. Important are the functions CallAsyncFunction and IsPromiseResolved.
/*********************************************************************
* NAN - Native Abstractions for Node.js
* Copyright (c) 2018 NAN contributors
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
*
* and now here: used as test basis by Gerrit Prange
********************************************************************/
#include <iostream>
#include <nan.h>
using namespace Nan;
class MyObject : public ObjectWrap {
public:
static NAN_MODULE_INIT(Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// these are the two functions in question
SetPrototypeMethod(tpl, "callAsyncFunction", CallAsyncFunction);
SetPrototypeMethod(tpl, "isPromiseResolved", IsPromiseResolved);
constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
Set(target, Nan::New("MyObject").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
private:
explicit MyObject(double value = 0) : value_(value) {}
~MyObject() {}
// here: the promise is stored as persistent object
Nan::Persistent<v8::Promise> *persistentPromise;
static NAN_METHOD(New) {
if (info.IsConstructCall()) {
double value = info[0]->IsUndefined() ? 0 : Nan::To<double>(info[0]).FromJust();
MyObject *obj = new MyObject(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = {info[0]};
v8::Local<v8::Function> cons = Nan::New(constructor());
info.GetReturnValue().Set(
Nan::NewInstance(cons, argc, argv).ToLocalChecked());
}
}
/* we get a callback function (async function),
* call this callback and get a promise returned
*/
static NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
const unsigned argc = 1;
v8::Local<v8::Value> argv[argc] = { Nan::New("hello world").ToLocalChecked() };
Callback cb(To<v8::Function>(info[0]).ToLocalChecked());
// call the callback - and get a Promise
Nan::MaybeLocal<v8::Value> promiseReturnValue = (*cb)->Call(GetCurrentContext()->Global(), argc, argv);
// check if the promise is already resolved. (should not be in this example!)
v8::Handle<v8::Promise> promiseReturnObject = v8::Handle<v8::Promise>::Cast ( promiseReturnValue.ToLocalChecked() );
v8::Promise::PromiseState promiseState = promiseReturnObject->State();
std::cout << " state: " << promiseState << std::endl;
// make the callback persistent
Nan::Persistent<v8::Promise> persistentPromiseReturnObject(promiseReturnObject);
obj->persistentPromise = &persistentPromiseReturnObject;
}
/* check if the callback is already resolved and return the state
*/
static NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
// get the persistent callback and convert it into a local object
v8::Local<v8::Object> objectToCheckPromise = Nan::New ( *obj->persistentPromise );
// THE LINE BELOW IS THE PROBLEM! actually, persiting does not seem to work.
v8::Local<v8::Promise> promiseObject = v8::Local<v8::Promise>::Cast ( objectToCheckPromise );
// get the promises state
v8::Promise::PromiseState promiseState = promiseObject->State();
// and return the state
std::cout << " in IsPromiseResolved state: " << promiseState << std::endl;
info.GetReturnValue().Set(Nan::New(promiseState));
}
static inline Persistent<v8::Function> & constructor() {
static Persistent<v8::Function> my_constructor;
return my_constructor;
}
double value_;
};
NODE_MODULE(objectwraphandle, MyObject::Init)
The actual error I get is:
FATAL ERROR: v8::Promise::Cast Could not convert to promise
1: node::Abort() [node]
2: 0x121a2cc [node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
4: v8::Promise::Cast(v8::Value*) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
5: v8::Local<v8::Promise> v8::Local<v8::Promise>::Cast<v8::Object>(v8::Local<v8::Object>) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
6: MyObject::IsPromiseResolved(Nan::FunctionCallbackInfo<v8::Value> const&) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
7: 0x7fb4dd8889dc [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
8: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [node]
9: 0xb9043c [node]
10: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
Sorry, this is a long post. (But I wanted to put the code here - if anyone wants to try this out.)
node.js v8 node.js-addon node-nan
add a comment |
The Task:
I call a callback from C++ that return a v8::Promise (so an async function).
Now I want to find out if the promise was resolved.
For this example here, I want to check from JS if the promise is resolved.
But "just beeing informed in the C++ addon" would be fine.
The Problem:
I failed to create a persistent Promise object in C++.
I works while I am still in the event loop. But when I get into the event loop again later on, the object is empty.
The code:
JS test code
// create an object in the addon
var OB = require('./build/Debug/objectwraphandle.node')
var obj = new OB.MyObject(42)
// just an async wait function
async function asyncFunc1(y) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('asyncFunc1: DONE'), 2000);
});
}
// pass the async function as callback to the addon and call it
obj.callAsyncFunction(asyncFunc1);
// ask the object, it the promise is already resolved.
// this should switch from 1 (Pending) to 0 (Resolved) after 2 seconds
console.log(" resolved? : " + obj.isPromiseResolved());
// but this core-dumps with:
// "FATAL ERROR: v8::Promise::Cast Could not convert to promise"
Now the C++ side (by the way - no need to say I am neither C++ nor JS guru)
(original taken from NAN - Native Abstractions for Node.js).
For reproducing, I put the full code here. Important are the functions CallAsyncFunction and IsPromiseResolved.
/*********************************************************************
* NAN - Native Abstractions for Node.js
* Copyright (c) 2018 NAN contributors
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
*
* and now here: used as test basis by Gerrit Prange
********************************************************************/
#include <iostream>
#include <nan.h>
using namespace Nan;
class MyObject : public ObjectWrap {
public:
static NAN_MODULE_INIT(Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// these are the two functions in question
SetPrototypeMethod(tpl, "callAsyncFunction", CallAsyncFunction);
SetPrototypeMethod(tpl, "isPromiseResolved", IsPromiseResolved);
constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
Set(target, Nan::New("MyObject").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
private:
explicit MyObject(double value = 0) : value_(value) {}
~MyObject() {}
// here: the promise is stored as persistent object
Nan::Persistent<v8::Promise> *persistentPromise;
static NAN_METHOD(New) {
if (info.IsConstructCall()) {
double value = info[0]->IsUndefined() ? 0 : Nan::To<double>(info[0]).FromJust();
MyObject *obj = new MyObject(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = {info[0]};
v8::Local<v8::Function> cons = Nan::New(constructor());
info.GetReturnValue().Set(
Nan::NewInstance(cons, argc, argv).ToLocalChecked());
}
}
/* we get a callback function (async function),
* call this callback and get a promise returned
*/
static NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
const unsigned argc = 1;
v8::Local<v8::Value> argv[argc] = { Nan::New("hello world").ToLocalChecked() };
Callback cb(To<v8::Function>(info[0]).ToLocalChecked());
// call the callback - and get a Promise
Nan::MaybeLocal<v8::Value> promiseReturnValue = (*cb)->Call(GetCurrentContext()->Global(), argc, argv);
// check if the promise is already resolved. (should not be in this example!)
v8::Handle<v8::Promise> promiseReturnObject = v8::Handle<v8::Promise>::Cast ( promiseReturnValue.ToLocalChecked() );
v8::Promise::PromiseState promiseState = promiseReturnObject->State();
std::cout << " state: " << promiseState << std::endl;
// make the callback persistent
Nan::Persistent<v8::Promise> persistentPromiseReturnObject(promiseReturnObject);
obj->persistentPromise = &persistentPromiseReturnObject;
}
/* check if the callback is already resolved and return the state
*/
static NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
// get the persistent callback and convert it into a local object
v8::Local<v8::Object> objectToCheckPromise = Nan::New ( *obj->persistentPromise );
// THE LINE BELOW IS THE PROBLEM! actually, persiting does not seem to work.
v8::Local<v8::Promise> promiseObject = v8::Local<v8::Promise>::Cast ( objectToCheckPromise );
// get the promises state
v8::Promise::PromiseState promiseState = promiseObject->State();
// and return the state
std::cout << " in IsPromiseResolved state: " << promiseState << std::endl;
info.GetReturnValue().Set(Nan::New(promiseState));
}
static inline Persistent<v8::Function> & constructor() {
static Persistent<v8::Function> my_constructor;
return my_constructor;
}
double value_;
};
NODE_MODULE(objectwraphandle, MyObject::Init)
The actual error I get is:
FATAL ERROR: v8::Promise::Cast Could not convert to promise
1: node::Abort() [node]
2: 0x121a2cc [node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
4: v8::Promise::Cast(v8::Value*) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
5: v8::Local<v8::Promise> v8::Local<v8::Promise>::Cast<v8::Object>(v8::Local<v8::Object>) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
6: MyObject::IsPromiseResolved(Nan::FunctionCallbackInfo<v8::Value> const&) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
7: 0x7fb4dd8889dc [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
8: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [node]
9: 0xb9043c [node]
10: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
Sorry, this is a long post. (But I wanted to put the code here - if anyone wants to try this out.)
node.js v8 node.js-addon node-nan
The Task:
I call a callback from C++ that return a v8::Promise (so an async function).
Now I want to find out if the promise was resolved.
For this example here, I want to check from JS if the promise is resolved.
But "just beeing informed in the C++ addon" would be fine.
The Problem:
I failed to create a persistent Promise object in C++.
I works while I am still in the event loop. But when I get into the event loop again later on, the object is empty.
The code:
JS test code
// create an object in the addon
var OB = require('./build/Debug/objectwraphandle.node')
var obj = new OB.MyObject(42)
// just an async wait function
async function asyncFunc1(y) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('asyncFunc1: DONE'), 2000);
});
}
// pass the async function as callback to the addon and call it
obj.callAsyncFunction(asyncFunc1);
// ask the object, it the promise is already resolved.
// this should switch from 1 (Pending) to 0 (Resolved) after 2 seconds
console.log(" resolved? : " + obj.isPromiseResolved());
// but this core-dumps with:
// "FATAL ERROR: v8::Promise::Cast Could not convert to promise"
Now the C++ side (by the way - no need to say I am neither C++ nor JS guru)
(original taken from NAN - Native Abstractions for Node.js).
For reproducing, I put the full code here. Important are the functions CallAsyncFunction and IsPromiseResolved.
/*********************************************************************
* NAN - Native Abstractions for Node.js
* Copyright (c) 2018 NAN contributors
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
*
* and now here: used as test basis by Gerrit Prange
********************************************************************/
#include <iostream>
#include <nan.h>
using namespace Nan;
class MyObject : public ObjectWrap {
public:
static NAN_MODULE_INIT(Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// these are the two functions in question
SetPrototypeMethod(tpl, "callAsyncFunction", CallAsyncFunction);
SetPrototypeMethod(tpl, "isPromiseResolved", IsPromiseResolved);
constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
Set(target, Nan::New("MyObject").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
private:
explicit MyObject(double value = 0) : value_(value) {}
~MyObject() {}
// here: the promise is stored as persistent object
Nan::Persistent<v8::Promise> *persistentPromise;
static NAN_METHOD(New) {
if (info.IsConstructCall()) {
double value = info[0]->IsUndefined() ? 0 : Nan::To<double>(info[0]).FromJust();
MyObject *obj = new MyObject(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = {info[0]};
v8::Local<v8::Function> cons = Nan::New(constructor());
info.GetReturnValue().Set(
Nan::NewInstance(cons, argc, argv).ToLocalChecked());
}
}
/* we get a callback function (async function),
* call this callback and get a promise returned
*/
static NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
const unsigned argc = 1;
v8::Local<v8::Value> argv[argc] = { Nan::New("hello world").ToLocalChecked() };
Callback cb(To<v8::Function>(info[0]).ToLocalChecked());
// call the callback - and get a Promise
Nan::MaybeLocal<v8::Value> promiseReturnValue = (*cb)->Call(GetCurrentContext()->Global(), argc, argv);
// check if the promise is already resolved. (should not be in this example!)
v8::Handle<v8::Promise> promiseReturnObject = v8::Handle<v8::Promise>::Cast ( promiseReturnValue.ToLocalChecked() );
v8::Promise::PromiseState promiseState = promiseReturnObject->State();
std::cout << " state: " << promiseState << std::endl;
// make the callback persistent
Nan::Persistent<v8::Promise> persistentPromiseReturnObject(promiseReturnObject);
obj->persistentPromise = &persistentPromiseReturnObject;
}
/* check if the callback is already resolved and return the state
*/
static NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
// get the persistent callback and convert it into a local object
v8::Local<v8::Object> objectToCheckPromise = Nan::New ( *obj->persistentPromise );
// THE LINE BELOW IS THE PROBLEM! actually, persiting does not seem to work.
v8::Local<v8::Promise> promiseObject = v8::Local<v8::Promise>::Cast ( objectToCheckPromise );
// get the promises state
v8::Promise::PromiseState promiseState = promiseObject->State();
// and return the state
std::cout << " in IsPromiseResolved state: " << promiseState << std::endl;
info.GetReturnValue().Set(Nan::New(promiseState));
}
static inline Persistent<v8::Function> & constructor() {
static Persistent<v8::Function> my_constructor;
return my_constructor;
}
double value_;
};
NODE_MODULE(objectwraphandle, MyObject::Init)
The actual error I get is:
FATAL ERROR: v8::Promise::Cast Could not convert to promise
1: node::Abort() [node]
2: 0x121a2cc [node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
4: v8::Promise::Cast(v8::Value*) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
5: v8::Local<v8::Promise> v8::Local<v8::Promise>::Cast<v8::Object>(v8::Local<v8::Object>) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
6: MyObject::IsPromiseResolved(Nan::FunctionCallbackInfo<v8::Value> const&) [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
7: 0x7fb4dd8889dc [/home/gpr/projects/own/nodejs/jsFromC_NAN_PromiseWait/build/Debug/objectwraphandle.node]
8: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [node]
9: 0xb9043c [node]
10: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
Sorry, this is a long post. (But I wanted to put the code here - if anyone wants to try this out.)
node.js v8 node.js-addon node-nan
node.js v8 node.js-addon node-nan
asked Jun 28 '18 at 10:54


GerritPGerritP
133
133
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You can store Promises in persistent handles. Your code should look something like:
class MyObject : public ObjectWrap {
// ...
private:
Nan::Persistent<Promise> persistentPromise; // not a pointer!
}
NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
// ... your function call here
// returnobj is a Local<Object>
Local<Promise> p = Local<Promise>::Cast(returnobj);
obj->persistentPromise.Reset(p);
}
NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.This());
Local<Promise> p = obj->persistentPromise.Get(Isolate::GetCurrent());
info.GetReturnValue().Set(p->State());
}
I don't know if there's ever a valid reason to take the address of or dereference a v8 type as an embedder (looking at your callback invocation and how you were setting the persistent handle). There are API methods that do these things safely.
BTW, Handle
is deprecated; Local
is its replacement.
add a comment |
Ok, so it looks like v8 Promise is not an object that can be made persistent.
But you can do this:
Add resolve and reject callbacks to the promise so that you get informed when the promise is resolved/rejected.
(I would have liked to add "direct c++ callbacks" instead of having to go via JS, but thats ok for now.)
Or you create a Resolver in your code, which can be made persistent and you can resolve or reject your resolver later in you code.
(Which was another way around my problem for me - maybe looking in that direction also helps you?)
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51081091%2fhow-to-check-in-an-node-js-c-addon-if-a-promise-is-resolved%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can store Promises in persistent handles. Your code should look something like:
class MyObject : public ObjectWrap {
// ...
private:
Nan::Persistent<Promise> persistentPromise; // not a pointer!
}
NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
// ... your function call here
// returnobj is a Local<Object>
Local<Promise> p = Local<Promise>::Cast(returnobj);
obj->persistentPromise.Reset(p);
}
NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.This());
Local<Promise> p = obj->persistentPromise.Get(Isolate::GetCurrent());
info.GetReturnValue().Set(p->State());
}
I don't know if there's ever a valid reason to take the address of or dereference a v8 type as an embedder (looking at your callback invocation and how you were setting the persistent handle). There are API methods that do these things safely.
BTW, Handle
is deprecated; Local
is its replacement.
add a comment |
You can store Promises in persistent handles. Your code should look something like:
class MyObject : public ObjectWrap {
// ...
private:
Nan::Persistent<Promise> persistentPromise; // not a pointer!
}
NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
// ... your function call here
// returnobj is a Local<Object>
Local<Promise> p = Local<Promise>::Cast(returnobj);
obj->persistentPromise.Reset(p);
}
NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.This());
Local<Promise> p = obj->persistentPromise.Get(Isolate::GetCurrent());
info.GetReturnValue().Set(p->State());
}
I don't know if there's ever a valid reason to take the address of or dereference a v8 type as an embedder (looking at your callback invocation and how you were setting the persistent handle). There are API methods that do these things safely.
BTW, Handle
is deprecated; Local
is its replacement.
add a comment |
You can store Promises in persistent handles. Your code should look something like:
class MyObject : public ObjectWrap {
// ...
private:
Nan::Persistent<Promise> persistentPromise; // not a pointer!
}
NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
// ... your function call here
// returnobj is a Local<Object>
Local<Promise> p = Local<Promise>::Cast(returnobj);
obj->persistentPromise.Reset(p);
}
NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.This());
Local<Promise> p = obj->persistentPromise.Get(Isolate::GetCurrent());
info.GetReturnValue().Set(p->State());
}
I don't know if there's ever a valid reason to take the address of or dereference a v8 type as an embedder (looking at your callback invocation and how you were setting the persistent handle). There are API methods that do these things safely.
BTW, Handle
is deprecated; Local
is its replacement.
You can store Promises in persistent handles. Your code should look something like:
class MyObject : public ObjectWrap {
// ...
private:
Nan::Persistent<Promise> persistentPromise; // not a pointer!
}
NAN_METHOD(CallAsyncFunction) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
// ... your function call here
// returnobj is a Local<Object>
Local<Promise> p = Local<Promise>::Cast(returnobj);
obj->persistentPromise.Reset(p);
}
NAN_METHOD(IsPromiseResolved) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.This());
Local<Promise> p = obj->persistentPromise.Get(Isolate::GetCurrent());
info.GetReturnValue().Set(p->State());
}
I don't know if there's ever a valid reason to take the address of or dereference a v8 type as an embedder (looking at your callback invocation and how you were setting the persistent handle). There are API methods that do these things safely.
BTW, Handle
is deprecated; Local
is its replacement.
answered Dec 29 '18 at 22:08
ZachBZachB
5,27913159
5,27913159
add a comment |
add a comment |
Ok, so it looks like v8 Promise is not an object that can be made persistent.
But you can do this:
Add resolve and reject callbacks to the promise so that you get informed when the promise is resolved/rejected.
(I would have liked to add "direct c++ callbacks" instead of having to go via JS, but thats ok for now.)
Or you create a Resolver in your code, which can be made persistent and you can resolve or reject your resolver later in you code.
(Which was another way around my problem for me - maybe looking in that direction also helps you?)
add a comment |
Ok, so it looks like v8 Promise is not an object that can be made persistent.
But you can do this:
Add resolve and reject callbacks to the promise so that you get informed when the promise is resolved/rejected.
(I would have liked to add "direct c++ callbacks" instead of having to go via JS, but thats ok for now.)
Or you create a Resolver in your code, which can be made persistent and you can resolve or reject your resolver later in you code.
(Which was another way around my problem for me - maybe looking in that direction also helps you?)
add a comment |
Ok, so it looks like v8 Promise is not an object that can be made persistent.
But you can do this:
Add resolve and reject callbacks to the promise so that you get informed when the promise is resolved/rejected.
(I would have liked to add "direct c++ callbacks" instead of having to go via JS, but thats ok for now.)
Or you create a Resolver in your code, which can be made persistent and you can resolve or reject your resolver later in you code.
(Which was another way around my problem for me - maybe looking in that direction also helps you?)
Ok, so it looks like v8 Promise is not an object that can be made persistent.
But you can do this:
Add resolve and reject callbacks to the promise so that you get informed when the promise is resolved/rejected.
(I would have liked to add "direct c++ callbacks" instead of having to go via JS, but thats ok for now.)
Or you create a Resolver in your code, which can be made persistent and you can resolve or reject your resolver later in you code.
(Which was another way around my problem for me - maybe looking in that direction also helps you?)
answered Aug 15 '18 at 8:07


GerritPGerritP
133
133
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51081091%2fhow-to-check-in-an-node-js-c-addon-if-a-promise-is-resolved%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
htoEEguZk,fID1Cw0Ex