Proper Method for Storing JavaScript Instances in Nan::ObjectWrap C++ Class

99 Views Asked by At

Let's say I have two classes that are developed in C++, but are exposed using Nan NodeJS native modules. For example, a "Sprite" and "Texture" class.

In the JavaScript, I want to be able to have a Sprite store a Texture as if it were just another property:

// Local instance of texture
var t = new Texture();

// Global instances of Sprites that won't be GC'd
global.spr = new Sprite();
global.spr2 = new Sprite();

// Same texture can be assigned to multiple sprites
spr.texture = t;
spr2.texture = t;

console.log(spr.texture);

On the C++ side of things, the "texture" property of the Sprite would be a Getter/Setter that stores or retrieves the Texture. The question is though, what would be the proper way to store an instance of Texture internally (from the provided v8::Local)? Like, what do I need to do to register it as "owned" by the Sprite and cause it not to get GC'd as it probably would be in the example above?

1

There are 1 best solutions below

0
On BEST ANSWER

You can have a Persistent handle as a member of your Sprite class that stores the Texture instance. The Sprite destructor needs to reset the the handle to avoid a leak.

class Sprite : public Nan::ObjectWrap {
public:
  Nan::Persistent<v8::Object> textureHandle;

  static NAN_SETTER(SetTexture) {
    Sprite* sprite = Nan::ObjectWrap::Unwrap<Sprite>(info.This());
    if (Nan::New(Texture::constructor)->HasInstance(value)) {
      sprite->textureHandle.Reset(value);
    } else {
      // value wasn't a Texture instance; do something
    }
  }

  static NAN_GETTER(GetTexture) {
    Sprite* sprite = Nan::ObjectWrap::Unwrap<Sprite>(info.This());
    Isolate* iso = Isolate::GetCurrent();
    if (sprite->textureHandle.IsEmpty()) {
      // Texture hasn't been set yet; do something
    } else {
      info.GetReturnValue().Set(sprite->TextureHandle.Get(iso));
    }
  }

  ~Sprite() {
    textureHandle.Reset();
  }
}

(Not shown: the initialization code to register the getter/setter.)