emnapi 0.45.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CMakeLists.txt CHANGED
@@ -38,7 +38,7 @@ set(EMNAPI_THREADS_SRC
38
38
  )
39
39
  set(EMNAPI_SRC ${ENAPI_BASIC_SRC} ${EMNAPI_THREADS_SRC})
40
40
 
41
- set(EMNAPI_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/include")
41
+ set(EMNAPI_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/include/node")
42
42
  set(EMNAPI_DEFINES "BUILDING_NODE_EXTENSION")
43
43
 
44
44
  set(EMNAPI_JS_LIB "${CMAKE_CURRENT_SOURCE_DIR}/dist/library_napi.js")
@@ -209,35 +209,41 @@ if(LIB_ARCH)
209
209
  endif()
210
210
 
211
211
  install(FILES
212
- ${CMAKE_CURRENT_SOURCE_DIR}/include/emnapi_common.h
213
- ${CMAKE_CURRENT_SOURCE_DIR}/include/emnapi.h
214
- ${CMAKE_CURRENT_SOURCE_DIR}/include/js_native_api_types.h
215
- ${CMAKE_CURRENT_SOURCE_DIR}/include/js_native_api.h
216
- ${CMAKE_CURRENT_SOURCE_DIR}/include/node_api_types.h
217
- ${CMAKE_CURRENT_SOURCE_DIR}/include/node_api.h
218
- ${CMAKE_CURRENT_SOURCE_DIR}/include/uv.h
219
- DESTINATION "include/${PROJECT_NAME}")
212
+ ${CMAKE_CURRENT_SOURCE_DIR}/common.gypi
213
+ ${CMAKE_CURRENT_SOURCE_DIR}/emnapi.gyp
214
+ DESTINATION ".")
215
+
216
+ install(FILES
217
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/emnapi_common.h
218
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/emnapi.h
219
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/js_native_api_types.h
220
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/js_native_api.h
221
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/node_api_types.h
222
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/node_api.h
223
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/uv.h
224
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/config.gypi
225
+ DESTINATION "include/node")
220
226
 
221
227
  install(DIRECTORY
222
- ${CMAKE_CURRENT_SOURCE_DIR}/include/uv
223
- DESTINATION "include/${PROJECT_NAME}")
228
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/node/uv
229
+ DESTINATION "include/node")
224
230
 
225
231
  install(FILES
226
232
  ${CMAKE_CURRENT_SOURCE_DIR}/dist/library_napi.js
227
- DESTINATION "lib/${PROJECT_NAME}")
233
+ DESTINATION "dist")
228
234
 
229
235
  if(EMNAPI_INSTALL_SRC)
230
236
  install(FILES
231
237
  ${EMNAPI_SRC}
232
238
  "${CMAKE_CURRENT_SOURCE_DIR}/src/emnapi_internal.h"
233
- DESTINATION "src/${PROJECT_NAME}")
239
+ DESTINATION "src")
234
240
  install(DIRECTORY
235
241
  ${CMAKE_CURRENT_SOURCE_DIR}/src/uv
236
- DESTINATION "src/${PROJECT_NAME}")
242
+ DESTINATION "src")
237
243
  install(DIRECTORY
238
244
  ${CMAKE_CURRENT_SOURCE_DIR}/src/malloc
239
- DESTINATION "src/${PROJECT_NAME}")
245
+ DESTINATION "src")
240
246
  install(DIRECTORY
241
247
  ${CMAKE_CURRENT_SOURCE_DIR}/src/thread
242
- DESTINATION "src/${PROJECT_NAME}")
248
+ DESTINATION "src")
243
249
  endif()
package/README.md CHANGED
@@ -4,15 +4,25 @@
4
4
  <img src="https://toyobayashi.github.io/emnapi-docs/emnapi.svg" alt="emnapi logo" width="256" />
5
5
  </p>
6
6
 
