From ceed54758ae98c553d2d695d5d65902205b32223 Mon Sep 17 00:00:00 2001 From: Momtchil Momtchev Date: Wed, 28 Jun 2023 07:21:10 +0100 Subject: [PATCH] Javascript Node-API support added Closes #2545 --- .github/workflows/ci.yml | 8 + .gitignore | 1 + CHANGES.current | 4 + Doc/Manual/Javascript.html | 67 +- Doc/Manual/Preprocessor.html | 1 + Examples/Makefile.in | 15 +- Examples/javascript/class/runme.js | 15 + Examples/javascript/functor/runme.js | 8 +- Examples/javascript/native/example.i | 17 +- Examples/test-suite/c_delete.i | 3 +- Examples/test-suite/c_delete_function.i | 3 +- Examples/test-suite/common.mk | 1 - Examples/test-suite/enum_forward.i | 2 +- Examples/test-suite/javascript/Makefile.in | 34 +- .../javascript/catches_strings_runme.js | 4 +- .../javascript/li_std_auto_ptr_runme.js | 6 +- .../javascript/li_std_pair_runme.js | 9 +- .../javascript/node_template/index.js.in | 2 +- .../node_template/napi-leaks-suppression.txt | 2 + Examples/test-suite/native_directive.i | 39 +- Examples/test-suite/nested.i | 2 +- Examples/test-suite/nested_extend_c.i | 4 +- Examples/test-suite/nested_structs.i | 2 +- Examples/test-suite/typemap_variables.i | 4 + Lib/javascript/napi/argcargv.i | 66 ++ Lib/javascript/napi/arrays_javascript.i | 88 ++ Lib/javascript/napi/ccomplex.i | 27 + Lib/javascript/napi/cdata.i | 1 + Lib/javascript/napi/cmalloc.i | 1 + Lib/javascript/napi/complex.i | 6 + Lib/javascript/napi/exception.i | 1 + Lib/javascript/napi/factory.i | 1 + Lib/javascript/napi/javascript.swg | 17 + Lib/javascript/napi/javascriptcode.swg | 880 ++++++++++++++++++ Lib/javascript/napi/javascriptcomplex.swg | 116 +++ Lib/javascript/napi/javascriptfragments.swg | 23 + Lib/javascript/napi/javascriptinit.swg | 111 +++ Lib/javascript/napi/javascriptprimtypes.swg | 387 ++++++++ Lib/javascript/napi/javascriptrun.swg | 446 +++++++++ Lib/javascript/napi/javascriptruntime.swg | 40 + Lib/javascript/napi/javascriptstrings.swg | 77 ++ Lib/javascript/napi/javascripttypemaps.swg | 56 ++ Lib/javascript/napi/nodejs_buffer.i | 47 + Lib/javascript/napi/std_auto_ptr.i | 39 + Lib/javascript/napi/std_common.i | 5 + Lib/javascript/napi/std_complex.i | 26 + Lib/javascript/napi/std_deque.i | 1 + Lib/javascript/napi/std_except.i | 1 + Lib/javascript/napi/std_map.i | 80 ++ Lib/javascript/napi/std_pair.i | 35 + Lib/javascript/napi/std_string.i | 1 + Lib/javascript/napi/std_unique_ptr.i | 39 + Lib/javascript/napi/std_vector.i | 99 ++ Lib/javascript/napi/stl.i | 10 + Lib/javascript/napi/swigmove.i | 1 + Lib/javascript/napi/typemaps.i | 148 +++ Lib/javascript/v8/javascriptkw.swg | 40 - Lib/{javascript/jsc => }/javascriptkw.swg | 25 +- Makefile.in | 2 +- Source/Modules/javascript.cxx | 717 +++++++++++++- Tools/CI-linux-environment.sh | 2 +- Tools/CI-linux-install.sh | 3 +- configure.ac | 28 +- 63 files changed, 3839 insertions(+), 107 deletions(-) create mode 100644 Examples/test-suite/javascript/node_template/napi-leaks-suppression.txt create mode 100644 Lib/javascript/napi/argcargv.i create mode 100644 Lib/javascript/napi/arrays_javascript.i create mode 100644 Lib/javascript/napi/ccomplex.i create mode 100644 Lib/javascript/napi/cdata.i create mode 100644 Lib/javascript/napi/cmalloc.i create mode 100644 Lib/javascript/napi/complex.i create mode 100644 Lib/javascript/napi/exception.i create mode 100644 Lib/javascript/napi/factory.i create mode 100644 Lib/javascript/napi/javascript.swg create mode 100644 Lib/javascript/napi/javascriptcode.swg create mode 100644 Lib/javascript/napi/javascriptcomplex.swg create mode 100644 Lib/javascript/napi/javascriptfragments.swg create mode 100644 Lib/javascript/napi/javascriptinit.swg create mode 100644 Lib/javascript/napi/javascriptprimtypes.swg create mode 100644 Lib/javascript/napi/javascriptrun.swg create mode 100644 Lib/javascript/napi/javascriptruntime.swg create mode 100644 Lib/javascript/napi/javascriptstrings.swg create mode 100644 Lib/javascript/napi/javascripttypemaps.swg create mode 100644 Lib/javascript/napi/nodejs_buffer.i create mode 100644 Lib/javascript/napi/std_auto_ptr.i create mode 100644 Lib/javascript/napi/std_common.i create mode 100644 Lib/javascript/napi/std_complex.i create mode 100644 Lib/javascript/napi/std_deque.i create mode 100644 Lib/javascript/napi/std_except.i create mode 100644 Lib/javascript/napi/std_map.i create mode 100644 Lib/javascript/napi/std_pair.i create mode 100644 Lib/javascript/napi/std_string.i create mode 100644 Lib/javascript/napi/std_unique_ptr.i create mode 100644 Lib/javascript/napi/std_vector.i create mode 100644 Lib/javascript/napi/stl.i create mode 100644 Lib/javascript/napi/swigmove.i create mode 100644 Lib/javascript/napi/typemaps.i delete mode 100644 Lib/javascript/v8/javascriptkw.swg rename Lib/{javascript/jsc => }/javascriptkw.swg (56%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa0b1925c..78f1b33dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,6 +98,14 @@ jobs: ENGINE: node VER: '18' CPPSTD: c++14 + - SWIGLANG: javascript + ENGINE: napi + VER: '14' + CPPSTD: c++11 + - SWIGLANG: javascript + ENGINE: napi + VER: '18' + CPPSTD: c++14 - SWIGLANG: javascript ENGINE: jsc VER: '4.0' diff --git a/.gitignore b/.gitignore index 56c4ad819..38c3bfa9b 100644 --- a/.gitignore +++ b/.gitignore @@ -157,6 +157,7 @@ Examples/java/doxygen/javadocs # Javascript Examples/test-suite/javascript/*/ *.gyp +!Examples/test-suite/javascript/node_template # Lua Examples/lua/dual/dual diff --git a/CHANGES.current b/CHANGES.current index 2a05dea09..650316cc8 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2023-06-27: mmomtchev + [Javascript] #2545 New Javascript generator targeting the Node.js + binary stable ABI Node-API. + 2023-06-27: olly [Java] Completely remove pragmas which were deprecated in 2002 and have triggered an error since SWIG 2.0: diff --git a/Doc/Manual/Javascript.html b/Doc/Manual/Javascript.html index c4545ecff..6289a0bdf 100644 --- a/Doc/Manual/Javascript.html +++ b/Doc/Manual/Javascript.html @@ -79,7 +79,7 @@ With node-webkit there is int gcd(int x, int y); extern double Foo; -

