Gathering detailed insights and metrics for @emnapi/wasi-threads
Gathering detailed insights and metrics for @emnapi/wasi-threads
Gathering detailed insights and metrics for @emnapi/wasi-threads
Gathering detailed insights and metrics for @emnapi/wasi-threads
Node-API implementation for Emscripten, wasi-sdk, clang wasm32 and napi-rs
npm install @emnapi/wasi-threads
Typescript
Module System
Node Version
NPM Version
99.8
Supply Chain
100
Quality
84.1
Maintenance
100
Vulnerability
100
License
C (42.27%)
TypeScript (25.99%)
JavaScript (18.41%)
C++ (9.46%)
CMake (1.79%)
Python (1.12%)
HTML (0.85%)
Rust (0.08%)
Assembly (0.03%)
Total Downloads
117,488,312
Last Day
508,859
Last Week
7,866,201
Last Month
30,222,261
Last Year
117,441,713
MIT License
198 Stars
1,017 Commits
7 Forks
9 Branches
5 Contributors
Updated on Jul 08, 2025
Minified
Minified + Gzipped
Latest Version
1.0.3
Package Id
@emnapi/wasi-threads@1.0.3
Unpacked Size
214.90 kB
Size
37.37 kB
File Count
15
NPM Version
10.1.0
Node Version
20.9.0
Published on
Jul 07, 2025
Cumulative downloads
Total Downloads
Last Day
6.3%
508,859
Compared to previous day
Last Week
-1.9%
7,866,201
Compared to previous week
Last Month
28.3%
30,222,261
Compared to previous month
Last Year
251,926.3%
117,441,713
Compared to previous year
1
This package makes wasi-threads proposal based WASI modules work in Node.js and browser.
index.html
1<script src="./node_modules/@tybys/wasm-util/dist/wasm-util.js"></script> 2<script src="./node_modules/@emnapi/wasi-threads/dist/wasi-threads.js"></script> 3<script src="./index.js"></script>
If your application will block browser main thread (for example pthread_join
), please run it in worker instead.
1<script> 2 // pthread_join (Atomics.wait) cannot be called in browser main thread 3 new Worker('./index.js') 4</script>
index.js
1const ENVIRONMENT_IS_NODE = 2 typeof process === 'object' && process !== null && 3 typeof process.versions === 'object' && process.versions !== null && 4 typeof process.versions.node === 'string'; 5 6(function (main) { 7 if (ENVIRONMENT_IS_NODE) { 8 main(require) 9 } else { 10 if (typeof importScripts === 'function') { 11 importScripts('./node_modules/@tybys/wasm-util/dist/wasm-util.js') 12 importScripts('./node_modules/@emnapi/wasi-threads/dist/wasi-threads.js') 13 } 14 const nodeWasi = { WASI: globalThis.wasmUtil.WASI } 15 const nodeWorkerThreads = { 16 Worker: globalThis.Worker 17 } 18 const _require = function (request) { 19 if (request === 'node:wasi' || request === 'wasi') return nodeWasi 20 if (request === 'node:worker_threads' || request === 'worker_threads') return nodeWorkerThreads 21 if (request === '@emnapi/wasi-threads') return globalThis.wasiThreads 22 throw new Error('Can not find module: ' + request) 23 } 24 main(_require) 25 } 26})(async function (require) { 27 const { WASI } = require('wasi') 28 const { Worker } = require('worker_threads') 29 const { WASIThreads } = require('@emnapi/wasi-threads') 30 31 const wasi = new WASI({ 32 version: 'preview1' 33 }) 34 const wasiThreads = new WASIThreads({ 35 wasi, 36 37 /** 38 * avoid Atomics.wait() deadlock during thread creation in browser 39 * see https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size 40 */ 41 reuseWorker: ENVIRONMENT_IS_NODE 42 ? false 43 : { 44 size: 4 /** greater than actual needs (2) */, 45 strict: true 46 }, 47 48 /** 49 * Synchronous thread creation 50 * pthread_create will not return until thread worker actually starts 51 */ 52 waitThreadStart: typeof window === 'undefined' ? 1000 : false, 53 54 onCreateWorker: () => { 55 return new Worker('./worker.js', { 56 execArgv: ['--experimental-wasi-unstable-preview1'] 57 }) 58 } 59 }) 60 const memory = new WebAssembly.Memory({ 61 initial: 16777216 / 65536, 62 maximum: 2147483648 / 65536, 63 shared: true 64 }) 65 let input 66 const file = 'path/to/your/wasi-module.wasm' 67 try { 68 input = require('fs').readFileSync(require('path').join(__dirname, file)) 69 } catch (err) { 70 const response = await fetch(file) 71 input = await response.arrayBuffer() 72 } 73 let { module, instance } = await WebAssembly.instantiate(input, { 74 env: { memory }, 75 wasi_snapshot_preview1: wasi.wasiImport, 76 ...wasiThreads.getImportObject() 77 }) 78 79 wasiThreads.setup(instance, module, memory) 80 await wasiThreads.preloadWorkers() 81 82 if (typeof instance.exports._start === 'function') { 83 return wasi.start(instance) 84 } else { 85 wasi.initialize(instance) 86 // instance.exports.exported_wasm_function() 87 } 88})
worker.js
1(function (main) { 2 const ENVIRONMENT_IS_NODE = 3 typeof process === 'object' && process !== null && 4 typeof process.versions === 'object' && process.versions !== null && 5 typeof process.versions.node === 'string' 6 7 if (ENVIRONMENT_IS_NODE) { 8 const _require = function (request) { 9 return require(request) 10 } 11 12 const _init = function () { 13 const nodeWorkerThreads = require('worker_threads') 14 const parentPort = nodeWorkerThreads.parentPort 15 16 parentPort.on('message', (data) => { 17 globalThis.onmessage({ data }) 18 }) 19 20 Object.assign(globalThis, { 21 self: globalThis, 22 require, 23 Worker: nodeWorkerThreads.Worker, 24 importScripts: function (f) { 25 (0, eval)(require('fs').readFileSync(f, 'utf8') + '//# sourceURL=' + f) 26 }, 27 postMessage: function (msg) { 28 parentPort.postMessage(msg) 29 } 30 }) 31 } 32 33 main(_require, _init) 34 } else { 35 importScripts('./node_modules/@tybys/wasm-util/dist/wasm-util.js') 36 importScripts('./node_modules/@emnapi/wasi-threads/dist/wasi-threads.js') 37 38 const nodeWasi = { WASI: globalThis.wasmUtil.WASI } 39 const _require = function (request) { 40 if (request === '@emnapi/wasi-threads') return globalThis.wasiThreads 41 if (request === 'node:wasi' || request === 'wasi') return nodeWasi 42 throw new Error('Can not find module: ' + request) 43 } 44 const _init = function () {} 45 main(_require, _init) 46 } 47})(function main (require, init) { 48 init() 49 50 const { WASI } = require('wasi') 51 const { ThreadMessageHandler, WASIThreads } = require('@emnapi/wasi-threads') 52 53 const handler = new ThreadMessageHandler({ 54 async onLoad ({ wasmModule, wasmMemory }) { 55 const wasi = new WASI({ 56 version: 'preview1' 57 }) 58 59 const wasiThreads = new WASIThreads({ 60 wasi, 61 childThread: true 62 }) 63 64 const originalInstance = await WebAssembly.instantiate(wasmModule, { 65 env: { 66 memory: wasmMemory, 67 }, 68 wasi_snapshot_preview1: wasi.wasiImport, 69 ...wasiThreads.getImportObject() 70 }) 71 72 // must call `initialize` instead of `start` in child thread 73 const instance = wasiThreads.initialize(originalInstance, wasmModule, wasmMemory) 74 75 return { module: wasmModule, instance } 76 } 77 }) 78 79 globalThis.onmessage = function (e) { 80 handler.handle(e) 81 // handle other messages 82 } 83})
No vulnerabilities found.
Reason
10 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
0 existing vulnerabilities detected
Reason
packaging workflow detected
Details
Reason
Found 1/18 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
security policy file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
Project has not signed or included provenance with any releases.
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-06-30
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More