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

Multi tool use
Multi tool use












1















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.)










share|improve this question



























    1















    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.)










    share|improve this question

























      1












      1








      1








      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.)










      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jun 28 '18 at 10:54









      GerritPGerritP

      133




      133
























          2 Answers
          2






          active

          oldest

          votes


















          0














          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.






          share|improve this answer































            0














            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?)






            share|improve this answer























              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
              });


              }
              });














              draft saved

              draft discarded


















              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









              0














              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.






              share|improve this answer




























                0














                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.






                share|improve this answer


























                  0












                  0








                  0







                  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.






                  share|improve this answer













                  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.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Dec 29 '18 at 22:08









                  ZachBZachB

                  5,27913159




                  5,27913159

























                      0














                      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?)






                      share|improve this answer




























                        0














                        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?)






                        share|improve this answer


























                          0












                          0








                          0







                          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?)






                          share|improve this answer













                          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?)







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Aug 15 '18 at 8:07









                          GerritPGerritP

                          133




                          133






























                              draft saved

                              draft discarded




















































                              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.




                              draft saved


                              draft discarded














                              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





















































                              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
                              T Bn,V fbouZ,B,Xl AUEkYB3Gu41V0UJGBS0JnG GKvvZxTcf3u1PNmgze KqpR2TU7uauhM6froUQdo45g

                              Popular posts from this blog

                              Monofisismo

                              Angular Downloading a file using contenturl with Basic Authentication

                              Olmecas