emnapi 0.35.0 → 0.36.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/README.md CHANGED
@@ -164,7 +164,7 @@ emcc -O3 \
164
164
  -I./node_modules/emnapi/include \
165
165
  -L./node_modules/emnapi/lib/wasm32-emscripten \
166
166
  --js-library=./node_modules/emnapi/dist/library_napi.js \
167
- -sEXPORTED_FUNCTIONS="['_malloc','_free']" \
167
+ -sEXPORTED_FUNCTIONS="['_napi_register_wasm_v1','_malloc','_free']" \
168
168
  -o hello.js \
169
169
  hello.c \
170
170
  -lemnapi
@@ -385,7 +385,7 @@ import { WASI } from '@tybys/wasm-util'
385
385
  import { Volume, createFsFromVolume } from 'memfs-browser'
386
386
 
387
387
  const fs = createFsFromVolume(Volume.fromJSON({ /* ... */ }))
388
- return instantiateNapiModule(fetch('./hello.wasm'), {
388
+ instantiateNapiModule(fetch('./hello.wasm'), {
389
389
  wasi: new WASI({ fs, /* ... */ })
390
390
  context: getDefaultContext(),
391
391
  overwriteImports (importObject) {
@@ -443,7 +443,7 @@ em++ -O3 \
443
443
  -I./node_modules/emnapi/include \
444
444
  -L./node_modules/emnapi/lib/wasm32-emscripten \
445
445
  --js-library=./node_modules/emnapi/dist/library_napi.js \
446
- -sEXPORTED_FUNCTIONS="['_malloc','_free']" \
446
+ -sEXPORTED_FUNCTIONS="['_napi_register_wasm_v1','_malloc','_free']" \
447
447
  -o hello.js \
448
448
  hello.cpp \
449
449
  -lemnapi
@@ -541,7 +541,7 @@ add_executable(hello hello.c)
541
541
  target_link_libraries(hello emnapi)
542
542
  if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
543
543
  target_link_options(hello PRIVATE
544
- "-sEXPORTED_FUNCTIONS=['_malloc','_free']"
544
+ "-sEXPORTED_FUNCTIONS=['_napi_register_wasm_v1','_malloc','_free']"
545
545
  )
546
546
  elseif(CMAKE_SYSTEM_NAME STREQUAL "WASI")
547
547
  set_target_properties(hello PROPERTIES SUFFIX ".wasm")
@@ -616,9 +616,9 @@ path = "src/main.rs"
616
616
  # crate-type = ["cdylib"]
617
617
 
618
618
  [dependencies]
619
- napi = { version = "2.10.13", default-features = false, features = ["napi8", "compat-mode"] }
619
+ napi = { version = "2.12.1", default-features = false, features = ["napi8"] }
620
620
  napi-sys = { version = "2.2.3", features = ["napi8"] }
621
- napi-derive = "2.10.0"
621
+ napi-derive = "2.12.2"
622
622
 
623
623
  [build-dependencies]
624
624
  napi-build = "2.0.1"
@@ -678,47 +678,61 @@ rustflags = [
678
678
  ```rust
679
679
  #![no_main]
680
680
 
681
- use napi::*;
681
+ use napi_derive::napi;
682
682
 
683
- #[cfg(target_arch = "wasm32")]
684
- use napi::bindgen_prelude::*;
685
- #[cfg(target_arch = "wasm32")]
686
- use napi_sys::*;
687
-
688
- #[macro_use]
689
- extern crate napi_derive;
690
-
691
- fn sum(a: i32, b: i32) -> i32 {
692
- a + b
683
+ #[napi]
684
+ fn fibonacci(n: u32) -> u32 {
685
+ match n {
686
+ 1 | 2 => 1,
687
+ _ => fibonacci(n - 1) + fibonacci(n - 2),
688
+ }
693
689
  }
690
+ ```
694
691
 
695
- #[js_function(2)]
696
- fn sum_js(ctx: CallContext) -> napi::Result<napi::JsNumber> {
697
- let arg0 = ctx.get::<napi::JsNumber>(0)?.get_int32()?;
698
- let arg1 = ctx.get::<napi::JsNumber>(1)?.get_int32()?;
699
- let ret = sum(arg0, arg1);
700
- ctx.env.create_int32(ret)
701
- }
692
+ </details>
693
+
694
+ <details>
695
+ <summary>index.js</summary><br />
702
696
 
703
- fn module_register(_env: napi::Env, mut exports: napi::JsObject) -> napi::Result<()> {
704
- exports.create_named_method("sum", sum_js)?;
697
+ ```js
698
+ const fs = require('fs')
699
+ const path = require('path')
700
+ const useWASI = false
705
701
 
706
- Ok(())
702
+ let wasi
703
+ if (useWASI) {
704
+ const { WASI } = require('wasi')
705
+ wasi = new WASI({ /* ... */ })
707
706
  }
708
707
 
709
- #[cfg(not(target_arch = "wasm32"))]
710
- #[module_exports]
711
- fn init(exports: napi::JsObject, env: napi::Env) -> napi::Result<()> {
712
- module_register(env, exports)
713
- }
708
+ const { instantiateNapiModule } = require('@emnapi/core')
714
709
 
715
- #[cfg(target_arch = "wasm32")]
716
- #[no_mangle]
717
- pub unsafe extern "C" fn napi_register_wasm_v1(env: napi_env, exports: napi_value) -> () {
718
- let env_object = napi::Env::from_raw(env);
719
- let exports_object = napi::JsObject::from_napi_value(env, exports).unwrap();
720
- module_register(env_object, exports_object).unwrap();
721
- }
710
+ const wasmBuffer = useWASI
711
+ ? fs.readFileSync(path.join(__dirname, './target/wasm32-wasi/release/binding.wasm'))
712
+ : fs.readFileSync(path.join(__dirname, './target/wasm32-unknown-unknown/release/binding.wasm'))
713
+
714
+ instantiateNapiModule(wasmBuffer, {
715
+ context: require('@emnapi/runtime').getDefaultContext(),
716
+ wasi,
717
+ beforeInit ({ instance }) {
718
+ for (const sym in instance.exports) {
719
+ if (sym.startsWith('__napi_register__')) {
720
+ instance.exports[sym]()
721
+ }
722
+ }
723
+ },
724
+ overwriteImports (importObject) {
725
+ importObject.env = {
726
+ ...importObject.env,
727
+ ...importObject.napi,
728
+ ...importObject.emnapi
729
+ }
730
+ }
731
+ }).then(({ instance, napiModule }) => {
732
+ const binding = napiModule.exports
733
+ // output: 5
734
+ console.log(binding.fibonacci(5))
735
+ })
722
736
  ```
723
737
 
724
738
  </details>
@@ -747,7 +761,7 @@ Now emnapi has 3 implementations of async work and 2 implementations of TSFN:
747
761
  | B | libemnapi-basic(-mt).a | ✅ | ✅ | ✅ | ✅ |
748
762
  | C | libemnapi-basic-mt.a | ❌ | ✅ | ❌ | ✅ |
749
763
  | D | libemnapi-mt.a | ✅ | ❌ | ❌ | ✅ |
750
- | E | libemnapi-basic-mt.a | ✅ | ✅ | ✅ | ✅ |
764
+ | E | libemnapi-basic(-mt).a | ✅ | ✅ | ✅ | ✅ |
751
765
 
752
766
  There are some limitations on browser about wasi-libc's pthread implementation, for example
753
767
  `pthread_mutex_lock` may call `__builtin_wasm_memory_atomic_wait32`(`memory.atomic.wait32`)
@@ -755,6 +769,15 @@ which is disallowed in browser JS main thread. While Emscripten's pthread implem
755
769
  has considered usage in browser. If you need to run your addon with multithreaded features on browser,
756
770
  we recommend you use Emscripten A & D, or bare wasm32 C & E.
757
771
 
772
+ Note: For browsers, all the multithreaded features relying on Web Workers (Emscripten pthread also relying on Web Workers)
773
+ require cross-origin isolation to enable `SharedArrayBuffer`. You can make a page cross-origin isolated
774
+ by serving the page with these headers:
775
+
776
+ ```
777
+ Cross-Origin-Embedder-Policy: require-corp
778
+ Cross-Origin-Opener-Policy: same-origin
779
+ ```
780
+
758
781
  #### About Prebuilt Libraries
759
782
 
760
783
  Prebuilt libraries can be found in the `lib` directory in `emnapi` npm package.
@@ -782,7 +805,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
782
805
  target_compile_options(hello PRIVATE "-pthread")
783
806
  target_link_options(hello PRIVATE
784
807
  "-sALLOW_MEMORY_GROWTH=1"
785
- "-sEXPORTED_FUNCTIONS=['_malloc','_free']"
808
+ "-sEXPORTED_FUNCTIONS=['_napi_register_wasm_v1','_malloc','_free']"
786
809
  "-pthread"
787
810
  "-sPTHREAD_POOL_SIZE=4"
788
811
  # try to specify stack size if you experience pthread errors
@@ -832,7 +855,7 @@ cmake -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk-pthread.cmake \
832
855
  -G Ninja -H. -Bbuild
833
856
 
834
857
  cmake -DCMAKE_TOOLCHAIN_FILE=node_modules/emnapi/cmake/wasm32.cmake \
835
- -DWASI_SDK_PREFIX=$WASI_SDK_PATH \
858
+ -DLLVM_PREFIX=$WASI_SDK_PATH \
836
859
  -DCMAKE_BUILD_TYPE=Release \
837
860
  -G Ninja -H. -Bbuild
838
861
 
@@ -16,10 +16,12 @@ 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
20
  set(CMAKE_AR ${LLVM_PREFIX}/bin/llvm-ar${WASM_HOST_EXE_SUFFIX})
20
21
  set(CMAKE_RANLIB ${LLVM_PREFIX}/bin/llvm-ranlib${WASM_HOST_EXE_SUFFIX})
21
22
  set(CMAKE_C_COMPILER_TARGET ${triple})
22
23
  set(CMAKE_CXX_COMPILER_TARGET ${triple})
24
+ set(CMAKE_ASM_COMPILER_TARGET ${triple})
23
25
 
24
26
  # Don't look in the sysroot for executables to run during the build
25
27
  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
@@ -1221,8 +1221,8 @@ function napi_create_reference(env, value, initial_refcount, result) {
1221
1221
  if (result == 0)
1222
1222
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
1223
1223
  var handle = emnapiCtx.handleStore.get(value);
1224
- if (!(handle.isObject() || handle.isFunction())) {
1225
- return envObject.setLastError(2 /* napi_status.napi_object_expected */);
1224
+ if (!(handle.isObject() || handle.isFunction() || handle.isSymbol())) {
1225
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
1226
1226
  }
1227
1227
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1228
1228
  var ref = emnapiCtx.createReference(envObject, handle.id, initial_refcount >>> 0, 1 /* Ownership.kUserland */);
@@ -4680,17 +4680,22 @@ function napi_create_string_latin1(env, str, length, result) {
4680
4680
  if (env == 0)
4681
4681
  return 1 /* napi_status.napi_invalid_arg */;
4682
4682
  var envObject = emnapiCtx.envStore.get(env);
4683
+ {{{ from64('length') }}};
4684
+ var autoLength = length === -1;
4685
+ length = length >>> 0;
4686
+ if (length !== 0) {
4687
+ if (str == 0)
4688
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4689
+ }
4683
4690
  if (result == 0)
4684
4691
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4685
4692
  {{{ from64('str') }}};
4686
- {{{ from64('length') }}};
4687
- length = length >>> 0;
4688
- if (!((length === 0xffffffff) || (length <= 2147483647)) || (!str)) {
4693
+ if (!(autoLength || (length <= 2147483647))) {
4689
4694
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4690
4695
  }
4691
4696
  var latin1String = '';
4692
4697
  var len = 0;
4693
- if (length === -1) {
4698
+ if (autoLength) {
4694
4699
  while (true) {
4695
4700
  var ch = {{{ makeGetValue('str', 0, 'u8') }}};
4696
4701
  if (!ch)
@@ -4719,11 +4724,17 @@ function napi_create_string_utf16(env, str, length, result) {
4719
4724
  if (env == 0)
4720
4725
  return 1 /* napi_status.napi_invalid_arg */;
4721
4726
  var envObject = emnapiCtx.envStore.get(env);
4727
+ {{{ from64('length') }}};
4728
+ var autoLength = length === -1;
4729
+ var sizelength = length >>> 0;
4730
+ if (length !== 0) {
4731
+ if (str == 0)
4732
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4733
+ }
4722
4734
  if (result == 0)
4723
4735
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4724
4736
  {{{ from64('str') }}};
4725
- {{{ from64('length') }}};
4726
- if (((length < -1) || (length > 2147483647)) || (!str)) {
4737
+ if (!(autoLength || (sizelength <= 2147483647))) {
4727
4738
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4728
4739
  }
4729
4740
  var utf16String = emnapiUtf16ToString(str, length);
@@ -4737,11 +4748,17 @@ function napi_create_string_utf8(env, str, length, result) {
4737
4748
  if (env == 0)
4738
4749
  return 1 /* napi_status.napi_invalid_arg */;
4739
4750
  var envObject = emnapiCtx.envStore.get(env);
4751
+ {{{ from64('length') }}};
4752
+ var autoLength = length === -1;
4753
+ var sizelength = length >>> 0;
4754
+ if (length !== 0) {
4755
+ if (str == 0)
4756
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4757
+ }
4740
4758
  if (result == 0)
4741
4759
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4742
4760
  {{{ from64('str') }}};
4743
- {{{ from64('length') }}};
4744
- if (((length < -1) || (length > 2147483647)) || (!str)) {
4761
+ if (!(autoLength || (sizelength <= 2147483647))) {
4745
4762
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4746
4763
  }
4747
4764
  var utf8String = emnapiUtf8ToString(str, length);
@@ -5336,7 +5353,13 @@ function node_api_symbol_for(env, utf8description, length, result) {
5336
5353
  {{{ from64('length') }}};
5337
5354
  {{{ from64('utf8description') }}};
5338
5355
  {{{ from64('result') }}};
5339
- if (((length < -1) || (length > 2147483647)) || (!utf8description)) {
5356
+ var autoLength = length === -1;
5357
+ var sizelength = length >>> 0;
5358
+ if (length !== 0) {
5359
+ if (utf8description == 0)
5360
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
5361
+ }
5362
+ if (!(autoLength || (sizelength <= 2147483647))) {
5340
5363
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
5341
5364
  }
5342
5365
  var descriptionString = emnapiUtf8ToString(utf8description, length);
@@ -5763,6 +5786,8 @@ mergeInto(LibraryManager.library, {
5763
5786
  return UTF8ToString(ptr);
5764
5787
  }
5765
5788
  length = length >>> 0;
5789
+ if (!length)
5790
+ return '';
5766
5791
  return emnapiUtf8Decoder.decode({{{ getUnsharedTextDecoderView('HEAPU8', 'ptr', 'ptr + length') }}});
5767
5792
  },
5768
5793
  $emnapiUtf16leDecoder__postset: 'emnapiUtf16leDecoder();',
@@ -5806,6 +5831,8 @@ mergeInto(LibraryManager.library, {
5806
5831
  return UTF16ToString(ptr);
5807
5832
  }
5808
5833
  length = length >>> 0;
5834
+ if (!length)
5835
+ return '';
5809
5836
  return emnapiUtf16leDecoder.decode({{{ getUnsharedTextDecoderView('HEAPU8', 'ptr', 'ptr + length * 2') }}});
5810
5837
  }
5811
5838
  });
Binary file
@@ -1,5 +1,5 @@
1
- emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.32 (eab98adf462c39f3c31d348331c4830bcaa36949)
2
- clang version 17.0.0 (https://github.com/llvm/llvm-project df82394e7a2d06506718cafa347bf7827c79fc4f)
1
+ emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.34 (57b21b8fdcbe3ebb523178b79465254668eab408)
2
+ clang version 17.0.0 (https://github.com/llvm/llvm-project a031f72187ce495b9faa4ccf99b1e901a3872f4b)
3
3
  Target: wasm32-unknown-emscripten
4
4
  Thread model: posix
5
5
  InstalledDir: /home/runner/work/emnapi/emnapi/emsdk-cache/emsdk-main/upstream/bin
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emnapi",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "Node-API implementation for Emscripten",
5
5
  "main": "index.js",
6
6
  "devDependencies": {
@@ -151,9 +151,25 @@ static void uv__async_io(uv_loop_t* loop) {
151
151
  }
152
152
  }
153
153
 
154
+ #if EMNAPI_USE_PROXYING
155
+
156
+ #undef emscripten_main_browser_thread_id
157
+
158
+ __attribute__((weak))
159
+ pthread_t emscripten_main_browser_thread_id(void) {
160
+ return NULL;
161
+ }
162
+
163
+ __attribute__((weak))
164
+ pthread_t emscripten_main_runtime_thread_id(void) {
165
+ return emscripten_main_browser_thread_id();
166
+ }
167
+ #endif
168
+
154
169
  static void uv__async_send(uv_loop_t* loop) {
155
170
  #if EMNAPI_USE_PROXYING
156
- pthread_t main_thread = emscripten_main_browser_thread_id();
171
+ pthread_t main_thread = emscripten_main_runtime_thread_id();
172
+ assert(main_thread != NULL);
157
173
  if (pthread_equal(main_thread, pthread_self())) {
158
174
  NEXT_TICK((void (*)(void *))uv__async_io, loop);
159
175
  } else {