From bf8d5e2588aa9487708707704fd6ee5d6063d31f Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Sat, 30 May 2015 20:49:35 -0500 Subject: [PATCH 1/2] Add support for Node v0.12.x - c++ native API Fix KABA-CCEAC/node-usb-detection#6 --- binding.gyp | 3 + package.json | 6 +- src/detection.cpp | 167 ++++++++++++++++++++++++---------------------- src/detection.h | 15 +++-- 4 files changed, 105 insertions(+), 86 deletions(-) diff --git a/binding.gyp b/binding.gyp index 0165a07..25bea41 100644 --- a/binding.gyp +++ b/binding.gyp @@ -7,6 +7,9 @@ "src/detection.h", "src/deviceList.cpp" ], + "include_dirs" : [ + "=0.4.11" + "eventemitter2": ">=0.4.11", + "nan": "^1.8.4" }, "gypfile": true, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "preinstall": "node-gyp rebuild" + "postinstall": "node-gyp rebuild" }, "repository": { "type": "git", @@ -19,6 +20,7 @@ "keywords": [ "usb", "list", + "insert", "add", "remove", "change", diff --git a/src/detection.cpp b/src/detection.cpp index 82e477a..af5c474 100644 --- a/src/detection.cpp +++ b/src/detection.cpp @@ -10,21 +10,22 @@ #define OBJECT_ITEM_DEVICE_ADDRESS "deviceAddress" -v8::Persistent addedCallback; +NanCallback* addedCallback; bool isAddedRegistered = false; -v8::Persistent removedCallback; +NanCallback* removedCallback; bool isRemovedRegistered = false; -v8::Handle RegisterAdded(const v8::Arguments& args) +void RegisterAdded(const v8::FunctionCallbackInfo& args) { - v8::HandleScope scope; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); - v8::Local callback; + v8::Local callback; if (args.Length() == 0) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("First argument must be a function")))); + return NanThrowTypeError("First argument must be a function"); } if (args.Length() == 1) @@ -32,44 +33,52 @@ v8::Handle RegisterAdded(const v8::Arguments& args) // callback if(!args[0]->IsFunction()) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("First argument must be a function")))); + return NanThrowTypeError("First argument must be a function"); } - callback = args[0]; + callback = args[0].As(); } - addedCallback = v8::Persistent::New(callback); + addedCallback = new NanCallback(callback); isAddedRegistered = true; - - return scope.Close(v8::Undefined()); } void NotifyAdded(ListResultItem_t* it) { - if (isAddedRegistered) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + + if (isAddedRegistered) { v8::Handle argv[1]; - v8::Local item = v8::Object::New(); - item->Set(v8::String::New(OBJECT_ITEM_LOCATION_ID), v8::Number::New(it->locationId)); - item->Set(v8::String::New(OBJECT_ITEM_VENDOR_ID), v8::Number::New(it->vendorId)); - item->Set(v8::String::New(OBJECT_ITEM_PRODUCT_ID), v8::Number::New(it->productId)); - item->Set(v8::String::New(OBJECT_ITEM_DEVICE_NAME), v8::String::New(it->deviceName.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_MANUFACTURER), v8::String::New(it->manufacturer.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_SERIAL_NUMBER), v8::String::New(it->serialNumber.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_DEVICE_ADDRESS), v8::Number::New(it->deviceAddress)); + v8::Local item = v8::Object::New(isolate); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_LOCATION_ID), v8::Number::New(isolate, it->locationId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_VENDOR_ID), v8::Number::New(isolate, it->vendorId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_PRODUCT_ID), v8::Number::New(isolate, it->productId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_DEVICE_NAME), v8::String::NewFromUtf8(isolate, it->deviceName.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_MANUFACTURER), v8::String::NewFromUtf8(isolate, it->manufacturer.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_SERIAL_NUMBER), v8::String::NewFromUtf8(isolate, it->serialNumber.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_DEVICE_ADDRESS), v8::Number::New(isolate, it->deviceAddress)); argv[0] = item; - v8::Function::Cast(*addedCallback)->Call(v8::Context::GetCurrent()->Global(), 1, argv); + //v8::Function::Cast(*addedCallback)->Call(isolate->GetCurrentContext()->Global(), 1, argv); + //v8::Local cb = v8::Local::New(isolate, addedCallback); + //NanCallback *callback = new NanCallback(cb); + //v8::Handle nan_argv[] = { + // NanNew(argv[0]) + //}; + addedCallback->Call(1, argv); } } -v8::Handle RegisterRemoved(const v8::Arguments& args) { - v8::HandleScope scope; +void RegisterRemoved(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); - v8::Local callback; + v8::Local callback; if (args.Length() == 0) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("First argument must be a function")))); + return NanThrowTypeError("First argument must be a function"); } if (args.Length() == 1) @@ -77,47 +86,52 @@ v8::Handle RegisterRemoved(const v8::Arguments& args) { // callback if(!args[0]->IsFunction()) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("First argument must be a function")))); + return NanThrowTypeError("First argument must be a function"); } - callback = args[0]; + callback = args[0].As(); } - removedCallback = v8::Persistent::New(callback); + removedCallback = new NanCallback(callback); isRemovedRegistered = true; - - return scope.Close(v8::Undefined()); } void NotifyRemoved(ListResultItem_t* it) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + if (isRemovedRegistered) { v8::Handle argv[1]; - v8::Local item = v8::Object::New(); - item->Set(v8::String::New(OBJECT_ITEM_LOCATION_ID), v8::Number::New(it->locationId)); - item->Set(v8::String::New(OBJECT_ITEM_VENDOR_ID), v8::Number::New(it->vendorId)); - item->Set(v8::String::New(OBJECT_ITEM_PRODUCT_ID), v8::Number::New(it->productId)); - item->Set(v8::String::New(OBJECT_ITEM_DEVICE_NAME), v8::String::New(it->deviceName.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_MANUFACTURER), v8::String::New(it->manufacturer.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_SERIAL_NUMBER), v8::String::New(it->serialNumber.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_DEVICE_ADDRESS), v8::Number::New(it->deviceAddress)); + v8::Local item = v8::Object::New(isolate); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_LOCATION_ID), v8::Number::New(isolate, it->locationId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_VENDOR_ID), v8::Number::New(isolate, it->vendorId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_PRODUCT_ID), v8::Number::New(isolate, it->productId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_DEVICE_NAME), v8::String::NewFromUtf8(isolate, it->deviceName.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_MANUFACTURER), v8::String::NewFromUtf8(isolate, it->manufacturer.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_SERIAL_NUMBER), v8::String::NewFromUtf8(isolate, it->serialNumber.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_DEVICE_ADDRESS), v8::Number::New(isolate, it->deviceAddress)); argv[0] = item; - v8::Function::Cast(*removedCallback)->Call(v8::Context::GetCurrent()->Global(), 1, argv); + //v8::Function::Cast(*removedCallback)->Call(v8::Context::GetCurrent()->Global(), 1, argv); + //v8::Local cb = v8::Local::New(isolate, removedCallback); + //NanCallback *callback = new NanCallback(cb); + removedCallback->Call(1, argv); } } -v8::Handle Find(const v8::Arguments& args) +void Find(const v8::FunctionCallbackInfo& args) { - v8::HandleScope scope; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); int vid = 0; int pid = 0; - v8::Local callback; + v8::Local callback; if (args.Length() == 0) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("First argument must be a function")))); + return NanThrowTypeError("First argument must be a function"); } if (args.Length() == 3) @@ -131,10 +145,10 @@ v8::Handle Find(const v8::Arguments& args) // callback if(!args[2]->IsFunction()) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("Third argument must be a function")))); + return NanThrowTypeError("Third argument must be a function"); } - callback = args[2]; + callback = args[2].As(); } if (args.Length() == 2) @@ -147,10 +161,10 @@ v8::Handle Find(const v8::Arguments& args) // callback if(!args[1]->IsFunction()) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("Second argument must be a function")))); + return NanThrowTypeError("Second argument must be a function"); } - callback = args[1]; + callback = args[1].As(); } if (args.Length() == 1) @@ -158,56 +172,62 @@ v8::Handle Find(const v8::Arguments& args) // callback if(!args[0]->IsFunction()) { - return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("First argument must be a function")))); + return NanThrowTypeError("First argument must be a function"); } - callback = args[0]; + callback = args[0].As(); } ListBaton* baton = new ListBaton(); strcpy(baton->errorString, ""); - baton->callback = v8::Persistent::New(callback); + baton->callback = new NanCallback(callback); + //baton->callback = v8::Persistent::New(isolate, callback); + //NanAssignPersistent(baton->callback, new NanCallback(callback)); baton->vid = vid; baton->pid = pid; uv_work_t* req = new uv_work_t(); req->data = baton; uv_queue_work(uv_default_loop(), req, EIO_Find, (uv_after_work_cb)EIO_AfterFind); - - return scope.Close(v8::Undefined()); } void EIO_AfterFind(uv_work_t* req) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + ListBaton* data = static_cast(req->data); v8::Handle argv[2]; if(data->errorString[0]) { - argv[0] = v8::Exception::Error(v8::String::New(data->errorString)); - argv[1] = v8::Undefined(); - } + argv[0] = v8::Exception::Error(v8::String::NewFromUtf8(isolate, data->errorString)); + argv[1] = NanUndefined(); + } else { - v8::Local results = v8::Array::New(); + v8::Local results = v8::Array::New(isolate); int i = 0; for(std::list::iterator it = data->results.begin(); it != data->results.end(); it++, i++) { - v8::Local item = v8::Object::New(); - item->Set(v8::String::New(OBJECT_ITEM_LOCATION_ID), v8::Number::New((*it)->locationId)); - item->Set(v8::String::New(OBJECT_ITEM_VENDOR_ID), v8::Number::New((*it)->vendorId)); - item->Set(v8::String::New(OBJECT_ITEM_PRODUCT_ID), v8::Number::New((*it)->productId)); - item->Set(v8::String::New(OBJECT_ITEM_DEVICE_NAME), v8::String::New((*it)->deviceName.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_MANUFACTURER), v8::String::New((*it)->manufacturer.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_SERIAL_NUMBER), v8::String::New((*it)->serialNumber.c_str())); - item->Set(v8::String::New(OBJECT_ITEM_DEVICE_ADDRESS), v8::Number::New((*it)->deviceAddress)); + v8::Local item = v8::Object::New(isolate); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_LOCATION_ID), v8::Number::New(isolate, (*it)->locationId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_VENDOR_ID), v8::Number::New(isolate, (*it)->vendorId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_PRODUCT_ID), v8::Number::New(isolate, (*it)->productId)); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_DEVICE_NAME), v8::String::NewFromUtf8(isolate, (*it)->deviceName.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_MANUFACTURER), v8::String::NewFromUtf8(isolate, (*it)->manufacturer.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_SERIAL_NUMBER), v8::String::NewFromUtf8(isolate, (*it)->serialNumber.c_str())); + item->Set(v8::String::NewFromUtf8(isolate, OBJECT_ITEM_DEVICE_ADDRESS), v8::Number::New(isolate, (*it)->deviceAddress)); results->Set(i, item); } - argv[0] = v8::Undefined(); + argv[0] = NanUndefined(); argv[1] = results; } - v8::Function::Cast(*data->callback)->Call(v8::Context::GetCurrent()->Global(), 2, argv); + //v8::Function::Cast(*data->callback)->Call(v8::Context::GetCurrent()->Global(), 2, argv); + //v8::Local cb = v8::Local::New(isolate, data->callback.As()); + //NanCallback *callback = new NanCallback(cb); + data->callback->Call(2, argv); - data->callback.Dispose(); + //data->callback.Dispose(); for(std::list::iterator it = data->results.begin(); it != data->results.end(); it++) { delete *it; @@ -216,28 +236,19 @@ void EIO_AfterFind(uv_work_t* req) delete req; } -v8::Handle StartMonitoring(const v8::Arguments& args) +void StartMonitoring(const v8::FunctionCallbackInfo& args) { - v8::HandleScope scope; - Start(); - - return scope.Close(v8::Undefined()); } -v8::Handle StopMonitoring(const v8::Arguments& args) +void StopMonitoring(const v8::FunctionCallbackInfo& args) { - v8::HandleScope scope; - Stop(); - - return scope.Close(v8::Undefined()); } extern "C" { void init (v8::Handle target) { - v8::HandleScope scope; NODE_SET_METHOD(target, "find", Find); NODE_SET_METHOD(target, "registerAdded", RegisterAdded); NODE_SET_METHOD(target, "registerRemoved", RegisterRemoved); diff --git a/src/detection.h b/src/detection.h index 6a16018..531c59f 100644 --- a/src/detection.h +++ b/src/detection.h @@ -4,37 +4,40 @@ #include #include +#include #include #include #include #include #include +#include #include "deviceList.h" -v8::Handle Find(const v8::Arguments& args); +void Find(const v8::FunctionCallbackInfo& args); void EIO_Find(uv_work_t* req); void EIO_AfterFind(uv_work_t* req); void InitDetection(); -v8::Handle StartMonitoring(const v8::Arguments& args); +void StartMonitoring(const v8::FunctionCallbackInfo& args); void Start(); -v8::Handle StopMonitoring(const v8::Arguments& args); +void StopMonitoring(const v8::FunctionCallbackInfo& args); void Stop(); struct ListBaton { public: - v8::Persistent callback; + //v8::Persistent callback; + NanCallback* callback; std::list results; char errorString[1024]; int vid; int pid; }; -v8::Handle RegisterAdded(const v8::Arguments& args); +void RegisterAdded(const v8::FunctionCallbackInfo& args); void NotifyAdded(ListResultItem_t* it); -v8::Handle RegisterRemoved(const v8::Arguments& args); +void RegisterRemoved(const v8::FunctionCallbackInfo& args); void NotifyRemoved(ListResultItem_t* it); #endif From f531a64e84cd296d2f70a9a7d9a389756941f69e Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Sat, 30 May 2015 20:51:46 -0500 Subject: [PATCH 2/2] Bump version v1.1.0 --- README.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b8d010b..e093908 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,10 @@ monitor.on('change:vid:pid', function(err, devices) {}); # Release Notes +## v1.1.0 + + - Add support for Node v0.12.x + ## v1.0.3 - revert "ready for node >= 0.11.4" diff --git a/package.json b/package.json index 8b11fc7..61b101f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "usb-detection", - "version": "1.0.3", + "version": "1.1.0", "description": "List USB devices in system and detect changes on them.", "main": "index.js", "dependencies": {