Skip to content

Napi::Reference not copyable, but semantically could be copyable #301

@DaAitch

Description

@DaAitch

Hi,

I don't understand why Napi::Reference can't be copied, although for Napi::Error it is allowed, implemented as protected. From technical point of view, the C-API allows create multiple reference holders of one value. When using lambdas captures we need copyable types.

Look at the following example. A 3rd party lib allocates some memory we want to store in an Napi::External with a finalizer. We need to reference handle to overlive lambda where it is freed and after handle is unreferenced.

// variable
Napi::Reference<Napi::External<H> > handle_; // H is handle type

Napi::Value MyClass::Alloc(const Napi::CallbackInfo& info) {
  Napi::EscapableHandleScope scope(info.Env());
  
  unsigned int size = info[0].ToNumber().Uint32Value();
  unsigned char* mem = lib_alloc(handle_.Value().Data(), size); // 3rd party alloc

  // lambda not copyable, because capture are not copyable

  // Either A)
  // create new Reference
  return scope.Escape(DMA<unsigned char>::constructor.New({
    // Napi::Persistent is noncopyable 
    Napi::External<unsigned char>::New(info.Env(), mem, [size, handle = Napi::Persistent(handle_.Value())](Napi::Env env, unsigned char* data) {
      lib_free(handle.Value().Data(), data, size); // 3rd party free
    })
  }));

  // Or B)
  // copy Reference
  return scope.Escape(DMA<unsigned char>::constructor.New({
    // Napi::Persistent is noncopyable 
    Napi::External<unsigned char>::New(info.Env(), mem, [size, handle = handle_](Napi::Env env, unsigned char* data) {
      lib_free(handle.Value().Data(), data, size); // 3rd party free
    })
  }));
}

I think we should make Napi::Reference copyable.
What do you think?

Best Regards
Philipp

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