Add packaging for npm and improve serialisation of numerical types git-svn-id: https://svn.apache.org/repos/asf/qpid/proton/branches/fadams-javascript-binding@1591980 13f79535-47bb-0310-9956-ffa450edef68
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/80c99528 Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/80c99528 Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/80c99528 Branch: refs/heads/master Commit: 80c995287c2ad4efee2a479b74bed3bf1984f2fd Parents: 33c895e Author: fadams <fadams@unknown> Authored: Fri May 2 17:30:42 2014 +0000 Committer: fadams <fadams@unknown> Committed: Fri May 2 17:30:42 2014 +0000 ---------------------------------------------------------------------- examples/messenger/c/CMakeLists.txt | 4 + examples/messenger/javascript/drain.js | 62 ++++++ examples/messenger/javascript/spout.js | 104 ++++++++++ proton-c/bindings/javascript/CMakeLists.txt | 32 ++- proton-c/bindings/javascript/README | 40 ++-- proton-c/bindings/javascript/binding.js | 118 +++++++++-- proton-c/bindings/javascript/drain.js | 63 ------ .../bindings/javascript/qpid-proton/LICENSE | 203 +++++++++++++++++++ .../bindings/javascript/qpid-proton/README.md | 4 + .../javascript/qpid-proton/package.json | 11 + proton-c/bindings/javascript/spout.js | 100 --------- proton-c/src/messenger/messenger.c | 4 + tools/cmake/Modules/FindNodePackages.cmake | 70 ++++--- 13 files changed, 572 insertions(+), 243 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/examples/messenger/c/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/messenger/c/CMakeLists.txt b/examples/messenger/c/CMakeLists.txt index 4f40924..1b32d0c 100644 --- a/examples/messenger/c/CMakeLists.txt +++ b/examples/messenger/c/CMakeLists.txt @@ -21,8 +21,12 @@ find_package(Proton REQUIRED) add_executable(recv recv.c) add_executable(send send.c) +add_executable(recv-async recv-async.c) +add_executable(send-async send-async.c) include_directories(${Proton_INCLUDE_DIRS}) target_link_libraries(recv ${Proton_LIBRARIES}) target_link_libraries(send ${Proton_LIBRARIES}) +target_link_libraries(recv-async ${Proton_LIBRARIES}) +target_link_libraries(send-async ${Proton_LIBRARIES}) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/examples/messenger/javascript/drain.js ---------------------------------------------------------------------- diff --git a/examples/messenger/javascript/drain.js b/examples/messenger/javascript/drain.js new file mode 100644 index 0000000..eacd8a2 --- /dev/null +++ b/examples/messenger/javascript/drain.js @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +// Check if the environment is Node.js and if so import the required library. +if (typeof exports !== "undefined" && exports !== null) { + proton = require("qpid-proton"); +} + +try { + var address = "amqp://~0.0.0.0"; + var message = new proton.Message(); + var messenger = new proton.Messenger(); + + function _process() { +// console.log(" *** process ***"); + + // Process incoming messages + + while (messenger.incoming()) { +console.log("in while loop\n"); + + var tracker = messenger.get(message); +console.log("tracker = " + tracker); + + console.log("Address: " + message.getAddress()); + console.log("Subject: " + message.getSubject()); + console.log("Content: " + message.body); + + messenger.accept(tracker); + } + }; + + //messenger.setIncomingWindow(1024); + + messenger.setNetworkCallback(_process); + messenger.start(); + + messenger.subscribe(address); + messenger.recv(); // Receive as many messages as messenger can buffer. + +} catch(e) { + console.log("Caught Exception " + e); +} + + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/examples/messenger/javascript/spout.js ---------------------------------------------------------------------- diff --git a/examples/messenger/javascript/spout.js b/examples/messenger/javascript/spout.js new file mode 100644 index 0000000..071eb72 --- /dev/null +++ b/examples/messenger/javascript/spout.js @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +// Check if the environment is Node.js and if so import the required library. +if (typeof exports !== "undefined" && exports !== null) { + proton = require("qpid-proton"); +} + +try { + var address = "amqp://0.0.0.0"; + var subject = "UK.WEATHER"; + var msgtext = "Hello World!"; + var tracker = null; + var running = true; + + var message = new proton.Message(); + var messenger = new proton.Messenger(); + + function _process() { +// console.log(" *** process ***"); + + // Process outgoing messages + var status = messenger.status(tracker); + if (status != proton.Status.PENDING) { +console.log("status = " + status); + + //messenger.settle(tracker); + //tracked--; + + if (running) { +console.log("stopping"); + messenger.stop(); + running = false; + } + } + + if (messenger.isStopped()) { +console.log("exiting"); + message.free(); + messenger.free(); + //exit(0); + } + }; + + + messenger.setOutgoingWindow(1024); + + messenger.setNetworkCallback(_process); + messenger.start(); + + message.setAddress(address); + message.setSubject(subject); + //message.body = msgtext; + //message.body = new proton.Data.UUID(); + //message.body = new proton.Data.Symbol("My Symbol"); + //message.body = new proton.Data.Binary("Monkey BathпогÑÐ¾Ð¼Ð·Ñ Ñвбнм"); + + /*message.body = new proton.Data.Binary(4); + var buffer = message.body.getBuffer(); + buffer[0] = 65; + buffer[1] = 77; + buffer[2] = 81; + buffer[3] = 80;*/ + + + //message.body = true; + //message.body = " \"127.0\" "; + + //message.body = 2147483647; // int + //message.body = -2147483649; // long + //message.body = 12147483649; // long + + + message.body = (121474.836490).asFloat(); // float TODO check me + //message.body = 12147483649.0.asFloat(); // float TODO check me + //message.body = (4294967296).asUnsignedInteger(); + //message.body = (255).asUnsignedByte(); + + + //message.body = ['Rod', 'Jane', 'Freddy']; + //message.body = ['Rod', 'Jane', 'Freddy', {cat: true, donkey: 'hee haw'}]; + + tracker = messenger.put(message); + +} catch(e) { + console.log("Caught Exception " + e); +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/CMakeLists.txt b/proton-c/bindings/javascript/CMakeLists.txt index 966d0ba..e043adb 100644 --- a/proton-c/bindings/javascript/CMakeLists.txt +++ b/proton-c/bindings/javascript/CMakeLists.txt @@ -222,9 +222,34 @@ set_target_properties( # This build is optimised and minified #LINK_FLAGS "-s \"EXPORT_NAME='proton'\" -s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -O2 --closure 1 --pre-js - LINK_FLAGS "-s \"EXPORT_NAME='proton'\" -s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -O2 --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-open.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding.js --post-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-close.js --js-library ${CMAKE_CURRENT_SOURCE_DIR}/my-library.js -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=\"[]\" -s EXPORTED_FUNCTIONS=\"['_test', '_uuid_generate', '_pn_bytes', '_pn_error_text', '_pn_code', '_pn_messenger', '_pn_messenger_name', '_pn_messenger_set_blocking', '_pn_messenger_free', '_pn_messenger_errno', '_pn_messenger_error', '_pn_messenger_get_outgoing_window', '_pn_messenger_set_outgoing_window', '_pn_messenger_get_incoming_window', '_pn_messenger_set_incoming_window', '_pn_messenger_start', '_pn_messenger_stop', '_pn_messenger_stopped', '_pn_messenger_subscribe', '_pn_messenger_put', '_pn_messenger_status', '_pn_messenger_buffered', '_pn_messenger_settle', '_pn_messenger_outgoing_tracker', '_pn_messenger_work', '_pn_messenger_recv', '_pn_m essenger_receiving', '_pn_messenger_get', '_pn_messenger_incoming_tracker', '_pn_messenger_incoming_subscription', '_pn_messenger_accept', '_pn_messenger_reject', '_pn_messenger_outgoing', '_pn_messenger_incoming', '_pn_messenger_route', '_pn_messenger_rewrite', '_pn_subscription_get_context', '_pn_subscription_set_context', '_pn_subscription_address', '_pn_message', '_pn_message_free', '_pn_message_get_address', '_pn_message_errno', '_pn_message_error', '_pn_message_set_address', '_pn_message_get_subject', '_pn_message_set_subject', '_pn_message_instructions', '_pn_message_annotations', '_pn_message_properties', '_pn_message_body', '_pn_data', '_pn_data_free', '_pn_data_error', '_pn_data_errno', '_pn_data_clear', '_pn_data_rewind', '_pn_data_next', '_pn_data_prev', '_pn_data_enter', '_pn_data_exit', '_pn_data_lookup', '_pn_data_narrow', '_pn_data_widen', '_pn_data_type', '_pn_data_encode', '_pn_data_decode', '_pn_data_put_list', '_pn_data_put_map', '_pn_data_put_array', '_pn_data_ put_described', '_pn_data_put_null', '_pn_data_put_bool', '_pn_data_put_ubyte', '_pn_data_put_byte', '_pn_data_put_ushort', '_pn_data_put_short', '_pn_data_put_uint', '_pn_data_put_int', '_pn_data_put_char', '_pn_data_put_ulong', '_pn_data_put_long', '_pn_data_put_timestamp', '_pn_data_put_float', '_pn_data_put_double', '_pn_data_put_decimal32', '_pn_data_put_decimal64', '_pn_data_put_decimal128', '_pn_data_put_uuid', '_pn_data_put_binary', '_pn_data_put_string', '_pn_data_put_symbol', '_pn_data_get_list', '_pn_data_get_map', '_pn_data_get_array', '_pn_data_is_described', '_pn_data_is_null', '_pn_data_get_bool', '_pn_data_get_ubyte', '_pn_data_get_byte', '_pn_data_get_ushort', '_pn_data_get_short', '_pn_data_get_uint', '_pn_data_get_int', '_pn_data_get_char', '_pn_data_get_ulong', '_pn_data_get_long', '_pn_data_get_timestamp', '_pn_data_get_float', '_pn_data_get_double', '_pn_data_get_decimal32', '_pn_data_get_decimal64', '_pn_data_get_decimal128', '_pn_data_get_uuid', '_pn_data_get _binary', '_pn_data_get_string', '_pn_data_get_symbol', '_pn_data_copy', '_pn_data_format', '_pn_data_dump']\"" + LINK_FLAGS "-s \"EXPORT_NAME='proton'\" -s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -O2 --closure 1 --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-open.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding.js --post-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-close.js --js-library ${CMAKE_CURRENT_SOURCE_DIR}/my-library.js -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=\"[]\" -s EXPORTED_FUNCTIONS=\"['_test', '_uuid_generate', '_pn_bytes', '_pn_error_text', '_pn_code', '_pn_messenger', '_pn_messenger_name', '_pn_messenger_set_blocking', '_pn_messenger_free', '_pn_messenger_errno', '_pn_messenger_error', '_pn_messenger_get_outgoing_window', '_pn_messenger_set_outgoing_window', '_pn_messenger_get_incoming_window', '_pn_messenger_set_incoming_window', '_pn_messenger_start', '_pn_messenger_stop', '_pn_messenger_stopped', '_pn_messenger_subscribe', '_pn_messenger_put', '_pn_messenger_status', '_pn_messenger_buffered', '_pn_messenger_settle', '_pn_messenger_outgoing_tracker', '_pn_messenger_work', '_pn_messenger_r ecv', '_pn_messenger_receiving', '_pn_messenger_get', '_pn_messenger_incoming_tracker', '_pn_messenger_incoming_subscription', '_pn_messenger_accept', '_pn_messenger_reject', '_pn_messenger_outgoing', '_pn_messenger_incoming', '_pn_messenger_route', '_pn_messenger_rewrite', '_pn_subscription_get_context', '_pn_subscription_set_context', '_pn_subscription_address', '_pn_message', '_pn_message_free', '_pn_message_get_address', '_pn_message_errno', '_pn_message_error', '_pn_message_set_address', '_pn_message_get_subject', '_pn_message_set_subject', '_pn_message_instructions', '_pn_message_annotations', '_pn_message_properties', '_pn_message_body', '_pn_data', '_pn_data_free', '_pn_data_error', '_pn_data_errno', '_pn_data_clear', '_pn_data_rewind', '_pn_data_next', '_pn_data_prev', '_pn_data_enter', '_pn_data_exit', '_pn_data_lookup', '_pn_data_narrow', '_pn_data_widen', '_pn_data_type', '_pn_data_encode', '_pn_data_decode', '_pn_data_put_list', '_pn_data_put_map', '_pn_data_put_array' , '_pn_data_put_described', '_pn_data_put_null', '_pn_data_put_bool', '_pn_data_put_ubyte', '_pn_data_put_byte', '_pn_data_put_ushort', '_pn_data_put_short', '_pn_data_put_uint', '_pn_data_put_int', '_pn_data_put_char', '_pn_data_put_ulong', '_pn_data_put_long', '_pn_data_put_timestamp', '_pn_data_put_float', '_pn_data_put_double', '_pn_data_put_decimal32', '_pn_data_put_decimal64', '_pn_data_put_decimal128', '_pn_data_put_uuid', '_pn_data_put_binary', '_pn_data_put_string', '_pn_data_put_symbol', '_pn_data_get_list', '_pn_data_get_map', '_pn_data_get_array', '_pn_data_is_described', '_pn_data_is_null', '_pn_data_get_bool', '_pn_data_get_ubyte', '_pn_data_get_byte', '_pn_data_get_ushort', '_pn_data_get_short', '_pn_data_get_uint', '_pn_data_get_int', '_pn_data_get_char', '_pn_data_get_ulong', '_pn_data_get_long', '_pn_data_get_timestamp', '_pn_data_get_float', '_pn_data_get_double', '_pn_data_get_decimal32', '_pn_data_get_decimal64', '_pn_data_get_decimal128', '_pn_data_get_uuid', ' _pn_data_get_binary', '_pn_data_get_string', '_pn_data_get_symbol', '_pn_data_copy', '_pn_data_format', '_pn_data_dump']\"" ) +# This command packages up the compiled proton.js into a node.js package called +# qpid-proton and copies it to the <proton>/node_modules directory. This allows +# the node.js test and example programs to do proton = require("qpid-proton"); +add_custom_command( + TARGET proton.js + COMMAND ${CMAKE_COMMAND} + -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/qpid-proton + ${PROJECT_SOURCE_DIR}/node_modules/qpid-proton + COMMAND ${CMAKE_COMMAND} + -E copy + ${CMAKE_CURRENT_BINARY_DIR}/proton.js + ${PROJECT_SOURCE_DIR}/node_modules/qpid-proton/lib + COMMENT "Building qpid-proton package for node.js" +) + +# The cleanall target removes the qpid-proton package from <proton>/node_modules +add_custom_target( + cleanall + COMMAND echo "CLEAN NODE MODULES" + COMMAND ${CMAKE_COMMAND} + -E remove_directory + ${PROJECT_SOURCE_DIR}/node_modules/qpid-proton +) + # If the docs target is specified and the jsdoc3 package for node.js has been # installed then build the JavaScript API documentation. if (NODE_JSDOC_FOUND) @@ -236,8 +261,3 @@ if (NODE_JSDOC_FOUND) endif (NODE_JSDOC_FOUND) -# Some hacks so check what's getting built TODO to get rid of eventually -#message(STATUS "qpid-proton-platform: ${qpid-proton-platform}") -#message(STATUS "qpid-proton-core: ${qpid-proton-core}") - - http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/README ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/README b/proton-c/bindings/javascript/README index 67702ff..1998a47 100644 --- a/proton-c/bindings/javascript/README +++ b/proton-c/bindings/javascript/README @@ -15,36 +15,35 @@ emscripten itself depends upon. https://github.com/kripken/emscripten/wiki/Emscr provides some fairly easy to follow instructions for getting started on several platforms the main dependencies are as follows (on Windows the SDK includes these): -* The Emscripten code, from github (git clone git://github.com/kripken/emscripten.git. The documentation suggests - master branch but in the short term incoming is probably better as a few updates to emscripten have been added - to help get proton working and these may take a little while to get merged back to master. -* LLVM with Clang. Version 3.2 is the officially supported version, others may not work. There are official clang - binaries that include LLVM for some platforms, if yours is not there then you should get the LLVM and Clang - sources and build them. +* The Emscripten code, from github (git clone git://github.com/kripken/emscripten.git. + The documentation suggests master branch but in the short term incoming is + probably better as a few updates to emscripten have been added to help get + proton working and these may take a little while to get merged back to master. +* LLVM with Clang. Emscripten uses LLVM and Clang, but at the moment the JavaScript + back-end for LLVM is off on a branch so you can't use a stock LLVM/Clang. + https://github.com/kripken/emscripten/wiki/LLVM-Backend has lots of explanation + and some easy to follow instructions for downloading and building fast-comp * Node.js (0.8 or above; 0.10.17 or above to run websocket-using servers in node) * Python 2.7.3 -* Optionally, if you want to use Closure Compiler to minify your code as much as possible, you will also need Java. +* Java is required in order to use the Closure Compiler to minify the code. + -If you haven't run Emscripten before it's a good idea to have a play with the tutorial -https://github.com/kripken/emscripten/wiki/Tutorial +If you haven't run Emscripten before it's a good idea to have a play with the +tutorial https://github.com/kripken/emscripten/wiki/Tutorial -when you are all set up with emscripten and have got the basic tests in the tutorial running -building Proton should be simple, simply go to the Proton root directory and follow the main -instructions in the README there, in precis (from the root directory) it's: + + +when you are all set up with emscripten and have got the basic tests in the +tutorial running building Proton should be simple, simply go to the Proton root +directory and follow the main instructions in the README there, in precis (from +the root directory) it's: mkdir build cd build cmake .. make - -In order to use WebSockets from Node.js you will need to install the "ws" package, the easiest -way to do this is to use npm. From <proton-root>/build/proton-c/bindings/javascript (or where -ever you decide to put the JavaScript binding library created by this build) simply do: - - npm install ws - and you should be all set, to test it's all working do: node recv-async.js @@ -59,8 +58,7 @@ in another KNOWN ISSUES ============ -send-async and recv-async are both pretty hacky at the moment and not really asynchronous, this will -be addressed ASAP. +send-async and recv-async are both pretty hacky at the moment. SUPPORT http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/binding.js ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/binding.js b/proton-c/bindings/javascript/binding.js index 269ee27..43634d4 100644 --- a/proton-c/bindings/javascript/binding.js +++ b/proton-c/bindings/javascript/binding.js @@ -25,7 +25,7 @@ * <p> * This JavaScript wrapper provides a somewhat more idiomatic object oriented * interface which abstracts the low-level emscripten based implementation details - * from client code. + * from client code. Any similarities to the Proton Python binding are deliberate. * @file */ @@ -123,7 +123,7 @@ Module['Messenger'] = function(name) { // Messenger Constructor. * freed. In C code compiled by emscripten saving and restoring of the stack * is automatic, but if we want to us ALLOC_STACK from native JavaScript we * need to explicitly save and restore the stack using Runtime.stackSave() - * and Runtime.stackRestore() or we will leak memory. + * and Runtime.stackRestore() or we will leak emscripten heap memory. * See https://github.com/kripken/emscripten/wiki/Interacting-with-code * The _pn_messenger constructor copies the char* passed to it. */ @@ -415,7 +415,7 @@ _Messenger_['put'] = function(message) { // the high 32 bits via the tempRet0 variable. We use Data.Long to pass the // low/high pair around to methods that require a tracker. var low = _pn_messenger_outgoing_tracker(this._messenger); - var high = tempRet0; + var high = Runtime.getTempRet0(); return new Data.Long(low, high); }; @@ -458,7 +458,7 @@ console.log("settle: not fully tested yet"); var flags = 0; if (tracker == null) { var low = _pn_messenger_outgoing_tracker(this._messenger); - var high = tempRet0; + var high = Runtime.getTempRet0(); tracker = new Data.Long(low, high); flags = Module['Messenger'].PN_CUMULATIVE; } @@ -531,12 +531,10 @@ _Messenger_['get'] = function(message) { // the high 32 bits via the tempRet0 variable. We use Data.Long to pass the // low/high pair around to methods that require a tracker. var low = _pn_messenger_incoming_tracker(this._messenger); - var high = tempRet0; + var high = Runtime.getTempRet0(); console.log("get low = " + low); console.log("get high = " + high); -console.log("get asm = " + asm); -console.log("get asm['tempRet0'] = " + asm['tempRet0']); return new Data.Long(low, high); }; @@ -577,7 +575,7 @@ console.log("accept: not fully tested yet"); var flags = 0; if (tracker == null) { var low = _pn_messenger_incoming_tracker(this._messenger); - var high = tempRet0; + var high = Runtime.getTempRet0(); tracker = new Data.Long(low, high); flags = Module['Messenger'].PN_CUMULATIVE; } @@ -602,7 +600,7 @@ console.log("reject: not fully tested yet"); var flags = 0; if (tracker == null) { var low = _pn_messenger_incoming_tracker(this._messenger); - var high = tempRet0; + var high = Runtime.getTempRet0(); tracker = new Data.Long(low, high); flags = Module['Messenger'].PN_CUMULATIVE; } @@ -1237,6 +1235,77 @@ Data['Symbol'].prototype['equals'] = function(rhs) { return this.toString() === rhs.toString(); }; +// ---------------------- JavaScript Number Extensions ------------------------ + +Number.prototype['asUnsignedByte'] = function() { + return new Data.TypedNumber('UnsignedByte', this); +}; + +Number.prototype['asByte'] = function() { + return new Data.TypedNumber('Byte', this); +}; + +Number.prototype['asUnsignedShort'] = function() { + return new Data.TypedNumber('UnsignedShort', this); +}; + +Number.prototype['asShort'] = function() { + return new Data.TypedNumber('Short', this); +}; + +Number.prototype['asUnsignedInteger'] = function() { + return new Data.TypedNumber('UnsignedInteger', this); +}; + +Number.prototype['asInteger'] = function() { + return new Data.TypedNumber('Integer', this); +}; + +Number.prototype['asUnsignedLong'] = function() { + return new Data.TypedNumber('UnsignedLong', this); +}; + +Number.prototype['asLong'] = function() { + return new Data.TypedNumber('Long', this); +}; + +Number.prototype['asFloat'] = function() { + return new Data.TypedNumber('Float', this); +}; + +Number.prototype['asDouble'] = function() { + return new Data.TypedNumber('Double', this); +}; + +Number.prototype['asChar'] = function() { + return new Data.TypedNumber('Char', this); +}; + +String.prototype['asChar'] = function() { + return new Data.TypedNumber('Char', this.charCodeAt(0)); +}; + +// ------------------------- proton.Data.TypedNumber -------------------------- +/** + * Create a proton.Data.TypedNumber. + * @classdesc + * This class is a simple wrapper class that allows a "type" to be recorded for + * a number. The idea is that the JavaScript Number class is extended with extra + * methods to allow numbers to be "modified" to TypedNumbers, so for example + * 1.0.asFloat() would modify 1.0 by returning a TypedNumber with type = Float + * and value = 1. The strings used for type correspond to the names of the Data + * put* methods e.g. UnsignedByte, Byte, UnsignedShort, Short, UnsignedInteger, + * Integer, UnsignedLong, Long, Float, Double, Char so that the correct method + * to call can be easily derived from the TypedNumber's type. + * @constructor proton.Data.TypedNumber + * @param {string} type the type of the Number. + * @param {number} value the most significant word. + */ +// Use dot notation as it is a "protected" inner class not exported from the closure. +Data.TypedNumber = function(type, value) { // Data.TypedNumber Constructor. + this.type = type; + this.value = value; +}; // ----------------------------- proton.Data.Long ----------------------------- /** @@ -1250,6 +1319,7 @@ Data['Symbol'].prototype['equals'] = function(rhs) { * @param {number} low the least significant word. * @param {number} high the most significant word. */ +// Use dot notation as it is a "protected" inner class not exported from the closure. Data.Long = function(low, high) { // Data.Long Constructor. this.low = low | 0; // force into 32 signed bits. this.high = high | 0; // force into 32 signed bits. @@ -1805,7 +1875,6 @@ _Data_['putInteger'] = function(i) { * @param {number} c a single character. */ _Data_['putChar'] = function(c) { -console.log("putChar not properly implemented yet"); this._check(_pn_data_put_char(this._data, c)); }; @@ -1850,6 +1919,7 @@ console.log("putTimestamp not properly implemented yet"); * @param {number} f a floating point value. */ _Data_['putFloat'] = function(f) { +console.log("putFloat f = " + f); this._check(_pn_data_put_float(this._data, f)); }; @@ -2043,7 +2113,7 @@ _Data_['getBoolean'] = function() { * @returns {number} value if the current node is an unsigned byte, returns 0 otherwise. */ _Data_['getUnsignedByte'] = function() { - return _pn_data_get_ubyte(this._data); + return _pn_data_get_ubyte(this._data) & 0xFF; // & 0xFF converts to unsigned; }; /** @@ -2059,7 +2129,7 @@ _Data_['getByte'] = function() { * @return value if the current node is an unsigned short, returns 0 otherwise. */ _Data_['getUnsignedShort'] = function() { - return _pn_data_get_ushort(this._data); + return _pn_data_get_ushort(this._data) & 0xFFFF; // & 0xFFFF converts to unsigned; }; /** @@ -2077,7 +2147,8 @@ _Data_['getShort'] = function() { * @returns {number} value if the current node is an unsigned int, returns 0 otherwise. */ _Data_['getUnsignedInteger'] = function() { - return _pn_data_get_uint(this._data); + var value = _pn_data_get_uint(this._data); + return (value > 0) ? value : 4294967296 + value; // 4294967296 == 2^32 }; /** @@ -2092,13 +2163,10 @@ _Data_['getInteger'] = function() { /** * @method getChar * @memberof! proton.Data# - * @returns {number} value if the current node is a character, returns 0 otherwise. + * @returns {string} the character represented by the unicode value of the current node. */ -// TODO should this be dealing with strings not numbers? _Data_['getChar'] = function() { -console.log("getChar not properly implemented yet"); -return "character"; - //return _pn_data_get_char(this._data); + return String.fromCharCode(_pn_data_get_char(this._data)); }; /** @@ -2107,6 +2175,7 @@ return "character"; * @returns {number} value if the current node is an unsigned long, returns 0 otherwise. */ _Data_['getUnsignedLong'] = function() { +console.log("getUnsignedLong"); return _pn_data_get_ulong(this._data); }; @@ -2123,7 +2192,7 @@ console.log("getLong"); // the 64 bit number and Data.Long.toNumber() to convert it back into a // JavaScript number. var low = _pn_data_get_long(this._data); - var high = tempRet0; + var high = Runtime.getTempRet0(); var long = new Data.Long(low, high); long = long.toNumber(); @@ -2442,8 +2511,12 @@ console.log("obj is quoted String " + quoted); this['putBinary'](obj); } else if (obj instanceof Data['Symbol']) { this['putSymbol'](obj); + } else if (obj instanceof Data.TypedNumber) { // Dot notation used for "protected" inner class. + // Call the appropriate serialisation method based upon the numerical type. + this['put' + obj.type](obj.value); } else if (Data.isNumber(obj)) { /** + * This block encodes standard JavaScript numbers by making some inferences. * Encoding JavaScript numbers is surprisingly complex and has several * gotchas. The code here tries to do what the author believes is the * most intuitive encoding of the native JavaScript Number. It first @@ -2454,9 +2527,10 @@ console.log("obj is quoted String " + quoted); * 32 bit Int value. N.B. JavaScript automagically coerces floating * point numbers with a zero Fractional Part into an exact integer so * numbers like 1.0, 100.0 etc. will be encoded as int or long here, - * which is unlikely to be what is wanted. There's no easy way around this - * the two main options are to add a very small fractional number or to - * represent the number in a String literal e.g. "1.0f", "1.0d", "1l" + * which is unlikely to be what is wanted. There's no easy "transparent" + * way around this. The TypedNumber approach above allows applications + * to express more explicitly what is require, for example 1.0.asFloat() + * (1).asUnsignedByte(), (5).asLong() etc. */ if (obj % 1 === 0) { console.log(obj + " is Integer Type " + (obj|0)); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/drain.js ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/drain.js b/proton-c/bindings/javascript/drain.js deleted file mode 100644 index 9d9c726..0000000 --- a/proton-c/bindings/javascript/drain.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// Check if the environment is Node.js and if so import the required library. -if (typeof exports !== "undefined" && exports !== null) { - proton = require("../../../bld/proton-c/bindings/javascript/proton.js"); -} - -try { - var address = "amqp://~0.0.0.0"; - var message = new proton.Message(); - var messenger = new proton.Messenger(); - - function _process() { -// console.log(" *** process ***"); - - // Process incoming messages - - while (messenger.incoming()) { -console.log("in while loop\n"); - - var tracker = messenger.get(message); -console.log("tracker = " + tracker); - - console.log("Address: " + message.getAddress()); - console.log("Subject: " + message.getSubject()); - console.log("Content: " + message.body); - - messenger.accept(tracker); - } - }; - - //messenger.setIncomingWindow(1024); -console.log("Break A"); - messenger.setNetworkCallback(_process); - messenger.start(); -console.log("Break B"); - messenger.subscribe(address); -console.log("Break C"); - messenger.recv(); // Receive as many messages as messenger can buffer. -console.log("Break D"); -} catch(e) { - console.log("Caught Exception " + e); -} - - http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/qpid-proton/LICENSE ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/qpid-proton/LICENSE b/proton-c/bindings/javascript/qpid-proton/LICENSE new file mode 100644 index 0000000..6b0b127 --- /dev/null +++ b/proton-c/bindings/javascript/qpid-proton/LICENSE @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/qpid-proton/README.md ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/qpid-proton/README.md b/proton-c/bindings/javascript/qpid-proton/README.md new file mode 100644 index 0000000..db026c7 --- /dev/null +++ b/proton-c/bindings/javascript/qpid-proton/README.md @@ -0,0 +1,4 @@ +qpid-proton +----------- + +apache qpid proton messenger AMQP 1.0 library http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/qpid-proton/package.json ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/qpid-proton/package.json b/proton-c/bindings/javascript/qpid-proton/package.json new file mode 100644 index 0000000..ffc5ebe --- /dev/null +++ b/proton-c/bindings/javascript/qpid-proton/package.json @@ -0,0 +1,11 @@ +{ + "name" : "qpid-proton", + "version": "0.7.0", + "description": "apache qpid proton messenger AMQP 1.0 library", + "repository": { + "type": "svn", + "url": "https://svn.apache.org/repos/asf/qpid/proton/trunk/" + }, + "main" : "./lib/proton.js", + "dependencies": {} +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/bindings/javascript/spout.js ---------------------------------------------------------------------- diff --git a/proton-c/bindings/javascript/spout.js b/proton-c/bindings/javascript/spout.js deleted file mode 100644 index 254b948..0000000 --- a/proton-c/bindings/javascript/spout.js +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// Check if the environment is Node.js and if so import the required library. -if (typeof exports !== "undefined" && exports !== null) { - proton = require("../../../bld/proton-c/bindings/javascript/proton.js"); -} - -try { - var address = "amqp://0.0.0.0"; - var subject = "UK.WEATHER"; - var msgtext = "Hello World!"; - var tracker = null; - var running = true; - - var message = new proton.Message(); - var messenger = new proton.Messenger(); - - function _process() { -// console.log(" *** process ***"); - - // Process outgoing messages - var status = messenger.status(tracker); - if (status != proton.Status.PENDING) { -console.log("status = " + status); - - //messenger.settle(tracker); - //tracked--; - - if (running) { -console.log("stopping"); - messenger.stop(); - running = false; - } - } - - if (messenger.isStopped()) { -console.log("exiting"); - message.free(); - messenger.free(); - //exit(0); - } - }; - - - messenger.setOutgoingWindow(1024); - - messenger.setNetworkCallback(_process); - messenger.start(); - - message.setAddress(address); - message.setSubject(subject); - //message.body = msgtext; - //message.body = new proton.Data.UUID(); - //message.body = new proton.Data.Symbol("My Symbol"); - //message.body = new proton.Data.Binary("Monkey BathпогÑÐ¾Ð¼Ð·Ñ Ñвбнм"); - - message.body = new proton.Data.Binary(4); - var buffer = message.body.getBuffer(); - buffer[0] = 65; - buffer[1] = 77; - buffer[2] = 81; - buffer[3] = 80; - - - //message.body = true; - //message.body = " \"127.0\" "; - - //message.body = 2147483647; // int - //message.body = -2147483649; // long - //message.body = 12147483649; // long - - //message.body = 2147483647.000001; // double - - //message.body = ['Rod', 'Jane', 'Freddy']; - //message.body = ['Rod', 'Jane', 'Freddy', {cat: true, donkey: 'hee haw'}]; - - - tracker = messenger.put(message); - -} catch(e) { - console.log("Caught Exception " + e); -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/proton-c/src/messenger/messenger.c ---------------------------------------------------------------------- diff --git a/proton-c/src/messenger/messenger.c b/proton-c/src/messenger/messenger.c index d2cd10c..29b2eeb 100644 --- a/proton-c/src/messenger/messenger.c +++ b/proton-c/src/messenger/messenger.c @@ -602,6 +602,10 @@ pn_messenger_t *pn_messenger(const char *name) pni_interruptor_finalize); pn_list_add(m->pending, m->interruptor); m->interrupted = false; + // Explicitly initialise pipe file descriptors to invalid values in case pipe + // fails, if we don't do this m->ctrl[0] could default to 0 - which is stdin. + m->ctrl[0] = -1; + m->ctrl[1] = -1; pn_pipe(m->io, m->ctrl); pni_selectable_set_fd(m->interruptor, m->ctrl[0]); pni_selectable_set_context(m->interruptor, m); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/80c99528/tools/cmake/Modules/FindNodePackages.cmake ---------------------------------------------------------------------- diff --git a/tools/cmake/Modules/FindNodePackages.cmake b/tools/cmake/Modules/FindNodePackages.cmake index 31c5551..bfbb36f 100644 --- a/tools/cmake/Modules/FindNodePackages.cmake +++ b/tools/cmake/Modules/FindNodePackages.cmake @@ -18,43 +18,51 @@ # # FindNodePackages -# This module finds and installs (optionally) required node.js packages using npm +# This module finds and installs (using npm) node.js packages that are used by +# the JavaScript binding. The binding should still compile if these packages +# cannot be installed but certain features might not work as described below. +# # * The ws package is the WebSocket library used by emscripten when the target is -# node.js, it isn't needed for applications hosted on a browser where native -# WebSockets will be used. +# node.js, it isn't needed for applications hosted on a browser (where native +# WebSockets will be used), but without it it won't work with node.js. # # * The jsdoc package is a JavaScript API document generator analogous to Doxygen # or JavaDoc, it is used by the docs target in the JavaScript binding. if (NOT NODE_PACKAGES_FOUND) - # Install ws node.js WebSocket library https://github.com/einaros/ws - message(STATUS "Installing node.js ws package") - - execute_process( - COMMAND npm install ws - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - OUTPUT_VARIABLE var - ) - - if (var) - message(STATUS "Node.js ws package has been installed") - set(NODE_WS_FOUND ON) - endif (var) - - # Install jsdoc3 API documentation generator for JavaScript https://github.com/jsdoc3/jsdoc - message(STATUS "Installing node.js jsdoc package") - - execute_process( - COMMAND npm install jsdoc - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - OUTPUT_VARIABLE var - ) - - if (var) - message(STATUS "Node.js jsdoc package has been installed") - set(NODE_JSDOC_FOUND ON) - set(JSDOC_EXE ${PROJECT_SOURCE_DIR}/node_modules/.bin/jsdoc) - endif (var) + # Check if the specified node.js package is already installed, if not install it. + macro(InstallPackage varname name) + execute_process( + COMMAND npm list --local ${name} + OUTPUT_VARIABLE check_package + ) + + set(${varname} OFF) + + if (check_package MATCHES "${name}@.") + message(STATUS "Found node.js package: ${name}") + set(${varname} ON) + else() + message(STATUS "Installing node.js package: ${name}") + + execute_process( + COMMAND npm install ${name} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE var + ) + + if (var) + message(STATUS "Installed node.js package: ${name}") + set(${varname} ON) + endif (var) + endif() + endmacro() + + # Check if ws WebSocket library https://github.com/einaros/ws is installed + InstallPackage("NODE_WS_FOUND" "ws") + + # Check if jsdoc3 API documentation generator https://github.com/jsdoc3/jsdoc is installed + InstallPackage("NODE_JSDOC_FOUND" "jsdoc") set(NODE_PACKAGES_FOUND ON) endif (NOT NODE_PACKAGES_FOUND) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