To build a Javascript module, run SWIG using the -javascript option and a desired target engine -jsc, -v8, or -node. The generator for node is essentially delegating to the v8 generator and adds some necessary preprocessor definitions.

+

To build a Javascript module, run SWIG using the -javascript option and a desired target engine -jsc, -v8, -node or -napi. -v8 allows for interfacing with a raw embedded version of V8. In this case, it is up to the user to implement a binary module loading protocol. There are two generators supporting Node.js. The older generator for node is essentially delegating to the v8 generator and adds some necessary preprocessor definitions. The more recent -napi generator produces node-addon-api that interfaces to Node.js through Node-API. The V8 generator is more mature, while the Node-API generator offers a number of advantages such as binary stable ABI allowing for publishing of universal binary modules on npm, Electron support and automatic multi-threading.

 $ swig -javascript -jsc example.i
@@ -92,6 +92,10 @@ $ swig -c++ -javascript -jsc example.i

The V8 code that SWIG generates requires at least V8 5.0. Keep in mind that this is theV8 version, not Node.js. To give some perspective, Node.js v6.0 uses V8 5.0, v12.0 - 7.4, v14.0 - 8.1...

+

The Node-API code that SWIG generates requires Node-API version 6. +This Node-API is available starting from Node.js v10.20 on the v10.x branch, +Node.js v12.17 on the v12.x branch and all versions starting from v14.0.

