forked from containers/crun
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: hack in support for wasm using Node.js
- hack in Node.js to run wasm with Node.js - only tested on hello world so far Signed-off-by: Michael Dawson <mdawson@devrus.com>
- Loading branch information
Showing
12 changed files
with
1,459 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# NODE-WASM-EXPERIMENT | ||
|
||
Experiment of integration Node.js to run wasm containers by | ||
hacking wastime integration | ||
|
||
# Node version | ||
|
||
The experiment uses the code from the | ||
[Extend Node-API to libnode](https://github.com/nodejs/node/pull/43542) | ||
PR. This was an easy way to get a set of C functions that would be integrated | ||
with crun that is C versus C++. That PR is likely a long way (if ever from | ||
landing) but reduced the work that it would have taken to build C wrapper | ||
using the Node.js C++ embedder API or converting the crun project over | ||
to C++. | ||
|
||
Node needs to be built with | ||
|
||
``` | ||
./configure --shared | ||
`` | ||
And the the resulting `../out/Release/libnode.so.108` copied to | ||
libnode.so in the node-lib directory added to this branch. | ||
The following files also need to be copied from `../src` directory | ||
in the Node.js project to the node-include directory added to this branch | ||
* js_native_api.h | ||
* js_native_api_types.h | ||
* node_api.h | ||
* node_api_types.h | ||
**NOTE:** I've included these as part of the PR along with the shared library | ||
so that everybody does not need to build the node shared library | ||
and extract the associated headers. May or may not work on the | ||
machine you run on. I built/ran on Fedora 36. | ||
# Building crun | ||
Before building running you will need to so the following: | ||
* copy the headers node-include/* into /usr/include | ||
* copy node-lib/libnode.so to /lib64 | ||
The file `buildit.sh` shows the steps used to build with | ||
node.js integrated. | ||
# Building wasm container | ||
The wasm to be run must be built an pushed to the local repository | ||
and be tagged as a wasm container. See | ||
[wasmtime-tutorial](https://github.com/font/wasmtime-tutorial.git) | ||
for more details. | ||
My specific stesp to build were as follows: | ||
```shell | ||
cargo build --target wasm32-wasi --release | ||
chomd +x ./target/wasm32-wasi/release/hello_wasm.wasm | ||
buildah build --annotation "module.wasm.image/variant=compat" -t wasm-test -f ./Containerfile | ||
``` | ||
|
||
with the resulting container being: | ||
|
||
```shell | ||
REPOSITORY TAG IMAGE ID CREATED SIZE | ||
localhost/wasm-test latest 8c9b454570f0 20 hours ago 2.01 MB | ||
``` | ||
|
||
# Running | ||
|
||
The file `runit.sh` has the steps I used to run. It hard codes | ||
the path to the updated crun to | ||
``` | ||
/root/wasmtime-tutorial/crun/crun` | ||
``` | ||
|
||
which will need to be updated for your path if you use the script | ||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
./configure --with-wasm_nodejs | ||
make |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
#ifndef SRC_JS_NATIVE_API_TYPES_H_ | ||
#define SRC_JS_NATIVE_API_TYPES_H_ | ||
|
||
// This file needs to be compatible with C compilers. | ||
// This is a public include file, and these includes have essentially | ||
// became part of it's API. | ||
#include <stddef.h> // NOLINT(modernize-deprecated-headers) | ||
#include <stdint.h> // NOLINT(modernize-deprecated-headers) | ||
|
||
#if !defined __cplusplus || (defined(_MSC_VER) && _MSC_VER < 1900) | ||
typedef uint16_t char16_t; | ||
#endif | ||
|
||
#ifndef NAPI_CDECL | ||
#ifdef _WIN32 | ||
#define NAPI_CDECL __cdecl | ||
#else | ||
#define NAPI_CDECL | ||
#endif | ||
#endif | ||
|
||
// JSVM API types are all opaque pointers for ABI stability | ||
// typedef undefined structs instead of void* for compile time type safety | ||
typedef struct napi_env__* napi_env; | ||
typedef struct napi_value__* napi_value; | ||
typedef struct napi_ref__* napi_ref; | ||
typedef struct napi_handle_scope__* napi_handle_scope; | ||
typedef struct napi_escapable_handle_scope__* napi_escapable_handle_scope; | ||
typedef struct napi_callback_info__* napi_callback_info; | ||
typedef struct napi_deferred__* napi_deferred; | ||
typedef struct napi_platform__* napi_platform; | ||
|
||
typedef enum { | ||
napi_default = 0, | ||
napi_writable = 1 << 0, | ||
napi_enumerable = 1 << 1, | ||
napi_configurable = 1 << 2, | ||
|
||
// Used with napi_define_class to distinguish static properties | ||
// from instance properties. Ignored by napi_define_properties. | ||
napi_static = 1 << 10, | ||
|
||
#if NAPI_VERSION >= 8 | ||
// Default for class methods. | ||
napi_default_method = napi_writable | napi_configurable, | ||
|
||
// Default for object properties, like in JS obj[prop]. | ||
napi_default_jsproperty = napi_writable | napi_enumerable | napi_configurable, | ||
#endif // NAPI_VERSION >= 8 | ||
} napi_property_attributes; | ||
|
||
typedef enum { | ||
// ES6 types (corresponds to typeof) | ||
napi_undefined, | ||
napi_null, | ||
napi_boolean, | ||
napi_number, | ||
napi_string, | ||
napi_symbol, | ||
napi_object, | ||
napi_function, | ||
napi_external, | ||
napi_bigint, | ||
} napi_valuetype; | ||
|
||
typedef enum { | ||
napi_int8_array, | ||
napi_uint8_array, | ||
napi_uint8_clamped_array, | ||
napi_int16_array, | ||
napi_uint16_array, | ||
napi_int32_array, | ||
napi_uint32_array, | ||
napi_float32_array, | ||
napi_float64_array, | ||
napi_bigint64_array, | ||
napi_biguint64_array, | ||
} napi_typedarray_type; | ||
|
||
typedef enum { | ||
napi_ok, | ||
napi_invalid_arg, | ||
napi_object_expected, | ||
napi_string_expected, | ||
napi_name_expected, | ||
napi_function_expected, | ||
napi_number_expected, | ||
napi_boolean_expected, | ||
napi_array_expected, | ||
napi_generic_failure, | ||
napi_pending_exception, | ||
napi_cancelled, | ||
napi_escape_called_twice, | ||
napi_handle_scope_mismatch, | ||
napi_callback_scope_mismatch, | ||
napi_queue_full, | ||
napi_closing, | ||
napi_bigint_expected, | ||
napi_date_expected, | ||
napi_arraybuffer_expected, | ||
napi_detachable_arraybuffer_expected, | ||
napi_would_deadlock // unused | ||
} napi_status; | ||
// Note: when adding a new enum value to `napi_status`, please also update | ||
// * `const int last_status` in the definition of `napi_get_last_error_info()' | ||
// in file js_native_api_v8.cc. | ||
// * `const char* error_messages[]` in file js_native_api_v8.cc with a brief | ||
// message explaining the error. | ||
// * the definition of `napi_status` in doc/api/n-api.md to reflect the newly | ||
// added value(s). | ||
|
||
typedef napi_value(NAPI_CDECL* napi_callback)(napi_env env, | ||
napi_callback_info info); | ||
typedef void(NAPI_CDECL* napi_finalize)(napi_env env, | ||
void* finalize_data, | ||
void* finalize_hint); | ||
|
||
typedef struct { | ||
// One of utf8name or name should be NULL. | ||
const char* utf8name; | ||
napi_value name; | ||
|
||
napi_callback method; | ||
napi_callback getter; | ||
napi_callback setter; | ||
napi_value value; | ||
|
||
napi_property_attributes attributes; | ||
void* data; | ||
} napi_property_descriptor; | ||
|
||
typedef struct { | ||
const char* error_message; | ||
void* engine_reserved; | ||
uint32_t engine_error_code; | ||
napi_status error_code; | ||
} napi_extended_error_info; | ||
|
||
#if NAPI_VERSION >= 6 | ||
typedef enum { | ||
napi_key_include_prototypes, | ||
napi_key_own_only | ||
} napi_key_collection_mode; | ||
|
||
typedef enum { | ||
napi_key_all_properties = 0, | ||
napi_key_writable = 1, | ||
napi_key_enumerable = 1 << 1, | ||
napi_key_configurable = 1 << 2, | ||
napi_key_skip_strings = 1 << 3, | ||
napi_key_skip_symbols = 1 << 4 | ||
} napi_key_filter; | ||
|
||
typedef enum { | ||
napi_key_keep_numbers, | ||
napi_key_numbers_to_strings | ||
} napi_key_conversion; | ||
#endif // NAPI_VERSION >= 6 | ||
|
||
#if NAPI_VERSION >= 8 | ||
typedef struct { | ||
uint64_t lower; | ||
uint64_t upper; | ||
} napi_type_tag; | ||
#endif // NAPI_VERSION >= 8 | ||
|
||
#endif // SRC_JS_NATIVE_API_TYPES_H_ |
Oops, something went wrong.