Stack Exchange
Can node-webkit C++ addon write to ImageData object created in JavaScript context?
I'm writing a node-webkit addon in C++ that decodes image data and returns an array of pixel data to the caller. The following code (abridged for brevity) works just fine:
caller.js
var image_data = canvas_context.createImageData(w, h);
var addon = require('decoder.node');
var decoder = new addon.Decoder();
var pixel_array = decoder.getPixelArray();
image_data.data.set(pixel_array);
canvas_context.putImageData(image_data);

decoder.cpp
Handle<Value> Decoder::getPixelArray(const Arguments &args) {
    HandleScope scope;

    // unwrap self
    DecoderObj *obj = ObjectWrap::Unwrap<DecoderObj>(args.This());
    if (obj == NULL) return scope.Close(Number::New(1));

    // get pointer to pixel data
    PixelPtr *ptr = NULL;
    uint64_t len = 0;
    obj->GetPixelsPtr((PixelPtr*)&ptr, &len);

    // create javascript native array
    // from http://luismreis.github.io/node-bindings-guide/docs/returning.html
    v8::Handle<Value> fun_val = Context::GetCurrent()->Global()->Get(String::New("Uint8ClampedArray"));
    v8::Handle<Function> fun = v8::Handle<Function>::Cast(fun_val);
    const unsigned argc = 1;
    Local<Value> argv[argc] = { Local<Value>::New(Uint32::New(len)) };
    Local<v8::Object> array = fun->NewInstance(argc, argv);

    // populate js native array with pixel ptr data
    array->SetIndexedPropertiesToExternalArrayData(ptr, v8::kExternalUnsignedByteArray, len);

    // return native array to javascript caller
    return scope.Close(array);
}

The only problem is when the caller invokes the set() method on the ImageData object. This has proven to be unacceptably slow (i.e. >= 20ms). I assume the slowness is due to a large amount of data being copied from one memory location to another. So I thought I'd try to fix this by passing a reference to the ImageData object into the addon, and then have the addon write directly to the object, thereby eliminating the need for a memory copy. Unfortunately I haven't been able to get this to work. Here's the modified code that doesn't work:
caller.js
var image_data = canvas_context.createImageData(w, h);
var addon = require('decoder.node');
var decoder = new addon.Decoder();
decoder.getPixelArray(image_data.data);
canvas_context.putImageData(image_data);

decoder.cpp
Handle<Value> Decoder::getPixelArray(const Arguments &args) {
    HandleScope scope;

    // unwrap self
    DecoderObj *obj = ObjectWrap::Unwrap<DecoderObj>(args.This());
    if (obj == NULL) return scope.Close(Number::New(1));

    // convert image_data arg into local array
    Local<Array> array = Array::Cast(*args[0]);

    // get pointer to pixel data
    PixelPtr *ptr = NULL;
    uint64_t len = 0;
    obj->GetPixelsPtr((PixelPtr*)&ptr, &len);

    // populate image_data array with pixel ptr data
    array->SetIndexedPropertiesToExternalArrayData(ptr, v8::kExternalUnsignedByteArray, len);
}

I know this doesn't work because putImageData() results in a black frame, whereas the original code successfully draws the actual frame as expected. 
Here is my question: is it possible to create an ImageData object and/or Uint8ClampedArray in JavaScript, pass it by reference into a Node.js addon, have the addon write to the object's memory location, and then be able to use the object in the JavaScript context without performing a memory copy??
I don't know if I'm doing it wrong, or it's impossible, or both.  :)

Aren't node.js addon and webkit different V8 instances?

@Petr This is a node-webkit addon not node.js. Sorry for the confusion. I edited the post.

are you sure that args[0] can be casted to a plain Array? I would probably try to do it the opposite way - allocate the image, call image decoder with the pointer to its data. This will eliminate the call to .set(), but I'm not really sure if this will work or not.
Btw I'm working on an addon that will bring an asynchronous imaging for node.js (http://blend2d.com), but it's not ready yet.

I think this should work for you http://stackoverflow.com/a/42143138/174527