+

To generate code for V8, you would run swig like so:

@@ -127,12 +131,17 @@ $ sudo apt-get install libjavascriptcoregtk-1.0-dev
 $ sudo apt-get install libv8-dev
+

Running with Node-API requires node-addon-api:

+
+
+$ sudo npm install -g node-addon-api
+

Examples can be run using

 $ make check-javascript-examples ENGINE=jsc
-

ENGINE can be node, jsc, or v8.

+

ENGINE can be node, jsc, v8, or napi.

The test-suite can be run using

@@ -150,15 +159,15 @@ $ make check-javascript-examples V8_VERSION=0x032530 ENGINE=v8

At the moment, the Javascript generators pass all tests syntactically, i.e., the generated source code compiles. However, there are still remaining runtime issues.

    -
  • Default optional arguments do not work for all targeted interpreters

  • +
  • Default optional arguments do not work for all targeted interpreters except Node-API

  • Multiple output arguments do not work for JSC

  • C89 incompatibility: the JSC generator might still generate C89 violating code

  • -
  • long long is not supported

  • +
  • long long is not supported except with Node-API

  • Javascript callbacks are not supported

  • instanceOf does not work under JSC

-

The primary development environment has been Linux (Ubuntu 12.04). Windows and Mac OS X have been tested sporadically. Therefore, the generators might have more issues on those platforms. Please report back any problem you observe to help us improving this module quickly.

+

The primary development environment has been Linux (Ubuntu 22.04). Windows and Mac OS X have been tested sporadically. Therefore, the generators might have more issues on those platforms. Please report back any problem you observe to help us improving this module quickly.

28.3 Integration

@@ -211,7 +220,25 @@ require("./build/Release/example")

A more detailed explanation is given in the Examples section.

-

28.3.1.1 Troubleshooting

+

28.3.1.1 Using yeoman to generate a Node-API skeleton

+

If targeting Node-API, the easiest way to bootstrap a project is by using the yeoman generator:

+
+
+$ sudo npm install -g yo
+$ sudo npm install -g generator-napi-module
+$ mkdir example
+$ cd example
+$ yo napi-module                     # the choice of template is irrelevant, SWIG will replace the C++ code
+$ npm install node-addon-api@latest  # the yeoman version is outdated
+$ swig -javascript -napi -c++ -o src/example.cc example.i
+$ node-gyp configure
+$ node-gyp build
+
+
+

There is also the node-magickwand project that can be used as a tutorial for building and publishing a complex C++ library to + npm as a ready-to-use real-world binary module.

+ +

28.3.1.2 Troubleshooting