JavaScript interoperability
Cheerp implements three advanced interoperability mechanisms to interface C++ code with pure JavaScript:
- Expose C++ classes and methods to JavaScript code
- Inlining JavaScript code within a C++ codebase.
- Use JavaScript methods and classes directly from C++
The jsexport attribute
The [[cheerp::jsexport]]
attribute can be applied to C++ class and struct definitions, to expose them to JavaScript.
See here for in-depth information about how to use it and its limitations.
A basic example of its usage would be:
This example exposes the a factorial free function and a JsStruct class, and allows one to create and use the JsStruct instances from JavaScript, for example:
Classes or struct that have to be JSExported have to tagged with both [[cheerp::jsexport]]
and [[cheerp::genericjs]]
.
The __asm__ keyword
A different mechanism allows one to inline JavaScript code in the middle of a C++ application. Similarly to a traditional architecture, the __asm__
keyword permits to write native (JavaScript) code. This functionality can be used to interface with external JS libraries which have no Cheerp compatible headers yet.
The following is a simple example of JavaScript inlining in C++:
It is possible to pass arguments and get values back from inline __asm__ code, here is a more complex example
The syntax follows the usual conventions of inline asm code, namely
Both the input constraints and clobber constraints parts are optional.
There are some Cheerp specific limitations at this time:
- Only the
"r"
constraint is supported. It represents a local variable in the generated JS code (equivalent to a register on traditional architecture). - Only integral types, floating point types and pointers to object in the
client
namespace (i.e. DOM or native JavaScript objects) can be used.
A working example/tutorial is here: example of _ asmjs _ and namespace client on Github
Code inside __asm__
tag should never throw to the external scope, and should consist of a single JS expression or statement without the final ;
.
Clobbering names
Cheerp minifies the output by default (unless the -cheerp-pretty-code
option is used). This happens by assigning the smallest possible symbols to the most used local or global variables. If you need to use temporary variables in inline asm code you need to declare those variables in the clobber list, for example
All names declared as clobbered will be globally excluded from the list of symbol that are used for minification. The effect is the same as marking those names as reserved using the -cheerp-reserved-names
command line option. For best results we recommend to choose temporary names while keeping the following into account:
- Using very short names (i.e. 1 or 2 letters) will reserve those symbols during minification, which may have a significant impact in terms of code size.
- Using names with a leading underscore (i.e
_foo
) may cause collisions with symbols in the global scope if-cheerp-pretty-code
is used. - For best compatibility we recommend to choose temporary values at least 3 letters long and without a leading underscore.
The CHEERP_OBJECT macro
A common use case for inline asm is to return a literal object to JavaScript:
This is usually much more performant than creating a new client::Object()
and populating it with the set_()
method.
The CHEERP_OBJECT
macro can be used to achieve the same result without the boilerplate and with a more elegant syntax:
Currently the macro has the following limitations:
- The maximum number of arguments is 16
- The arguments need to be global or local variable names, and the same names will be used for the js object fields
The client namespace
Cheerp treats every function and class inside the client
namespace as a declaration for something implemented by the browser or JavaScript. You are free to add new declarations there for functions implemented in JavaScript. For example:
And on the JavaScript side:
The CHEERP_SAFE_INLINE macro
As an alternative to directly using inline JS code Cheerp also provides a macro designed to quickly introduce type safe DOM code in existing code, which can be especially useful when compiling with the cheerp-wasm
target.
Example usage:
The cheerp::ArrayRef
class and cheerp::makeArrayRef
helpers
Cheerp provides an helper class to simplify access to JS array-like objects, such as client::Array
and client::Int32Array
. It’s common to pass them as pointers, which makes it inconvenient to use the operator[]
to access their elements. The cheerp::ArrayRef
class can be wrapper around a pointer to use the operator[]
more naturally. cheerp::makeArrayRef
is an helper to automatically deduce the right template type for the cheerp::ArrayRef
class.