7
+ ## Sponsors
8
+
9
+ <p align="center">
10
+ <a href="https://cdn.jsdelivr.net/gh/toyobayashi/toyobayashi/sponsorkit/sponsors.svg">
11
+ <img src='https://cdn.jsdelivr.net/gh/toyobayashi/toyobayashi/sponsorkit/sponsors.svg'/>
12
+ </a>
13
+ </p>
14
+
7
15
  [![Build](https://github.com/toyobayashi/emnapi/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/toyobayashi/emnapi/actions/workflows/main.yml)
8
16
 
9
- [Node-API](https://nodejs.org/docs/latest/api/n-api.html) implementation for [Emscripten](https://emscripten.org/index.html), [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) and clang with wasm support. napi-rs support is comming soon.
17
+ [Node-API](https://nodejs.org/docs/latest/api/n-api.html) implementation for [Emscripten](https://emscripten.org/index.html), [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) and clang with wasm support.
10
18
 
11
19
  This project aims to
12
20
 
13
21
  - Help users port their or existing Node-API native addons to wasm with code change as less as possible.
14
22
  - Make runtime behavior matches native Node.js as much as possible.
15
23
 
24
+ This project also powers the WebAssembly feature for [napi-rs](https://github.com/napi-rs/napi-rs), and enables many Node.js native addons to run on [StackBlitz](https://stackblitz.com)'s WebContainer.
25
+
16
26
  See documentation for more details:
17
27
  - [https://toyobayashi.github.io/emnapi-docs/guide/](https://toyobayashi.github.io/emnapi-docs/guide/)
18
28
  - [https://emnapi-docs.vercel.app/guide/](https://emnapi-docs.vercel.app/guide/)
@@ -167,7 +177,7 @@ module.exports = (function (exports) {
167
177
  emcc -O3 \
168
178
  -DBUILDING_NODE_EXTENSION \
169
179
  "-DNAPI_EXTERN=__attribute__((__import_module__(\"env\")))" \
170
- -I./node_modules/emnapi/include \
180
+ -I./node_modules/emnapi/include/node \
171
181
  -L./node_modules/emnapi/lib/wasm32-emscripten \
172
182
  --js-library=./node_modules/emnapi/dist/library_napi.js \
173
183
  -sEXPORTED_FUNCTIONS="['_malloc','_free','_napi_register_wasm_v1','_node_api_module_get_api_version_v1']" \
@@ -184,7 +194,7 @@ emcc -O3 \
184
194
  ```bash
185
195
  clang -O3 \
186
196
  -DBUILDING_NODE_EXTENSION \
187
- -I./node_modules/emnapi/include \
197
+ -I./node_modules/emnapi/include/node \
188
198
  -L./node_modules/emnapi/lib/wasm32-wasi \
189
199
  --target=wasm32-wasi \
190
200
  --sysroot=$WASI_SDK_PATH/share/wasi-sysroot \
@@ -212,7 +222,7 @@ Choose `libdlmalloc.a` or `libemmalloc.a` for `malloc` and `free`.
212
222
  ```bash
213
223
  clang -O3 \
214
224
  -DBUILDING_NODE_EXTENSION \
215
- -I./node_modules/emnapi/include \
225
+ -I./node_modules/emnapi/include/node \
216
226
  -L./node_modules/emnapi/lib/wasm32 \
217
227
  --target=wasm32 \
218
228
  -nostdlib \
@@ -456,7 +466,7 @@ em++ -O3 \
456
466
  "-DNAPI_EXTERN=__attribute__((__import_module__(\"env\")))" \
457
467
  -DNAPI_DISABLE_CPP_EXCEPTIONS \
458
468
  -DNODE_ADDON_API_ENABLE_MAYBE \
459
- -I./node_modules/emnapi/include \
469
+ -I./node_modules/emnapi/include/node \
460
470
  -I./node_modules/node-addon-api \
461
471
  -L./node_modules/emnapi/lib/wasm32-emscripten \
462
472
  --js-library=./node_modules/emnapi/dist/library_napi.js \
@@ -476,7 +486,7 @@ clang++ -O3 \
476
486
  -DBUILDING_NODE_EXTENSION \
477
487
  -DNAPI_DISABLE_CPP_EXCEPTIONS \
478
488
  -DNODE_ADDON_API_ENABLE_MAYBE \
479
- -I./node_modules/emnapi/include \
489
+ -I./node_modules/emnapi/include/node \
480
490
  -I./node_modules/node-addon-api \
481
491
  -L./node_modules/emnapi/lib/wasm32-wasi \
482
492
  --target=wasm32-wasi \
@@ -508,7 +518,7 @@ You can still use `wasm32-unknown-unknown` target if you use Node-API C API only
508
518
  ```bash
509
519
  clang++ -O3 \
510
520
  -DBUILDING_NODE_EXTENSION \
511
- -I./node_modules/emnapi/include \
521
+ -I./node_modules/emnapi/include/node \
512
522
  -L./node_modules/emnapi/lib/wasm32 \
513
523
  --target=wasm32 \
514
524
  -fno-exceptions \
@@ -615,158 +625,166 @@ cmake --build build
615
625
 
616
626
  Output code can run in recent version modern browsers and Node.js latest LTS. IE is not supported.
617
627
 
618
- ### Using Rust (Experimental)
628
+ ### Using node-gyp (Experimental)
619
629
 
620
- Currently you can use [napi-rs](https://github.com/napi-rs/napi-rs) like this, more work is working in progress.
630
+ Currently node-gyp works on Linux only and don't support static library linking in cross-compiling.
631
+ There are opened PRs to try to make node-gyp work fine.
621
632
 
622
- Note: WASI target require rust nightly toolchain.
633
+ - https://github.com/nodejs/gyp-next/pull/222
634
+ - https://github.com/nodejs/node-gyp/pull/2974
623
635
 
624
- <details>
625
- <summary>Cargo.toml</summary><br />
626
-
627
- ```toml
628
- [package]
629
- edition = "2021"
630
- name = "binding"
631
- version = "0.0.0"
632
-
633
- # We should build binary for WASI reactor
634
- # https://github.com/rust-lang/rust/pull/79997
635
- # https://github.com/WebAssembly/WASI/issues/24
636
- # for wasm
637
- [[bin]]
638
- name = "binding"
639
- path = "src/main.rs"
640
-
641
- # for native
642
- # [lib]
643
- # name = "binding"
644
- # path = "src/lib.rs"
645
- # crate-type = ["cdylib"]
646
-
647
- [dependencies]
648
- napi = { version = "2.12.1", default-features = false, features = ["napi8"] }
649
- napi-sys = { version = "2.2.3", features = ["napi8"] }
650
- napi-derive = "2.12.2"
651
-
652
- [build-dependencies]
653
- napi-build = "2.0.1"
654
-
655
- [profile.release]
656
- strip = "symbols"
657
- ```
636
+ If you experienced issues on Windows or macOS, please check the PRs for upstream changes detail and see
637
+ [emnapi-node-gyp-test](https://github.com/toyobayashi/emnapi-node-gyp-test) for examples.
658
638
 
659
- </details>
639
+ - Variables
660
640
 
661
- <details>
662
- <summary>.cargo/config.toml</summary><br />
663
-
664
- ```toml
665
- [build]
666
- target = [
667
- "wasm32-unknown-unknown",
668
- "wasm32-wasi"
669
- ]
670
-
671
- [target.wasm32-unknown-unknown]
672
- rustflags = [
673
- "-L./node_modules/emnapi/lib/wasm32",
674
- "-lemnapi",
675
- "-ldlmalloc",
676
- # "-lemmalloc",
677
- "-C", "link-arg=--no-entry",
678
- "-C", "link-arg=--initial-memory=16777216",
679
- "-C", "link-arg=--export-dynamic",
680
- "-C", "link-arg=--export=malloc",
681
- "-C", "link-arg=--export=free",
682
- "-C", "link-arg=--export=napi_register_wasm_v1",
683
- "-C", "link-arg=--export-if-defined=node_api_module_get_api_version_v1",
684
- "-C", "link-arg=--export-table",
685
- "-C", "link-arg=--import-undefined",
686
- ]
687
-
688
- [target.wasm32-wasi]
689
- rustflags = [
690
- "-L./node_modules/emnapi/lib/wasm32-wasi",
691
- "-lemnapi",
692
- "-C", "link-arg=--initial-memory=16777216",
693
- "-C", "link-arg=--export-dynamic",
694
- "-C", "link-arg=--export=malloc",
695
- "-C", "link-arg=--export=free",
696
- "-C", "link-arg=--export=napi_register_wasm_v1",
697
- "-C", "link-arg=--export-if-defined=node_api_module_get_api_version_v1",
698
- "-C", "link-arg=--export-table",
699
- "-C", "link-arg=--import-undefined",
700
- "-Z", "wasi-exec-model=reactor", # +nightly
701
- ]
702
- ```
641
+ Arch: `node-gyp configure --arch=<wasm32 | wasm64>`
703
642
 
704
- </details>
643
+ ```ts
644
+ // node-gyp configure -- -Dvariable_name=value
705
645
 
706
- <details>
707
- <summary>src/main.rs</summary><br />
646
+ declare var OS: 'emscripten' | 'wasi' | 'unknown' | ''
708
647
 
709
- ```rust
710
- #![no_main]
648
+ /**
649
+ * Enable async work and threadsafe-functions
650
+ * @default 0
651
+ */
652
+ declare var wasm_threads: 0 | 1
711
653
 
712
- use napi_derive::napi;
654
+ /** @default 1048576 */
655
+ declare var stack_size: number
713
656
 
714
- #[napi]
715
- fn fibonacci(n: u32) -> u32 {
716
- match n {
717
- 1 | 2 => 1,
718
- _ => fibonacci(n - 1) + fibonacci(n - 2),
719
- }
657
+ /** @default 16777216 */
658
+ declare var initial_memory: number
659
+
660
+ /** @default 2147483648 */
661
+ declare var max_memory: number
662
+
663
+ /** @default path.join(path.dirname(commonGypiPath,'./dist/library_napi.js')) */
664
+ declare var emnapi_js_library: string
665
+
666
+ /** @default 0 */
667
+ declare var emnapi_manual_linking: 0 | 1
668
+ ```
669
+
670
+ - Create `binding.gyp`
671
+
672
+
673
+ ```py
674
+ {
675
+ "targets": [
676
+ {
677
+ "target_name": "hello",
678
+ "sources": [
679
+ "hello.c"
680
+ ],
681
+ "conditions": [
682
+ ["OS == 'emscripten'", {
683
+ "product_extension": "js", # required
684
+
685
+ # Windows and Linux
686
+ "cflags": [],
687
+ "cflags_c": [],
688
+ "cflags_cc": [],
689
+ "ldflags": [],
690
+
691
+ # macOS uses following config
692
+ 'xcode_settings': {
693
+ "WARNING_CFLAGS": [], # cflags
694
+ "OTHER_CFLAGS": [], # cflags_c
695
+ "OTHER_CPLUSPLUSFLAGS": [], # cflags_cc
696
+ "OTHER_LDFLAGS": [] # ldflags
697
+ }
698
+ }],
699
+ ["OS == 'wasi'", {
700
+ # ...
701
+ }],
702
+ ["OS == 'unknown' or OS == ''", {
703
+ # ...
704
+ }]
705
+ ]
706
+ }
707
+ ]
720
708
  }
721
709
  ```
722
710
 
723
- </details>
711
+ - Add the following environment variables.
724
712
 
725
- <details>
726
- <summary>index.js</summary><br />
713
+ ```bash
714
+ # Linux or macOS
715
+ export GYP_CROSSCOMPILE=1
727
716
 
728
- ```js
729
- const fs = require('fs')
730
- const path = require('path')
731
- const useWASI = false
717
+ # emscripten
718
+ export AR_target="$EMSDK/upstream/emscripten/emar"
719
+ export CC_target="$EMSDK/upstream/emscripten/emcc"
720
+ export CXX_target="$EMSDK/upstream/emscripten/em++"
732
721
 
733
- let wasi
734
- if (useWASI) {
735
- const { WASI } = require('wasi')
736
- wasi = new WASI({ /* ... */ })
737
- }
722
+ # wasi-sdk
723
+ export AR_target="$WASI_SDK_PATH/bin/ar"
724
+ export CC_target="$WASI_SDK_PATH/bin/clang"
725
+ export CXX_target="$WASI_SDK_PATH/bin/clang++"
726
+ ```
738
727
 
739
- const { instantiateNapiModule } = require('@emnapi/core')
728
+ ```bat
729
+ @REM Windows
740
730
 
741
- const wasmBuffer = useWASI
742
- ? fs.readFileSync(path.join(__dirname, './target/wasm32-wasi/release/binding.wasm'))
743
- : fs.readFileSync(path.join(__dirname, './target/wasm32-unknown-unknown/release/binding.wasm'))
744
-
745
- instantiateNapiModule(wasmBuffer, {
746
- context: require('@emnapi/runtime').getDefaultContext(),
747
- wasi,
748
- beforeInit ({ instance }) {
749
- for (const sym in instance.exports) {
750
- if (sym.startsWith('__napi_register__')) {
751
- instance.exports[sym]()
752
- }
753
- }
754
- },
755
- overwriteImports (importObject) {
756
- importObject.env = {
757
- ...importObject.env,
758
- ...importObject.napi,
759
- ...importObject.emnapi
760
- }
761
- }
762
- }).then(({ napiModule }) => {
763
- const binding = napiModule.exports
764
- // output: 5
765
- console.log(binding.fibonacci(5))
766
- })
731
+ set GYP_CROSSCOMPILE=1
732
+
733
+ @REM emscripten
734
+ call set AR_target=%%EMSDK:\=/%%/upstream/emscripten/emar.bat
735
+ call set CC_target=%%EMSDK:\=/%%/upstream/emscripten/emcc.bat
736
+ call set CXX_target=%%EMSDK:\=/%%/upstream/emscripten/em++.bat
737
+
738
+ @REM wasi-sdk
739
+ call set AR_target=%%WASI_SDK_PATH:\=/%%/bin/ar.exe
740
+ call set CC_target=%%WASI_SDK_PATH:\=/%%/bin/clang.exe
741
+ call set CXX_target=%%WASI_SDK_PATH:\=/%%/bin/clang++.exe
767
742
  ```
768
743
 
769
- </details>
744
+ - Build
745
+
746
+ ```bash
747
+ # Linux or macOS
748
+
749
+ # emscripten
750
+ emmake node-gyp rebuild \
751
+ --arch=wasm32 \
752
+ --nodedir=./node_modules/emnapi \
753
+ -- -f make-linux -DOS=emscripten # -Dwasm_threads=1
754
+
755
+ # wasi
756
+ node-gyp rebuild \
757
+ --arch=wasm32 \
758
+ --nodedir=./node_modules/emnapi \
759
+ -- -f make-linux -DOS=wasi # -Dwasm_threads=1
760
+
761
+ # bare wasm32
762
+ node-gyp rebuild \
763
+ --arch=wasm32 \
764
+ --nodedir=./node_modules/emnapi \
765
+ -- -f make-linux -DOS=unknown # -Dwasm_threads=1
766
+ ```
767
+
768
+ ```bat
769
+ @REM Use make generator on Windows
770
+ @REM Run the bat file in POSIX-like environment (e.g. Cygwin)
771
+
772
+ @REM emscripten
773
+ call npx.cmd node-gyp configure --arch=wasm32 --nodedir=./node_modules/emnapi -- -f make-linux -DOS=emscripten
774
+ call emmake.bat make -C %~dp0build
775
+
776
+ @REM wasi
777
+ call npx.cmd node-gyp configure --arch=wasm32 --nodedir=./node_modules/emnapi -- -f make-linux -DOS=wasi
778
+ make -C %~dp0build
779
+
780
+ @REM bare wasm32
781
+ call npx.cmd node-gyp configure --arch=wasm32 --nodedir=./node_modules/emnapi -- -f make-linux -DOS=unknown
782
+ make -C %~dp0build
783
+ ```
784
+
785
+ ### Using Rust
786
+
787
+ See [napi-rs](https://github.com/napi-rs/napi-rs)
770
788
 
771
789
  ### Multithread
772
790
 
@@ -846,7 +864,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
846
864
  "-sDEFAULT_PTHREAD_STACK_SIZE=2MB"
847
865
  )
848
866
  elseif(CMAKE_C_COMPILER_TARGET STREQUAL "wasm32-wasi-threads")
849
- # Experimental
850
867
  target_link_libraries(hello emnapi-mt)
851
868
  set_target_properties(hello PROPERTIES SUFFIX ".wasm")
852
869
  target_compile_options(hello PRIVATE "-fno-exceptions" "-pthread")
@@ -887,7 +904,7 @@ emcmake cmake -DCMAKE_BUILD_TYPE=Release \
887
904
  -DEMNAPI_WORKER_POOL_SIZE=4 \
888
905
  -G Ninja -H. -Bbuild
889
906
 
890
- # wasi-sdk with thread support (Experimental)
907
+ # wasi-sdk with thread support
891
908
  cmake -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk-pthread.cmake \
892
909
  -DWASI_SDK_PREFIX=$WASI_SDK_PATH \
893
910
  -DEMNAPI_FIND_NODE_ADDON_API=ON \
@@ -16,7 +16,7 @@ endif()
16
16
 
17
17
  set(CMAKE_C_COMPILER ${LLVM_PREFIX}/bin/clang${WASM_HOST_EXE_SUFFIX})
18
18
  set(CMAKE_CXX_COMPILER ${LLVM_PREFIX}/bin/clang++${WASM_HOST_EXE_SUFFIX})
19
- set(CMAKE_ASM_COMPILER ${LLVM_PREFIX}/bin/clang${WASI_HOST_EXE_SUFFIX})
19
+ set(CMAKE_ASM_COMPILER ${LLVM_PREFIX}/bin/clang${WASM_HOST_EXE_SUFFIX})
20
20
  set(CMAKE_AR ${LLVM_PREFIX}/bin/llvm-ar${WASM_HOST_EXE_SUFFIX})
21
21
  set(CMAKE_RANLIB ${LLVM_PREFIX}/bin/llvm-ranlib${WASM_HOST_EXE_SUFFIX})
22
22
  set(CMAKE_C_COMPILER_TARGET ${triple})