Hi Node.js Gurus!
When writing a node.js extension how do you safely return an object that
has node::Buffer properties safely so they don't get garbage collected
afterwards?
Code extract from my node-sodium library, a port of lib sodium to node.
#define NEW_BUFFER_AND_PTR(name, size) \
Buffer* name = Buffer::New(size); \
unsigned char* name ## _ptr = (unsigned char*)Buffer::Data(name)
Handle<Value> bind_crypto_sign_keypair(const Arguments& args) {
HandleScope scope;
NEW_BUFFER_AND_PTR(vk, crypto_sign_PUBLICKEYBYTES);
NEW_BUFFER_AND_PTR(sk, crypto_sign_SECRETKEYBYTES);
if( crypto_sign_keypair(vk_ptr, sk_ptr) == 0) {
Local<Object> result = Object::New();
result->Set(String::NewSymbol("publicKey"), vk->handle_);
result->Set(String::NewSymbol("secretKey"), sk->handle_);
return scope.Close(result);
}
return scope.Close(Undefined());
}
This function creates a set of public and secret keys used for signing.
In Javascript I do
var keys = binding.crypto_sign_keypair();
console.log(keys.publicKey);
console.log(keys.secretKey);
This works, but sometimes garbage collection is run and the buffers become
invalid, and all I get is a stack dump and a crash that starts with the
output:
#
# Fatal error in ../deps/v8/src/api.h, line 297
# CHECK(allow_empty_handle || that != __null) failed
#
==== Stack trace ============================================
Security context: 0x2190c4706b71 <JS Object>#0#
Got a suggestion to store the buffer handle in a Local like so
Handle<Value> bind_crypto_box_keypair(const Arguments& args) {
HandleScope scope;
NEW_BUFFER_AND_PTR(pk, crypto_box_PUBLICKEYBYTES);
NEW_BUFFER_AND_PTR(sk, crypto_box_SECRETKEYBYTES);
if( crypto_box_keypair(pk_ptr, sk_ptr) == 0) {
Local<Object> result = Object::New();
// Make sure the key buffers are not garbage collected
Local<Value> pkH = pk->handle_;
Local<Value> skH = sk->handle_;
result->Set(String::NewSymbol("publicKey"), pkH, DontDelete);
result->Set(String::NewSymbol("secretKey"), skH, DontDelete);
return scope.Close(result);
}
return scope.Close(Undefined());
}
But now I get the following compilation error:
../sodium.cc:865:22: error: no viable conversion from
'v8::Persistent<v8::Object>' to 'Local<v8::Value>'
Local<Value> skH = sk->handle_;
^ ~~~~~~~~~~~
/Users/xx/.node-gyp/0.10.26/deps/v8/include/v8.h:269:26: note: candidate
constructor (the implicit copy constructor) not viable: no known
conversion from 'v8::Persistent<v8::Object>' to 'const
v8::Local<v8::Value> &' for 1st argument
template <class T> class Local : public Handle<T> {
^
/Users/xx/.node-gyp/0.10.26/deps/v8/include/v8.h:272:29: note: candidate
template ignored: could not match 'Local' against 'Persistent'
template <class S> inline Local(Local<S> that)
^
/Users/xx/.node-gyp/0.10.26/deps/v8/include/v8.h:281:29: note: candidate
template ignored: could not match 'S *' against
'v8::Persistent<v8::Object>'
template <class S> inline Local(S* that) : Handle<T>(that) { }
What am I doing wrong and what is the proper way to return buffers inside
objects to javascript from a C extension?
Any help is very appreciated. I am stuck!
--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
---
You received this message because you are subscribed to the Google Groups
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.