#include #include #include #include #include #include #include #include using namespace std; using namespace nomad; namespace nomad { using v8::Function; using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; using v8::Object; using v8::String; using v8::Value; using v8::Number; using v8::Integer; using v8::Boolean; using v8::Array; using v8::Persistent; NomadAccessor accessor; Isolate * v8Isolate; /** * Init function to initialise the Cameo Nomad addon. */ void Init(const FunctionCallbackInfo& args) { // Get the V8 isolate. v8Isolate = args.GetIsolate(); // Get the args. v8::String::Utf8Value param1(args[0]->ToString()); string electronArgs(*param1); // Parse the args. size_t pos = electronArgs.find_last_of(',') + 1; string lastArg = electronArgs.substr(pos, electronArgs.length() - pos); // We only need the last argument that we convert to an array. char *argv[1] = {(char *)lastArg.c_str()}; // Initialise the Nomad accessor. accessor.init(1, argv); accessor.connectNomadServer("tcp://localhost:7000"); args.GetReturnValue().Set(Undefined(v8Isolate)); } /** * Terminate function to terminate the Cameo Nomad addon. */ void Terminate(const FunctionCallbackInfo& args) { accessor.terminate(); } /** * Gets the property id. */ void GetPropertyId(const FunctionCallbackInfo& args) { v8::String::Utf8Value param0(args[0]->ToString()); std::string servantName(*param0); v8::String::Utf8Value param1(args[1]->ToString()); std::string propertyName(*param1); args.GetReturnValue().Set(Number::New(args.GetIsolate(), accessor.getPropertyId(servantName, propertyName))); } /** * Gets the float64 property value. */ void GetFloat64Property(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(Number::New(args.GetIsolate(), accessor.getFloat64Value(Local::Cast(args[0])->Value()))); } /** * Gets the int32 property value. */ void GetInt32Property(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(Number::New(args.GetIsolate(), accessor.getInt32Value(Local::Cast(args[0])->Value()))); } /** * Gets the boolean property value. */ void GetBooleanProperty(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.getBooleanValue(Local::Cast(args[0])->Value()))); } /** * Gets the string property value. */ void GetStringProperty(const FunctionCallbackInfo& args) { string value = accessor.getStringValue(Local::Cast(args[0])->Value()); args.GetReturnValue().Set(String::NewFromUtf8(args.GetIsolate(), value.c_str())); } /** * Gets the int32 array property value. */ void GetInt32ArrayProperty(const FunctionCallbackInfo& args) { Local array = Array::New(args.GetIsolate(), 0); vector arrayValue = accessor.getInt32Array(Local::Cast(args[0])->Value()); for (int i = 0; i < arrayValue.size(); ++i) { array->Set(i, Integer::New(args.GetIsolate(), arrayValue[i])); } args.GetReturnValue().Set(array); } /** * Gets the float64 array property value. */ void GetFloat64ArrayProperty(const FunctionCallbackInfo& args) { Local array = Array::New(args.GetIsolate(), 0); vector arrayValue = accessor.getFloat64Array(Local::Cast(args[0])->Value()); for (int i = 0; i < arrayValue.size(); ++i) { array->Set(i, Number::New(args.GetIsolate(), arrayValue[i])); } args.GetReturnValue().Set(array); } /** * Sets the float64 property value. */ void SetFloat64Property(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setFloat64Value(Local::Cast(args[0])->Value(), Local::Cast(args[1])->Value()))); } /** * Sets the int32 property value. */ void SetInt32Property(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setInt32Value(Local::Cast(args[0])->Value(), Local::Cast(args[1])->Value()))); } /** * Sets the boolean property value. */ void SetBooleanProperty(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setBooleanValue(Local::Cast(args[0])->Value(), Local::Cast(args[1])->Value()))); } /** * Sets the string property value. */ void SetStringProperty(const FunctionCallbackInfo& args) { v8::String::Utf8Value param1(args[1]->ToString()); std::string value(*param1); args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setStringValue(Local::Cast(args[0])->Value(), value))); } /** * Work structure is be used to pass the callback function and data * from the initiating function to the function which triggers the callback. */ template struct Work { uv_work_t request; Persistent callback; Type result; }; static void WorkAsync(uv_work_t *req) { // Do nothing. } /** * WorkAsyncComplete function is called once we are ready to trigger the callback * function in JS. */ template static void WorkAsyncComplete(uv_work_t *req, int status) { Isolate * isolate = Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); Work *work = static_cast *>(req->data); // Get the result and pass it to the JS callback. Local argv[1] = {JSType::New(isolate, work->result)}; // https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065 Local::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv); work->callback.Reset(); delete work; } /** * StringWorkAsyncComplete function is called once we are ready to trigger the callback * function in JS. */ static void StringWorkAsyncComplete(uv_work_t *req, int status) { Isolate * isolate = Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); Work *work = static_cast *>(req->data); // Get the result and pass it to the JS callback. Local argv[1] = {String::NewFromUtf8(isolate, work->result.c_str())}; // https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065 Local::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv); work->callback.Reset(); delete work; } /** * Float64ArrayWorkAsyncComplete function is called once we are ready to trigger the callback * function in JS. */ static void Float64ArrayWorkAsyncComplete(uv_work_t *req, int status) { Isolate * isolate = Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); Work > *work = static_cast > *>(req->data); // Get the result and pass it to the JS callback. Local array = Array::New(isolate, 0); const vector& arrayValue = work->result; for (int i = 0; i < arrayValue.size(); ++i) { array->Set(i, Number::New(isolate, arrayValue[i])); } Local argv[1] = {array}; // https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065 Local::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv); work->callback.Reset(); delete work; } /** * Int32ArrayWorkAsyncComplete function is called once we are ready to trigger the callback * function in JS. */ static void Int32ArrayWorkAsyncComplete(uv_work_t *req, int status) { Isolate * isolate = Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); Work > *work = static_cast > *>(req->data); // Get the result and pass it to the JS callback. Local array = Array::New(isolate, 0); const vector& arrayValue = work->result; for (int i = 0; i < arrayValue.size(); ++i) { array->Set(i, Integer::New(isolate, arrayValue[i])); } Local argv[1] = {array}; // https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065 Local::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv); work->callback.Reset(); delete work; } template void PropertyChanged(Persistent* callback, Type value) { Work * work = new Work(); work->request.data = work; work->callback.Reset(v8Isolate, *callback); work->result = value; uv_queue_work(uv_default_loop(), &work->request, WorkAsync, WorkAsyncComplete); } void StringPropertyChanged(Persistent* callback, const std::string& value) { Work * work = new Work(); work->request.data = work; work->callback.Reset(v8Isolate, *callback); work->result = value; uv_queue_work(uv_default_loop(), &work->request, WorkAsync, StringWorkAsyncComplete); } void Float64ArrayPropertyChanged(Persistent* callback, const std::vector& value) { Work > * work = new Work >(); work->request.data = work; work->callback.Reset(v8Isolate, *callback); work->result = value; uv_queue_work(uv_default_loop(), &work->request, WorkAsync, Float64ArrayWorkAsyncComplete); } void Int32ArrayPropertyChanged(Persistent* callback, const std::vector& value) { Work > * work = new Work >(); work->request.data = work; work->callback.Reset(v8Isolate, *callback); work->result = value; uv_queue_work(uv_default_loop(), &work->request, WorkAsync, Int32ArrayWorkAsyncComplete); } void RegisterFloat64PropertyChanged(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); int propertyId = Local::Cast(args[0])->Value(); Local callback = Local::Cast(args[1]); // The persistent function callback is allocated (should not) to allow to use it through the boost function parameter. // That could lead to a memory leak. Persistent* pCallback = new Persistent(); pCallback->Reset(isolate, callback); accessor.registerFloat64PropertyChanged(propertyId, boost::bind(&PropertyChanged, pCallback, _1)); args.GetReturnValue().Set(Undefined(isolate)); } void RegisterInt32PropertyChanged(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); int propertyId = Local::Cast(args[0])->Value(); Local callback = Local::Cast(args[1]); // The persistent function callback is allocated (should not) to allow to use it through the boost function parameter. // That could lead to a memory leak. Persistent* pCallback = new Persistent(); pCallback->Reset(isolate, callback); accessor.registerInt32PropertyChanged(propertyId, boost::bind(&PropertyChanged, pCallback, _1)); args.GetReturnValue().Set(Undefined(isolate)); } void RegisterBooleanPropertyChanged(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); int propertyId = Local::Cast(args[0])->Value(); Local callback = Local::Cast(args[1]); // The persistent function callback is allocated (should not) to allow to use it through the boost function parameter. // That could lead to a memory leak. Persistent* pCallback = new Persistent(); pCallback->Reset(isolate, callback); accessor.registerBooleanPropertyChanged(propertyId, boost::bind(&PropertyChanged, pCallback, _1)); args.GetReturnValue().Set(Undefined(isolate)); } void RegisterStringPropertyChanged(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); int propertyId = Local::Cast(args[0])->Value(); Local callback = Local::Cast(args[1]); // The persistent function callback is allocated (should not) to allow to use it through the boost function parameter. // That could lead to a memory leak. Persistent* pCallback = new Persistent(); pCallback->Reset(isolate, callback); accessor.registerStringPropertyChanged(propertyId, boost::bind(&StringPropertyChanged, pCallback, _1)); args.GetReturnValue().Set(Undefined(isolate)); } void RegisterFloat64ArrayPropertyChanged(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); int propertyId = Local::Cast(args[0])->Value(); Local callback = Local::Cast(args[1]); // The persistent function callback is allocated (should not) to allow to use it through the boost function parameter. // That could lead to a memory leak. Persistent* pCallback = new Persistent(); pCallback->Reset(isolate, callback); accessor.registerFloat64ArrayPropertyChanged(propertyId, boost::bind(&Float64ArrayPropertyChanged, pCallback, _1)); args.GetReturnValue().Set(Undefined(isolate)); } void RegisterInt32ArrayPropertyChanged(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); int propertyId = Local::Cast(args[0])->Value(); Local callback = Local::Cast(args[1]); // The persistent function callback is allocated (should not) to allow to use it through the boost function parameter. // That could lead to a memory leak. Persistent* pCallback = new Persistent(); pCallback->Reset(isolate, callback); accessor.registerInt32ArrayPropertyChanged(propertyId, boost::bind(&Int32ArrayPropertyChanged, pCallback, _1)); args.GetReturnValue().Set(Undefined(isolate)); } /** * The init function declares what we will make visible to node. */ void init(Local exports) { // Register the functions. NODE_SET_METHOD(exports, "init", Init); NODE_SET_METHOD(exports, "terminate", Terminate); NODE_SET_METHOD(exports, "getPropertyId", GetPropertyId); NODE_SET_METHOD(exports, "getFloat64Property", GetFloat64Property); NODE_SET_METHOD(exports, "getInt32Property", GetInt32Property); NODE_SET_METHOD(exports, "getBooleanProperty", GetBooleanProperty); NODE_SET_METHOD(exports, "getStringProperty", GetStringProperty); NODE_SET_METHOD(exports, "getInt32ArrayProperty", GetInt32ArrayProperty); NODE_SET_METHOD(exports, "getFloat64ArrayProperty", GetFloat64ArrayProperty); NODE_SET_METHOD(exports, "setFloat64Property", SetFloat64Property); NODE_SET_METHOD(exports, "setInt32Property", SetInt32Property); NODE_SET_METHOD(exports, "setStringProperty", SetStringProperty); NODE_SET_METHOD(exports, "setBooleanProperty", SetBooleanProperty); NODE_SET_METHOD(exports, "registerFloat64PropertyChanged", RegisterFloat64PropertyChanged); NODE_SET_METHOD(exports, "registerInt32PropertyChanged", RegisterInt32PropertyChanged); NODE_SET_METHOD(exports, "registerBooleanPropertyChanged", RegisterBooleanPropertyChanged); NODE_SET_METHOD(exports, "registerStringPropertyChanged", RegisterStringPropertyChanged); NODE_SET_METHOD(exports, "registerFloat64ArrayPropertyChanged", RegisterFloat64ArrayPropertyChanged); NODE_SET_METHOD(exports, "registerInt32ArrayPropertyChanged", RegisterInt32ArrayPropertyChanged); } NODE_MODULE(cameonomadAddon, init) }