{"_id":"napi-wasm","_rev":"4325515","name":"napi-wasm","description":"An implementation of napi for wasm","dist-tags":{"latest":"1.1.3"},"maintainers":[{"name":"devongovett","email":"devongovett@gmail.com"}],"time":{"modified":"2026-04-07T22:47:38.000Z","created":"2022-12-29T11:11:51.435Z","1.1.3":"2024-08-31T20:35:48.115Z","1.1.2":"2024-08-31T20:31:30.505Z","1.1.1":"2024-08-31T20:23:37.448Z","1.1.0":"2023-07-24T03:26:48.316Z","1.0.1":"2022-12-29T17:30:03.960Z","0.0.1-security":"2022-12-29T11:11:51.435Z"},"users":{},"author":{"name":"Devon Govett","email":"devongovett@gmail.com"},"repository":{"type":"git","url":"git+https://github.com/devongovett/napi-wasm.git"},"versions":{"1.1.3":{"name":"napi-wasm","version":"1.1.3","description":"An implementation of napi for wasm","main":"index.mjs","exports":{"import":"./index.mjs","require":"./index.js"},"scripts":{"prepublishOnly":"sed 's/^export //g' index.mjs > index.js && echo '\nexports.Environment = Environment;\nexports.napi = napi;' >> index.js"},"repository":{"type":"git","url":"git+https://github.com/devongovett/napi-wasm.git"},"keywords":["napi","wasm","node-api","rust"],"author":{"name":"Devon Govett","email":"devongovett@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/devongovett/napi-wasm/issues"},"homepage":"https://github.com/devongovett/napi-wasm#readme","_id":"napi-wasm@1.1.3","gitHead":"bbde4dc54b23d56889e4ca8a23704424df7ae05e","_nodeVersion":"20.9.0","_npmVersion":"10.4.0","dist":{"shasum":"7bb95c88e6561f84880bb67195437b1cfbe99224","size":15943,"noattachment":false,"key":"/napi-wasm/-/napi-wasm-1.1.3.tgz","tarball":"http://registry.cnpm.dingdandao.com/napi-wasm/download/napi-wasm-1.1.3.tgz"},"_npmUser":{"name":"devongovett","email":"devongovett@gmail.com"},"directories":{},"maintainers":[{"name":"devongovett","email":"devongovett@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/napi-wasm_1.1.3_1725136547912_0.26219257982901834"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2024-08-31T20:35:48.115Z","publish_time":1725136548115,"_source_registry_name":"default","_cnpm_publish_time":1725136548115},"1.1.2":{"name":"napi-wasm","version":"1.1.2","description":"An implementation of napi for wasm","main":"index.mjs","exports":{"import":"./index.mjs","require":"./index.js"},"scripts":{"prepublishOnly":"sed 's/^export //g' index.mjs > index.js && echo '\nexports.Environment = Environment;\nexports.napi = napi;' >> index.js"},"repository":{"type":"git","url":"git+https://github.com/devongovett/napi-wasm.git"},"keywords":["napi","wasm","node-api","rust"],"author":{"name":"Devon Govett","email":"devongovett@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/devongovett/napi-wasm/issues"},"homepage":"https://github.com/devongovett/napi-wasm#readme","_id":"napi-wasm@1.1.2","gitHead":"2ade9ac8a6d93d5d89fe7273bee49c2ad171fe04","_nodeVersion":"20.9.0","_npmVersion":"10.4.0","dist":{"shasum":"d05a85222499c49e56d953e40b868110ebc294b1","size":15675,"noattachment":false,"key":"/napi-wasm/-/napi-wasm-1.1.2.tgz","tarball":"http://registry.cnpm.dingdandao.com/napi-wasm/download/napi-wasm-1.1.2.tgz"},"_npmUser":{"name":"devongovett","email":"devongovett@gmail.com"},"directories":{},"maintainers":[{"name":"devongovett","email":"devongovett@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/napi-wasm_1.1.2_1725136290335_0.3496736054881897"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2024-08-31T20:31:30.505Z","publish_time":1725136290505,"_source_registry_name":"default","_cnpm_publish_time":1725136290505},"1.1.1":{"name":"napi-wasm","version":"1.1.1","description":"An implementation of napi for wasm","main":"index.mjs","exports":{"import":"./index.mjs","require":"./index.js"},"scripts":{"prepublishOnly":"sed 's/^export //g' index.mjs > index.js && echo '\nexports.Environment = Environment;\nexports.napi = napi;' >> index.js"},"repository":{"type":"git","url":"git+https://github.com/devongovett/napi-wasm.git"},"keywords":["napi","wasm","node-api","rust"],"author":{"name":"Devon Govett","email":"devongovett@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/devongovett/napi-wasm/issues"},"homepage":"https://github.com/devongovett/napi-wasm#readme","_id":"napi-wasm@1.1.1","gitHead":"9b78e4cfb77018099a06ba48da50f701d02b86a8","_nodeVersion":"20.9.0","_npmVersion":"10.4.0","dist":{"shasum":"668e06561bb058e6b11e6ae367811f503cb4bf50","size":15655,"noattachment":false,"key":"/napi-wasm/-/napi-wasm-1.1.1.tgz","tarball":"http://registry.cnpm.dingdandao.com/napi-wasm/download/napi-wasm-1.1.1.tgz"},"_npmUser":{"name":"devongovett","email":"devongovett@gmail.com"},"directories":{},"maintainers":[{"name":"devongovett","email":"devongovett@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/napi-wasm_1.1.1_1725135817279_0.9732817017549575"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2024-08-31T20:23:37.448Z","publish_time":1725135817448,"_source_registry_name":"default","_cnpm_publish_time":1725135817448},"1.1.0":{"name":"napi-wasm","version":"1.1.0","description":"An implementation of napi for wasm","main":"index.mjs","exports":{"import":"./index.mjs","require":"./index.js"},"scripts":{"prepublishOnly":"sed 's/^export //g' index.mjs > index.js && echo '\nexports.Environment = Environment;\nexports.napi = napi;' >> index.js"},"repository":{"type":"git","url":"git+https://github.com/devongovett/napi-wasm.git"},"keywords":["napi","wasm","node-api","rust"],"author":{"name":"Devon Govett","email":"devongovett@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/devongovett/napi-wasm/issues"},"homepage":"https://github.com/devongovett/napi-wasm#readme","gitHead":"e596b7a8e37f72fe2340e37d520183fc65afe3a2","_id":"napi-wasm@1.1.0","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"shasum":"bbe617823765ae9c1bc12ff5942370eae7b2ba4e","size":15549,"noattachment":false,"key":"/napi-wasm/-/napi-wasm-1.1.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/napi-wasm/download/napi-wasm-1.1.0.tgz"},"_npmUser":{"name":"devongovett","email":"devongovett@gmail.com"},"directories":{},"maintainers":[{"name":"devongovett","email":"devongovett@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/napi-wasm_1.1.0_1690169208162_0.007470240092879665"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2023-07-24T03:26:48.316Z","publish_time":1690169208316,"_source_registry_name":"default","_cnpm_publish_time":1690169208316},"1.0.1":{"name":"napi-wasm","version":"1.0.1","description":"An implementation of napi for wasm","main":"index.mjs","exports":{"import":"./index.mjs","require":"./index.js"},"scripts":{"prepublishOnly":"sed 's/^export //g' index.mjs > index.js && echo '\nexports.Environment = Environment;\nexports.napi = napi;' >> index.js"},"repository":{"type":"git","url":"git+https://github.com/devongovett/napi-wasm.git"},"keywords":["napi","wasm","node-api","rust"],"author":{"name":"Devon Govett","email":"devongovett@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/devongovett/napi-wasm/issues"},"homepage":"https://github.com/devongovett/napi-wasm#readme","gitHead":"ee05fa723927b8f58b3dd5b79ff0c83513d0e544","_id":"napi-wasm@1.0.1","_nodeVersion":"16.15.0","_npmVersion":"8.5.5","dist":{"shasum":"b186b9f9f1a54c321c4a1ea852a31a9691792a24","size":14913,"noattachment":false,"key":"/napi-wasm/-/napi-wasm-1.0.1.tgz","tarball":"http://registry.cnpm.dingdandao.com/napi-wasm/download/napi-wasm-1.0.1.tgz"},"_npmUser":{"name":"devongovett","email":"devongovett@gmail.com"},"directories":{},"maintainers":[{"name":"devongovett","email":"devongovett@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/napi-wasm_1.0.1_1672335003760_0.3493354522604426"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2022-12-29T17:30:09.263Z","publish_time":1672335003960,"_cnpm_publish_time":1672335003960},"0.0.1-security":{"name":"napi-wasm","version":"0.0.1-security","description":"security holding package","repository":{"type":"git","url":"git+https://github.com/npm/security-holder.git"},"bugs":{"url":"https://github.com/npm/security-holder/issues"},"homepage":"https://github.com/npm/security-holder#readme","_id":"napi-wasm@0.0.1-security","_nodeVersion":"12.19.0","_npmVersion":"8.19.1","dist":{"shasum":"42b9edac076f5e73adb0338208fb1a776b1037eb","size":419,"noattachment":false,"key":"/napi-wasm/-/napi-wasm-0.0.1-security.tgz","tarball":"http://registry.cnpm.dingdandao.com/napi-wasm/download/napi-wasm-0.0.1-security.tgz"},"_npmUser":{"name":"lisayu","email":"lisa@npmjs.com"},"directories":{},"maintainers":[{"name":"devongovett","email":"devongovett@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/napi-wasm_0.0.1-security_1672312311299_0.9159403851987413"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2022-12-29T11:11:54.422Z","publish_time":1672312311435,"_cnpm_publish_time":1672312311435}},"readme":"# napi-wasm\n\nAn implementation of the [napi](https://nodejs.org/api/n-api.html) API for WASM. Enables using some native Node modules in browsers and other environments.\n\n## Setup\n\nTo use napi-wasm, there are a few requirements:\n\n1. Configure your linker to export an indirect function table. With ldd, this is the `--export-table` flag. This enables JavaScript to call callback functions registered by WASM. It is exposed in the WebAssembly exports as `__indirect_function_table`.\n2. Export a function from your WASM build named `napi_register_module_v1` (Node's default), or `napi_register_wasm_v1` for WASM-specific builds. This is called during initialization to setup the `exports` object for your module. It receives an environment and an exports object pointer as arguments, which you can add properties to.\n3. Include a function named `napi_wasm_malloc` in your WASM build. This is called from JavaScript by napi-wasm to allocate memory in the WASM heap. It should accept a `uint32` size argument indicating the number of bytes to allocate, and return a `uint8` pointer to allocated memory.\n4. Compile for the `wasm32-unknown-unknown` target.\n\n### In Rust\n\nThe above steps should apply for any programming language, but here's an example in Rust. First, define a `napi_wasm_malloc` function so JavaScript can allocate memory in the WASM heap using the default allocator.\n\n```rust\nuse std::alloc::{alloc, Layout};\n\n#[no_mangle]\npub extern \"C\" fn napi_wasm_malloc(size: usize) -> *mut u8 {\n  let align = std::mem::align_of::<usize>();\n  if let Ok(layout) = Layout::from_size_align(size, align) {\n    unsafe {\n      if layout.size() > 0 {\n        let ptr = alloc(layout);\n        if !ptr.is_null() {\n          return ptr;\n        }\n      } else {\n        return align as *mut u8;\n      }\n    }\n  }\n\n  std::process::abort();\n}\n```\n\nNext, implement `napi_register_wasm_v1` to register your module exports. We'll use the [napi-rs](https://github.com/napi-rs/napi-rs) bindings in this example to make it a bit nicer than calling C APIs directly. Note that the napi-rs `#[module_exports]` macro currently doesn't work in WASM because Rust doesn't support ctor setup functions in WASM targets yet, so we'll need to do this manually.\n\n```rust\nuse napi::{Env, JsObject, NapiValue};\n\n#[no_mangle]\npub unsafe extern \"C\" fn napi_register_wasm_v1(raw_env: napi::sys::napi_env, raw_exports: napi::sys::napi_value) {\n  let env = Env::from_raw(raw_env);\n  let exports = JsObject::from_raw_unchecked(raw_env, raw_exports);\n\n  exports.create_named_method(\"transform\", transform);\n}\n\n#[js_function(1)]\nfn transform(ctx: CallContext) -> napi::Result<JsUnknown> {\n  // ...\n}\n```\n\nTo compile, you need to export a function table and use the correct target.\n\n```shell\n RUSTFLAGS=\"-C link-arg=--export-table\" cargo build --target wasm32-unknown-unknown\n```\n\nThis will output a file in `target/wasm32-unknown-unknown/debug/YOUR_CRATE.wasm` which you can load in a JavaScript environment.\n\nYou can also put the rust flags in a `.cargo/config.toml` file so you don't need to provide the environment variable each time you run `cargo build`.\n\n```toml\n[target.wasm32-unknown-unknown]\nrustflags = [\"-C\", \"link-arg=--export-table\"]\n```\n\n### Loading\n\nTo load a WASM file and initialize a napi environment, you'll need to import the `napi-wasm` package. You instantiate a WASM module as usual, providing `napi` as the `env` import key. This provides the napi functions for your WASM module to use.\n\nThen, pass the WASM instance to the `Environment` constructor to setup a napi environment. This will call `napi_register_wasm_v1` or `napi_register_module_v1` to setup the exports object. Then you can call functions on the exports object as you would in Node.\n\n```js\nimport { Environment, napi } from 'napi-wasm';\n\n// Construct a URL and instantiate a WebAssembly module as usual.\nconst url = new URL('path/to/lib.wasm', import.meta.url);\nconst { instance } = await WebAssembly.instantiateStreaming(fetch(url), {\n  env: napi\n});\n\n// Create an environment.\nlet env = new Environment(instance);\nlet exports = env.exports;\n\n// Use exports as usual!\nexports.transform({\n  // ...\n});\n```\n\nWhen you are done with an `Environment`, call the `destroy()` function to clean up memory.\n","_attachments":{},"homepage":"https://github.com/devongovett/napi-wasm#readme","bugs":{"url":"https://github.com/devongovett/napi-wasm/issues"},"license":"MIT"}