mirror of https://github.com/swig/swig
parent
4e20b7d71e
commit
ceed54758a
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -79,7 +79,7 @@ With <a href="https://github.com/rogerwang/node-webkit">node-webkit</a> there is
|
|||
int gcd(int x, int y);
|
||||
extern double Foo;</pre>
|
||||
</div>
|
||||
<p>To build a Javascript module, run SWIG using the <code>-javascript</code> option and a desired target engine <code>-jsc</code>, <code>-v8</code>, or <code>-node</code>. The generator for <code>node</code> is essentially delegating to the <code>v8</code> generator and adds some necessary preprocessor definitions.</p>
|
||||
<p>To build a Javascript module, run SWIG using the <code>-javascript</code> option and a desired target engine <code>-jsc</code>, <code>-v8</code>, <code>-node</code> or <code>-napi</code>. <code>-v8</code> 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 <code>node</code> is essentially delegating to the <code>v8</code> generator and adds some necessary preprocessor definitions. The more recent <code>-napi</code> generator produces <code>node-addon-api</code> 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.</p>
|
||||
<div class="shell">
|
||||
<pre>
|
||||
$ swig -javascript -jsc example.i</pre>
|
||||
|
@ -92,6 +92,10 @@ $ swig -c++ -javascript -jsc example.i</pre>
|
|||
<p>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...</p>
|
||||
<p>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.</p>
|
||||
</p>
|
||||
<p>To generate code for V8, you would run swig like so:</p>
|
||||
<div class="shell">
|
||||
<pre>
|
||||
|
@ -127,12 +131,17 @@ $ sudo apt-get install libjavascriptcoregtk-1.0-dev</pre>
|
|||
<pre>
|
||||
$ sudo apt-get install libv8-dev</pre>
|
||||
</div>
|
||||
<p>Running with Node-API requires <code>node-addon-api</code>:</p>
|
||||
<div class="shell">
|
||||
<pre>
|
||||
$ sudo npm install -g node-addon-api</pre>
|
||||
</div>
|
||||
<p>Examples can be run using</p>
|
||||
<div class="shell">
|
||||
<pre>
|
||||
$ make check-javascript-examples ENGINE=jsc</pre>
|
||||
</div>
|
||||
<p><code>ENGINE</code> can be <code>node</code>, <code>jsc</code>, or <code>v8</code>.</p>
|
||||
<p><code>ENGINE</code> can be <code>node</code>, <code>jsc</code>, <code>v8</code>, or <code>napi</code>.</p>
|
||||
<p>The test-suite can be run using</p>
|
||||
<div class="shell">
|
||||
<pre>
|
||||
|
@ -150,15 +159,15 @@ $ make check-javascript-examples V8_VERSION=0x032530 ENGINE=v8</pre>
|
|||
<p>At the moment, the Javascript generators pass all tests syntactically, i.e., the generated source code compiles. However, there are still remaining runtime issues.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>Default optional arguments do not work for all targeted interpreters</p></li>
|
||||
<li><p>Default optional arguments do not work for all targeted interpreters except Node-API</p></li>
|
||||
<li><p>Multiple output arguments do not work for JSC</p></li>
|
||||
<li><p>C89 incompatibility: the JSC generator might still generate C89 violating code</p></li>
|
||||
<li><p><code>long long</code> is not supported</p></li>
|
||||
<li><p><code>long long</code> is not supported except with Node-API</p></li>
|
||||
<li><p>Javascript callbacks are not supported</p></li>
|
||||
<li><p><code>instanceOf</code> does not work under JSC</p></li>
|
||||
</ul>
|
||||
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
|
||||
<H2><a name="Javascript_integration">28.3 Integration</a></H2>
|
||||
|
||||
|
@ -211,7 +220,25 @@ require("./build/Release/example")</pre>
|
|||
</div>
|
||||
<p>A more detailed explanation is given in the <a href="#Javascript_examples">Examples</a> section.</p>
|
||||
|
||||
<H4><a name="Javascript_troubleshooting">28.3.1.1 Troubleshooting</a></H4>
|
||||
<H4><a name="Using_yeoman">28.3.1.1 Using <code>yeoman</code> to generate a Node-API skeleton</a></H4>
|
||||
<p>If targeting Node-API, the easiest way to bootstrap a project is by using the <code>yeoman</code> generator: </p>
|
||||
<div class="shell">
|
||||
<pre>
|
||||
$ 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
|
||||
</pre>
|
||||
</div>
|
||||
<p>There is also the <a href="https://github.com/mmomtchev/node-magickwand"><code>node-magickwand</code></a> 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.</p>
|
||||
|
||||
<H4><a name="Javascript_troubleshooting">28.3.1.2 Troubleshooting</a></H4>
|
||||
|
||||
|
||||
<ul>
|
||||
|
@ -605,7 +632,7 @@ at emitKey (readline.js:1095:12)</pre>
|
|||
<H3><a name="Javascript_source_code">28.5.1 Source Code</a></H3>
|
||||
|
||||
|
||||
<p>The Javascript module is implemented in <code>Source/Modules/javascript.cxx</code>. It dispatches the code generation to a <code>JSEmitter</code> instance, <code>V8Emitter</code> or <code>JSCEmitter</code>. Additionally there are some helpers: <code>Template</code>, for templated code generation, and <code>JSEmitterState</code>, which is used to manage state information during AST traversal. This rough map shall make it easier to find a way through this huge source file:</p>
|
||||
<p>The Javascript module is implemented in <code>Source/Modules/javascript.cxx</code>. It dispatches the code generation to a <code>JSEmitter</code> instance, <code>V8Emitter</code>, <code>JSCEmitter</code> or <code>NAPIEmitter</code>. Additionally there are some helpers: <code>Template</code>, for templated code generation, and <code>JSEmitterState</code>, which is used to manage state information during AST traversal. This rough map shall make it easier to find a way through this huge source file:</p>
|
||||
<div class="code">
|
||||
<pre>
|
||||
// module wide defines
|
||||
|
@ -629,6 +656,7 @@ class JSEmitter { ... };
|
|||
|
||||
JSEmitter *swig_javascript_create_JSCEmitter();
|
||||
JSEmitter *swig_javascript_create_V8Emitter();
|
||||
JSEmitter *swig_javascript_create_NAPIEmitter();
|
||||
|
||||
// ###############################
|
||||
// # Javascript module
|
||||
|
@ -706,7 +734,7 @@ Template::Template(const String *code_) { ... }
|
|||
<H3><a name="Javascript_code_templates">28.5.2 Code Templates</a></H3>
|
||||
|
||||
|
||||
<p>All generated code is created on the basis of code templates. The templates for <em>JavascriptCore</em> can be found in <code>Lib/javascript/jsc/javascriptcode.swg</code>, for <em>v8</em> in <code>Lib/javascript/v8/javascriptcode.swg</code>.</p>
|
||||
<p>All generated code is created on the basis of code templates. The templates for <em>JavascriptCore</em> can be found in <code>Lib/javascript/jsc/javascriptcode.swg</code>, for <em>v8</em> in <code>Lib/javascript/v8/javascriptcode.swg</code> and for <em>Node-API</em> in <code>Lib/javascript/napi.javascriptcode.swg</code>.</p>
|
||||
<p>To track the originating code template for generated code you can run</p>
|
||||
<div class="shell">
|
||||
<pre>
|
||||
|
@ -985,5 +1013,28 @@ if(js_exception)
|
|||
}</pre>
|
||||
</div>
|
||||
|
||||
<H3><a name="Javascript_napi_exceptions">28.5.6 Handling Exceptions in Node-API</a></H3>
|
||||
<p>Node-API is the only generator that provides fully automatic conversion of C++ exceptions to JavaScript exceptions when building with C++ exceptions enabled in `binding.gyp`:</p>
|
||||
<div class="code">
|
||||
<pre>
|
||||
'conditions': [
|
||||
['OS=="mac"',
|
||||
{
|
||||
'xcode_settings': {
|
||||
'GCC_ENABLE_CPP_RTTI': 'YES',
|
||||
'GCC_ENABLE_CPP_EXCEPTIONS' : 'YES'
|
||||
}
|
||||
}
|
||||
],
|
||||
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"',
|
||||
{
|
||||
'cflags!': [ '-fno-exceptions' ],
|
||||
'cflags_cc!': [ '-fno-exceptions', '-fno-rtti' ]
|
||||
}
|
||||
]
|
||||
]
|
||||
</pre>
|
||||
</div>
|
||||
<p>In this case, nothing else is needed for the C++ exceptions to be passed to JavaScript.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -132,6 +132,7 @@ SWIGJAVA Defined when using Java
|
|||
SWIGJAVASCRIPT Defined when using Javascript
|
||||
SWIG_JAVASCRIPT_JSC Defined when using Javascript with -jsc
|
||||
SWIG_JAVASCRIPT_V8 Defined when using Javascript with -v8 or -node
|
||||
SWIG_JAVASCRIPT_NAPI Defined when using Javascript with -napi
|
||||
SWIGLUA Defined when using Lua
|
||||
SWIGMZSCHEME Defined when using Mzscheme
|
||||
SWIGOCAML Defined when using OCaml
|
||||
|
|
|
@ -688,8 +688,10 @@ endif
|
|||
# Creating and building Javascript wrappers
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
NAPI_DIR = @NODENAPI_DIR@
|
||||
|
||||
javascript_wrapper:
|
||||
ifeq (node,$(JSENGINE))
|
||||
ifeq ($(JSENGINE), $(filter $(JSENGINE), node napi))
|
||||
$(SWIG) -javascript $(SWIGOPT) -$(JSENGINE) -o $(INTERFACEDIR)$(TARGET)_wrap.cxx $(INTERFACEPATH)
|
||||
else
|
||||
$(SWIG) -javascript $(SWIGOPT) -$(JSENGINE) -o $(INTERFACEDIR)$(TARGET)_wrap.c $(INTERFACEPATH)
|
||||
|
@ -702,15 +704,18 @@ javascript_build: $(SRCDIR_SRCS)
|
|||
ifeq (node,$(JSENGINE))
|
||||
sed -e 's|$$srcdir|./$(SRCDIR)|g' $(SRCDIR)binding.gyp.in > binding.gyp
|
||||
MAKEFLAGS= $(NODEGYP) --loglevel=silent configure build 1>>/dev/null
|
||||
else ifeq (napi,$(JSENGINE))
|
||||
sed -e 's|$$srcdir|./$(SRCDIR)|g' $(SRCDIR)binding.gyp.in > binding.gyp
|
||||
MAKEFLAGS= CXXFLAGS="$(CXXFLAGS) -I$(NAPI_DIR)" $(NODEGYP) --loglevel=silent configure build 1>>/dev/null
|
||||
else
|
||||
$(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(JSINCLUDES)
|
||||
$(LDSHARED) $(CCSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
|
||||
endif
|
||||
|
||||
javascript_build_cpp: $(SRCDIR_SRCS)
|
||||
ifeq (node,$(JSENGINE))
|
||||
ifeq ($(JSENGINE), $(filter $(JSENGINE), node napi))
|
||||
sed -e 's|$$srcdir|./$(SRCDIR)|g' $(SRCDIR)binding.gyp.in > binding.gyp
|
||||
MAKEFLAGS= $(NODEGYP) --loglevel=silent configure build 1>>/dev/null
|
||||
MAKEFLAGS= CXXFLAGS="$(CXXFLAGS) -I$(NAPI_DIR)" $(NODEGYP) --loglevel=silent configure build 1>>/dev/null
|
||||
else
|
||||
$(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(JSINCLUDES)
|
||||
$(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
|
||||
|
@ -740,7 +745,7 @@ javascript_cpp: $(SRCDIR_SRCS) javascript_custom_interpreter
|
|||
javascript_custom_interpreter:
|
||||
(cd $(ROOT_DIR)/Tools/javascript && $(MAKE) JSENGINE='$(JSENGINE)')
|
||||
|
||||
ifeq (node,$(JSENGINE))
|
||||
ifeq ($(JSENGINE), $(filter $(JSENGINE), node napi))
|
||||
javascript_run:
|
||||
env NODE_PATH=$$PWD:$(SRCDIR) $(RUNTOOL) $(NODEJS) $(SRCDIR)$(RUNME).js $(RUNPIPE)
|
||||
else
|
||||
|
@ -761,7 +766,7 @@ ifeq (, $(ENGINE))
|
|||
echo "Version depends on the interpreter"; \
|
||||
fi
|
||||
endif
|
||||
ifeq (node, $(ENGINE))
|
||||
ifeq ($(ENGINE), $(filter $(ENGINE), node napi))
|
||||
echo "Node.js: `($(NODEJS) --version)`"
|
||||
echo "node-gyp: `($(NODEGYP) --version)`"
|
||||
endif
|
||||
|
|
|
@ -7,6 +7,12 @@ c = new example.Circle(10);
|
|||
console.log("Created circle " + c);
|
||||
s = new example.Square(10);
|
||||
console.log("Created square " + s);
|
||||
try {
|
||||
new example.Shape();
|
||||
console.error("Should have thrown");
|
||||
} catch {
|
||||
console.log("Instantiating abstract class Shape failed");
|
||||
}
|
||||
|
||||
// ----- Access a static member -----
|
||||
console.log("\nA total of " + example.Shape.nshapes + " shapes were created"); // access static member as properties of the class object
|
||||
|
@ -21,6 +27,15 @@ c.y = 30;
|
|||
s.x = -10;
|
||||
s.y = 5;
|
||||
|
||||
// ----- Check inheritance -----
|
||||
console.log("Square instanceof Shape: ", s instanceof example.Shape);
|
||||
console.log("Square instanceof Circle: ", s instanceof example.Circle);
|
||||
console.log("Square instanceof Square: ", s instanceof example.Square);
|
||||
|
||||
// ----- Use an inherited method -----
|
||||
s.move(1, 1);
|
||||
c.move(-1, -1);
|
||||
|
||||
console.log("\nHere is their new position:");
|
||||
console.log("Circle = (" + c.x + "," + c.y + ")");
|
||||
console.log("Square = (" + s.x + "," + s.y + ")");
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
var example = require("example");
|
||||
|
||||
a = new example.intSum(0);
|
||||
a = new example.intSum(1);
|
||||
b = new example.doubleSum(100.0);
|
||||
c = new example.intSum();
|
||||
|
||||
// Use the objects. They should be callable just like a normal
|
||||
// javascript function.
|
||||
|
||||
for (i=1;i<=100;i++)
|
||||
for (i=1;i<=100;i++) {
|
||||
a.call(i); // Note: function call
|
||||
b.call(Math.sqrt(i)); // Note: function call
|
||||
c.call(i);
|
||||
}
|
||||
|
||||
console.log(a.result());
|
||||
console.log(b.result());
|
||||
console.log(c.result());
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ int placeholder() { return 0; }
|
|||
// actual demo code
|
||||
%wrapper
|
||||
%{
|
||||
#ifdef SWIG_V8_VERSION /* Engine: Node || V8 */
|
||||
#if defined(SWIG_V8_VERSION) /* Engine: Node || V8 */
|
||||
|
||||
static SwigV8ReturnValue JavaScript_do_work(const SwigV8Arguments &args) {
|
||||
SWIGV8_HANDLESCOPE();
|
||||
|
@ -24,6 +24,21 @@ int placeholder() { return 0; }
|
|||
SWIGV8_RETURN(SWIGV8_UNDEFINED());
|
||||
}
|
||||
|
||||
#elif defined(NAPI_VERSION) /* Engine: NAPI */
|
||||
|
||||
static Napi::Value JavaScript_do_work(const Napi::CallbackInfo &args) {
|
||||
Napi::Env env = args.Env();
|
||||
Napi::EscapableHandleScope scope(env);
|
||||
const int MY_MAGIC_NUMBER = 5;
|
||||
Napi::Value jsresult =
|
||||
SWIG_From_int(env, static_cast< int >(MY_MAGIC_NUMBER));
|
||||
if (args.Length() != 0)
|
||||
SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments.");
|
||||
return scope.Escape(jsresult);
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
|
||||
#else /* Engine: JavaScriptCore */
|
||||
|
||||
static JSValueRef JavaScript_do_work(JSContextRef context,
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
%warnfilter(SWIGWARN_PARSE_KEYWORD) delete;
|
||||
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) /* Octave and Javascript/v8 compiles wrappers as C++ */
|
||||
/* Octave and Javascript/v8 compiles wrappers as C++ */
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) && !defined(SWIG_JAVASCRIPT_NAPI)
|
||||
|
||||
%inline %{
|
||||
struct delete {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
%warnfilter(SWIGWARN_PARSE_KEYWORD) delete;
|
||||
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) /* Octave and Javascript/v8 compiles wrappers as C++ */
|
||||
/* Octave and Javascript/v8 compiles wrappers as C++ */
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) && !defined(SWIG_JAVASCRIPT_NAPI)
|
||||
|
||||
%inline %{
|
||||
double delete(double d) { return d; }
|
||||
|
|
|
@ -412,7 +412,6 @@ CPP_TEST_CASES += \
|
|||
smart_pointer_protected \
|
||||
smart_pointer_rename \
|
||||
smart_pointer_simple \
|
||||
smart_pointer_static \
|
||||
smart_pointer_template_const_overload \
|
||||
smart_pointer_template_defaults_overload \
|
||||
smart_pointer_templatemethods \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%module enum_forward
|
||||
|
||||
/* This contains C code that is not valid C++03 and Octave, and Javascript(v8) wrappers are always compiled as C++ */
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8)
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) && !defined(SWIG_JAVASCRIPT_NAPI)
|
||||
%{
|
||||
enum ForwardEnum1 { AAA, BBB };
|
||||
enum ForwardEnum2 { CCC, DDD };
|
||||
|
|
|
@ -8,7 +8,7 @@ NODEJS = @NODEJS@
|
|||
SCRIPTSUFFIX = _runme.js
|
||||
OBJEXT = @OBJEXT@
|
||||
SO = @SO@
|
||||
GYP_CXXFLAGS = @BOOST_CPPFLAGS@ @PLATCXXFLAGS@
|
||||
GYP_CXXFLAGS = @BOOST_CPPFLAGS@ @PLATCXXFLAGS@ -I$(shell npm config get prefix)/lib/node_modules/node-addon-api
|
||||
|
||||
HAVE_CXX11 = @HAVE_CXX11@
|
||||
HAVE_CXX14 = @HAVE_CXX14@
|
||||
|
@ -27,6 +27,9 @@ CPP_TEST_CASES += \
|
|||
li_std_containers_int \
|
||||
li_std_map_member
|
||||
|
||||
CPP_TEST_BROKEN += \
|
||||
smart_pointer_static \
|
||||
|
||||
SWIGEXE = $(top_builddir)/swig
|
||||
SWIG_LIB_DIR = $(top_srcdir)/Lib
|
||||
|
||||
|
@ -68,8 +71,9 @@ _setup = \
|
|||
|
||||
SWIGOPT += -$(JSENGINE)
|
||||
|
||||
ifeq (node,$(JSENGINE))
|
||||
|
||||
ifeq ($(JSENGINE), $(filter $(JSENGINE), node napi))
|
||||
SWIGOPT += -DBUILDING_NODE_EXTENSION=1
|
||||
|
||||
# shut up some warnings
|
||||
|
||||
# dunno... ignoring generously
|
||||
|
@ -81,31 +85,45 @@ ifeq (node,$(JSENGINE))
|
|||
member_funcptr_galore.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\"
|
||||
director_unwrap_result.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\"
|
||||
|
||||
# Run with asan:
|
||||
# ASAN=1 ENGINE=napi make <test_name>.cpptest
|
||||
#
|
||||
ifneq (, $(ASAN))
|
||||
GYP_CFLAGS += \"-fsanitize=address\"
|
||||
GYP_OPTS = --debug
|
||||
ASAN_PRELOAD = $(shell $(CC) -print-file-name=libasan.so)
|
||||
LSAN_OPTIONS = suppressions=$(srcdir)/node_template/napi-leaks-suppression.txt
|
||||
BUILD = Debug
|
||||
else
|
||||
BUILD = Release
|
||||
endif
|
||||
|
||||
setup_node = \
|
||||
test -d $* || mkdir $* && \
|
||||
sed -e 's|$$testcase|$*|g; s|$$cflags|$(GYP_CFLAGS)|g; s|$$cxxflags|"$(GYP_CXXFLAGS)"|g; s|$$srcdir|$(srcdir)|g' \
|
||||
$(srcdir)/node_template/binding.gyp.in > $*/binding.gyp && \
|
||||
sed -e 's|$$testcase|$*|g;' \
|
||||
sed -e 's|$$testcase|$*|g; s|$$build|$(BUILD)|g;' \
|
||||
$(srcdir)/node_template/index.js.in > $*/index.js
|
||||
|
||||
|
||||
# Note: we need to use swig in C parse mode, but make node-gyp believe it is c++ (via file extension)
|
||||
swig_and_compile_c = \
|
||||
$(setup_node) && \
|
||||
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' \
|
||||
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
|
||||
SWIGOPT='-javascript $(SWIGOPT) -o $*_wrap.cxx $(srcdir)/../$*.i' swiginvoke && \
|
||||
MAKEFLAGS= $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null
|
||||
MAKEFLAGS= $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure $(GYP_OPTS) build 1>>/dev/null
|
||||
|
||||
swig_and_compile_cpp = \
|
||||
$(setup_node) && \
|
||||
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' \
|
||||
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
|
||||
SWIGOPT='-c++ -javascript $(SWIGOPT) $(srcdir)/../$*.i' swiginvoke && \
|
||||
MAKEFLAGS= $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null
|
||||
MAKEFLAGS= $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure $(GYP_OPTS) build 1>>/dev/null
|
||||
|
||||
run_testcase = \
|
||||
if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then \
|
||||
env NODE_PATH=$$PWD:$(srcdir) $(RUNTOOL) $(NODEJS) $(srcdir)/$*$(SCRIPTSUFFIX); \
|
||||
env NODE_PATH=$$PWD:$(srcdir) LD_PRELOAD=$(ASAN_PRELOAD) LSAN_OPTIONS=$(LSAN_OPTIONS) \
|
||||
$(RUNTOOL) $(NODEJS) $(srcdir)/$*$(SCRIPTSUFFIX); \
|
||||
fi
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ exception_thrown = false;
|
|||
try {
|
||||
catches_strings.StringsThrower.charstring();
|
||||
} catch (e) {
|
||||
if (!e.message.includes("charstring message"))
|
||||
if (!(e.message || e).includes("charstring message"))
|
||||
throw new Error("incorrect exception message " + e.message);
|
||||
exception_thrown = true;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ exception_thrown = false;
|
|||
try {
|
||||
catches_strings.StringsThrower.stdstring();
|
||||
} catch (e) {
|
||||
if (!e.message.includes("stdstring message"))
|
||||
if (!(e.message || e).includes("stdstring message"))
|
||||
throw new Error("incorrect exception message " + e.message);
|
||||
exception_thrown = true;
|
||||
}
|
||||
|
|
|
@ -96,11 +96,11 @@ checkCount(0);
|
|||
|
||||
// overloaded parameters
|
||||
if (li_std_auto_ptr.overloadTest() != 0)
|
||||
throw new RuntimeException("overloadTest failed");
|
||||
throw new Error("overloadTest failed");
|
||||
if (li_std_auto_ptr.overloadTest(null) != 1)
|
||||
throw new RuntimeException("overloadTest failed");
|
||||
throw new Error("overloadTest failed");
|
||||
if (li_std_auto_ptr.overloadTest(new li_std_auto_ptr.Klass("over")) != 1)
|
||||
throw new RuntimeException("overloadTest failed");
|
||||
throw new Error("overloadTest failed");
|
||||
checkCount(0);
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,14 @@ function check(flag) {
|
|||
|
||||
intPair = li_std_pair.makeIntPair(7, 6);
|
||||
check(typeof intPair === 'object');
|
||||
check(Object.keys(intPair).length == 2);
|
||||
if (Object.keys(intPair).length) {
|
||||
// When using raw V8, intPair will be an object with two properties
|
||||
check(Object.keys(intPair).length == 2);
|
||||
} else {
|
||||
// When using NAPI, intPair will be an object of class intPair whose
|
||||
// prototype will have two properties
|
||||
check(Object.keys(Object.getPrototypeOf(intPair)).length == 2);
|
||||
}
|
||||
check(intPair.first === 7);
|
||||
check(intPair.second === 6);
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
module.exports = require('./build/Release/$testcase');
|
||||
module.exports = require('./build/$build/$testcase');
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
leak:Init
|
||||
leak:napi_module_register
|
|
@ -48,8 +48,35 @@ extern "C" JNIEXPORT jint JNICALL Java_native_1directive_native_1directiveJNI_Co
|
|||
|
||||
#ifdef SWIGJAVASCRIPT
|
||||
%native(CountAlphaCharacters) void JavaScript_alpha_count();
|
||||
#if defined(SWIG_JAVASCRIPT_NAPI) /* engine = napi */
|
||||
%{
|
||||
|
||||
static Napi::Value JavaScript_alpha_count(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::EscapableHandleScope scope(env);
|
||||
|
||||
Napi::Value jsresult;
|
||||
char *arg1 = (char *)0;
|
||||
int res1;
|
||||
char *buf1 = 0;
|
||||
int alloc1 = 0;
|
||||
int result;
|
||||
if (info.Length() != 1) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for _wrap_alpha_count.");
|
||||
res1 = SWIG_AsCharPtrAndSize(info[0], &buf1, NULL, &alloc1);
|
||||
if (!SWIG_IsOK(res1))
|
||||
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "alpha_count" "', argument " "1"" of type '" "char const *""'");
|
||||
arg1 = reinterpret_cast< char * >(buf1);
|
||||
result = (int)alpha_count((char const *)arg1);
|
||||
jsresult = SWIG_From_int(env, static_cast< int >(result));
|
||||
if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
|
||||
return scope.Escape(jsresult);
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
|
||||
%}
|
||||
#elif defined(SWIG_JAVASCRIPT_V8) /* engine = node || v8 */
|
||||
%{
|
||||
#ifdef SWIG_V8_VERSION /* engine = node || v8 */
|
||||
|
||||
static SwigV8ReturnValue JavaScript_alpha_count(const SwigV8Arguments &args) {
|
||||
SWIGV8_HANDLESCOPE();
|
||||
|
@ -72,7 +99,9 @@ fail:
|
|||
SWIGV8_RETURN(SWIGV8_UNDEFINED());
|
||||
}
|
||||
|
||||
#else /* engine = jsc */
|
||||
%}
|
||||
#elif defined(SWIG_JAVASCRIPT_JSC) /* engine = jsc */
|
||||
%{
|
||||
|
||||
static JSValueRef JavaScript_alpha_count(JSContextRef context, JSObjectRef function,
|
||||
JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception)
|
||||
|
@ -96,7 +125,11 @@ fail:
|
|||
return JSValueMakeUndefined(context);
|
||||
}
|
||||
|
||||
#endif /* engine */
|
||||
%}
|
||||
#else
|
||||
%{
|
||||
#error No valid JS engine configured
|
||||
%}
|
||||
#endif /* engine */
|
||||
#endif /* SWIGJAVASCRIPT */
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ Also tests reported error when a #define placed in a deeply embedded struct/unio
|
|||
%rename(InUnNamed) OuterStructNamed::Inner_union_named;
|
||||
#endif
|
||||
|
||||
#if defined(SWIG_JAVASCRIPT_V8)
|
||||
#if defined(SWIG_JAVASCRIPT_V8) || defined(SWIG_JAVASCRIPT_NAPI)
|
||||
|
||||
%inline %{
|
||||
#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%module nested_extend_c
|
||||
|
||||
#if defined(SWIG_JAVASCRIPT_V8)
|
||||
#if defined(SWIG_JAVASCRIPT_V8) || defined(SWIG_JAVASCRIPT_NAPI)
|
||||
|
||||
%inline %{
|
||||
#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
|
@ -16,7 +16,7 @@
|
|||
#include "stdlib.h"
|
||||
%}
|
||||
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8)
|
||||
#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) && !defined(SWIG_JAVASCRIPT_NAPI)
|
||||
%extend hiA {
|
||||
hiA() {
|
||||
union hiA *self = (union hiA *)malloc(sizeof(union hiA));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%module nested_structs
|
||||
|
||||
#if defined(SWIG_JAVASCRIPT_V8)
|
||||
#if defined(SWIG_JAVASCRIPT_V8) || defined(SWIG_JAVASCRIPT_NAPI)
|
||||
|
||||
%inline %{
|
||||
#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
%header %{
|
||||
#define OUT_NULL_VALUE SWIGV8_NULL()
|
||||
%}
|
||||
#elif defined(SWIG_JAVASCRIPT_NAPI)
|
||||
%header %{
|
||||
#define OUT_NULL_VALUE env.Null()
|
||||
%}
|
||||
#else
|
||||
%header %{
|
||||
#define OUT_NULL_VALUE 0
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* ------------------------------------------------------------
|
||||
* SWIG library containing argc and argv multi-argument typemaps
|
||||
* ------------------------------------------------------------ */
|
||||
|
||||
%{
|
||||
SWIGINTERN int SWIG_AsVal_string (Napi::Value valRef, Napi::String *str)
|
||||
{
|
||||
if (!valRef.IsString()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if(str != SWIG_NULLPTR) {
|
||||
*str = valRef.ToString();
|
||||
}
|
||||
return SWIG_OK;
|
||||
}
|
||||
%}
|
||||
|
||||
%typemap(in) (int ARGC, char **ARGV) {
|
||||
$1_ltype i, len;
|
||||
size_t arraysize;
|
||||
Napi::Array array;
|
||||
if (!$input.IsArray()) {
|
||||
SWIG_exception_fail(SWIG_ERROR, "not array");
|
||||
}
|
||||
array = $input.As<Napi::Array>();
|
||||
len = array.Length();
|
||||
arraysize = (len+1)*sizeof($*2_ltype);
|
||||
$1 = len;
|
||||
$2 = ($2_ltype) malloc(arraysize);
|
||||
if ($2 == SWIG_NULLPTR) {
|
||||
SWIG_exception_fail(SWIG_ERROR, "memory allocation of array failed");
|
||||
}
|
||||
memset($2, 0, arraysize);
|
||||
for (i = 0; i < len; i++) {
|
||||
int res, slen;
|
||||
$*2_ltype pstr;
|
||||
Napi::String napi_str;
|
||||
Napi::Value jsvalue = array.Get(i);
|
||||
res = SWIG_AsVal_string(jsvalue, &napi_str);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
SWIG_exception_fail(SWIG_ERROR, "failed to convert to string");
|
||||
}
|
||||
std::string str = napi_str.Utf8Value();
|
||||
slen = str.size();
|
||||
pstr = ($*2_ltype) malloc(slen + 1);
|
||||
if (pstr == SWIG_NULLPTR) {
|
||||
SWIG_exception_fail(SWIG_ERROR, "memory allocation of a string failed");
|
||||
}
|
||||
if (slen) {
|
||||
memcpy(pstr, str.c_str(), slen);
|
||||
}
|
||||
pstr[slen] = 0;
|
||||
$2[i] = pstr;
|
||||
}
|
||||
$2[i] = SWIG_NULLPTR;
|
||||
}
|
||||
|
||||
%typemap(freearg) (int ARGC, char **ARGV) {
|
||||
if ($2 != SWIG_NULLPTR) {
|
||||
$1_ltype i;
|
||||
for (i = 0; i < $1; i++) {
|
||||
free((void *)$2[i]);
|
||||
}
|
||||
free((void *)$2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* arrays_javascript.i
|
||||
*
|
||||
* These typemaps give more natural support for arrays. The typemaps are not efficient
|
||||
* as there is a lot of copying of the array values whenever the array is passed to C/C++
|
||||
* from JavaScript and vice versa. The JavaScript array is expected to be the same size as the C array.
|
||||
* An exception is thrown if they are not.
|
||||
*
|
||||
* Example usage:
|
||||
* Wrapping:
|
||||
*
|
||||
* %include <arrays_javascript.i>
|
||||
* %inline %{
|
||||
* extern int FiddleSticks[3];
|
||||
* %}
|
||||
*
|
||||
* Use from JavaScript like this:
|
||||
*
|
||||
* var fs = [10, 11, 12];
|
||||
* example.FiddleSticks = fs;
|
||||
* fs = example.FiddleSticks;
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
%fragment("SWIG_NAPI_GetIntProperty", "header", fragment=SWIG_AsVal_frag(int)) {}
|
||||
%fragment("SWIG_NAPI_GetNumberProperty", "header", fragment=SWIG_AsVal_frag(double)) {}
|
||||
%fragment("SWIG_NAPI_OutInt", "header", fragment=SWIG_From_frag(int)) {}
|
||||
%fragment("SWIG_NAPI_OutNumber", "header", fragment=SWIG_From_frag(double)) {}
|
||||
|
||||
%define JAVASCRIPT_ARRAYS_IN_DECL(NAME, CTYPE, ANY, ANYLENGTH)
|
||||
|
||||
%typemap(in, fragment=NAME) CTYPE[ANY] {
|
||||
if ($input.IsArray()) {
|
||||
Napi::Env env = $input.Env();
|
||||
// Convert into Array
|
||||
Napi::Array array = $input.As<Napi::Array>();
|
||||
|
||||
int length = ANYLENGTH;
|
||||
|
||||
$1 = ($*1_ltype *)malloc(sizeof($*1_ltype) * length);
|
||||
|
||||
// Get each element from array
|
||||
for (int i = 0; i < length; i++) {
|
||||
Napi::Value jsvalue = array.Get(i);
|
||||
$*1_ltype temp;
|
||||
|
||||
// Get primitive value from JSObject
|
||||
int res = SWIG_AsVal(CTYPE)(jsvalue, &temp);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
SWIG_Error(SWIG_ERROR, "Failed to convert $input to double");
|
||||
}
|
||||
arg$argnum[i] = temp;
|
||||
}
|
||||
} else {
|
||||
Napi::Env env = $input.Env();
|
||||
SWIG_Error(SWIG_ERROR, "$input is not an array");
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(freearg) CTYPE[ANY] {
|
||||
free($1);
|
||||
}
|
||||
|
||||
%enddef
|
||||
|
||||
%define JAVASCRIPT_ARRAYS_OUT_DECL(NAME, CTYPE)
|
||||
|
||||
%typemap(out, fragment=NAME) CTYPE[ANY] {
|
||||
int length = $1_dim0;
|
||||
Napi::Array array = Napi::Array::New(env, length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
array.Set(i, SWIG_From(CTYPE)($1[i]));
|
||||
}
|
||||
|
||||
$result = array;
|
||||
}
|
||||
|
||||
%enddef
|
||||
|
||||
JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetIntProperty", int, , array.Length())
|
||||
JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetIntProperty", int, ANY, $1_dim0)
|
||||
JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetNumberProperty", double, , array.Length())
|
||||
JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetNumberProperty", double, ANY, $1_dim0)
|
||||
|
||||
JAVASCRIPT_ARRAYS_OUT_DECL("SWIG_NAPI_OutInt", int)
|
||||
JAVASCRIPT_ARRAYS_OUT_DECL("SWIG_NAPI_OutNumber", double)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* ccomplex.i
|
||||
*
|
||||
* C complex typemaps
|
||||
* ISO C99: 7.3 Complex arithmetic <complex.h>
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
%include <javascriptcomplex.swg>
|
||||
|
||||
%{
|
||||
#include <complex.h>
|
||||
%}
|
||||
|
||||
#define complex _Complex
|
||||
|
||||
/* C complex constructor */
|
||||
#define CCplxConst(r, i) ((r) + I*(i))
|
||||
|
||||
%swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag);
|
||||
%swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag);
|
||||
%swig_cplxdbl_convn(_Complex, CCplxConst, creal, cimag);
|
||||
|
||||
/* declaring the typemaps */
|
||||
%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex);
|
||||
%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex);
|
||||
%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, _Complex);
|
|
@ -0,0 +1 @@
|
|||
%include <typemaps/cdata.swg>
|
|
@ -0,0 +1 @@
|
|||
%include <typemaps/cmalloc.swg>
|
|
@ -0,0 +1,6 @@
|
|||
#ifdef __cplusplus
|
||||
%include <std_complex.i>
|
||||
#else
|
||||
%include <ccomplex.i>
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
%include <typemaps/exception.swg>
|
|
@ -0,0 +1 @@
|
|||
%include <typemaps/factory.swg>
|
|
@ -0,0 +1,17 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* javascript.swg
|
||||
*
|
||||
* Javascript typemaps
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%include <typemaps/swigmacros.swg>
|
||||
|
||||
%include <javascripttypemaps.swg>
|
||||
|
||||
%include <javascriptruntime.swg>
|
||||
|
||||
%include <javascriptkw.swg>
|
||||
|
||||
%include <javascriptcode.swg>
|
||||
|
||||
%include <javascriptinit.swg>
|
|
@ -0,0 +1,880 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* js_ctor: template for wrapping a ctor.
|
||||
* - $jswrapper: wrapper of called ctor
|
||||
* - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none)
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* - $jsargcount: number of arguments
|
||||
* - $jsargrequired: minimum number of arguments
|
||||
* - $jsmangledname: mangled name of class
|
||||
* - $jsmangledtype: mangled type of class
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%fragment("js_ctor", "templates") %{
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
// js_ctor
|
||||
// This is the main constructor
|
||||
$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(const Napi::CallbackInfo &info)
|
||||
: $jsparent_templ<SWIG_OBJ_WRAP>(true, info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
this->info = SWIGTYPE_$jsmangledtype;
|
||||
if (info.Length() == 1 && info[0].IsExternal()) {
|
||||
// This constructor has been called internally from C++/SWIG
|
||||
// to wrap an already existing C++ object in JS
|
||||
this->self = info[0].As<Napi::External<void>>().Data();
|
||||
this->owned = false;
|
||||
return;
|
||||
}
|
||||
this->owned = true;
|
||||
|
||||
$jslocals
|
||||
if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) {
|
||||
SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper.");
|
||||
}
|
||||
$jscode
|
||||
this->self = result;
|
||||
return;
|
||||
goto fail;
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the bypass constructor to be used from child classes
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(bool, const Napi::CallbackInfo &info)
|
||||
: $jsparent_templ<SWIG_OBJ_WRAP>(true, info) {}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_veto_ctor: a vetoing ctor for abstract classes
|
||||
* - $jsmangledname: mangled name of class
|
||||
* - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_veto_ctor", "templates")
|
||||
%{
|
||||
// js_veto_ctor
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(const Napi::CallbackInfo &info)
|
||||
: $jsparent_templ<SWIG_OBJ_WRAP>(true, info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() == 1 && info[0].IsExternal()) {
|
||||
// This constructor has been called internally from C++/SWIG
|
||||
// to wrap an already existing C++ object in JS as its
|
||||
// base abstract class
|
||||
this->self = info[0].As<Napi::External<void>>().Data();
|
||||
this->owned = false;
|
||||
return;
|
||||
}
|
||||
SWIG_Error(SWIG_ERROR, "Class $jsname can not be instantiated");
|
||||
return;
|
||||
goto fail;
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the extendable constructor to be used from child classes
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(bool, const Napi::CallbackInfo &info)
|
||||
: $jsparent_templ<SWIG_OBJ_WRAP>(true, info) {
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_ctor_dispatcher: dispatcher for overloaded constructors
|
||||
* - $jsmangledname: mangled name of class
|
||||
* - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none)
|
||||
* - $jsdispatchcases: part containing code for dispatching
|
||||
* - $jsmangledtype: mangled type of class
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_ctor_dispatcher", "templates")
|
||||
%{
|
||||
// js_ctor_dispatcher
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(const Napi::CallbackInfo &info)
|
||||
: $jsparent_templ<SWIG_OBJ_WRAP>(true, info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Object self;
|
||||
NAPI_CHECK_RESULT(info.This().ToObject(), self);
|
||||
this->info = SWIGTYPE_$jsmangledtype;
|
||||
if (info.Length() == 1 && info[0].IsExternal()) {
|
||||
// This constructor has been called internally from C++/SWIG
|
||||
// to wrap an already existing C++ object in JS
|
||||
this->self = info[0].As<Napi::External<void>>().Data();
|
||||
this->owned = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// switch all cases by means of series of if-returns.
|
||||
$jsdispatchcases
|
||||
|
||||
// default:
|
||||
SWIG_Error(SWIG_ERROR, "Illegal arguments for construction of $jsmangledname");
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the extendable constructor to be used from child classes
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(bool, const Napi::CallbackInfo &info)
|
||||
: $jsparent_templ<SWIG_OBJ_WRAP>(true, info) {
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_overloaded_ctor: template for wrapping a ctor.
|
||||
* - $jswrapper: wrapper of called ctor
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* - $jsargcount: number of arguments
|
||||
* - $jsargrequired: minimum number of arguments
|
||||
* - $jsmangledtype: mangled type of class
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_overloaded_ctor", "templates") %{
|
||||
// js_overloaded_ctor
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Object self;
|
||||
$jslocals
|
||||
NAPI_CHECK_RESULT(info.This().ToObject(), self);
|
||||
this->owned = true;
|
||||
if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) {
|
||||
SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper.");
|
||||
}
|
||||
$jscode
|
||||
this->self = result;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_ctor_dispatch_case: template for a dispatch case for calling an overloaded ctor.
|
||||
* - $jsargcount: number of arguments of called ctor
|
||||
* - $jsargrequired: minimum number of arguments
|
||||
* - $jswrapper: wrapper of called ctor
|
||||
*
|
||||
* Note: a try-catch-like mechanism is used to switch cases
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_ctor_dispatch_case", "templates")
|
||||
%{
|
||||
// js_ctor_dispatch_case
|
||||
if(static_cast<int>(info.Length()) >= $jsargrequired && static_cast<int>(info.Length()) <= $jsargcount) {
|
||||
#ifdef NAPI_CPP_EXCEPTIONS
|
||||
bool tryNext = false;
|
||||
try {
|
||||
$jswrapper(info);
|
||||
} catch (const Napi::TypeError &) {
|
||||
tryNext = true;
|
||||
} catch (const Napi::Error &e) {
|
||||
throw e;
|
||||
}
|
||||
if (!tryNext)
|
||||
return;
|
||||
#else
|
||||
$jswrapper(info);
|
||||
if (env.IsExceptionPending()) {
|
||||
Napi::Error e = env.GetAndClearPendingException();
|
||||
Napi::Value typeErrorValue;
|
||||
bool isTypeError;
|
||||
Napi::Function typeErrorCons;
|
||||
// Yes, this is ugly
|
||||
// TODO: Fix this in Node.js when the core team grows up
|
||||
NAPI_CHECK_RESULT(env.Global().Get("TypeError"), typeErrorValue);
|
||||
typeErrorCons = typeErrorValue.As<Napi::Function>();
|
||||
NAPI_CHECK_RESULT(e.Value().InstanceOf(typeErrorCons), isTypeError);
|
||||
if (!isTypeError) {
|
||||
// This is not the error you are looking for
|
||||
e.ThrowAsJavaScriptException();
|
||||
SWIG_fail;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_check_arg: template for checking if an argument exists
|
||||
* - $jsarg: number of argument
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_check_arg", "templates")
|
||||
%{if(info.Length() > $jsarg)%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_dtor: template for a destructor wrapper
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jstype: class type
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_dtor", "templates")
|
||||
%{
|
||||
// js_dtor
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
$jsmangledname_templ<SWIG_OBJ_WRAP>::~$jsmangledname_templ() {
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_dtoroverride: template for a destructor wrapper
|
||||
* - ${classname_mangled}: mangled class name
|
||||
* - $jstype: class type
|
||||
* - ${destructor_action}: The custom destructor action to invoke.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_dtoroverride", "templates")
|
||||
%{
|
||||
// js_dtoroverride
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
${classname_mangled}_templ<SWIG_OBJ_WRAP>::~${classname_mangled}_templ() {
|
||||
auto arg1 = reinterpret_cast<$jstype>(this->self);
|
||||
if (this->owned && arg1) {
|
||||
${destructor_action}
|
||||
this->self = nullptr;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_global_getter: template for global getter function wrappers
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_global_getter", "templates")
|
||||
%{
|
||||
// js_global_getter
|
||||
Napi::Value $jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
$jscode
|
||||
return jsresult;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_global_setter: template for global setter function wrappers
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_global_setter", "templates")
|
||||
%{
|
||||
// js_global_setter
|
||||
void $jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value value = info.Length() > 0 ? info[0] : Napi::Value();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
$jscode
|
||||
return;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_register_global_variable: template for a statement that registers a global variable
|
||||
* - $jsname: variable name
|
||||
* - $jsparent: parent namespace
|
||||
* - $jsgetter: wrapper of the getter function
|
||||
* - $jssetter: wrapper of the setter function
|
||||
*
|
||||
* Note: this template is also used for global variables.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_register_global_variable", "templates")
|
||||
%{
|
||||
// jsnapi_register_global_variable
|
||||
do {
|
||||
Napi::PropertyDescriptor pd = Napi::PropertyDescriptor::Accessor<$jsgetter, $jssetter>("$jsname");
|
||||
NAPI_CHECK_MAYBE($jsparent.DefineProperties({pd}));
|
||||
} while (0);
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_global_function: template for function wrappers
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jsargcount: number of arguments
|
||||
* - $jsargrequired: minimum number of arguments
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_global_function", "templates")
|
||||
%{
|
||||
// js_global_function
|
||||
Napi::Value $jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) {
|
||||
SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper.");
|
||||
}
|
||||
|
||||
$jscode
|
||||
return jsresult;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_global_function_dispatcher: template for a global function dispatcher for
|
||||
* global overloaded functions
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jsname: name of the wrapped function
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_global_function_dispatcher", "templates")
|
||||
%{
|
||||
// js_global_function_dispatcher
|
||||
Napi::Value $jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jscode
|
||||
|
||||
SWIG_Error(SWIG_ERROR, "Illegal arguments for function $jsname.");
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_register_global_function: template for a statement that registers a global function
|
||||
* - $jsname: function name
|
||||
* - $jsparent: parent namespace
|
||||
* - $jswrapper: name of the JS wrapper
|
||||
*
|
||||
* Note: this template is also used for global variables.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_register_global_function", "templates")
|
||||
%{
|
||||
// jsnapi_register_global_function
|
||||
do {
|
||||
Napi::PropertyDescriptor pd = Napi::PropertyDescriptor::Function("$jsname", $jswrapper);
|
||||
NAPI_CHECK_MAYBE($jsparent.DefineProperties({pd}));
|
||||
} while (0);
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_getter: template for getter function wrappers
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_getter", "templates")
|
||||
%{
|
||||
// js_getter
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
$jscode
|
||||
return jsresult;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_setter: template for setter function wrappers
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_setter", "templates")
|
||||
%{
|
||||
// js_setter
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
void $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info, const Napi::Value &value) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
$jscode
|
||||
return;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_function: template for function wrappers
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jsargcount: minimum number of arguments
|
||||
* - $jsargrequired: minimum number of arguments
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_function", "templates")
|
||||
%{
|
||||
// js_function
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) {
|
||||
SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper.");
|
||||
}
|
||||
|
||||
$jscode
|
||||
return jsresult;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_function_dispatcher: template for a function dispatcher for overloaded functions
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jsname: name of the wrapped function
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_function_dispatcher", "templates")
|
||||
%{
|
||||
// js_function_dispatcher
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jscode
|
||||
|
||||
SWIG_Error(SWIG_ERROR, "Illegal arguments for function $jsname.");
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_overloaded_function: template for a overloaded function
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_overloaded_function", "templates")
|
||||
%{
|
||||
// js_overloaded_function
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
$jscode
|
||||
return jsresult;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_global_overloaded_function: template for a global overloaded function
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jslocals: locals part of wrapper
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_global_overloaded_function", "templates")
|
||||
%{
|
||||
// js_global_overloaded_function
|
||||
Napi::Value $jswrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
$jslocals
|
||||
$jscode
|
||||
return jsresult;
|
||||
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_function_dispatch_case: template for a case used in the function dispatcher
|
||||
* - $jswrapper: wrapper function name
|
||||
* - $jsargcount: number of arguments of overloaded function
|
||||
* - $jsargrequired: minimum number of arguments
|
||||
* - $jscode: code part of wrapper
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment ("js_function_dispatch_case", "templates")
|
||||
%{
|
||||
// js_function_dispatch_case
|
||||
if(static_cast<int>(info.Length()) >= $jsargrequired && static_cast<int>(info.Length()) <= $jsargcount) {
|
||||
#ifdef NAPI_CPP_EXCEPTIONS
|
||||
bool tryNext = false;
|
||||
try {
|
||||
jsresult = $jswrapper(info);
|
||||
} catch (const Napi::TypeError &) {
|
||||
tryNext = true;
|
||||
} catch (const Napi::Error &e) {
|
||||
throw e;
|
||||
}
|
||||
if (!tryNext)
|
||||
return jsresult;
|
||||
#else
|
||||
$jswrapper(info);
|
||||
if (env.IsExceptionPending()) {
|
||||
Napi::Error e = env.GetAndClearPendingException();
|
||||
Napi::Value typeErrorValue;
|
||||
bool isTypeError;
|
||||
Napi::Function typeErrorCons;
|
||||
// Yes, this is ugly
|
||||
// TODO: Fix this in Node.js when the core team grows up
|
||||
NAPI_CHECK_RESULT(env.Global().Get("TypeError"), typeErrorValue);
|
||||
typeErrorCons = typeErrorValue.As<Napi::Function>();
|
||||
NAPI_CHECK_RESULT(e.Value().InstanceOf(typeErrorCons), isTypeError);
|
||||
if (!isTypeError) {
|
||||
// This is not the error you are looking for
|
||||
e.ThrowAsJavaScriptException();
|
||||
SWIG_fail;
|
||||
}
|
||||
} else {
|
||||
return jsresult;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_class_prologue_template: template for a class prologue
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_class_prologue_template", "templates")
|
||||
%{
|
||||
// jsnapi_class_prologue_template
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
class $jsmangledname_templ : public $jsparent_templ<SWIG_OBJ_WRAP> {
|
||||
public:
|
||||
$jsmangledname_templ(const Napi::CallbackInfo &);
|
||||
$jsmangledname_templ(bool, const Napi::CallbackInfo &);
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_class_dtor_declaration: template for a class destructor declaration
|
||||
* - $jsmangledname: mangled class name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_class_dtor_declaration", "templates")
|
||||
%{
|
||||
virtual ~$jsmangledname_templ();
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_class_method_declaration: template for a class method declaration
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jswrapper: method name
|
||||
* - $jsstatic: static modifier
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_class_method_declaration", "templates")
|
||||
%{
|
||||
// jsnapi_class_method_declaration
|
||||
$jsstatic Napi::Value $jswrapper(const Napi::CallbackInfo &);
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_class_setter_declaration: template for a class method declaration
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jswrapper: method name
|
||||
* - $jsstatic: static modifier
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_class_setter_declaration", "templates")
|
||||
%{
|
||||
// jsnapi_class_setter_declaration
|
||||
$jsstatic void $jswrapper(const Napi::CallbackInfo &, const Napi::Value &);
|
||||
%}
|
||||
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_class_epilogue_template: template for a class epilogue
|
||||
* - $jsmangledname: mangled class name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_class_epilogue_template", "templates")
|
||||
%{
|
||||
// jsnapi_class_epilogue_template
|
||||
static void JS_veto_set_static_variable(const Napi::CallbackInfo &, const Napi::Value &);
|
||||
void JS_veto_set_variable(const Napi::CallbackInfo &, const Napi::Value &);
|
||||
};
|
||||
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
void $jsmangledname_templ<SWIG_OBJ_WRAP>::JS_veto_set_static_variable(const Napi::CallbackInfo &info, const Napi::Value &value) {
|
||||
SWIG_NAPI_Raise(info.Env(), "Tried to write read-only variable.");
|
||||
}
|
||||
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
void $jsmangledname_templ<SWIG_OBJ_WRAP>::JS_veto_set_variable(const Napi::CallbackInfo &info, const Napi::Value &value) {
|
||||
SWIG_NAPI_Raise(info.Env(), "Tried to write read-only variable.");
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_class_instance: template for a class declaration instance
|
||||
* - $jsmangledname: mangled class name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_declare_class_instance", "templates")
|
||||
%{
|
||||
// jsnapi_class_instance
|
||||
class $jsmangledname_inst : public $jsmangledname_templ<$jsmangledname_inst> {
|
||||
public:
|
||||
using $jsmangledname_templ::$jsmangledname_templ;
|
||||
virtual ~$jsmangledname_inst() {};
|
||||
static void GetMembers(
|
||||
Napi::Env,
|
||||
std::map<std::string, $jsmangledname_templ::PropertyDescriptor> &,
|
||||
std::map<std::string, $jsmangledname_templ::PropertyDescriptor> &
|
||||
);
|
||||
static Napi::Function GetClass(Napi::Env);
|
||||
};
|
||||
%}
|
||||
|
||||
|
||||
/*
|
||||
* Inheritance is still not officially supported in NAPI
|
||||
* Refer to this for my workaround:
|
||||
* https://mmomtchev.medium.com/c-class-inheritance-with-node-api-and-node-addon-api-c180334d9902
|
||||
*/
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_inherited_class_prologue_template: template for a class prologue
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsparent: mangled name of parent class
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_inherited_class_prologue_template", "templates")
|
||||
%{
|
||||
// jsnapi_inherited_class_prologue_template
|
||||
SWIG_NAPI_ClientData $jsmangledname_clientData;
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
class $jsmangledname_templ : public $jsparent_templ<SWIG_OBJ_WRAP> {
|
||||
public:
|
||||
$jsmangledname_templ(const Napi::CallbackInfo& info);
|
||||
%}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_getclass: template for creating a class object
|
||||
* - $jsname: class name
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsfunctions: member functions
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_getclass", "templates")
|
||||
%{
|
||||
/* Class: $jsname ($jsmangledname) */
|
||||
// jsnapi_getclass
|
||||
Napi::Function $jsmangledname_inst::GetClass(Napi::Env env) {
|
||||
std::map<std::string, $jsmangledname_templ::PropertyDescriptor> members, staticMembers;
|
||||
GetMembers(env, members, staticMembers);
|
||||
|
||||
std::vector<$jsmangledname_inst::PropertyDescriptor> symbolTable;
|
||||
for (auto it = members.begin(); it != members.end(); it++)
|
||||
symbolTable.push_back(it->second);
|
||||
for (auto it = staticMembers.begin(); it != staticMembers.end(); it++)
|
||||
symbolTable.push_back(it->second);
|
||||
|
||||
return Napi::ObjectWrap<$jsmangledname_inst>::DefineClass(env, "$jsname", symbolTable);
|
||||
}
|
||||
|
||||
void $jsmangledname_inst::GetMembers(
|
||||
Napi::Env env,
|
||||
std::map<std::string, $jsmangledname_templ::PropertyDescriptor> &members,
|
||||
std::map<std::string, $jsmangledname_templ::PropertyDescriptor> &staticMembers
|
||||
) {
|
||||
std::map<std::string, $jsparent_templ<$jsparent_inst>::PropertyDescriptor> baseMembers, baseStaticMembers;
|
||||
$jsparent_inst::GetMembers(env, baseMembers, baseStaticMembers);
|
||||
members.insert(baseMembers.begin(), baseMembers.end());
|
||||
staticMembers.insert(staticMembers.begin(), staticMembers.end());
|
||||
|
||||
/* register wrapper functions */
|
||||
$jsnapiwrappers
|
||||
/* add static class functions and variables */
|
||||
$jsnapistaticwrappers
|
||||
}
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_registerclass: template for regsitering a class object
|
||||
* - $jsname: class name
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsparent: parent namespace
|
||||
* - $jsmangledtype: mangled class type
|
||||
* - $jsclassidx: class index in the class table
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_registerclass", "templates")
|
||||
%{
|
||||
|
||||
/* Class: $jsname ($jsmangledname) */
|
||||
// jsnapi_registerclass
|
||||
Napi::Function $jsmangledname_ctor = $jsmangledname_inst::GetClass(env);
|
||||
$jsparent.Set("$jsname", $jsmangledname_ctor);
|
||||
if (SWIGTYPE_$jsmangledtype->clientdata == nullptr) {
|
||||
SWIGTYPE_$jsmangledtype->clientdata = new size_t($jsclassidx);
|
||||
}
|
||||
Napi::FunctionReference *$jsmangledname_ctor_ref = new Napi::FunctionReference();
|
||||
*$jsmangledname_ctor_ref = Napi::Persistent($jsmangledname_ctor);
|
||||
env.GetInstanceData<EnvInstanceData>()->ctor[$jsclassidx] = $jsmangledname_ctor_ref;
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_setup_inheritance: setup inheritance between two classes
|
||||
* - $jsname: class name
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsparent: mangled name of parent class
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_setup_inheritance", "templates")
|
||||
%{
|
||||
// Inheritance for $jsmangledname ($jsname) <- $jsparent
|
||||
// jsnapi_setup_inheritance
|
||||
do {
|
||||
Napi::Value protoBase, protoSub;
|
||||
NAPI_CHECK_RESULT($jsmangledname_ctor.Get("prototype"), protoSub);
|
||||
NAPI_CHECK_RESULT($jsparent_ctor.Get("prototype"), protoBase);
|
||||
NAPI_CHECK_MAYBE(setProto.Call({$jsmangledname_ctor, $jsparent_ctor}));
|
||||
NAPI_CHECK_MAYBE(setProto.Call({protoSub, protoBase}));
|
||||
} while (0);
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_create_namespace: template for a statement that creates a namespace object.
|
||||
* - $jsmangledname: mangled namespace name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_create_namespace", "templates")
|
||||
%{
|
||||
// jsnapi_create_namespace
|
||||
Napi::Object $jsmangledname = Napi::Object::New(env);
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_register_namespace: template for a statement that registers a namespace in a parent namespace.
|
||||
* - $jsname: name of namespace
|
||||
* - $jsmangledname: mangled name of namespace
|
||||
* - $jsparent: mangled name of parent namespace
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_register_namespace", "templates")
|
||||
%{
|
||||
// jsnapi_register_namespace
|
||||
NAPI_CHECK_MAYBE($jsparent.Set("$jsname", $jsmangledname));
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_member_function_descriptor: template for a statement that registers a member function.
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsname: name of the function
|
||||
* - $jswrapper: wrapper of the member function
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_register_member_function", "templates")
|
||||
%{
|
||||
// jsnapi_member_function_descriptor
|
||||
members.erase("$jsname");
|
||||
members.insert({"$jsname",
|
||||
$jsmangledname_templ::InstanceMethod("$jsname",
|
||||
&$jsmangledname_templ::$jswrapper,
|
||||
static_cast<napi_property_attributes>(napi_writable | napi_configurable))
|
||||
});
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_register_member_variable: template for a statement that registers a member variable.
|
||||
* - $jsname: name of the function
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsgetter: wrapper of the getter function
|
||||
* - $jssetter: wrapper of the setter function
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_register_member_variable", "templates")
|
||||
%{
|
||||
// jsnapi_register_member_variable
|
||||
members.erase("$jsname");
|
||||
members.insert({"$jsname",
|
||||
$jsmangledname_templ::InstanceAccessor("$jsname",
|
||||
&$jsmangledname_templ::$jsgetter,
|
||||
&$jsmangledname_templ::$jssetter,
|
||||
static_cast<napi_property_attributes>(napi_writable | napi_enumerable | napi_configurable))
|
||||
});
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_register_static_function: template for a statement that registers a static class function.
|
||||
* - $jsname: function name
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jswrapper: wrapper of the function
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_register_static_function", "templates")
|
||||
%{
|
||||
// jsnapi_register_static_function
|
||||
staticMembers.erase("$jsname");
|
||||
staticMembers.insert({"$jsname",
|
||||
StaticMethod("$jsname",
|
||||
&$jsmangledname_templ::$jswrapper,
|
||||
static_cast<napi_property_attributes>(napi_writable | napi_configurable))
|
||||
});
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* jsnapi_register_static_variable: template for a statement that registers a static variable.
|
||||
* - $jsname: variable name
|
||||
* - $jsmangledname: mangled class name
|
||||
* - $jsgetter: wrapper of the getter function
|
||||
* - $jssetter: wrapper of the setter function
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("jsnapi_register_static_variable", "templates")
|
||||
%{
|
||||
// jsnapi_register_static_variable
|
||||
staticMembers.erase("$jsname");
|
||||
staticMembers.insert({"$jsname",
|
||||
StaticAccessor("$jsname",
|
||||
&$jsmangledname_templ::$jsgetter,
|
||||
&$jsmangledname_templ::$jssetter,
|
||||
static_cast<napi_property_attributes>(napi_writable | napi_enumerable | napi_configurable))
|
||||
});
|
||||
%}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Defines the As/From converters for double/float complex, you need to
|
||||
provide complex Type, the Name you want to use in the converters,
|
||||
the complex Constructor method, and the Real and Imag complex
|
||||
accessor methods.
|
||||
|
||||
See the std_complex.i and ccomplex.i for concrete examples.
|
||||
*/
|
||||
|
||||
/* the common from converter */
|
||||
%define %swig_fromcplx_conv(Type, Real, Imag)
|
||||
%fragment(SWIG_From_frag(Type),"header",
|
||||
fragment=SWIG_From_frag(double))
|
||||
{
|
||||
SWIGINTERNINLINE Napi::Value
|
||||
SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c)
|
||||
{
|
||||
Napi::Array vals = Napi::Array::New(0);
|
||||
|
||||
vals.Set(0, SWIG_From(double)(Real(c)));
|
||||
vals.Set(1, SWIG_From(double)(Imag(c)));
|
||||
return vals;
|
||||
}
|
||||
}
|
||||
%enddef
|
||||
|
||||
/* the double case */
|
||||
%define %swig_cplxdbl_conv(Type, Constructor, Real, Imag)
|
||||
%fragment(SWIG_AsVal_frag(Type),"header",
|
||||
fragment=SWIG_AsVal_frag(double))
|
||||
{
|
||||
SWIGINTERN int
|
||||
SWIG_AsVal_dec(Type) (Napi::Value o, Type* val)
|
||||
{
|
||||
if (o.IsArray()) {
|
||||
Napi::Array array = Napi::Array::Cast(o);
|
||||
|
||||
if (array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2].");
|
||||
double re, im;
|
||||
Napi::Value r;
|
||||
|
||||
r = array.Get(0);
|
||||
if (!r.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
re = r.ToNumber().DoubleValue();
|
||||
|
||||
r = array.Get(1);
|
||||
if (!r.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
im = r.ToNumber().DoubleValue();
|
||||
|
||||
if (val) *val = Constructor(re, im);
|
||||
return SWIG_OK;
|
||||
} else if (o.IsNumber()) {
|
||||
double d = o.ToNumber().DoubleValue();
|
||||
if (val) *val = Constructor(d, 0.0);
|
||||
return SWIG_OK;
|
||||
}
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
}
|
||||
%swig_fromcplx_conv(Type, Real, Imag);
|
||||
%enddef
|
||||
|
||||
/* the float case */
|
||||
%define %swig_cplxflt_conv(Type, Constructor, Real, Imag)
|
||||
%fragment(SWIG_AsVal_frag(Type),"header",
|
||||
fragment=SWIG_AsVal_frag(float)) {
|
||||
SWIGINTERN int
|
||||
SWIG_AsVal_dec(Type) (Napi::Value o, Type* val)
|
||||
{
|
||||
if (o.IsArray()) {
|
||||
Napi::Array array = o.As<Napi::Array>();
|
||||
|
||||
if (array.Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2].");
|
||||
double re, im;
|
||||
Napi::Value r;
|
||||
|
||||
r = array.Get(0);
|
||||
if (!r.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
re = r.ToNumber().DoubleValue();
|
||||
|
||||
r = array.Get(1);
|
||||
if (!r.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
im = r.ToNumber().DoubleValue();
|
||||
|
||||
if ((-FLT_MAX <= re && re <= FLT_MAX) && (-FLT_MAX <= im && im <= FLT_MAX)) {
|
||||
if (val) *val = Constructor(%numeric_cast(re, float),
|
||||
%numeric_cast(im, float));
|
||||
return SWIG_OK;
|
||||
} else {
|
||||
return SWIG_OverflowError;
|
||||
}
|
||||
} else if (o.IsNumber()) {
|
||||
float f = static_cast<float>(o.ToNumber().DoubleValue());
|
||||
if (val) *val = Constructor(f, 0.0);
|
||||
return SWIG_OK;
|
||||
}
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
}
|
||||
%swig_fromcplx_conv(Type, Real, Imag);
|
||||
%enddef
|
||||
|
||||
#define %swig_cplxflt_convn(Type, Constructor, Real, Imag) \
|
||||
%swig_cplxflt_conv(Type, Constructor, Real, Imag)
|
||||
|
||||
|
||||
#define %swig_cplxdbl_convn(Type, Constructor, Real, Imag) \
|
||||
%swig_cplxdbl_conv(Type, Constructor, Real, Imag)
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
|
||||
Create a file with this name, 'javascriptfragments.swg', in your working
|
||||
directory and add all the %fragments you want to take precedence
|
||||
over the default ones defined by swig.
|
||||
|
||||
For example, if you add:
|
||||
|
||||
%fragment(SWIG_AsVal_frag(int),"header") {
|
||||
SWIGINTERNINLINE int
|
||||
SWIG_AsVal(int)(PyObject *obj, int *val)
|
||||
{
|
||||
<your code here>;
|
||||
}
|
||||
}
|
||||
|
||||
this will replace the code used to retrieve an integer value for all
|
||||
the typemaps that need it, including:
|
||||
|
||||
int, std::vector<int>, std::list<std::pair<int,int> >, etc.
|
||||
|
||||
|
||||
*/
|
|
@ -0,0 +1,111 @@
|
|||
%insert(header) %{
|
||||
#include <assert.h>
|
||||
%}
|
||||
|
||||
%insert(init) %{
|
||||
|
||||
EnvInstanceData::EnvInstanceData(Napi::Env env, swig_module_info *swig_module) :
|
||||
env(env), SWIG_NAPI_ObjectWrapCtor(nullptr), ctor(nullptr), swig_module(swig_module) {
|
||||
ctor = new Napi::FunctionReference*[swig_module->size + 1];
|
||||
for (size_t i = 0; i <= swig_module->size; i++) {
|
||||
ctor[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
EnvInstanceData::~EnvInstanceData() {
|
||||
for (size_t i = 0; i <= swig_module->size; i++) {
|
||||
if (ctor[i] != nullptr)
|
||||
delete ctor[i];
|
||||
ctor[i] = nullptr;
|
||||
}
|
||||
delete [] ctor;
|
||||
delete SWIG_NAPI_ObjectWrapCtor;
|
||||
}
|
||||
|
||||
SWIGRUNTIME void
|
||||
SWIG_NAPI_SetModule(Napi::Env env, swig_module_info *swig_module) {
|
||||
auto data = new EnvInstanceData(env, swig_module);
|
||||
env.SetInstanceData(data);
|
||||
}
|
||||
|
||||
SWIGRUNTIME swig_module_info *
|
||||
SWIG_NAPI_GetModule(Napi::Env env) {
|
||||
auto data = env.GetInstanceData<EnvInstanceData>();
|
||||
if (data == nullptr) return nullptr;
|
||||
return data->swig_module;
|
||||
}
|
||||
|
||||
#define SWIG_GetModule(clientdata) SWIG_NAPI_GetModule(clientdata)
|
||||
#define SWIG_SetModule(clientdata, pointer) SWIG_NAPI_SetModule(clientdata, pointer)
|
||||
#define SWIG_INIT_CLIENT_DATA_TYPE Napi::Env
|
||||
|
||||
%}
|
||||
|
||||
%insert(init) "swiginit.swg"
|
||||
|
||||
// Open the initializer function definition here
|
||||
|
||||
%fragment ("js_initializer_define", "templates") %{
|
||||
#define SWIG_NAPI_INIT $jsname_initialize
|
||||
%}
|
||||
|
||||
%insert(init) %{
|
||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||
SWIG_InitializeModule(env);
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_init_inheritance: template for enabling the inheritance
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_init_inheritance", "templates")
|
||||
%{
|
||||
Napi::Value jsObjectValue, jsSetProtoValue;
|
||||
Napi::Object jsObject;
|
||||
Napi::Function setProto;
|
||||
NAPI_CHECK_RESULT(env.Global().Get("Object"), jsObjectValue);
|
||||
NAPI_CHECK_RESULT(jsObjectValue.ToObject(), jsObject);
|
||||
NAPI_CHECK_RESULT(jsObject.Get("setPrototypeOf"), jsSetProtoValue);
|
||||
setProto = jsSetProtoValue.As<Napi::Function>();
|
||||
%}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* js_initializer: template for the module initializer function
|
||||
* - $jsname: module name
|
||||
* - $jsnapipreinheritance: the previous template
|
||||
* - $jsnapinspaces: part with code creating namespace objects
|
||||
* - $jsnapiwrappers: part with code that registers wrapper functions
|
||||
* - $jsnapiinitinheritance: part with inherit statements
|
||||
* - $jsnapistaticwrappers: part with code adding static functions to class objects
|
||||
* - $jsnapiregisterclasses: part with code that registers class objects in namespaces
|
||||
* - $jsnapiregisternspaces: part with code that registers namespaces in parent namespaces
|
||||
* ----------------------------------------------------------------------------- */
|
||||
%fragment("js_initializer", "templates")
|
||||
%{
|
||||
Napi::Function SWIG_NAPI_ObjectWrap_ctor = SWIG_NAPI_ObjectWrap_inst::GetClass(env);
|
||||
Napi::FunctionReference *SWIG_NAPI_ObjectWrap_ctor_ref = new Napi::FunctionReference();
|
||||
*SWIG_NAPI_ObjectWrap_ctor_ref = Napi::Persistent(SWIG_NAPI_ObjectWrap_ctor);
|
||||
env.GetInstanceData<EnvInstanceData>()->SWIG_NAPI_ObjectWrapCtor = SWIG_NAPI_ObjectWrap_ctor_ref;
|
||||
|
||||
/* create objects for namespaces */
|
||||
$jsnapinspaces
|
||||
|
||||
/* register classes */
|
||||
$jsnapiregisterclasses
|
||||
|
||||
/* enable inheritance */
|
||||
$jsnapipreinheritance
|
||||
|
||||
/* setup inheritances */
|
||||
$jsnapiinitinheritance
|
||||
|
||||
/* create and register namespace objects */
|
||||
$jsnapiregisternspaces
|
||||
|
||||
return exports;
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Object();
|
||||
}
|
||||
|
||||
NODE_API_MODULE($jsname, Init)
|
||||
%}
|
|
@ -0,0 +1,387 @@
|
|||
/* ------------------------------------------------------------
|
||||
* Primitive Types
|
||||
* ------------------------------------------------------------ */
|
||||
|
||||
/* boolean */
|
||||
|
||||
%fragment(SWIG_From_frag(bool),"header", "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_bool(Napi::Env env, bool val)
|
||||
{
|
||||
return Napi::Boolean::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%fragment(SWIG_AsVal_frag(bool),"header",
|
||||
fragment=SWIG_AsVal_frag(long)) {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(bool)(Napi::Value obj, bool *val)
|
||||
{
|
||||
if(!obj.IsBoolean()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
|
||||
Napi::Boolean b;
|
||||
NAPI_CHECK_RESULT(obj.ToBoolean(), b);
|
||||
if (val) *val = b.Value();
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* char */
|
||||
|
||||
%fragment(SWIG_From_frag(unsigned char), "header") {
|
||||
SWIGINTERNINLINE Napi::Value
|
||||
SWIG_From_unsigned_SS_char(Napi::Env env, unsigned char c)
|
||||
{
|
||||
return Napi::Number::New(env, static_cast<double>(c));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%fragment(SWIG_From_frag(signed char), "header") {
|
||||
SWIGINTERNINLINE Napi::Value
|
||||
SWIG_From_signed_SS_char(Napi::Env env, signed char c)
|
||||
{
|
||||
return Napi::Number::New(env, static_cast<double>(c));
|
||||
}
|
||||
}
|
||||
|
||||
/* int */
|
||||
|
||||
%fragment(SWIG_From_frag(int), "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_int(Napi::Env env, int val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(int),"header") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(int)(Napi::Value valRef, int* val)
|
||||
{
|
||||
if (!valRef.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(valRef.ToNumber(), num);
|
||||
*val = static_cast<int>(num.Int32Value());
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* unsigned int */
|
||||
|
||||
%fragment(SWIG_From_frag(unsigned int), "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_unsigned_SS_int(Napi::Env env, unsigned int val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(unsigned int),"header") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(unsigned int)(Napi::Value valRef, unsigned int* val)
|
||||
{
|
||||
if (!valRef.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(valRef.ToNumber(), num);
|
||||
if (num.Int64Value() < 0) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
*val = static_cast<unsigned int>(num.Uint32Value());
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* short */
|
||||
|
||||
%fragment("SWIG_Env_FromShort", "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_short(Napi::Env env, short val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(short),"header") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(short)(Napi::Value valRef, short* val)
|
||||
{
|
||||
if (!valRef.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(valRef.ToNumber(), num);
|
||||
*val = static_cast<short>(num.Int32Value());
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* unsigned short */
|
||||
|
||||
%fragment(SWIG_From_frag(unsigned short), "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_unsigned_SS_short(Napi::Env env, unsigned short val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(unsigned short),"header") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(unsigned short)(Napi::Value valRef, unsigned short* val)
|
||||
{
|
||||
if (!valRef.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(valRef.ToNumber(), num);
|
||||
if (num.Int64Value() < 0) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
*val = static_cast<unsigned short>(num.Uint32Value());
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* long */
|
||||
|
||||
%fragment(SWIG_From_frag(long), "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_long(Napi::Env env, long val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(long),"header",
|
||||
fragment="SWIG_CanCastAsInteger") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(long)(Napi::Value obj, long* val)
|
||||
{
|
||||
if (!obj.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(obj.ToNumber(), num);
|
||||
*val = static_cast<long>(num.Int64Value());
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* unsigned long */
|
||||
|
||||
%fragment(SWIG_From_frag(unsigned long), "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_unsigned_SS_long(Napi::Env env, unsigned long val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(unsigned long),"header",
|
||||
fragment="SWIG_CanCastAsInteger") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(unsigned long)(Napi::Value obj, unsigned long *val)
|
||||
{
|
||||
if(!obj.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(obj.ToNumber(), num);
|
||||
if (num.Int64Value() < 0) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
*val = static_cast<unsigned long>(num.Int64Value());
|
||||
}
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* long long */
|
||||
|
||||
%fragment(SWIG_From_frag(long long), "header", fragment="SWIG_LongLongAvailable") {
|
||||
%#ifdef SWIG_LONG_LONG_AVAILABLE
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_long_SS_long(Napi::Env env, long long val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
%#endif
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(long long),"header",
|
||||
fragment=SWIG_AsVal_frag(long),
|
||||
fragment="SWIG_CanCastAsInteger",
|
||||
fragment="SWIG_LongLongAvailable") {
|
||||
%#ifdef SWIG_LONG_LONG_AVAILABLE
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(long long)(Napi::Value obj, long long* val)
|
||||
{
|
||||
if(!obj.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(obj.ToNumber(), num);
|
||||
*val = static_cast<long long>(num.Int64Value());
|
||||
}
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
%#endif
|
||||
}
|
||||
|
||||
/* unsigned long long */
|
||||
|
||||
%fragment(SWIG_From_frag(unsigned long long), "header", fragment="SWIG_LongLongAvailable") {
|
||||
%#ifdef SWIG_LONG_LONG_AVAILABLE
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_unsigned_SS_long_SS_long(Napi::Env env, unsigned long long val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
%#endif
|
||||
}
|
||||
|
||||
|
||||
%fragment(SWIG_AsVal_frag(unsigned long long),"header",
|
||||
fragment=SWIG_AsVal_frag(unsigned long),
|
||||
fragment="SWIG_CanCastAsInteger",
|
||||
fragment="SWIG_LongLongAvailable") {
|
||||
%#ifdef SWIG_LONG_LONG_AVAILABLE
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(unsigned long long)(Napi::Value obj, unsigned long long *val)
|
||||
{
|
||||
if(!obj.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (obj.ToNumber().Int64Value() < 0) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
if (val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(obj.ToNumber(), num);
|
||||
*val = static_cast<unsigned long long>(num.Int64Value());
|
||||
}
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
%#endif
|
||||
}
|
||||
|
||||
|
||||
/* float */
|
||||
|
||||
%fragment(SWIG_From_frag(float), "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_float(Napi::Env env, float val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(float),"header") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(float)(Napi::Value obj, float *val)
|
||||
{
|
||||
if(!obj.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
|
||||
if(val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(obj.ToNumber(), num);
|
||||
*val = static_cast<float>(num.DoubleValue());
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* double */
|
||||
|
||||
%fragment(SWIG_From_frag(double), "header") {
|
||||
SWIGINTERN
|
||||
Napi::Value SWIG_From_double(Napi::Env env, double val)
|
||||
{
|
||||
return Napi::Number::New(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
%fragment(SWIG_AsVal_frag(double),"header") {
|
||||
SWIGINTERN
|
||||
int SWIG_AsVal_dec(double)(Napi::Value obj, double *val)
|
||||
{
|
||||
if(!obj.IsNumber()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
|
||||
if(val) {
|
||||
Napi::Number num;
|
||||
NAPI_CHECK_RESULT(obj.ToNumber(), num);
|
||||
*val = static_cast<double>(num.DoubleValue());
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,446 @@
|
|||
/* ---------------------------------------------------------------------------
|
||||
* Error handling
|
||||
*
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* We support several forms:
|
||||
*
|
||||
* SWIG_Raise("Error message")
|
||||
* which creates an Error object with the error message
|
||||
*
|
||||
* SWIG_Raise(SWIG_TypeError, "Type error")
|
||||
* which creates the specified error type with the message
|
||||
*
|
||||
* SWIG_Raise(obj)
|
||||
* which throws the object itself
|
||||
*
|
||||
* SWIG_Raise(obj, "Exception const &", SWIGType_p_Exception)
|
||||
* which also throws the object itself and discards the unneeded extra type info
|
||||
*
|
||||
* These must be functions instead of macros to use the C++ overloading to
|
||||
* resolve the arguments
|
||||
*/
|
||||
#define SWIG_exception(code, msg) SWIG_Error(code, msg)
|
||||
#define SWIG_fail goto fail
|
||||
|
||||
#ifdef NAPI_CPP_EXCEPTIONS
|
||||
|
||||
#define SWIG_Error(code, msg) SWIG_NAPI_Raise(env, code, msg)
|
||||
#define NAPI_CHECK_MAYBE(maybe) (maybe)
|
||||
#define NAPI_CHECK_RESULT(maybe, result) (result = maybe)
|
||||
|
||||
SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, const char *msg) {
|
||||
throw Napi::Error::New(env, msg);
|
||||
}
|
||||
|
||||
SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, int type, const char *msg) {
|
||||
switch(type) {
|
||||
default:
|
||||
case SWIG_IOError:
|
||||
case SWIG_MemoryError:
|
||||
case SWIG_SystemError:
|
||||
case SWIG_RuntimeError:
|
||||
case SWIG_DivisionByZero:
|
||||
case SWIG_SyntaxError:
|
||||
throw Napi::Error::New(env, msg);
|
||||
case SWIG_OverflowError:
|
||||
case SWIG_IndexError:
|
||||
throw Napi::RangeError::New(env, msg);
|
||||
case SWIG_ValueError:
|
||||
case SWIG_TypeError:
|
||||
throw Napi::TypeError::New(env, msg);
|
||||
}
|
||||
}
|
||||
|
||||
SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, Napi::Value obj,
|
||||
const char *msg = nullptr, swig_type_info *info = nullptr) {
|
||||
throw Napi::Error(env, obj);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define SWIG_Error(code, msg) do { SWIG_NAPI_Raise(env, code, msg); SWIG_fail; } while (0)
|
||||
#define NAPI_CHECK_MAYBE(maybe) do { if (maybe.IsNothing()) SWIG_fail; } while (0)
|
||||
#define NAPI_CHECK_RESULT(maybe, result) \
|
||||
do { \
|
||||
auto r = maybe; \
|
||||
if (r.IsNothing()) SWIG_fail; \
|
||||
result = r.Unwrap(); \
|
||||
} while (0)
|
||||
|
||||
SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, const char *msg) {
|
||||
Napi::Error::New(env, msg).ThrowAsJavaScriptException();
|
||||
}
|
||||
|
||||
SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, int type, const char *msg) {
|
||||
switch(type) {
|
||||
default:
|
||||
case SWIG_IOError:
|
||||
case SWIG_MemoryError:
|
||||
case SWIG_SystemError:
|
||||
case SWIG_RuntimeError:
|
||||
case SWIG_DivisionByZero:
|
||||
case SWIG_SyntaxError:
|
||||
Napi::Error::New(env, msg).ThrowAsJavaScriptException();
|
||||
return;
|
||||
case SWIG_OverflowError:
|
||||
case SWIG_IndexError:
|
||||
Napi::RangeError::New(env, msg).ThrowAsJavaScriptException();
|
||||
return;
|
||||
case SWIG_ValueError:
|
||||
case SWIG_TypeError:
|
||||
Napi::TypeError::New(env, msg).ThrowAsJavaScriptException();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, Napi::Value obj,
|
||||
const char *msg = nullptr, swig_type_info *info = nullptr) {
|
||||
Napi::Error(env, obj).ThrowAsJavaScriptException();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void JS_veto_set_variable(const Napi::CallbackInfo &info) {
|
||||
SWIG_NAPI_Raise(info.Env(), "Tried to write read-only variable.");
|
||||
}
|
||||
|
||||
struct EnvInstanceData {
|
||||
Napi::Env env;
|
||||
// Base class per-environment constructor, used to check
|
||||
// if a JS object is a SWIG wrapper
|
||||
Napi::FunctionReference *SWIG_NAPI_ObjectWrapCtor;
|
||||
// Per-environment wrapper constructors, indexed by the number in
|
||||
// swig_type->clientdata
|
||||
Napi::FunctionReference **ctor;
|
||||
swig_module_info *swig_module;
|
||||
EnvInstanceData(Napi::Env, swig_module_info *);
|
||||
~EnvInstanceData();
|
||||
};
|
||||
|
||||
typedef size_t SWIG_NAPI_ClientData;
|
||||
|
||||
// Base class for all wrapped objects,
|
||||
// used mostly when unwrapping unknown objects
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
class SWIG_NAPI_ObjectWrap_templ : public Napi::ObjectWrap<SWIG_OBJ_WRAP> {
|
||||
public:
|
||||
void *self;
|
||||
bool owned;
|
||||
size_t size;
|
||||
swig_type_info *info;
|
||||
SWIG_NAPI_ObjectWrap_templ(const Napi::CallbackInfo &info);
|
||||
SWIG_NAPI_ObjectWrap_templ(bool, const Napi::CallbackInfo &info) :
|
||||
Napi::ObjectWrap<SWIG_OBJ_WRAP>(info),
|
||||
self(nullptr),
|
||||
owned(true),
|
||||
size(0),
|
||||
info(nullptr)
|
||||
{}
|
||||
virtual ~SWIG_NAPI_ObjectWrap_templ() {};
|
||||
|
||||
Napi::Value ToString(const Napi::CallbackInfo &info);
|
||||
};
|
||||
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
SWIG_NAPI_ObjectWrap_templ<SWIG_OBJ_WRAP>::SWIG_NAPI_ObjectWrap_templ(const Napi::CallbackInfo &info) :
|
||||
Napi::ObjectWrap<SWIG_OBJ_WRAP>(info), size(0), info(nullptr) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() == 1 && info[0].IsExternal()) {
|
||||
// This constructor has been called internally from C++/SWIG
|
||||
// to wrap an already existing C++ object of unknown type in JS
|
||||
this->self = info[0].As<Napi::External<void>>().Data();
|
||||
this->owned = false;
|
||||
} else {
|
||||
SWIG_Error(SWIG_ERROR, "This constructor is not accessible from JS");
|
||||
}
|
||||
return;
|
||||
goto fail;
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename SWIG_OBJ_WRAP>
|
||||
Napi::Value SWIG_NAPI_ObjectWrap_templ<SWIG_OBJ_WRAP>::ToString(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
static char repr[128];
|
||||
const char *name = SWIG_TypePrettyName(this->info);
|
||||
snprintf(repr, sizeof(repr), "{SwigObject %s (%s) at %p %s}",
|
||||
this->info ? this->info->name : "unknown",
|
||||
name ? name : "unknown",
|
||||
this->self,
|
||||
this->owned ? "[owned]" : "[copy]");
|
||||
return Napi::String::New(env, repr);
|
||||
}
|
||||
|
||||
class SWIG_NAPI_ObjectWrap_inst : public SWIG_NAPI_ObjectWrap_templ<SWIG_NAPI_ObjectWrap_inst> {
|
||||
public:
|
||||
using SWIG_NAPI_ObjectWrap_templ::SWIG_NAPI_ObjectWrap_templ;
|
||||
static Napi::Function GetClass(Napi::Env);
|
||||
static void GetMembers(
|
||||
Napi::Env,
|
||||
std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> &,
|
||||
std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> &
|
||||
);
|
||||
};
|
||||
|
||||
void SWIG_NAPI_ObjectWrap_inst::GetMembers(
|
||||
Napi::Env env,
|
||||
std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> &members,
|
||||
std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> &
|
||||
) {
|
||||
members.erase("toString");
|
||||
members.insert({"toString", SWIG_NAPI_ObjectWrap_templ::InstanceMethod("toString", &SWIG_NAPI_ObjectWrap_templ::ToString)});
|
||||
}
|
||||
|
||||
Napi::Function SWIG_NAPI_ObjectWrap_inst::GetClass(Napi::Env env) {
|
||||
return Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::DefineClass(env, "SwigObject", {});
|
||||
}
|
||||
|
||||
SWIGRUNTIME int SWIG_NAPI_ConvertInstancePtr(Napi::Object objRef, void **ptr, swig_type_info *info, int flags) {
|
||||
SWIG_NAPI_ObjectWrap_inst *ow;
|
||||
Napi::Env env = objRef.Env();
|
||||
if(!objRef.IsObject()) return SWIG_ERROR;
|
||||
|
||||
// Check if this is a SWIG wrapper
|
||||
Napi::FunctionReference *ctor = env.GetInstanceData<EnvInstanceData>()->SWIG_NAPI_ObjectWrapCtor;
|
||||
bool instanceOf;
|
||||
NAPI_CHECK_RESULT(objRef.InstanceOf(ctor->Value()), instanceOf);
|
||||
if (!instanceOf) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
|
||||
ow = Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(objRef);
|
||||
|
||||
// Now check if the SWIG type is compatible unless the types match exactly or the type is unknown
|
||||
if(info && ow->info != info && ow->info != nullptr) {
|
||||
swig_cast_info *tc = SWIG_TypeCheckStruct(ow->info, info);
|
||||
if (!tc && ow->info->name) {
|
||||
tc = SWIG_TypeCheck(ow->info->name, info);
|
||||
}
|
||||
bool type_valid = tc != 0;
|
||||
if(!type_valid) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
int newmemory = 0;
|
||||
*ptr = SWIG_TypeCast(tc, ow->self, &newmemory);
|
||||
assert(!newmemory); /* newmemory handling not yet implemented */
|
||||
} else {
|
||||
*ptr = ow->self;
|
||||
}
|
||||
|
||||
if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !ow->owned) {
|
||||
return SWIG_ERROR_RELEASE_NOT_OWNED;
|
||||
} else {
|
||||
if (flags & SWIG_POINTER_DISOWN) {
|
||||
ow->owned = false;
|
||||
}
|
||||
if (flags & SWIG_POINTER_CLEAR) {
|
||||
ow->self = nullptr;
|
||||
}
|
||||
}
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
|
||||
|
||||
SWIGRUNTIME int SWIG_NAPI_GetInstancePtr(Napi::Value valRef, void **ptr) {
|
||||
SWIG_NAPI_ObjectWrap_inst *ow;
|
||||
if(!valRef.IsObject()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
Napi::Object objRef;
|
||||
NAPI_CHECK_RESULT(valRef.ToObject(), objRef);
|
||||
ow = Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(objRef);
|
||||
|
||||
if(ow->self == nullptr) {
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
|
||||
*ptr = ow->self;
|
||||
return SWIG_OK;
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
|
||||
|
||||
SWIGRUNTIME int SWIG_NAPI_ConvertPtr(Napi::Value valRef, void **ptr, swig_type_info *info, int flags) {
|
||||
// special case: JavaScript null => C NULL pointer
|
||||
if (valRef.IsNull()) {
|
||||
*ptr=0;
|
||||
return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK;
|
||||
}
|
||||
|
||||
if (!valRef.IsObject()) {
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
|
||||
Napi::Object objRef;
|
||||
NAPI_CHECK_RESULT(valRef.ToObject(), objRef);
|
||||
return SWIG_NAPI_ConvertInstancePtr(objRef, ptr, info, flags);
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
|
||||
SWIGRUNTIME Napi::Value SWIG_NAPI_NewPointerObj(Napi::Env env, void *ptr, swig_type_info *info, int flags) {
|
||||
Napi::External<void> native;
|
||||
Napi::FunctionReference *ctor;
|
||||
|
||||
if (ptr == nullptr) {
|
||||
return env.Null();
|
||||
}
|
||||
native = Napi::External<void>::New(env, ptr);
|
||||
|
||||
size_t *idx = info != nullptr ?
|
||||
reinterpret_cast<SWIG_NAPI_ClientData *>(info->clientdata) :
|
||||
nullptr;
|
||||
if (idx == nullptr) {
|
||||
// This type does not have a dedicated wrapper
|
||||
ctor = env.GetInstanceData<EnvInstanceData>()->SWIG_NAPI_ObjectWrapCtor;
|
||||
} else {
|
||||
ctor = env.GetInstanceData<EnvInstanceData>()->ctor[*idx];
|
||||
}
|
||||
|
||||
Napi::Value wrapped;
|
||||
NAPI_CHECK_RESULT(ctor->New({native}), wrapped);
|
||||
|
||||
// Preserve the type even if using the generic wrapper
|
||||
if (idx == nullptr && info != nullptr) {
|
||||
Napi::Object obj;
|
||||
NAPI_CHECK_RESULT(wrapped.ToObject(), obj);
|
||||
Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(obj)->info = info;
|
||||
}
|
||||
|
||||
if ((flags & SWIG_POINTER_OWN) == SWIG_POINTER_OWN) {
|
||||
Napi::Object obj;
|
||||
NAPI_CHECK_RESULT(wrapped.ToObject(), obj);
|
||||
Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(obj)->owned = true;
|
||||
}
|
||||
|
||||
return wrapped;
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
|
||||
#define SWIG_ConvertPtr(obj, ptr, info, flags) SWIG_NAPI_ConvertPtr(obj, ptr, info, flags)
|
||||
#define SWIG_NewPointerObj(ptr, info, flags) SWIG_NAPI_NewPointerObj(env, ptr, info, flags)
|
||||
|
||||
#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_NAPI_ConvertInstancePtr(obj, pptr, type, flags)
|
||||
#define SWIG_NewInstanceObj(thisvalue, type, flags) SWIG_NAPI_NewPointerObj(env, thisvalue, type, flags)
|
||||
|
||||
#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_NAPI_ConvertPtr(obj, pptr, type, 0)
|
||||
#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NAPI_NewPointerObj(env, ptr, type, 0)
|
||||
|
||||
#define SWIG_GetInstancePtr(obj, ptr) SWIG_NAPI_GetInstancePtr(obj, ptr)
|
||||
|
||||
SWIGRUNTIME Napi::Value _SWIG_NAPI_wrap_equals(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
void *arg1 = (void *) 0 ;
|
||||
void *arg2 = (void *) 0 ;
|
||||
bool result;
|
||||
int res1;
|
||||
int res2;
|
||||
|
||||
if(info.Length() != 1) SWIG_Error(SWIG_ERROR, "Illegal number of arguments for equals.");
|
||||
|
||||
res1 = SWIG_GetInstancePtr(info.This(), &arg1);
|
||||
if (!SWIG_IsOK(res1)) {
|
||||
SWIG_Error(SWIG_ERROR, "Could not get pointer from 'this' object for equals.");
|
||||
}
|
||||
res2 = SWIG_GetInstancePtr(info[0], &arg2);
|
||||
if (!SWIG_IsOK(res2)) {
|
||||
SWIG_Error(SWIG_ArgError(res2), " in method '" "equals" "', argument " "1"" of type '" "void *""'");
|
||||
}
|
||||
|
||||
result = (bool)(arg1 == arg2);
|
||||
jsresult = Napi::Boolean::New(env, result);
|
||||
|
||||
return jsresult;
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
|
||||
SWIGRUNTIME Napi::Value _wrap_getCPtr(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::Value jsresult;
|
||||
void *arg1 = (void *) 0 ;
|
||||
long result;
|
||||
int res1;
|
||||
|
||||
res1 = SWIG_GetInstancePtr(info.This(), &arg1);
|
||||
if (!SWIG_IsOK(res1)) {
|
||||
SWIG_Error(SWIG_ArgError(res1), " in method '" "getCPtr" "', argument " "1"" of type '" "void *""'");
|
||||
}
|
||||
|
||||
result = (long)arg1;
|
||||
jsresult = Napi::Number::New(env, result);
|
||||
|
||||
return jsresult;
|
||||
goto fail;
|
||||
fail:
|
||||
return Napi::Value();
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* PackedData object
|
||||
* (objects visible to JS that do not have a dedicated wrapper but must preserve type)
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
SWIGRUNTIME
|
||||
Napi::Value SWIG_NAPI_NewPackedObj(Napi::Env env, void *data, size_t size, swig_type_info *type) {
|
||||
void *data_copy = new uint8_t[size];
|
||||
memcpy(data_copy, data, size);
|
||||
Napi::Value val = SWIG_NAPI_NewPointerObj(env, data_copy, type, SWIG_POINTER_OWN);
|
||||
Napi::Object obj;
|
||||
if (val.IsEmpty()) goto fail;
|
||||
|
||||
NAPI_CHECK_RESULT(val.ToObject(), obj);
|
||||
Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(obj)->size = size;
|
||||
|
||||
fail:
|
||||
return val;
|
||||
}
|
||||
|
||||
SWIGRUNTIME
|
||||
int SWIG_NAPI_ConvertPacked(Napi::Value valRef, void *ptr, size_t size, swig_type_info *type) {
|
||||
void *tmp;
|
||||
if (!SWIG_IsOK(SWIG_NAPI_ConvertPtr(valRef, &tmp, type, 0))) {
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
memcpy(ptr, tmp, size);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_NAPI_ConvertPacked(obj, ptr, sz, ty)
|
||||
#define SWIG_NewMemberObj(ptr, sz, type) SWIG_NAPI_NewPackedObj(env, ptr, sz, type)
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Support for IN/OUTPUT typemaps (see Lib/typemaps/inoutlist.swg)
|
||||
*
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
SWIGRUNTIME
|
||||
|
||||
Napi::Value SWIG_NAPI_AppendOutput(Napi::Env env, Napi::Value result, Napi::Value obj) {
|
||||
if (result.IsUndefined()) {
|
||||
result = Napi::Array::New(env);
|
||||
} else if (!result.IsArray()) {
|
||||
Napi::Array tmparr = Napi::Array::New(env);
|
||||
tmparr.Set(static_cast<uint32_t>(0), result);
|
||||
result = tmparr;
|
||||
}
|
||||
|
||||
Napi::Array arr = result.As<Napi::Array>();
|
||||
arr.Set(arr.Length(), obj);
|
||||
return arr;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* javascriptruntime.swg
|
||||
*
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
// NAPI
|
||||
// ----------
|
||||
|
||||
%insert(runtime) %{
|
||||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS)
|
||||
#define NAPI_CPP_EXCEPTIONS
|
||||
#else
|
||||
#define NAPI_DISABLE_CPP_EXCEPTIONS
|
||||
#define NODE_ADDON_API_ENABLE_MAYBE
|
||||
#endif
|
||||
|
||||
// This gives us
|
||||
// Branch Node.js v10.x - from v10.20.0
|
||||
// Branch Node.js v12.x - from v12.17.0
|
||||
// Everything from Node.js v14.0.0 on
|
||||
// Our limiting feature is napi_set_instance_data
|
||||
#ifndef NAPI_VERSION
|
||||
#define NAPI_VERSION 6
|
||||
#elif NAPI_VERSION < 6
|
||||
#error NAPI_VERSION 6 is the minimum supported target (Node.js >=14, >=12.17, >=10.20)
|
||||
#endif
|
||||
#include <napi.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
%}
|
||||
|
||||
%insert(runtime) "swigrun.swg"; /* SWIG API */
|
||||
%insert(runtime) "swigerrors.swg"; /* SWIG errors */
|
||||
|
||||
%insert(runtime) "javascriptrun.swg"
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
|
||||
/* ------------------------------------------------------------
|
||||
* utility methods for char strings
|
||||
* ------------------------------------------------------------ */
|
||||
%fragment("SWIG_AsCharPtrAndSize", "header", fragment="SWIG_pchar_descriptor") {
|
||||
SWIGINTERN int
|
||||
SWIG_AsCharPtrAndSize(Napi::Value valRef, char** cptr, size_t* psize, int *alloc)
|
||||
{
|
||||
if(valRef.IsString()) {
|
||||
Napi::String js_str;
|
||||
NAPI_CHECK_RESULT(valRef.ToString(), js_str);
|
||||
|
||||
std::string str = js_str.Utf8Value();
|
||||
size_t len = str.size() + 1;
|
||||
char* cstr = (char*) %new_array(len, char);
|
||||
memcpy(cstr, str.data(), len);
|
||||
|
||||
if(alloc) *alloc = SWIG_NEWOBJ;
|
||||
if(psize) *psize = len;
|
||||
if(cptr) *cptr = cstr;
|
||||
|
||||
return SWIG_OK;
|
||||
} else {
|
||||
if(valRef.IsObject()) {
|
||||
swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
|
||||
Napi::Object obj;
|
||||
NAPI_CHECK_RESULT(valRef.ToObject(), obj);
|
||||
// try if the object is a wrapped char[]
|
||||
if (pchar_descriptor) {
|
||||
void* vptr = 0;
|
||||
if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) {
|
||||
if (cptr) *cptr = (char *) vptr;
|
||||
if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0;
|
||||
if (alloc) *alloc = SWIG_OLDOBJ;
|
||||
return SWIG_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
goto fail;
|
||||
fail:
|
||||
return SWIG_TypeError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%fragment(SWIG_From_frag(char), "header") {
|
||||
SWIGINTERNINLINE Napi::Value
|
||||
SWIG_From_char(Napi::Env env, char c)
|
||||
{
|
||||
Napi::String js_str = Napi::String::New(env, &c, 1);
|
||||
return js_str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%fragment("SWIG_FromCharPtr", "header", fragment = "SWIG_FromCharPtrAndSize") {
|
||||
// Override the default one with an empty one
|
||||
}
|
||||
|
||||
%fragment("SWIG_FromCharPtrAndSize", "header") {
|
||||
SWIGINTERNINLINE Napi::Value
|
||||
SWIG_Env_FromCharPtrAndSize(Napi::Env env, const char* carray, size_t size)
|
||||
{
|
||||
if (carray) {
|
||||
Napi::String js_str = Napi::String::New(env, carray, size);
|
||||
return js_str;
|
||||
} else {
|
||||
return env.Undefined();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%insert(runtime) %{
|
||||
#define SWIG_FromCharPtrAndSize(cptr, size) SWIG_Env_FromCharPtrAndSize(env, cptr, size)
|
||||
#define SWIG_FromCharPtr(cptr) SWIG_Env_FromCharPtrAndSize(env, cptr, strlen(cptr))
|
||||
%}
|
|
@ -0,0 +1,56 @@
|
|||
/* ------------------------------------------------------------
|
||||
* Typemap specializations for Javascript
|
||||
* ------------------------------------------------------------ */
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
* Fragment section
|
||||
* ------------------------------------------------------------ */
|
||||
|
||||
/* These macros are necessary to provide an extra parameter
|
||||
to SWIG_AsVal_dec functions (Napi::Env environment).
|
||||
They must be defined before including `typemaps/fragments.swg`
|
||||
*/
|
||||
#define SWIG_FROM_DECL_ARGS SWIG_NAPI_FROM_DECL_ARGS
|
||||
#define SWIG_FROM_CALL_ARGS SWIG_NAPI_FROM_CALL_ARGS
|
||||
|
||||
/* Include fundamental fragemt definitions */
|
||||
%include <typemaps/fragments.swg>
|
||||
|
||||
/* Look for user fragments file. */
|
||||
%include <javascriptfragments.swg>
|
||||
|
||||
/* Javascript fragments for fundamental types */
|
||||
%include <javascriptprimtypes.swg>
|
||||
|
||||
/* Javascript fragments for char* strings */
|
||||
%include <javascriptstrings.swg>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
* Unified typemap section
|
||||
* ------------------------------------------------------------ */
|
||||
|
||||
/* Javascript types */
|
||||
|
||||
#define SWIG_Object Napi::Value
|
||||
#define VOID_Object env.Undefined()
|
||||
|
||||
/* Overload of the output/constant/exception/dirout handling */
|
||||
|
||||
/* append output */
|
||||
#define SWIG_AppendOutput(result, obj) SWIG_NAPI_AppendOutput(env, result, obj)
|
||||
|
||||
/* set constant */
|
||||
#define SWIG_SetConstant(name, obj)
|
||||
|
||||
/* raise */
|
||||
#define SWIG_Raise(...) SWIG_NAPI_Raise(env, __VA_ARGS__)
|
||||
|
||||
%insert("runtime") %{
|
||||
#define SWIG_NAPI_FROM_DECL_ARGS(arg1) (Napi::Env env, arg1)
|
||||
#define SWIG_NAPI_FROM_CALL_ARGS(arg1) (env, arg1)
|
||||
%}
|
||||
|
||||
|
||||
/* Include the unified typemap library */
|
||||
%include <typemaps/swigtypemaps.swg>
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* To include generic versions of the in typemaps, add:
|
||||
*
|
||||
* %typemap(in) (void *, size_t) = (const void* buffer_data, const size_t buffer_len);
|
||||
* %typemap(typecheck) (void *, size_t) = (const void* buffer_data, const size_t buffer_len);
|
||||
*
|
||||
* or to discriminate by argument names:
|
||||
* %typemap(in) (void *data, size_t length) = (const void* buffer_data, const size_t buffer_len);
|
||||
* %typemap(typecheck) (void *data, size_t length) = (const void* buffer_data, const size_t buffer_len);
|
||||
*/
|
||||
|
||||
%typemap(in) (const void* buffer_data, const size_t buffer_len) {
|
||||
if ($input.IsBuffer()) {
|
||||
Napi::Buffer<char> buf = $input.As<Napi::Buffer<char>>();
|
||||
$1 = reinterpret_cast<void *>(buf.Data());
|
||||
$2 = buf.ByteLength();
|
||||
} else {
|
||||
SWIG_exception_fail(SWIG_TypeError, "in method '$symname', argument is not a Buffer");
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_VOIDPTR) (const void* buffer_data, const size_t buffer_len) {
|
||||
$1 = $input.IsBuffer();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* In order to use the argout typemap, the function must have the following signature:
|
||||
*
|
||||
* void buffer(void **buffer_data, size_t *buffer_len)
|
||||
*
|
||||
* In this case, this function will be wrapped by a JS function that takes
|
||||
* no arguments (because of numinputs=0) and returns a Buffer
|
||||
*/
|
||||
|
||||
%typemap(in, numinputs=0) (void **buffer_data, size_t *buffer_len) (void *temp_data, size_t temp_len) {
|
||||
$1 = &temp_data;
|
||||
$2 = &temp_len;
|
||||
}
|
||||
%typemap(argout) (void **buffer_data, size_t *buffer_len) {
|
||||
if (*$1 != nullptr) {
|
||||
Napi::Buffer<char> buf = Napi::Buffer<char>::Copy(env, reinterpret_cast<char *>(*$1), *$2);
|
||||
NAPI_CHECK_RESULT(buf.As<Napi::Value>(), $result);
|
||||
} else {
|
||||
$result = env.Null();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* std_auto_ptr.i
|
||||
*
|
||||
* SWIG library file for handling std::auto_ptr.
|
||||
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
|
||||
* class when returning a std::auto_ptr from a function.
|
||||
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
|
||||
* C++ layer when passed as a parameter to a wrapped function.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%define %auto_ptr(TYPE)
|
||||
%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
|
||||
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
|
||||
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
|
||||
} else {
|
||||
%argument_fail(res, "TYPE *", $symname, $argnum);
|
||||
}
|
||||
}
|
||||
$1.reset((TYPE *)argp);
|
||||
}
|
||||
|
||||
%typemap (out) std::auto_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > {
|
||||
void *vptr = 0;
|
||||
int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0);
|
||||
$1 = SWIG_CheckState(res);
|
||||
}
|
||||
|
||||
%template() std::auto_ptr< TYPE >;
|
||||
%enddef
|
||||
|
||||
namespace std {
|
||||
template <class T> class auto_ptr {};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
%include <std_except.i>
|
||||
|
||||
%apply size_t { std::size_t };
|
||||
%apply const size_t& { const std::size_t& };
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* STD C++ complex typemaps
|
||||
*/
|
||||
|
||||
%include <javascriptcomplex.swg>
|
||||
|
||||
%{
|
||||
#include <complex>
|
||||
%}
|
||||
|
||||
namespace std {
|
||||
%naturalvar complex;
|
||||
template<typename T> class complex;
|
||||
%template() complex<double>;
|
||||
%template() complex<float>;
|
||||
}
|
||||
|
||||
/* defining the complex as/from converters */
|
||||
|
||||
%swig_cplxdbl_convn(std::complex<double>, std::complex<double>, std::real, std::imag)
|
||||
%swig_cplxflt_convn(std::complex<float>, std::complex<float>, std::real, std::imag)
|
||||
|
||||
/* defining the typemaps */
|
||||
|
||||
%typemaps_primitive(%checkcode(CPLXDBL), std::complex<double>);
|
||||
%typemaps_primitive(%checkcode(CPLXFLT), std::complex<float>);
|
|
@ -0,0 +1 @@
|
|||
%include <std/_std_deque.i>
|
|
@ -0,0 +1 @@
|
|||
%include <typemaps/std_except.swg>
|
|
@ -0,0 +1,80 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* std_map.i
|
||||
*
|
||||
* SWIG typemaps for std::map
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%include <std_common.i>
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// std::map
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
%{
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
%}
|
||||
|
||||
// exported class
|
||||
|
||||
namespace std {
|
||||
|
||||
template<class K, class T, class C = std::less<K> > class map {
|
||||
// add typemaps here
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef K key_type;
|
||||
typedef T mapped_type;
|
||||
typedef std::pair< const K, T > value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
map();
|
||||
map(const map& other);
|
||||
|
||||
unsigned int size() const;
|
||||
bool empty() const;
|
||||
void clear();
|
||||
%extend {
|
||||
const T& get(const K& key) throw (std::out_of_range) {
|
||||
std::map< K, T, C >::iterator i = self->find(key);
|
||||
if (i != self->end())
|
||||
return i->second;
|
||||
else
|
||||
throw std::out_of_range("key not found");
|
||||
}
|
||||
void set(const K& key, const T& x) {
|
||||
(*self)[key] = x;
|
||||
}
|
||||
void del(const K& key) throw (std::out_of_range) {
|
||||
std::map< K, T, C >::iterator i = self->find(key);
|
||||
if (i != self->end())
|
||||
self->erase(i);
|
||||
else
|
||||
throw std::out_of_range("key not found");
|
||||
}
|
||||
bool has_key(const K& key) {
|
||||
std::map< K, T, C >::iterator i = self->find(key);
|
||||
return i != self->end();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Legacy macros (deprecated)
|
||||
%define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO)
|
||||
#warning "specialize_std_map_on_key ignored - macro is deprecated and no longer necessary"
|
||||
%enddef
|
||||
|
||||
%define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO)
|
||||
#warning "specialize_std_map_on_value ignored - macro is deprecated and no longer necessary"
|
||||
%enddef
|
||||
|
||||
%define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO)
|
||||
#warning "specialize_std_map_on_both ignored - macro is deprecated and no longer necessary"
|
||||
%enddef
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* std_pair.i
|
||||
*
|
||||
* SWIG typemaps for std::pair
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%include <std_common.i>
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// std::pair
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
%{
|
||||
#include <utility>
|
||||
%}
|
||||
|
||||
namespace std {
|
||||
|
||||
template<class T, class U> struct pair {
|
||||
typedef T first_type;
|
||||
typedef U second_type;
|
||||
|
||||
pair();
|
||||
pair(T first, U second);
|
||||
pair(const pair& other);
|
||||
|
||||
template <class U1, class U2> pair(const pair<U1, U2> &other);
|
||||
|
||||
T first;
|
||||
U second;
|
||||
};
|
||||
|
||||
// add specializations here
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
%include <typemaps/std_string.swg>
|
|
@ -0,0 +1,39 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* std_unique_ptr.i
|
||||
*
|
||||
* SWIG library file for handling std::unique_ptr.
|
||||
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
|
||||
* class when returning a std::unique_ptr from a function.
|
||||
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
|
||||
* C++ layer when passed as a parameter to a wrapped function.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%define %unique_ptr(TYPE)
|
||||
%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
|
||||
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
|
||||
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
|
||||
} else {
|
||||
%argument_fail(res, "TYPE *", $symname, $argnum);
|
||||
}
|
||||
}
|
||||
$1.reset((TYPE *)argp);
|
||||
}
|
||||
|
||||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > {
|
||||
void *vptr = 0;
|
||||
int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0);
|
||||
$1 = SWIG_CheckState(res);
|
||||
}
|
||||
|
||||
%template() std::unique_ptr< TYPE >;
|
||||
%enddef
|
||||
|
||||
namespace std {
|
||||
template <class T> class unique_ptr {};
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* std_vector.i
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%include <std_common.i>
|
||||
|
||||
%{
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
%}
|
||||
|
||||
namespace std {
|
||||
|
||||
template<class T> class vector {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
vector();
|
||||
vector(size_type n);
|
||||
vector(const vector& other);
|
||||
|
||||
size_type size() const;
|
||||
size_type capacity() const;
|
||||
void reserve(size_type n);
|
||||
%rename(isEmpty) empty;
|
||||
bool empty() const;
|
||||
void clear();
|
||||
%rename(add) push_back;
|
||||
void push_back(const value_type& x);
|
||||
%extend {
|
||||
const_reference get(int i) throw (std::out_of_range) {
|
||||
int size = int(self->size());
|
||||
if (i>=0 && i<size)
|
||||
return (*self)[i];
|
||||
else
|
||||
throw std::out_of_range("vector index out of range");
|
||||
}
|
||||
void set(int i, const value_type& val) throw (std::out_of_range) {
|
||||
int size = int(self->size());
|
||||
if (i>=0 && i<size)
|
||||
(*self)[i] = val;
|
||||
else
|
||||
throw std::out_of_range("vector index out of range");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// bool specialization
|
||||
template<> class vector<bool> {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type& reference;
|
||||
typedef bool const_reference;
|
||||
|
||||
vector();
|
||||
vector(size_type n);
|
||||
vector(const vector& other);
|
||||
|
||||
size_type size() const;
|
||||
size_type capacity() const;
|
||||
void reserve(size_type n);
|
||||
%rename(isEmpty) empty;
|
||||
bool empty() const;
|
||||
void clear();
|
||||
%rename(add) push_back;
|
||||
void push_back(const value_type& x);
|
||||
%extend {
|
||||
bool get(int i) throw (std::out_of_range) {
|
||||
int size = int(self->size());
|
||||
if (i>=0 && i<size)
|
||||
return (*self)[i];
|
||||
else
|
||||
throw std::out_of_range("vector index out of range");
|
||||
}
|
||||
void set(int i, const value_type& val) throw (std::out_of_range) {
|
||||
int size = int(self->size());
|
||||
if (i>=0 && i<size)
|
||||
(*self)[i] = val;
|
||||
else
|
||||
throw std::out_of_range("vector index out of range");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
%define specialize_std_vector(T)
|
||||
#warning "specialize_std_vector - specialization for type T no longer needed"
|
||||
%enddef
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* stl.i
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%include <std_common.i>
|
||||
%include <std_string.i>
|
||||
%include <std_vector.i>
|
||||
%include <std_map.i>
|
||||
%include <std_pair.i>
|
||||
|
|
@ -0,0 +1 @@
|
|||
%include <typemaps/swigmove.swg>
|
|
@ -0,0 +1,148 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* typemaps.i
|
||||
*
|
||||
* Pointer handling
|
||||
* These mappings provide support for input/output arguments and common
|
||||
* uses for C/C++ pointers.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
// INPUT typemaps.
|
||||
// These remap a C pointer to be an "INPUT" value which is passed by value
|
||||
// instead of reference.
|
||||
|
||||
/*
|
||||
The following methods can be applied to turn a pointer into a simple
|
||||
"input" value. That is, instead of passing a pointer to an object,
|
||||
you would use a real value instead.
|
||||
|
||||
int *INPUT
|
||||
short *INPUT
|
||||
long *INPUT
|
||||
long long *INPUT
|
||||
unsigned int *INPUT
|
||||
unsigned short *INPUT
|
||||
unsigned long *INPUT
|
||||
unsigned long long *INPUT
|
||||
unsigned char *INPUT
|
||||
bool *INPUT
|
||||
float *INPUT
|
||||
double *INPUT
|
||||
|
||||
To use these, suppose you had a C function like this :
|
||||
|
||||
double fadd(double *a, double *b) {
|
||||
return *a+*b;
|
||||
}
|
||||
|
||||
You could wrap it with SWIG as follows :
|
||||
|
||||
%include <typemaps.i>
|
||||
double fadd(double *INPUT, double *INPUT);
|
||||
|
||||
or you can use the %apply directive :
|
||||
|
||||
%include <typemaps.i>
|
||||
%apply double *INPUT { double *a, double *b };
|
||||
double fadd(double *a, double *b);
|
||||
|
||||
*/
|
||||
|
||||
// OUTPUT typemaps. These typemaps are used for parameters that
|
||||
// are output only. The output value is appended to the result as
|
||||
// a list element.
|
||||
|
||||
/*
|
||||
The following methods can be applied to turn a pointer into an "output"
|
||||
value. When calling a function, no input value would be given for
|
||||
a parameter, but an output value would be returned. In the case of
|
||||
multiple output values, they are returned in the form of a Python tuple.
|
||||
|
||||
int *OUTPUT
|
||||
short *OUTPUT
|
||||
long *OUTPUT
|
||||
long long *OUTPUT
|
||||
unsigned int *OUTPUT
|
||||
unsigned short *OUTPUT
|
||||
unsigned long *OUTPUT
|
||||
unsigned long long *OUTPUT
|
||||
unsigned char *OUTPUT
|
||||
bool *OUTPUT
|
||||
float *OUTPUT
|
||||
double *OUTPUT
|
||||
|
||||
For example, suppose you were trying to wrap the modf() function in the
|
||||
C math library which splits x into integral and fractional parts (and
|
||||
returns the integer part in one of its parameters) :
|
||||
|
||||
double modf(double x, double *ip);
|
||||
|
||||
You could wrap it with SWIG as follows :
|
||||
|
||||
%include <typemaps.i>
|
||||
double modf(double x, double *OUTPUT);
|
||||
|
||||
or you can use the %apply directive :
|
||||
|
||||
%include <typemaps.i>
|
||||
%apply double *OUTPUT { double *ip };
|
||||
double modf(double x, double *ip);
|
||||
|
||||
The Python output of the function would be a tuple containing both
|
||||
output values.
|
||||
|
||||
*/
|
||||
|
||||
// INOUT
|
||||
// Mappings for an argument that is both an input and output
|
||||
// parameter
|
||||
|
||||
/*
|
||||
The following methods can be applied to make a function parameter both
|
||||
an input and output value. This combines the behavior of both the
|
||||
"INPUT" and "OUTPUT" methods described earlier. Output values are
|
||||
returned in the form of a Python tuple.
|
||||
|
||||
int *INOUT
|
||||
short *INOUT
|
||||
long *INOUT
|
||||
long long *INOUT
|
||||
unsigned int *INOUT
|
||||
unsigned short *INOUT
|
||||
unsigned long *INOUT
|
||||
unsigned long long *INOUT
|
||||
unsigned char *INOUT
|
||||
bool *INOUT
|
||||
float *INOUT
|
||||
double *INOUT
|
||||
|
||||
For example, suppose you were trying to wrap the following function :
|
||||
|
||||
void neg(double *x) {
|
||||
*x = -(*x);
|
||||
}
|
||||
|
||||
You could wrap it with SWIG as follows :
|
||||
|
||||
%include <typemaps.i>
|
||||
void neg(double *INOUT);
|
||||
|
||||
or you can use the %apply directive :
|
||||
|
||||
%include <typemaps.i>
|
||||
%apply double *INOUT { double *x };
|
||||
void neg(double *x);
|
||||
|
||||
Unlike C, this mapping does not directly modify the input value (since
|
||||
this makes no sense in Python). Rather, the modified input value shows
|
||||
up as the return value of the function. Thus, to apply this function
|
||||
to a Python variable you might do this :
|
||||
|
||||
x = neg(x)
|
||||
|
||||
Note : previous versions of SWIG used the symbol 'BOTH' to mark
|
||||
input/output arguments. This is still supported, but will be slowly
|
||||
phased out in future releases.
|
||||
|
||||
*/
|
||||
|
||||
%include <typemaps/typemaps.swg>
|
|
@ -1,40 +0,0 @@
|
|||
#ifndef JAVASCRIPT_JAVASCRIPTKW_SWG_
|
||||
#define JAVASCRIPT_JAVASCRIPTKW_SWG_
|
||||
|
||||
/* Warnings for Java keywords */
|
||||
#define JAVASCRIPTKW(x) %keywordwarn("'" `x` "' is a javascript keyword, renaming to '_"`x`"'",rename="_%s") `x`
|
||||
|
||||
/* Taken from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Reserved_Words */
|
||||
|
||||
JAVASCRIPTKW(break);
|
||||
JAVASCRIPTKW(case);
|
||||
JAVASCRIPTKW(catch);
|
||||
JAVASCRIPTKW(continue);
|
||||
JAVASCRIPTKW(default);
|
||||
JAVASCRIPTKW(delete);
|
||||
JAVASCRIPTKW(do);
|
||||
JAVASCRIPTKW(else);
|
||||
JAVASCRIPTKW(finally);
|
||||
JAVASCRIPTKW(for);
|
||||
JAVASCRIPTKW(function);
|
||||
JAVASCRIPTKW(if);
|
||||
JAVASCRIPTKW(in);
|
||||
JAVASCRIPTKW(instanceof);
|
||||
JAVASCRIPTKW(new);
|
||||
JAVASCRIPTKW(return);
|
||||
JAVASCRIPTKW(switch);
|
||||
JAVASCRIPTKW(this);
|
||||
JAVASCRIPTKW(throw);
|
||||
JAVASCRIPTKW(try);
|
||||
JAVASCRIPTKW(typeof);
|
||||
JAVASCRIPTKW(var);
|
||||
JAVASCRIPTKW(void);
|
||||
JAVASCRIPTKW(while);
|
||||
JAVASCRIPTKW(with);
|
||||
|
||||
/* others bad names if any*/
|
||||
// for example %namewarn("321:clone() is a javascript bad method name") *::clone();
|
||||
|
||||
#undef JAVASCRIPTKW
|
||||
|
||||
#endif //JAVASCRIPT_JAVASCRIPTKW_SWG_
|
|
@ -4,24 +4,46 @@
|
|||
/* Warnings for Java keywords */
|
||||
#define JAVASCRIPTKW(x) %keywordwarn("'" `x` "' is a javascript keyword, renaming to '_"`x`"'",rename="_%s") `x`
|
||||
|
||||
/* Taken from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Reserved_Words */
|
||||
/* Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#keywords */
|
||||
/* This the union of all currently reserved keywords in ECMAScript 4 to 6 in both sloppy and strict mode */
|
||||
|
||||
JAVASCRIPTKW(arguments);
|
||||
JAVASCRIPTKW(await);
|
||||
JAVASCRIPTKW(break);
|
||||
JAVASCRIPTKW(case);
|
||||
JAVASCRIPTKW(catch);
|
||||
JAVASCRIPTKW(class);
|
||||
JAVASCRIPTKW(const);
|
||||
JAVASCRIPTKW(continue);
|
||||
JAVASCRIPTKW(debugger);
|
||||
JAVASCRIPTKW(default);
|
||||
JAVASCRIPTKW(delete);
|
||||
JAVASCRIPTKW(do);
|
||||
JAVASCRIPTKW(else);
|
||||
JAVASCRIPTKW(enum);
|
||||
JAVASCRIPTKW(eval);
|
||||
JAVASCRIPTKW(export);
|
||||
JAVASCRIPTKW(extends);
|
||||
JAVASCRIPTKW(false);
|
||||
JAVASCRIPTKW(finally);
|
||||
JAVASCRIPTKW(for);
|
||||
JAVASCRIPTKW(function);
|
||||
JAVASCRIPTKW(if);
|
||||
JAVASCRIPTKW(implements);
|
||||
JAVASCRIPTKW(import);
|
||||
JAVASCRIPTKW(in);
|
||||
JAVASCRIPTKW(instanceof);
|
||||
JAVASCRIPTKW(interface);
|
||||
JAVASCRIPTKW(let);
|
||||
JAVASCRIPTKW(new);
|
||||
JAVASCRIPTKW(null);
|
||||
JAVASCRIPTKW(package);
|
||||
JAVASCRIPTKW(private);
|
||||
JAVASCRIPTKW(protected);
|
||||
JAVASCRIPTKW(public);
|
||||
JAVASCRIPTKW(return);
|
||||
JAVASCRIPTKW(static);
|
||||
JAVASCRIPTKW(super);
|
||||
JAVASCRIPTKW(switch);
|
||||
JAVASCRIPTKW(this);
|
||||
JAVASCRIPTKW(throw);
|
||||
|
@ -31,6 +53,7 @@ JAVASCRIPTKW(var);
|
|||
JAVASCRIPTKW(void);
|
||||
JAVASCRIPTKW(while);
|
||||
JAVASCRIPTKW(with);
|
||||
JAVASCRIPTKW(yield);
|
||||
|
||||
/* others bad names if any*/
|
||||
// for example %namewarn("321:clone() is a javascript bad method name") *::clone();
|
|
@ -436,7 +436,7 @@ install-main:
|
|||
|
||||
lib-languages = typemaps tcl perl5 python guile java mzscheme ruby php ocaml octave \
|
||||
csharp lua r go d javascript javascript/jsc \
|
||||
javascript/v8 scilab xml
|
||||
javascript/v8 javascript/napi scilab xml
|
||||
|
||||
lib-modules = std
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ static bool js_template_enable_debug = false;
|
|||
#define IS_IMMUTABLE "is_immutable"
|
||||
#define IS_STATIC "is_static"
|
||||
#define IS_ABSTRACT "is_abstract"
|
||||
#define IS_WRAPPED "is_wrapped"
|
||||
#define GETTER "getter"
|
||||
#define SETTER "setter"
|
||||
#define PARENT "parent"
|
||||
|
@ -127,7 +128,8 @@ public:
|
|||
enum JSEngine {
|
||||
JavascriptCore,
|
||||
V8,
|
||||
NodeJS
|
||||
NodeJS,
|
||||
NAPI
|
||||
};
|
||||
|
||||
JSEmitter(JSEngine engine);
|
||||
|
@ -274,6 +276,15 @@ protected:
|
|||
|
||||
virtual int emitNamespaces() = 0;
|
||||
|
||||
virtual const char *getFunctionTemplate(bool);
|
||||
|
||||
virtual const char *getFunctionDispatcherTemplate(bool);
|
||||
|
||||
virtual const char *getOverloadedFunctionTemplate(bool);
|
||||
|
||||
virtual const char *getSetterTemplate(bool);
|
||||
|
||||
virtual const char *getGetterTemplate(bool);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -295,6 +306,7 @@ protected:
|
|||
JSEmitter *swig_javascript_create_JSCEmitter();
|
||||
JSEmitter *swig_javascript_create_V8Emitter();
|
||||
JSEmitter *swig_javascript_create_NodeJSEmitter();
|
||||
JSEmitter *swig_javascript_create_NAPIEmitter();
|
||||
|
||||
/**********************************************************************
|
||||
* JAVASCRIPT: SWIG module implementation
|
||||
|
@ -514,14 +526,14 @@ int JAVASCRIPT::top(Node *n) {
|
|||
return SWIG_OK;
|
||||
}
|
||||
|
||||
static const char *usage = (char *) "\
|
||||
static const char *usage = (char *)"\
|
||||
Javascript Options (available with -javascript)\n\
|
||||
-jsc - creates a JavascriptCore extension \n\
|
||||
-v8 - creates a v8 extension \n\
|
||||
-node - creates a node.js extension \n\
|
||||
-napi - creates a NAPI extension \n\
|
||||
-debug-codetemplates - generates information about the origin of code templates\n";
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* main()
|
||||
*
|
||||
|
@ -557,6 +569,13 @@ void JAVASCRIPT::main(int argc, char *argv[]) {
|
|||
}
|
||||
Swig_mark_arg(i);
|
||||
engine = JSEmitter::NodeJS;
|
||||
} else if (strcmp(argv[i], "-napi") == 0) {
|
||||
if (engine != -1) {
|
||||
Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
|
||||
Exit(EXIT_FAILURE);
|
||||
}
|
||||
Swig_mark_arg(i);
|
||||
engine = JSEmitter::NAPI;
|
||||
} else if (strcmp(argv[i], "-debug-codetemplates") == 0) {
|
||||
Swig_mark_arg(i);
|
||||
js_template_enable_debug = true;
|
||||
|
@ -590,9 +609,20 @@ void JAVASCRIPT::main(int argc, char *argv[]) {
|
|||
SWIG_library_directory("javascript/jsc");
|
||||
break;
|
||||
}
|
||||
case JSEmitter::NAPI:
|
||||
{
|
||||
emitter = swig_javascript_create_NAPIEmitter();
|
||||
Preprocessor_define("SWIG_JAVASCRIPT_NAPI 1", 0);
|
||||
SWIG_library_directory("javascript/napi");
|
||||
Preprocessor_define("BUILDING_NODE_EXTENSION 1", 0);
|
||||
if (!cparse_cplusplus) {
|
||||
Swig_cparse_cplusplusout(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Printf(stderr, "SWIG Javascript: Unknown engine. Please specify one of '-jsc', '-v8' or '-node'.\n");
|
||||
Printf(stderr, "SWIG Javascript: Unknown engine. Please specify one of '-jsc', '-v8', '-node' or '-napi'.\n");
|
||||
Exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
@ -846,6 +876,26 @@ int JSEmitter::enterVariable(Node *n) {
|
|||
return SWIG_OK;
|
||||
}
|
||||
|
||||
const char *JSEmitter::getFunctionTemplate(bool) {
|
||||
return "js_function";
|
||||
}
|
||||
|
||||
const char *JSEmitter::getFunctionDispatcherTemplate(bool) {
|
||||
return "js_function_dispatcher";
|
||||
}
|
||||
|
||||
const char *JSEmitter::getOverloadedFunctionTemplate(bool) {
|
||||
return "js_overloaded_function";
|
||||
}
|
||||
|
||||
const char *JSEmitter::getGetterTemplate(bool) {
|
||||
return "js_getter";
|
||||
}
|
||||
|
||||
const char *JSEmitter::getSetterTemplate(bool) {
|
||||
return "js_setter";
|
||||
}
|
||||
|
||||
int JSEmitter::emitCtor(Node *n) {
|
||||
|
||||
Wrapper *wrapper = NewWrapper();
|
||||
|
@ -876,11 +926,13 @@ int JSEmitter::emitCtor(Node *n) {
|
|||
|
||||
emitCleanupCode(n, wrapper, params);
|
||||
|
||||
t_ctor.replace("$jswrapper", wrap_name)
|
||||
t_ctor.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", wrap_name)
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jslocals", wrapper->locals)
|
||||
.replace("$jscode", wrapper->code)
|
||||
.replace("$jsargcount", Getattr(n, ARGCOUNT))
|
||||
.replace("$jsparent", state.clazz(PARENT_MANGLED))
|
||||
.replace("$jsargrequired", Getattr(n, ARGREQUIRED))
|
||||
.pretty_print(f_wrappers);
|
||||
|
||||
|
@ -898,9 +950,11 @@ int JSEmitter::emitCtor(Node *n) {
|
|||
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
|
||||
Template t_mainctor(getTemplate("js_ctor_dispatcher"));
|
||||
t_mainctor.replace("$jswrapper", wrap_name)
|
||||
.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsdispatchcases", state.clazz(CTOR_DISPATCHERS))
|
||||
.pretty_print(f_wrappers);
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsdispatchcases", state.clazz(CTOR_DISPATCHERS))
|
||||
.replace("$jsparent", state.clazz(PARENT_MANGLED))
|
||||
.pretty_print(f_wrappers);
|
||||
state.clazz(CTOR, wrap_name);
|
||||
}
|
||||
} else {
|
||||
|
@ -1036,7 +1090,7 @@ int JSEmitter::emitDtor(Node *n) {
|
|||
|
||||
int JSEmitter::emitGetter(Node *n, bool is_member, bool is_static) {
|
||||
Wrapper *wrapper = NewWrapper();
|
||||
Template t_getter(getTemplate("js_getter"));
|
||||
Template t_getter(getTemplate(getGetterTemplate(is_member)));
|
||||
|
||||
// prepare wrapper name
|
||||
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
|
||||
|
@ -1055,7 +1109,8 @@ int JSEmitter::emitGetter(Node *n, bool is_member, bool is_static) {
|
|||
|
||||
emitCleanupCode(n, wrapper, params);
|
||||
|
||||
t_getter.replace("$jswrapper", wrap_name)
|
||||
t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", wrap_name)
|
||||
.replace("$jslocals", wrapper->locals)
|
||||
.replace("$jscode", wrapper->code)
|
||||
.pretty_print(f_wrappers);
|
||||
|
@ -1074,7 +1129,7 @@ int JSEmitter::emitSetter(Node *n, bool is_member, bool is_static) {
|
|||
|
||||
Wrapper *wrapper = NewWrapper();
|
||||
|
||||
Template t_setter(getTemplate("js_setter"));
|
||||
Template t_setter(getTemplate(getSetterTemplate(is_member)));
|
||||
|
||||
// prepare wrapper name
|
||||
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
|
||||
|
@ -1093,7 +1148,8 @@ int JSEmitter::emitSetter(Node *n, bool is_member, bool is_static) {
|
|||
|
||||
emitCleanupCode(n, wrapper, params);
|
||||
|
||||
t_setter.replace("$jswrapper", wrap_name)
|
||||
t_setter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", wrap_name)
|
||||
.replace("$jslocals", wrapper->locals)
|
||||
.replace("$jscode", wrapper->code)
|
||||
.pretty_print(f_wrappers);
|
||||
|
@ -1128,7 +1184,8 @@ int JSEmitter::emitConstant(Node *n) {
|
|||
value = Getattr(n, "cppvalue");
|
||||
}
|
||||
|
||||
Template t_getter(getTemplate("js_getter"));
|
||||
bool is_member = GetFlag(n, "ismember");
|
||||
Template t_getter(getTemplate(getGetterTemplate(is_member)));
|
||||
|
||||
// call the variable methods as a constants are
|
||||
// registered in same way
|
||||
|
@ -1151,13 +1208,19 @@ int JSEmitter::emitConstant(Node *n) {
|
|||
|
||||
marshalOutput(n, 0, wrapper, NewString(""), value, false);
|
||||
|
||||
t_getter.replace("$jswrapper", wname)
|
||||
t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", wname)
|
||||
.replace("$jslocals", wrapper->locals)
|
||||
.replace("$jscode", wrapper->code)
|
||||
.pretty_print(f_wrappers);
|
||||
|
||||
exitVariable(n);
|
||||
|
||||
// This is the counterpart to the "constant" test in
|
||||
// exitVariable, it prevents double setting of
|
||||
// symbols that are both constants and variables
|
||||
SetFlag(n, "constant");
|
||||
|
||||
DelWrapper(wrapper);
|
||||
|
||||
return SWIG_OK;
|
||||
|
@ -1165,7 +1228,7 @@ int JSEmitter::emitConstant(Node *n) {
|
|||
|
||||
int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
|
||||
Wrapper *wrapper = NewWrapper();
|
||||
Template t_function(getTemplate("js_function"));
|
||||
Template t_function(getTemplate(getFunctionTemplate(is_member)));
|
||||
|
||||
bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
|
||||
|
||||
|
@ -1173,7 +1236,7 @@ int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
|
|||
String *iname = Getattr(n, "sym:name");
|
||||
String *wrap_name = Swig_name_wrapper(iname);
|
||||
if (is_overloaded) {
|
||||
t_function = getTemplate("js_overloaded_function");
|
||||
t_function = getTemplate(getOverloadedFunctionTemplate(is_member));
|
||||
Append(wrap_name, Getattr(n, "sym:overname"));
|
||||
}
|
||||
Setattr(n, "wrap:name", wrap_name);
|
||||
|
@ -1190,7 +1253,8 @@ int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
|
|||
emitCleanupCode(n, wrapper, params);
|
||||
Replaceall(wrapper->code, "$symname", iname);
|
||||
|
||||
t_function.replace("$jswrapper", wrap_name)
|
||||
t_function.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", wrap_name)
|
||||
.replace("$jslocals", wrapper->locals)
|
||||
.replace("$jscode", wrapper->code)
|
||||
.replace("$jsargcount", Getattr(n, ARGCOUNT))
|
||||
|
@ -1202,7 +1266,7 @@ int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
|
|||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int JSEmitter::emitFunctionDispatcher(Node *n, bool /*is_member */ ) {
|
||||
int JSEmitter::emitFunctionDispatcher(Node *n, bool is_member) {
|
||||
Wrapper *wrapper = NewWrapper();
|
||||
|
||||
// Generate call list, go to first node
|
||||
|
@ -1226,7 +1290,7 @@ int JSEmitter::emitFunctionDispatcher(Node *n, bool /*is_member */ ) {
|
|||
|
||||
} while ((sibl = Getattr(sibl, "sym:nextSibling")));
|
||||
|
||||
Template t_function(getTemplate("js_function_dispatcher"));
|
||||
Template t_function(getTemplate(getFunctionDispatcherTemplate(is_member)));
|
||||
|
||||
// Note: this dispatcher function gets called after the last overloaded function has been created.
|
||||
// At this time, n.wrap:name contains the name of the last wrapper function.
|
||||
|
@ -1255,6 +1319,7 @@ int JSEmitter::emitFunctionDispatcher(Node *n, bool /*is_member */ ) {
|
|||
|
||||
// call this here, to replace all variables
|
||||
t_function.replace("$jswrapper", final_wrap_name)
|
||||
.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.function(NAME))
|
||||
.pretty_print(f_wrappers);
|
||||
|
||||
|
@ -2355,10 +2420,624 @@ int V8Emitter::emitNamespaces() {
|
|||
return SWIG_OK;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAPI: JSEmitter implementation for N-API
|
||||
**********************************************************************/
|
||||
|
||||
class NAPIEmitter : public JSEmitter {
|
||||
public:
|
||||
NAPIEmitter();
|
||||
|
||||
virtual ~NAPIEmitter();
|
||||
virtual int initialize(Node *n);
|
||||
virtual int dump(Node *n);
|
||||
virtual int close();
|
||||
virtual int enterClass(Node *n);
|
||||
virtual int exitClass(Node *n);
|
||||
virtual int enterVariable(Node *n);
|
||||
virtual int exitVariable(Node *n);
|
||||
virtual int exitFunction(Node *n);
|
||||
|
||||
protected:
|
||||
virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper,
|
||||
MarshallingMode mode, bool is_member,
|
||||
bool is_static);
|
||||
virtual int emitNamespaces();
|
||||
virtual int emitCtor(Node *);
|
||||
virtual int emitDtor(Node *);
|
||||
virtual int emitClassMethodDeclaration(Node *);
|
||||
|
||||
virtual const char *getFunctionTemplate(bool is_member);
|
||||
virtual const char *getFunctionDispatcherTemplate(bool is_member);
|
||||
virtual const char *getOverloadedFunctionTemplate(bool is_member);
|
||||
virtual const char *getSetterTemplate(bool is_member);
|
||||
virtual const char *getGetterTemplate(bool is_member);
|
||||
|
||||
protected:
|
||||
/* built-in parts */
|
||||
String *f_runtime;
|
||||
String *f_header;
|
||||
String *f_init;
|
||||
String *f_post_init;
|
||||
|
||||
/* class declarations */
|
||||
String *f_class_declarations;
|
||||
|
||||
/* parts for initilizer */
|
||||
String *f_init_namespaces;
|
||||
String *f_init_wrappers;
|
||||
String *f_init_inheritance;
|
||||
String *f_init_static_wrappers;
|
||||
String *f_init_register_classes;
|
||||
String *f_init_register_namespaces;
|
||||
|
||||
// the output cpp file
|
||||
File *f_wrap_cpp;
|
||||
|
||||
String *NULL_STR;
|
||||
String *VETO_SET;
|
||||
String *moduleName;
|
||||
|
||||
// the current index in the class table
|
||||
size_t class_idx;
|
||||
};
|
||||
|
||||
NAPIEmitter::NAPIEmitter()
|
||||
: JSEmitter(JSEmitter::NAPI), NULL_STR(NewString("0")),
|
||||
VETO_SET(NewString("JS_veto_set_variable")), class_idx(0) {}
|
||||
|
||||
NAPIEmitter::~NAPIEmitter() {
|
||||
Delete(NULL_STR);
|
||||
Delete(VETO_SET);
|
||||
}
|
||||
|
||||
int NAPIEmitter::initialize(Node *n) {
|
||||
JSEmitter::initialize(n);
|
||||
|
||||
moduleName = Getattr(n, "name");
|
||||
|
||||
// Get the output file name
|
||||
String *outfile = Getattr(n, "outfile");
|
||||
f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files());
|
||||
if (!f_wrap_cpp) {
|
||||
FileErrorDisplay(outfile);
|
||||
Exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
f_runtime = NewString("");
|
||||
f_header = NewString("");
|
||||
f_init = NewString("");
|
||||
f_post_init = NewString("");
|
||||
|
||||
f_class_declarations = NewString("");
|
||||
|
||||
f_init_namespaces = NewString("");
|
||||
f_init_wrappers = NewString("");
|
||||
f_init_inheritance = NewString("");
|
||||
f_init_static_wrappers = NewString("");
|
||||
f_init_register_classes = NewString("");
|
||||
f_init_register_namespaces = NewString("");
|
||||
|
||||
// note: this is necessary for built-in generation of SWIG runtime code
|
||||
Swig_register_filebyname("begin", f_wrap_cpp);
|
||||
Swig_register_filebyname("runtime", f_runtime);
|
||||
Swig_register_filebyname("header", f_header);
|
||||
Swig_register_filebyname("wrapper", f_wrappers);
|
||||
Swig_register_filebyname("init", f_init);
|
||||
Swig_register_filebyname("post-init", f_post_init);
|
||||
|
||||
state.globals(FORCE_CPP, NewString("1"));
|
||||
|
||||
Swig_banner(f_wrap_cpp);
|
||||
|
||||
Swig_obligatory_macros(f_runtime, "JAVASCRIPT");
|
||||
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::dump(Node *n) {
|
||||
/* Get the module name */
|
||||
String *module = Getattr(n, "name");
|
||||
|
||||
Template initializer_define(getTemplate("js_initializer_define"));
|
||||
initializer_define.replace("$jsname", module).pretty_print(f_header);
|
||||
|
||||
SwigType_emit_type_table(f_runtime, f_wrappers);
|
||||
|
||||
Printv(f_wrap_cpp, f_runtime, "\n", 0);
|
||||
Printv(f_wrap_cpp, f_header, "\n", 0);
|
||||
Printv(f_wrap_cpp, f_class_declarations, "\n", 0);
|
||||
Printv(f_wrap_cpp, f_wrappers, "\n", 0);
|
||||
|
||||
emitNamespaces();
|
||||
|
||||
String *inheritance = NewStringEmpty();
|
||||
if (Len(f_init_inheritance) > 0) {
|
||||
Template t_inheritance(getTemplate("js_init_inheritance"));
|
||||
t_inheritance.pretty_print(inheritance);
|
||||
}
|
||||
|
||||
// compose the initializer function using a template
|
||||
// filled with sub-parts
|
||||
Template initializer(getTemplate("js_initializer"));
|
||||
initializer.replace("$jsname", moduleName)
|
||||
.replace("$jsnapinspaces", f_init_namespaces)
|
||||
.replace("$jsnapipreinheritance", inheritance)
|
||||
.replace("$jsnapiinitinheritance", f_init_inheritance)
|
||||
.replace("$jsnapiregisterclasses", f_init_register_classes)
|
||||
.replace("$jsnapiregisternspaces", f_init_register_namespaces);
|
||||
Printv(f_init, initializer.str(), 0);
|
||||
|
||||
Printv(f_wrap_cpp, f_init, 0);
|
||||
|
||||
Printv(f_wrap_cpp, f_post_init, 0);
|
||||
|
||||
Delete(inheritance);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::close() {
|
||||
Delete(f_runtime);
|
||||
Delete(f_header);
|
||||
Delete(f_class_declarations);
|
||||
Delete(f_init_namespaces);
|
||||
Delete(f_init_wrappers);
|
||||
Delete(f_init_inheritance);
|
||||
Delete(f_init_static_wrappers);
|
||||
Delete(f_init_register_classes);
|
||||
Delete(f_init_register_namespaces);
|
||||
Delete(f_init);
|
||||
Delete(f_post_init);
|
||||
Delete(f_wrap_cpp);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
const char *NAPIEmitter::getFunctionTemplate(bool is_member) {
|
||||
return is_member ? "js_function" : "js_global_function";
|
||||
}
|
||||
|
||||
const char *NAPIEmitter::getFunctionDispatcherTemplate(bool is_member) {
|
||||
return is_member ? "js_function_dispatcher" : "js_global_function_dispatcher";
|
||||
}
|
||||
|
||||
const char *NAPIEmitter::getOverloadedFunctionTemplate(bool is_member) {
|
||||
return is_member ? "js_overloaded_function" : "js_global_overloaded_function";
|
||||
}
|
||||
|
||||
const char *NAPIEmitter::getGetterTemplate(bool is_member) {
|
||||
return is_member ? "js_getter" : "js_global_getter";
|
||||
}
|
||||
|
||||
const char *NAPIEmitter::getSetterTemplate(bool is_member) {
|
||||
return is_member ? "js_setter" : "js_global_setter";
|
||||
}
|
||||
|
||||
int NAPIEmitter::enterClass(Node *n) {
|
||||
JSEmitter::enterClass(n);
|
||||
|
||||
// emit registration of class template
|
||||
String *idx = NewString("");
|
||||
Printf(idx, "%d", class_idx++);
|
||||
Template t_register = getTemplate("jsnapi_registerclass");
|
||||
t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsparent", Getattr(state.clazz("nspace"), NAME_MANGLED))
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jsclassidx", idx)
|
||||
.trim()
|
||||
.pretty_print(f_init_register_classes);
|
||||
Delete(idx);
|
||||
|
||||
// emit inheritance
|
||||
String *baseMangled;
|
||||
Node *baseClass = getBaseClass(n);
|
||||
SetFlag(n, IS_WRAPPED);
|
||||
if (baseClass && GetFlag(baseClass, IS_WRAPPED)) {
|
||||
String *jsName = NewString("");
|
||||
String *nspace = Getattr(baseClass, "sym:nspace");
|
||||
if (Len(nspace) == 0) nspace = Getattr(current_namespace, NAME_MANGLED);
|
||||
Printf(jsName, "%s_%s", nspace, Getattr(baseClass, "sym:name"));
|
||||
baseMangled = SwigType_manglestr(jsName);
|
||||
Delete(jsName);
|
||||
|
||||
f_init_wrappers = Copy(Getattr(baseClass, MEMBER_FUNCTIONS));
|
||||
f_init_static_wrappers = Copy(Getattr(baseClass, STATIC_FUNCTIONS));
|
||||
} else {
|
||||
baseMangled = NewString("SWIG_NAPI_ObjectWrap");
|
||||
f_init_wrappers = NewString("");
|
||||
f_init_static_wrappers = NewString("");
|
||||
}
|
||||
state.clazz(PARENT_MANGLED, baseMangled);
|
||||
|
||||
Template t_setup_inheritance(getTemplate("jsnapi_setup_inheritance"));
|
||||
t_setup_inheritance.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", state.clazz(CTOR))
|
||||
.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsparent", baseMangled)
|
||||
.pretty_print(f_init_inheritance);
|
||||
|
||||
// emit declaration of a NAPI class template
|
||||
Template t_decl_class(getTemplate("jsnapi_class_prologue_template"));
|
||||
t_decl_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsparent", baseMangled)
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
|
||||
Delete(baseMangled);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::exitClass(Node *n) {
|
||||
if (GetFlag(state.clazz(), IS_ABSTRACT)) {
|
||||
Template t_veto_ctor(getTemplate("js_veto_ctor"));
|
||||
t_veto_ctor.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", state.clazz(CTOR))
|
||||
.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsparent", state.clazz(PARENT_MANGLED))
|
||||
.pretty_print(f_wrappers);
|
||||
}
|
||||
|
||||
/* Note: this makes sure that there is a swig_type added for this class */
|
||||
String *clientData = NewString("");
|
||||
Printf(clientData, "&%s_clientData", state.clazz(NAME_MANGLED));
|
||||
|
||||
/* Note: this makes sure that there is a swig_type added for this class */
|
||||
SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0"));
|
||||
|
||||
// emit definition of NAPI class template
|
||||
Template t_def_class = getTemplate("jsnapi_class_epilogue_template");
|
||||
t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jsdtor", state.clazz(DTOR))
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
|
||||
Template t_class_instance = getTemplate("jsnapi_declare_class_instance");
|
||||
t_class_instance.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
|
||||
Template t_class_template = getTemplate("jsnapi_getclass");
|
||||
t_class_template.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsnapiwrappers", f_init_wrappers)
|
||||
.replace("$jsnapistaticwrappers", f_init_static_wrappers)
|
||||
.replace("$jsparent", state.clazz(PARENT_MANGLED))
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
|
||||
/* Save these to be reused in the child classes */
|
||||
Setattr(n, MEMBER_FUNCTIONS, f_init_wrappers);
|
||||
Setattr(n, STATIC_FUNCTIONS, f_init_static_wrappers);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::enterVariable(Node *n) {
|
||||
// Somehow, this is not always reset
|
||||
// (some constructs like smart pointers reuse Nodes)
|
||||
UnsetFlag(n, "constant");
|
||||
|
||||
JSEmitter::enterVariable(n);
|
||||
|
||||
state.variable(GETTER, VETO_SET);
|
||||
state.variable(SETTER, VETO_SET);
|
||||
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::exitVariable(Node *n) {
|
||||
// Due to special handling of C++ "static const" member variables
|
||||
// (refer to the comment in lang.cxx:Language::staticmembervariableHandler)
|
||||
// a static const member variable may get transformed into a constant
|
||||
// and be emitted by emitConstant which will result calling exitVariable twice
|
||||
if (GetFlag(n, "constant")) {
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
if (GetFlag(n, "ismember")) {
|
||||
String *modifier = NewStringEmpty();
|
||||
if (GetFlag(state.variable(), IS_STATIC) ||
|
||||
Equal(Getattr(n, "nodeType"), "enumitem")) {
|
||||
Template t_register = getTemplate("jsnapi_register_static_variable");
|
||||
t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.variable(NAME))
|
||||
.replace("$jsgetter", state.variable(GETTER))
|
||||
.replace("$jssetter", state.variable(SETTER) != VETO_SET
|
||||
? state.variable(SETTER)
|
||||
: "JS_veto_set_static_variable")
|
||||
.trim()
|
||||
.pretty_print(f_init_static_wrappers);
|
||||
Append(modifier, "static");
|
||||
} else {
|
||||
Template t_register = getTemplate("jsnapi_register_member_variable");
|
||||
t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.variable(NAME))
|
||||
.replace("$jsgetter", state.variable(GETTER))
|
||||
.replace("$jssetter", state.variable(SETTER))
|
||||
.trim()
|
||||
.pretty_print(f_init_wrappers);
|
||||
}
|
||||
|
||||
// emit declaration of a class member function
|
||||
Template t_getter = getTemplate("jsnapi_class_method_declaration");
|
||||
t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jsdtor", state.clazz(DTOR))
|
||||
.replace("$jswrapper", state.variable(GETTER))
|
||||
.replace("$jsstatic", modifier)
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
if (state.variable(SETTER) != VETO_SET) {
|
||||
Template t_setter = getTemplate("jsnapi_class_setter_declaration");
|
||||
t_setter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jsdtor", state.clazz(DTOR))
|
||||
.replace("$jswrapper", state.variable(SETTER))
|
||||
.replace("$jsstatic", modifier)
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
}
|
||||
Delete(modifier);
|
||||
} else {
|
||||
Template t_register = getTemplate("jsnapi_register_global_variable");
|
||||
t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
|
||||
.replace("$jsname", state.variable(NAME))
|
||||
.replace("$jsgetter", state.variable(GETTER))
|
||||
.replace("$jssetter", state.variable(SETTER))
|
||||
.trim()
|
||||
.pretty_print(f_init_register_namespaces);
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::emitClassMethodDeclaration(Node *) {
|
||||
// emit declaration of a class member function
|
||||
Template t_def_class = getTemplate("jsnapi_class_method_declaration");
|
||||
t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.clazz(NAME))
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jsdtor", state.clazz(DTOR))
|
||||
.replace("$jswrapper", state.function(WRAPPER_NAME))
|
||||
.replace("$jsstatic", GetFlag(state.function(), IS_STATIC) ? "static" : "")
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::exitFunction(Node *n) {
|
||||
bool is_member =
|
||||
GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
|
||||
|
||||
// create a dispatcher for overloaded functions
|
||||
bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
|
||||
if (is_overloaded) {
|
||||
emitClassMethodDeclaration(n);
|
||||
if (!Getattr(n, "sym:nextSibling")) {
|
||||
emitFunctionDispatcher(n, is_member);
|
||||
} else {
|
||||
return SWIG_OK;
|
||||
}
|
||||
}
|
||||
// register the function at the specific context
|
||||
if (is_member) {
|
||||
if (GetFlag(state.function(), IS_STATIC)) {
|
||||
Template t_register = getTemplate("jsnapi_register_static_function");
|
||||
t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.function(NAME))
|
||||
.replace("$jswrapper", state.function(WRAPPER_NAME))
|
||||
.trim()
|
||||
.pretty_print(f_init_static_wrappers);
|
||||
} else {
|
||||
Template t_register = getTemplate("jsnapi_register_member_function");
|
||||
t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jsname", state.function(NAME))
|
||||
.replace("$jswrapper", state.function(WRAPPER_NAME))
|
||||
.trim()
|
||||
.pretty_print(f_init_wrappers);
|
||||
}
|
||||
|
||||
emitClassMethodDeclaration(n);
|
||||
} else {
|
||||
// Note: a global function is treated like a static function
|
||||
// with the parent being a nspace object instead of class object
|
||||
Template t_register = getTemplate("jsnapi_register_global_function");
|
||||
t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
|
||||
.replace("$jsname", state.function(NAME))
|
||||
.replace("$jswrapper", state.function(WRAPPER_NAME))
|
||||
.trim()
|
||||
.pretty_print(f_init_register_namespaces);
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
void NAPIEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper,
|
||||
MarshallingMode mode, bool is_member,
|
||||
bool is_static) {
|
||||
Parm *p;
|
||||
String *tm;
|
||||
|
||||
int startIdx = 0;
|
||||
if (is_member && !is_static && mode != Ctor) {
|
||||
startIdx = 1;
|
||||
}
|
||||
// store number of arguments for argument checks
|
||||
int num_args = emit_num_arguments(parms) - startIdx;
|
||||
String *argcount = NewString("");
|
||||
Printf(argcount, "%d", num_args);
|
||||
Setattr(n, ARGCOUNT, argcount);
|
||||
int num_required = emit_num_required(parms) - startIdx;
|
||||
SetInt(n, ARGREQUIRED, num_required);
|
||||
|
||||
int i = 0;
|
||||
for (p = parms; p;) {
|
||||
String *arg = NewString("");
|
||||
String *type = Getattr(p, "type");
|
||||
|
||||
// ignore varargs
|
||||
if (SwigType_isvarargs(type))
|
||||
break;
|
||||
|
||||
switch (mode) {
|
||||
case Getter:
|
||||
if (is_member && !is_static && i == 0) {
|
||||
Printv(arg, "info.This()", 0);
|
||||
i++;
|
||||
} else {
|
||||
Printf(arg, "info[%d]", i - startIdx);
|
||||
SetInt(p, INDEX, i - startIdx);
|
||||
i += GetInt(p, "tmap:in:numinputs");
|
||||
}
|
||||
break;
|
||||
case Function:
|
||||
if (is_member && !is_static && i == 0) {
|
||||
Printv(arg, "info.This()", 0);
|
||||
i++;
|
||||
} else {
|
||||
Printf(arg, "info[%d]", i - startIdx);
|
||||
SetInt(p, INDEX, i - startIdx);
|
||||
i += GetInt(p, "tmap:in:numinputs");
|
||||
}
|
||||
break;
|
||||
case Setter:
|
||||
if (is_member && !is_static && i == 0) {
|
||||
Printv(arg, "info.This()", 0);
|
||||
i++;
|
||||
} else {
|
||||
Printv(arg, "value", 0);
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
case Ctor:
|
||||
Printf(arg, "info[%d]", i);
|
||||
SetInt(p, INDEX, i - startIdx);
|
||||
i += GetInt(p, "tmap:in:numinputs");
|
||||
break;
|
||||
default:
|
||||
Printf(stderr, "Illegal MarshallingMode.");
|
||||
Exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tm = emitInputTypemap(n, p, wrapper, arg);
|
||||
Delete(arg);
|
||||
|
||||
if (tm) {
|
||||
p = Getattr(p, "tmap:in:next");
|
||||
} else {
|
||||
p = nextSibling(p);
|
||||
}
|
||||
}
|
||||
|
||||
for (p = parms; p;) {
|
||||
tm = emitCheckTypemap(n, p, wrapper, Getattr(p, "emit:input"));
|
||||
if (tm) {
|
||||
p = Getattr(p, "tmap:in:next");
|
||||
} else {
|
||||
p = nextSibling(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int NAPIEmitter::emitNamespaces() {
|
||||
Iterator it;
|
||||
for (it = First(namespaces); it.item; it = Next(it)) {
|
||||
Hash *entry = it.item;
|
||||
String *name = Getattr(entry, NAME);
|
||||
String *name_mangled = Getattr(entry, NAME_MANGLED);
|
||||
String *parent = Getattr(entry, PARENT);
|
||||
String *parent_mangled = Getattr(entry, PARENT_MANGLED);
|
||||
|
||||
bool do_create = true;
|
||||
bool do_register = true;
|
||||
|
||||
if (Equal(parent, "")) {
|
||||
do_register = false;
|
||||
}
|
||||
// Note: 'exports' is by convention the name of the object where
|
||||
// globals are stored into
|
||||
if (Equal(name, "exports")) {
|
||||
do_create = false;
|
||||
}
|
||||
|
||||
if (do_create) {
|
||||
// create namespace object and register it to the parent scope
|
||||
Template t_create_ns = getTemplate("jsnapi_create_namespace");
|
||||
t_create_ns.replace("$jsmangledname", name_mangled)
|
||||
.trim()
|
||||
.pretty_print(f_init_namespaces);
|
||||
}
|
||||
|
||||
if (do_register) {
|
||||
Template t_register_ns = getTemplate("jsnapi_register_namespace");
|
||||
t_register_ns.replace("$jsmangledname", name_mangled)
|
||||
.replace("$jsname", name)
|
||||
.replace("$jsparent", parent_mangled)
|
||||
.trim();
|
||||
|
||||
// prepend in order to achieve reversed order of registration statements
|
||||
String *tmp_register_stmt = NewString("");
|
||||
t_register_ns.pretty_print(tmp_register_stmt);
|
||||
Insert(f_init_register_namespaces, 0, tmp_register_stmt);
|
||||
Delete(tmp_register_stmt);
|
||||
}
|
||||
}
|
||||
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::emitCtor(Node *n) {
|
||||
int r;
|
||||
|
||||
// Constructor renaming does not work in JavaScript
|
||||
// This allows us to slip past the unit test which
|
||||
// is broken for all JavaScript backends
|
||||
if (GetFlag(n, "sym:overloaded")) {
|
||||
if (!Getattr(n, "sym:nextSibling")) {
|
||||
if (GetFlag(state.clazz(), "ctor:dispatcher:emitted")) {
|
||||
return SWIG_OK;
|
||||
}
|
||||
SetFlag(state.clazz(), "ctor:dispatcher:emitted");
|
||||
}
|
||||
}
|
||||
|
||||
r = JSEmitter::emitCtor(n);
|
||||
if (r != SWIG_OK)
|
||||
return r;
|
||||
|
||||
Template t_getter = getTemplate("jsnapi_class_method_declaration");
|
||||
t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.replace("$jswrapper", Getattr(n, "wrap:name"))
|
||||
.replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
|
||||
.replace("$jsstatic", "")
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
int NAPIEmitter::emitDtor(Node *n) {
|
||||
// NAPI destructors must have a class declaration
|
||||
Template t_getter = getTemplate("jsnapi_class_dtor_declaration");
|
||||
t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
|
||||
.trim()
|
||||
.pretty_print(f_class_declarations);
|
||||
return JSEmitter::emitDtor(n);
|
||||
}
|
||||
|
||||
JSEmitter *swig_javascript_create_V8Emitter() {
|
||||
return new V8Emitter();
|
||||
}
|
||||
|
||||
JSEmitter *swig_javascript_create_NAPIEmitter() {
|
||||
return new NAPIEmitter();
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Helper implementations
|
||||
**********************************************************************/
|
||||
|
|
|
@ -14,7 +14,7 @@ case "$SWIGLANG" in
|
|||
;;
|
||||
"javascript")
|
||||
case "$ENGINE" in
|
||||
"node")
|
||||
"node"|"napi")
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
|
||||
nvm use ${VER}
|
||||
|
|
|
@ -40,7 +40,7 @@ case "$SWIGLANG" in
|
|||
;;
|
||||
"javascript")
|
||||
case "$ENGINE" in
|
||||
"node")
|
||||
"node"|"napi")
|
||||
$RETRY wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.10/install.sh | bash
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
|
||||
|
@ -56,6 +56,7 @@ case "$SWIGLANG" in
|
|||
else
|
||||
$RETRY npm install -g node-gyp
|
||||
fi
|
||||
$RETRY npm install -g node-addon-api
|
||||
;;
|
||||
"jsc")
|
||||
$RETRY sudo apt-get install -qq libjavascriptcoregtk-${VER}-dev
|
||||
|
|
28
configure.ac
28
configure.ac
|
@ -1186,11 +1186,35 @@ else
|
|||
AC_CHECK_PROGS(NODEJS, [node nodejs])
|
||||
|
||||
if test -n "$NODEJS"; then
|
||||
# node-gyp is needed to run the test-suite/examples
|
||||
# node-gyp and npm are needed to run the test-suite/examples
|
||||
AC_CHECK_PROGS(NODEGYP, node-gyp)
|
||||
if test -z "$NODEGYP"; then
|
||||
NODEJS=
|
||||
fi
|
||||
AC_CHECK_PROGS(NODENPM, npm)
|
||||
if test -z "$NODENPM"; then
|
||||
NODEJS=
|
||||
fi
|
||||
JSNAPIENABLED=
|
||||
if test -n "$NODEJS"; then
|
||||
AC_LANG_PUSH([C++])
|
||||
NODENAPI_DIR=$(npm config get prefix)/lib/node_modules/node-addon-api
|
||||
CXXFLAGS_SAVED=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS -I/usr/include/node -I/usr/local/include/node -I$NODENAPI_DIR"
|
||||
AC_CHECK_HEADERS([node_api.h napi.h], [JSNAPIENABLED=1], [])
|
||||
CXXFLAGS=$CXXFLAGS_SAVED
|
||||
|
||||
AC_LANG_POP([C++])
|
||||
AC_SUBST(NODENAPI_DIR)
|
||||
fi
|
||||
AC_SUBST(JSNAPIENABLED)
|
||||
|
||||
AC_MSG_CHECKING(for Node-API (napi) generator support)
|
||||
if test -n "$JSNAPIENABLED"; then
|
||||
AC_MSG_RESULT(enabled)
|
||||
else
|
||||
AC_MSG_RESULT(disabled)
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------------
|
||||
|
@ -2624,7 +2648,7 @@ AC_SUBST(SKIP_JAVA)
|
|||
|
||||
|
||||
SKIP_JAVASCRIPT=
|
||||
if test -z "$JAVASCRIPT" || ( test -z "$NODEJS" && test -z "$JSCENABLED" && test -z "$JSV8ENABLED" ) ; then
|
||||
if test -z "$JAVASCRIPT" || ( test -z "$NODEJS" && test -z "$JSCENABLED" && test -z "$JSV8ENABLED" && test -z "$JSNAPIENABLED" ) ; then
|
||||
SKIP_JAVASCRIPT="1"
|
||||
fi
|
||||
AC_SUBST(SKIP_JAVASCRIPT)
|
||||
|
|
Loading…
Reference in New Issue