Skip to content

Is it safe to use Napi::Addon and Napi::ObjectWrap together? #1097

Closed

Description

@Patick-Bateman

I have an addon which contains most methods on class inherited from Napi::Addon, and i have another class (SimpleObject in this example) whose lifetime needs to be bound to JS code. Is it safe to use it like in the example below, or there is a better alternative? Thx.

Example (simplified):

class SimpleObject : public Napi::ObjectWrap<SimpleObject> {
  static Napi::Object Init(Napi::Env env, Napi::Object exports) {
    std::string class_name = "SimpleObject";

    Napi::Function constructor = DefineClass(env, class_name.c_str(), {
        InstanceMethod("getValue", &SimpleObject::GetValue),
    });

    auto* constructor_ref = new Napi::FunctionReference();

    *constructor_ref = Napi::Persistent(constructor);

    exports.Set(class_name, constructor);

    env.SetInstanceData(constructor_ref);

    return exports;
  }
};

class SimpleAddon : public Napi::Addon<SimpleAddon> {
public:
  SimpleAddon(Napi::Env env, Napi::Object exports) {
      SimpleObject::Init(env, exports); // init SimpleObject here as well
  
      DefineAddon(exports, {
      InstanceMethod("someMethod", &SimpleAddon::SomeMethod),
  });  
  }
};

NODE_API_ADDON(SimpleAddon)

Activity

  1. gabrielschulhof commented on Nov 5, 2021

    @gabrielschulhof
    Contributor

    @Patick-Bateman Napi::Addon uses env.SetInstanceData() internally, so setting the constructor as the instance data will overwrite Napi::Addon's data. You will want to store the persistent reference to the constructor as an instance variable of your SimpleAddon class:

    class SimpleObject : public Napi::ObjectWrap<SimpleObject> {
      static Napi::FunctionReference Init(Napi::Env env, Napi::Object exports) {
        std::string class_name = "SimpleObject";
    
        Napi::Function constructor = DefineClass(env, class_name.c_str(), {
            InstanceMethod("getValue", &Receipt::GetValue),
        });
    
        return Napi::Persistent(constructor);
      }
    };
    
    class SimpleAddon : public Napi::Addon<SimpleAddon> {
    public:
      SimpleAddon(Napi::Env env, Napi::Object exports) {
          simple_object_constructor = SimpleObject::init(env);
    
          exports["SimpleObject"] = simple_object_constructor.Value();  
    
          DefineAddon(exports, {
          InstanceMethod("someMethod", &SimpleAddon::SomeMethod),
          
      });  
      }
    private:
      Napi::FunctionReference simple_object_constructor;
    };
    
    NODE_API_ADDON(SimpleAddon)
  2. added a commit that references this issue on Sep 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions