diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..8515f874 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.'cfg(target_os = "wasi")'] +rustflags = ["-C", "target-feature=+atomics,+bulk-memory"] diff --git a/.eslintignore b/.eslintignore index fab70af3..5fc9f1a8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -14,4 +14,6 @@ target scripts triples/index.js rollup.config.js -crates/cli/index.js \ No newline at end of file +crates/cli/index.js +examples/napi/index.wasi.mjs +examples/napi/wasi-worker.mjs diff --git a/.eslintrc.yml b/.eslintrc.yml index 1803c5fb..2933b970 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -5,7 +5,8 @@ parserOptions: jsx: true ecmaVersion: latest sourceType: module - extraFileExtensions: ['.cjs', '.mjs'] + project: + - ./tsconfig.root-lint.json env: browser: true @@ -23,6 +24,7 @@ extends: globals: BigInt: 'readonly' NodeJS: 'readonly' + globalThis: true rules: # 0 = off, 1 = warn, 2 = error @@ -205,6 +207,15 @@ overrides: project: - ./examples/tsconfig.json rules: + 'import/order': + [ + 2, + { + 'newlines-between': 'always', + 'alphabetize': { 'order': 'asc', 'caseInsensitive': true }, + }, + ] + 'import/no-extraneous-dependencies': 0 - files: @@ -223,6 +234,8 @@ overrides: - files: - ./*.js + - ./*.cjs + - ./*.mjs plugins: - '@typescript-eslint' parserOptions: diff --git a/.github/workflows/test-release.yaml b/.github/workflows/test-release.yaml index a87ac22a..e78bd785 100644 --- a/.github/workflows/test-release.yaml +++ b/.github/workflows/test-release.yaml @@ -63,7 +63,7 @@ jobs: strategy: fail-fast: false matrix: - node: ['16', '18', '20'] + node: ['18', '20'] settings: - host: ubuntu-latest target: x86_64-unknown-linux-gnu @@ -71,7 +71,7 @@ jobs: test: | yarn test:cli yarn test --verbose - yarn tsc -p examples/napi/tsconfig.json --noEmit + yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck yarn test:macro toolchain: stable - host: ubuntu-latest @@ -80,7 +80,7 @@ jobs: test: | yarn test:cli yarn test --verbose - yarn tsc -p examples/napi/tsconfig.json --noEmit + yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck yarn test:macro toolchain: 1.65.0 - host: macos-latest @@ -89,7 +89,7 @@ jobs: test: | yarn test:cli yarn test --verbose - yarn tsc -p examples/napi/tsconfig.json --noEmit + yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck yarn test:macro toolchain: stable - host: windows-latest @@ -98,7 +98,7 @@ jobs: test: | yarn test:cli yarn test --verbose - yarn tsc -p examples/napi/tsconfig.json --noEmit + yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck yarn test:macro toolchain: stable - host: windows-latest @@ -118,9 +118,6 @@ jobs: - settings: toolchain: 1.65.0 node: 20 - - settings: - target: i686-pc-windows-msvc - node: 16 - settings: target: i686-pc-windows-msvc node: 18 @@ -311,7 +308,7 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 18, 20] + node: [18, 20] settings: - image: 'node:{:version}-slim' target: x86_64-unknown-linux-gnu @@ -486,6 +483,42 @@ jobs: - name: Check build run: cargo check -p ${{ matrix.settings.package }} -F ${{ matrix.settings.features }} + test-node-wasi: + runs-on: ubuntu-latest + name: Test node wasi target + timeout-minutes: 10 + continue-on-error: true + steps: + - uses: actions/checkout@v4 + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'yarn' + - name: Install + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + targets: wasm32-wasi-preview1-threads + - name: Cache cargo + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: stable-wasm32-wasi-preview1-threads-node@18-cargo-cache + - name: Install dependencies + run: yarn install --immutable --mode=skip-build + - name: Build + run: | + yarn build + yarn workspace @examples/napi build --target wasm32-wasi-preview1-threads + - name: Test + run: yarn workspace @examples/napi test -s + env: + WASI_TEST: 'true' + test-latest-bun: runs-on: ubuntu-latest name: Test latest bun diff --git a/.github/workflows/zig.yaml b/.github/workflows/zig.yaml index 2a338267..ea192eba 100644 --- a/.github/workflows/zig.yaml +++ b/.github/workflows/zig.yaml @@ -53,7 +53,7 @@ jobs: - name: Install ziglang uses: goto-bus-stop/setup-zig@v2 with: - version: 0.10.1 + version: 0.11.0 - name: Install dependencies run: yarn install --immutable --mode=skip-build - name: install MacOS SDK diff --git a/cli/package.json b/cli/package.json index 3e41309c..bc6077a7 100644 --- a/cli/package.json +++ b/cli/package.json @@ -68,24 +68,48 @@ }, "dependencies": { "@octokit/rest": "^20.0.1", + "@tybys/wasm-util": "0.8.0", "clipanion": "^3.2.1", "colorette": "^2.0.20", "debug": "^4.3.4", + "emnapi": "0.43.1", "inquirer": "^9.2.8", "js-yaml": "^4.1.0", "lodash-es": "^4.17.21", + "toml": "^3.0.0", "typanion": "^3.13.0" }, "devDependencies": { + "@emnapi/core": "0.43.1", + "@emnapi/runtime": "0.43.1", + "@types/debug": "^4.1.7", "@types/inquirer": "^9.0.3", "@types/js-yaml": "^4.0.5", "@types/lodash-es": "^4.17.8", "ava": "^5.3.1", - "esbuild": "^0.19.0", + "env-paths": "^3.0.0", + "esbuild": "^0.19.5", "prettier": "^3.0.0", "ts-node": "^10.9.1", + "tslib": "^2.6.1", "typescript": "^5.1.6" }, + "peerDependencies": { + "@emnapi/runtime": "0.43.1", + "@tybys/wasm-util": "0.8.0", + "emnapi": "0.43.1" + }, + "peerDependenciesMeta": { + "@emnapi/runtime": { + "optional": true + }, + "@tybys/wasm-util": { + "optional": true + }, + "emnapi": { + "optional": true + } + }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" diff --git a/cli/src/api/artifacts.ts b/cli/src/api/artifacts.ts index 314a1184..86548735 100644 --- a/cli/src/api/artifacts.ts +++ b/cli/src/api/artifacts.ts @@ -1,4 +1,4 @@ -import { join, parse, resolve } from 'path' +import { join, parse, resolve } from 'node:path' import * as colors from 'colorette' diff --git a/cli/src/api/build.ts b/cli/src/api/build.ts index 6842b2d0..6acf41c9 100644 --- a/cli/src/api/build.ts +++ b/cli/src/api/build.ts @@ -1,7 +1,8 @@ -import { spawn } from 'child_process' -import { createHash } from 'crypto' -import { tmpdir } from 'os' -import { parse, join, resolve } from 'path' +import { spawn } from 'node:child_process' +import { createHash } from 'node:crypto' +import { createRequire } from 'node:module' +import { tmpdir } from 'node:os' +import { parse, join, resolve } from 'node:path' import * as colors from 'colorette' @@ -20,6 +21,7 @@ import { parseMetadata, parseTriple, processTypeDef, + readFileAsync, readNapiConfig, Target, targetToEnvVar, @@ -28,11 +30,14 @@ import { writeFileAsync, } from '../utils/index.js' +import { createWasiBinding } from './load-wasi-template.js' import { createCjsBinding } from './templates/index.js' +import { WASI_WORKER_TEMPLATE } from './wasi-worker-template.js' const debug = debugFactory('build') +const require = createRequire(import.meta.url) -type OutputKind = 'js' | 'dts' | 'node' | 'exe' +type OutputKind = 'js' | 'dts' | 'node' | 'exe' | 'wasm' type Output = { kind: OutputKind path: string @@ -383,6 +388,16 @@ class Builder { } // END LINKER + if (this.target.platform === 'wasi') { + const emnapi = join( + require.resolve('emnapi'), + '..', + 'lib', + 'wasm32-wasi-threads', + ) + this.envs.EMNAPI_LINK_DIR = emnapi + } + debug('Set envs: ') Object.entries(this.envs).forEach(([k, v]) => { debug(' %i', `${k}=${v}`) @@ -471,7 +486,34 @@ class Builder { // only for cdylib if (this.cdyLibName) { const idents = await this.generateTypeDef() - await this.writeJsBinding(idents) + const intermediateWasiRegisterFile = this.envs.WASI_REGISTER_TMP_PATH + const wasiRegisterFunctions = + this.target.arch === 'wasm32' + ? JSON.parse( + await readFileAsync(intermediateWasiRegisterFile, 'utf8').catch( + (err) => { + console.warn( + `Read ${colors.yellowBright( + intermediateWasiRegisterFile, + )} failed, reason: ${err.message}`, + ) + return `[]` + }, + ), + ) + : [] + const jsOutput = await this.writeJsBinding(idents) + const wasmOutput = await this.writeWasiBinding( + wasiRegisterFunctions, + jsOutput?.path ?? 'index', + idents, + ) + if (jsOutput) { + this.outputs.push(jsOutput) + } + if (wasmOutput) { + this.outputs.push(wasmOutput) + } } return this.outputs @@ -517,6 +559,8 @@ class Builder { ? `lib${cdyLib}.dylib` : this.target.platform === 'win32' ? `${cdyLib}.dll` + : this.target.platform === 'wasi' || this.target.platform === 'wasm' + ? `${cdyLib}.wasm` : `lib${cdyLib}.so` let destName = this.config.binaryName @@ -526,7 +570,11 @@ class Builder { if (this.options.platform) { destName += `.${this.target.platformArchABI}` } - destName += '.node' + if (srcName.endsWith('.wasm')) { + destName += '.wasi-wasm32.wasm' + } else { + destName += '.node' + } return [srcName, destName] } else if (this.binName) { @@ -592,12 +640,42 @@ class Builder { debug('Writing js binding to:') debug(' %i', dest) await writeFileAsync(dest, cjs, 'utf-8') - this.outputs.push({ + return { kind: 'js', path: dest, - }) + } satisfies Output } catch (e) { throw new Error('Failed to write js binding file', { cause: e }) } } + + private async writeWasiBinding( + wasiRegisterFunctions: string[], + distFileName: string | undefined, + idents: string[], + ) { + if (distFileName && wasiRegisterFunctions.length) { + const { name, dir } = parse(distFileName) + const newPath = join(dir, `${name}.wasi.mjs`) + const workerPath = join(dir, 'wasi-worker.mjs') + const declareCodes = `const { ${idents.join(', ')} } = binding\n` + const exportsCode = `export {\n${idents + .map((ident) => ` ${ident}`) + .join(',\n')}\n}` + await writeFileAsync( + newPath, + createWasiBinding(this.config.binaryName, wasiRegisterFunctions) + + declareCodes + + exportsCode + + '\n', + 'utf8', + ) + await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8') + return { + kind: 'wasm', + path: newPath, + } satisfies Output + } + return null + } } diff --git a/cli/src/api/load-wasi-template.ts b/cli/src/api/load-wasi-template.ts new file mode 100644 index 00000000..c7d0ddf9 --- /dev/null +++ b/cli/src/api/load-wasi-template.ts @@ -0,0 +1,65 @@ +export const createWasiBinding = ( + localName: string, + wasiRegisterFunctions: string[], +) => `/* eslint-disable */ +/* prettier-ignore */ + +/* auto-generated by NAPI-RS */ + +import * as __nodeFsPromises from 'node:fs/promises' +import * as __nodePath from 'node:path' +import { WASI as __nodeWASI } from 'node:wasi' +import { Worker } from 'node:worker_threads' +import * as __nodeURL from 'node:url' + +import { instantiateNapiModule as __emnapiInstantiateNapiModule } from '@emnapi/core' +import { getDefaultContext as __emnapiGetDefaultContext } from '@emnapi/runtime' + +const __wasi = new __nodeWASI({ + env: process.env, + preopens: { + '/': __nodePath.join(__nodeURL.fileURLToPath(import.meta.url), '..'), + } +}) + +const __dirname = __nodePath.join(__nodeURL.fileURLToPath(import.meta.url), '..') + +const __emnapiContext = __emnapiGetDefaultContext() + +const __sharedMemory = new WebAssembly.Memory({ + initial: 1024, + maximum: 10240, + shared: true, +}) + +const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = await __emnapiInstantiateNapiModule(__nodeFsPromises.readFile(__nodePath.join(__dirname, '${localName}.wasi-wasm32.wasm')), { + context: __emnapiContext, + asyncWorkPoolSize: 4, + wasi: __wasi, + onCreateWorker() { + return new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), { + env: process.env, + execArgv: ['--experimental-wasi-unstable-preview1'], + }) + }, + overwriteImports(importObject) { + importObject.env = { + ...importObject.env, + ...importObject.napi, + ...importObject.emnapi, + memory: __sharedMemory, + } + }, + beforeInit({ instance }) { + __napi_rs_initialize_modules(instance) + } +}) + +function __napi_rs_initialize_modules(__napiInstance) { +${wasiRegisterFunctions + .map((name) => ` __napiInstance.exports['${name}']()`) + .join('\n')} +} + +const binding = __napiModule.exports +` diff --git a/cli/src/api/new.ts b/cli/src/api/new.ts index 667226c1..aab2039f 100644 --- a/cli/src/api/new.ts +++ b/cli/src/api/new.ts @@ -157,10 +157,7 @@ function generateGithubWorkflow(options: NewOptions): Output | null { return { target: './.github/workflows/ci.yml', - content: createGithubActionsCIYml( - getBinaryName(options.name), - options.targets, - ), + content: createGithubActionsCIYml(options.targets), } } diff --git a/cli/src/api/templates/.gitignore.ts b/cli/src/api/templates/.gitignore.ts index 635d75c2..709c3be1 100644 --- a/cli/src/api/templates/.gitignore.ts +++ b/cli/src/api/templates/.gitignore.ts @@ -195,4 +195,5 @@ Cargo.lock !.yarn/versions *.node +*.wasm ` diff --git a/cli/src/api/templates/ci.yml.ts b/cli/src/api/templates/ci.yml.ts index f8f5770d..01ba4ad7 100644 --- a/cli/src/api/templates/ci.yml.ts +++ b/cli/src/api/templates/ci.yml.ts @@ -17,10 +17,7 @@ const TEST_LINUX_AARCH64_MUSL = 'test-linux-aarch64-musl-binding' const TEST_LINUX_ARM_GNUEABIHF = 'test-linux-arm-gnueabihf-binding' const UNIVERSAL_MACOS = 'universal-macOS' -export const createGithubActionsCIYml = ( - binaryName: string, - targets: string[], -) => { +export const createGithubActionsCIYml = (targets: string[]) => { const allTargets = new Set( targets.flatMap((t) => { const platform = parseTriple(t) diff --git a/cli/src/api/wasi-worker-template.ts b/cli/src/api/wasi-worker-template.ts new file mode 100644 index 00000000..acadf361 --- /dev/null +++ b/cli/src/api/wasi-worker-template.ts @@ -0,0 +1,52 @@ +export const WASI_WORKER_TEMPLATE = `import fs from "node:fs"; +import { createRequire } from "node:module"; +import { parentPort, Worker } from "node:worker_threads"; + +import { instantiateNapiModuleSync, MessageHandler } from "@emnapi/core"; +import { WASI } from "@tybys/wasm-util"; + +const require = createRequire(import.meta.url); + +if (parentPort) { + parentPort.on("message", (data) => { + globalThis.onmessage({ data }); + }); +} + +Object.assign(globalThis, { + self: globalThis, + require, + Worker, + importScripts: function (f) { + ;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f); + }, + postMessage: function (msg) { + if (parentPort) { + parentPort.postMessage(msg); + } + }, +}); + +const handler = new MessageHandler({ + onLoad({ wasmModule, wasmMemory }) { + const wasi = new WASI({ fs }); + + return instantiateNapiModuleSync(wasmModule, { + childThread: true, + wasi, + overwriteImports(importObject) { + importObject.env = { + ...importObject.env, + ...importObject.napi, + ...importObject.emnapi, + memory: wasmMemory + }; + }, + }); + }, +}); + +globalThis.onmessage = function (e) { + handler.handle(e); +}; +` diff --git a/cli/src/utils/target.ts b/cli/src/utils/target.ts index 341ecf37..fe5a18b3 100644 --- a/cli/src/utils/target.ts +++ b/cli/src/utils/target.ts @@ -1,5 +1,7 @@ import { execSync } from 'child_process' +export type Platform = NodeJS.Platform | 'wasm' | 'wasi' + export const AVAILABLE_TARGETS = [ 'aarch64-apple-darwin', 'aarch64-linux-android', @@ -63,24 +65,22 @@ export const NodeArchToCpu: Record = { riscv64: 'riscv64gc', } -const SysToNodePlatform: Record = { +const SysToNodePlatform: Record = { linux: 'linux', freebsd: 'freebsd', darwin: 'darwin', windows: 'win32', } -export const UniArchsByPlatform: Partial< - Record -> = { +export const UniArchsByPlatform: Partial> = { darwin: ['x64', 'arm64'], } export interface Target { triple: string platformArchABI: string - platform: NodeJS.Platform - arch: NodeJSArch + platform: Platform + arch: NodeJSArch | 'wasm32' abi: string | null } @@ -95,6 +95,15 @@ export interface Target { * - `abi` = The ABI, for example `gnu`, `android`, `eabi`, etc. */ export function parseTriple(rawTriple: string): Target { + if (rawTriple === 'wasm32-wasi-preview1-threads') { + return { + triple: rawTriple, + platformArchABI: rawTriple, + platform: 'wasi', + arch: 'wasm32', + abi: 'wasi', + } + } const triple = rawTriple.endsWith('eabi') ? `${rawTriple.slice(0, -4)}-eabi` : rawTriple @@ -114,7 +123,7 @@ export function parseTriple(rawTriple: string): Target { ;[cpu, , sys, abi = null] = triples } - const platform = SysToNodePlatform[sys] ?? (sys as NodeJS.Platform) + const platform = SysToNodePlatform[sys] ?? (sys as Platform) const arch = CpuToNodeArch[cpu] ?? (cpu as NodeJSArch) return { triple: rawTriple, diff --git a/cli/tsconfig.json b/cli/tsconfig.json index 92d0e13d..bccf7770 100644 --- a/cli/tsconfig.json +++ b/cli/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "../tsconfig.json", "compilerOptions": { "strict": true, "target": "ES2022", diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 7c8aceb7..b3c477e6 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -1,5 +1,6 @@ mod android; mod macos; +mod wasi; pub fn setup() { println!("cargo:rerun-if-env-changed=DEBUG_GENERATED_CODE"); @@ -9,6 +10,9 @@ pub fn setup() { macos::setup(); } Ok("android") => if android::setup().is_ok() {}, + Ok("wasi") => { + wasi::setup(); + } _ => {} } } diff --git a/crates/build/src/wasi.rs b/crates/build/src/wasi.rs new file mode 100644 index 00000000..242ff395 --- /dev/null +++ b/crates/build/src/wasi.rs @@ -0,0 +1,22 @@ +use std::env; + +pub fn setup() { + let link_dir = env::var("EMNAPI_LINK_DIR").expect("EMNAPI_LINK_DIR must be set"); + println!("cargo:rerun-if-env-changed=EMNAPI_LINK_DIR"); + println!("cargo:rerun-if-env-changed=WASI_REGISTER_TMP_PATH"); + println!("cargo:rustc-link-search={}", link_dir); + println!("cargo:rustc-link-lib=static=emnapi-basic-mt"); + println!("cargo:rustc-link-arg=--export-dynamic"); + println!("cargo:rustc-link-arg=--export=malloc"); + println!("cargo:rustc-link-arg=--export=free"); + println!("cargo:rustc-link-arg=--export=napi_register_wasm_v1"); + println!("cargo:rustc-link-arg=--export-if-defined=node_api_module_get_api_version_v1"); + println!("cargo:rustc-link-arg=--export-table"); + println!("cargo:rustc-link-arg=--export=emnapi_async_worker_create"); + println!("cargo:rustc-link-arg=--export=emnapi_async_worker_init"); + println!("cargo:rustc-link-arg=--import-memory"); + println!("cargo:rustc-link-arg=--import-undefined"); + println!("cargo:rustc-link-arg=--shared-memory"); + println!("cargo:rustc-link-arg=--max-memory=2147483648"); + println!("cargo:rustc-link-arg=--no-check-features"); +} diff --git a/crates/napi/Cargo.toml b/crates/napi/Cargo.toml index 501590f9..9cbb043d 100644 --- a/crates/napi/Cargo.toml +++ b/crates/napi/Cargo.toml @@ -75,11 +75,11 @@ version = "0.8" optional = true version = "0.4" -[target.'cfg(target_arch = "wasm32")'.dependencies] +[target.'cfg(target_os = "wasi")'.dependencies] tokio = { version = "1", optional = true, features = ["rt", "sync"] } napi-derive = { path = "../macro", version = "2.10.1", default-features = false } -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +[target.'cfg(not(target_os = "wasi"))'.dependencies] tokio = { version = "1", optional = true, features = [ "rt", "rt-multi-thread", diff --git a/crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs b/crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs index 00acafbb..e479b269 100644 --- a/crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs +++ b/crates/napi/src/bindgen_runtime/js_values/arraybuffer.rs @@ -7,13 +7,24 @@ use std::sync::{ Arc, }; -#[cfg(all(feature = "napi4", not(target_arch = "wasm32")))] +#[cfg(all(feature = "napi4", not(target_os = "wasi")))] use crate::bindgen_prelude::{CUSTOM_GC_TSFN, THREADS_CAN_ACCESS_ENV, THREAD_DESTROYED}; pub use crate::js_values::TypedArrayType; use crate::{check_status, sys, Error, Result, Status}; use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue}; +#[cfg(target_os = "wasi")] +extern "C" { + fn emnapi_sync_memory( + env: crate::sys::napi_env, + js_to_wasm: bool, + arraybuffer_or_view: crate::sys::napi_value, + byte_offset: usize, + length: usize, + ) -> crate::sys::napi_status; +} + trait Finalizer { type RustType; @@ -122,6 +133,49 @@ macro_rules! impl_typed_array { impl $name { fn noop_finalize(_data: *mut $rust_type, _length: usize) {} + #[cfg(target_os = "wasi")] + pub fn sync(&mut self, env: &crate::Env) { + if let Some((reference, _)) = self.raw { + let mut value = ptr::null_mut(); + let mut array_buffer = ptr::null_mut(); + crate::check_status_or_throw!( + env.raw(), + unsafe { crate::sys::napi_get_reference_value(env.raw(), reference, &mut value) }, + "Failed to get reference value from TypedArray while syncing" + ); + crate::check_status_or_throw!( + env.raw(), + unsafe { + crate::sys::napi_get_typedarray_info( + env.raw(), + value, + &mut ($typed_array_type as i32) as *mut i32, + &mut self.length as *mut usize, + ptr::null_mut(), + &mut array_buffer, + &mut self.byte_offset as *mut usize, + ) + }, + "Failed to get ArrayBuffer under the TypedArray while syncing" + ); + crate::check_status_or_throw!( + env.raw(), + unsafe { + emnapi_sync_memory( + env.raw(), + false, + array_buffer, + self.byte_offset, + self.length, + ) + }, + "Failed to sync memory" + ); + } else { + return; + } + } + pub fn new(mut data: Vec<$rust_type>) -> Self { data.shrink_to_fit(); let ret = $name { diff --git a/crates/napi/src/bindgen_runtime/mod.rs b/crates/napi/src/bindgen_runtime/mod.rs index 26fd11ef..82dfb3ee 100644 --- a/crates/napi/src/bindgen_runtime/mod.rs +++ b/crates/napi/src/bindgen_runtime/mod.rs @@ -34,17 +34,18 @@ pub unsafe extern "C" fn raw_finalize_unchecked( finalize_data: *mut c_void, _finalize_hint: *mut c_void, ) { - let data = *unsafe { Box::from_raw(finalize_data as *mut T) }; + let data: Box = unsafe { Box::from_raw(finalize_data.cast()) }; if let Err(err) = data.finalize(unsafe { Env::from_raw(env) }) { let e: JsError = err.into(); unsafe { e.throw_into(env) }; + return; } if let Some((_, ref_val, finalize_callbacks_ptr)) = REFERENCE_MAP.with(|reference_map| reference_map.borrow_mut().remove(&finalize_data)) { let finalize_callbacks_rc = unsafe { Rc::from_raw(finalize_callbacks_ptr) }; - #[cfg(debug_assertions)] + #[cfg(all(debug_assertions, not(target_os = "wasi")))] { let rc_strong_count = Rc::strong_count(&finalize_callbacks_rc); // If `Rc` strong count is 2, it means the finalize of referenced `Object` is called before the `fn drop` of the `Reference` diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index 22c12abb..b0b43374 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -374,6 +374,7 @@ impl Env { )) } + #[cfg(not(target_os = "wasi"))] /// This function gives V8 an indication of the amount of externally allocated memory that is kept alive by JavaScript objects (i.e. a JavaScript object that points to its own memory allocated by a native module). /// /// Registering externally allocated memory will trigger global garbage collections more often than it would otherwise. @@ -385,6 +386,12 @@ impl Env { Ok(changed) } + #[cfg(target_os = "wasi")] + #[allow(unused_variables)] + pub fn adjust_external_memory(&mut self, size: i64) -> Result { + Ok(0) + } + /// This API allocates a node::Buffer object and initializes it with data copied from the passed-in buffer. /// /// While this is still a fully-supported data structure, in most cases using a TypedArray will suffice. diff --git a/crates/napi/src/js_values/deferred.rs b/crates/napi/src/js_values/deferred.rs index a1c5583c..c990fdee 100644 --- a/crates/napi/src/js_values/deferred.rs +++ b/crates/napi/src/js_values/deferred.rs @@ -3,7 +3,9 @@ use std::marker::PhantomData; use std::os::raw::c_void; use std::ptr; -use crate::bindgen_runtime::{ToNapiValue, THREAD_DESTROYED}; +#[cfg(all(feature = "napi4", not(target_arch = "wasm32")))] +use crate::bindgen_prelude::THREAD_DESTROYED; +use crate::bindgen_runtime::ToNapiValue; use crate::{check_status, JsObject, Value}; use crate::{sys, Env, Error, Result}; #[cfg(feature = "deferred_trace")] diff --git a/crates/napi/src/tokio_runtime.rs b/crates/napi/src/tokio_runtime.rs index 5aaa97b7..eebc0d29 100644 --- a/crates/napi/src/tokio_runtime.rs +++ b/crates/napi/src/tokio_runtime.rs @@ -6,13 +6,13 @@ use tokio::runtime::Runtime; use crate::{sys, JsDeferred, JsUnknown, NapiValue, Result}; fn create_runtime() -> Option { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(target_os = "wasi"))] { let runtime = tokio::runtime::Runtime::new().expect("Create tokio runtime failed"); Some(runtime) } - #[cfg(target_arch = "wasm32")] + #[cfg(target_os = "wasi")] { tokio::runtime::Builder::new_current_thread() .enable_all() diff --git a/examples/napi-shared/Cargo.toml b/examples/napi-shared/Cargo.toml index c2761df6..37798474 100644 --- a/examples/napi-shared/Cargo.toml +++ b/examples/napi-shared/Cargo.toml @@ -10,9 +10,7 @@ crate-type = ["cdylib", "lib"] [dependencies] napi = { path = "../../crates/napi", default-features = false, features = [ - "tokio_fs", "napi8", - "tokio_rt", "serde-json", "async", "experimental", diff --git a/examples/napi/.gitignore b/examples/napi/.gitignore index a59f269a..f0551e76 100644 --- a/examples/napi/.gitignore +++ b/examples/napi/.gitignore @@ -1,2 +1,3 @@ *.node wip/ +*.wasm diff --git a/examples/napi/Cargo.toml b/examples/napi/Cargo.toml index 1c10e596..4f4ad587 100644 --- a/examples/napi/Cargo.toml +++ b/examples/napi/Cargo.toml @@ -14,23 +14,43 @@ snmalloc = ["snmalloc-rs"] [dependencies] chrono = "0.4" futures = "0.3" -napi = { path = "../../crates/napi", default-features = false, features = [ - "tokio_fs", - "napi9", - "tokio_rt", - "serde-json", - "async", - "experimental", - "latin1", - "chrono_date", - "deferred_trace", -] } napi-derive = { path = "../../crates/macro", features = ["type-def"] } napi-shared = { path = "../napi-shared" } serde = "1" serde_derive = "1" serde_json = "1" -tokio = { version = "1.20.0", features = ["full"] } + +[target.'cfg(not(target_os = "wasi"))'.dependencies] +napi = { path = "../../crates/napi", default-features = false, features = [ + "napi9", + "serde-json", + "experimental", + "latin1", + "chrono_date", + "tokio", + "async", + "tokio_rt", + "tokio_fs", + "tokio_macros", + "deferred_trace", +] } +tokio = { version = "1", features = ["rt", "time"] } + +[target.'cfg(target_os = "wasi")'.dependencies] +napi = { path = "../../crates/napi", default-features = false, features = [ + "napi9", + "serde-json", + "experimental", + "latin1", + "chrono_date", + "tokio", + "async", + "tokio_rt", + "tokio_macros", + "tokio_sync", + "deferred_trace", +] } +tokio = { version = "1", default-features = false, features = ["rt", "time"] } [dependencies.snmalloc-rs] version = "0.3" diff --git a/examples/napi/__tests__/error-msg.spec.ts b/examples/napi/__tests__/error-msg.spec.ts index 2a0600a2..bd6feeb2 100644 --- a/examples/napi/__tests__/error-msg.spec.ts +++ b/examples/napi/__tests__/error-msg.spec.ts @@ -1,10 +1,6 @@ -import { createRequire } from 'node:module' - import test from 'ava' -const require = createRequire(import.meta.url) - -const { receiveString }: typeof import('../index.js') = require('../index.node') +const { receiveString } = (await import('../index.js')).default test('Function message', (t) => { // @ts-expect-error diff --git a/examples/napi/__tests__/generator.spec.ts b/examples/napi/__tests__/generator.spec.ts index 7fb2eff7..97efbf4a 100644 --- a/examples/napi/__tests__/generator.spec.ts +++ b/examples/napi/__tests__/generator.spec.ts @@ -1,14 +1,8 @@ -import { createRequire } from 'node:module' +import ava from 'ava' -import test from 'ava' +const { Fib, Fib2, Fib3 } = (await import('../index.js')).default -const require = createRequire(import.meta.url) - -const { - Fib, - Fib2, - Fib3, -}: typeof import('../index.js') = require('../index.node') +const test = process.env.WASI_TEST ? ava.skip : ava for (const [index, factory] of [ () => new Fib(), diff --git a/examples/napi/__tests__/object-attr.spec.ts b/examples/napi/__tests__/object-attr.spec.ts index 4e401063..99d06590 100644 --- a/examples/napi/__tests__/object-attr.spec.ts +++ b/examples/napi/__tests__/object-attr.spec.ts @@ -1,12 +1,8 @@ -import { createRequire } from 'node:module' +import ava from 'ava' -import test from 'ava' +const { NotWritableClass } = (await import('../index.js')).default -const require = createRequire(import.meta.url) - -const { - NotWritableClass, -}: typeof import('../index.js') = require('../index.node') +const test = process.env.WASI_TEST ? ava.skip : ava test('Not Writable Class', (t) => { const obj = new NotWritableClass('1') diff --git a/examples/napi/__tests__/strict.spec.ts b/examples/napi/__tests__/strict.spec.ts index 5bef827a..b62a17f9 100644 --- a/examples/napi/__tests__/strict.spec.ts +++ b/examples/napi/__tests__/strict.spec.ts @@ -1,9 +1,5 @@ -import { createRequire } from 'node:module' - import test from 'ava' -const require = createRequire(import.meta.url) - const { validateArray, validateTypedArray, @@ -24,7 +20,7 @@ const { returnUndefinedIfInvalid, returnUndefinedIfInvalidPromise, validateOptional, -}: typeof import('../index.d.ts') = require('../index.node') +} = (await import('../index.js')).default test('should validate array', (t) => { t.is(validateArray([1, 2, 3]), 3) @@ -127,8 +123,21 @@ test('should validate Map', (t) => { }) }) -test('should validate promise', async (t) => { - t.is(await validatePromise(Promise.resolve(1)), 2) +test.only('should validate promise', async (t) => { + if (process.env.WASI_TEST) { + t.pass() + return + } + t.is( + await validatePromise( + new Promise((resolve) => { + setTimeout(() => { + resolve(1) + }, 100) + }), + ), + 2, + ) // @ts-expect-error await t.throwsAsync(() => validatePromise(1), { code: 'InvalidArg', diff --git a/examples/napi/__tests__/tsfn-error.cjs b/examples/napi/__tests__/tsfn-error.cjs index a91d5d85..91c2019e 100644 --- a/examples/napi/__tests__/tsfn-error.cjs +++ b/examples/napi/__tests__/tsfn-error.cjs @@ -1,3 +1,3 @@ -const { threadsafeFunctionFatalModeError } = require('../index.node') - -threadsafeFunctionFatalModeError(() => {}) +import('../index.js').then(({ default: { threadsafeFunctionFatalModeError } }) => { + return threadsafeFunctionFatalModeError(() => {}) +}) diff --git a/examples/napi/__tests__/typegen.spec.ts b/examples/napi/__tests__/typegen.spec.ts index dd440622..f0428754 100644 --- a/examples/napi/__tests__/typegen.spec.ts +++ b/examples/napi/__tests__/typegen.spec.ts @@ -7,5 +7,9 @@ import test from 'ava' const __dirname = join(fileURLToPath(import.meta.url), '..') test('should generate correct type def file', (t) => { - t.snapshot(readFileSync(join(__dirname, '..', 'index.d.ts'), 'utf8')) + if (process.env.WASI_TEST) { + t.pass() + } else { + t.snapshot(readFileSync(join(__dirname, '..', 'index.d.ts'), 'utf8')) + } }) diff --git a/examples/napi/__tests__/values.spec.ts b/examples/napi/__tests__/values.spec.ts index cce98b95..b562a1d8 100644 --- a/examples/napi/__tests__/values.spec.ts +++ b/examples/napi/__tests__/values.spec.ts @@ -1,5 +1,4 @@ import { exec } from 'node:child_process' -import { createRequire } from 'node:module' import { join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -9,7 +8,6 @@ import type { AliasedStruct } from '../index.js' import { test } from './test.framework.js' -const require = createRequire(import.meta.url) const __dirname = join(fileURLToPath(import.meta.url), '..') const { @@ -141,7 +139,10 @@ const { chronoNativeDateTime, chronoNativeDateTimeReturn, throwAsyncError, -}: typeof import('../index.d.ts') = require('../index.node') +} = (await import('../index.js')).default + +const Napi4Test = Number(process.versions.napi) >= 4 ? test : test.skip +const isWasiTest = !!process.env.WASI_TEST test('export const', (t) => { t.is(DEFAULT_COST, 12) @@ -310,7 +311,7 @@ test('should be able to into_reference', (t) => { test('callback', (t) => { getCwd((cwd) => { - t.is(cwd, process.cwd()) + t.is(cwd, process.env.WASI_TEST ? '/' : process.cwd()) }) t.throws( @@ -345,7 +346,11 @@ test('return function', (t) => { }) }) -test('callback function return Promise', async (t) => { +Napi4Test('callback function return Promise', async (t) => { + if (isWasiTest) { + t.pass() + return + } const cbSpy = spy() await callbackReturnPromise(() => '1', spy) t.is(cbSpy.callCount, 0) @@ -360,7 +365,11 @@ test('callback function return Promise', async (t) => { t.deepEqual(cbSpy.args, [['42']]) }) -test('callback function return Promise and spawn', async (t) => { +Napi4Test('callback function return Promise and spawn', async (t) => { + if (isWasiTest) { + t.pass() + return + } const finalReturn = await callbackReturnPromiseAndSpawn((input) => Promise.resolve(`${input} world`), ) @@ -433,7 +442,9 @@ test('Async error with stack trace', async (t) => { const err = await t.throwsAsync(() => throwAsyncError()) t.not(err?.stack, undefined) t.deepEqual(err!.message, 'Async Error') - t.regex(err!.stack!, /.+at .+values\.spec\.ts:\d+:\d+.+/gm) + if (!process.env.WASI_TEST) { + t.regex(err!.stack!, /.+at .+values\.spec\.ts:\d+:\d+.+/gm) + } }) test('custom status code in Error', (t) => { @@ -488,10 +499,13 @@ test('aliased rust struct and enum', (t) => { }) test('serde-json', (t) => { + if (process.env.WASI_TEST) { + t.pass() + return + } const packageJson = readPackageJson() t.is(packageJson.name, '@examples/napi') t.is(packageJson.version, '0.0.0') - t.is(packageJson.dependencies, undefined) t.snapshot(Object.keys(packageJson.devDependencies!).sort()) t.is(getPackageJsonName(packageJson), '@examples/napi') @@ -574,6 +588,10 @@ test('create external TypedArray', (t) => { }) test('mutate TypedArray', (t) => { + if (isWasiTest) { + t.pass() + return + } const input = new Float32Array([1, 2, 3, 4, 5]) mutateTypedArray(input) t.deepEqual(input, new Float32Array([2.0, 4.0, 6.0, 8.0, 10.0])) @@ -587,6 +605,10 @@ test('deref uint8 array', (t) => { }) test('async', async (t) => { + if (process.env.WASI_TEST) { + t.pass() + return + } const bufPromise = readFileAsync(join(__dirname, '../package.json')) await t.notThrowsAsync(bufPromise) const buf = await bufPromise @@ -639,6 +661,11 @@ test('receive class reference in either', (t) => { }) test('receive different class', (t) => { + // TODO: fix the napi_unwrap error from the emnapi + if (isWasiTest) { + t.pass() + return + } const a = new JsClassForEither() const b = new AnotherClassForEither() t.is(receiveDifferentClass(a), 42) @@ -764,8 +791,6 @@ BigIntTest('from i128 i64', (t) => { t.is(bigintFromI128(), BigInt('-100')) }) -const Napi4Test = Number(process.versions.napi) >= 4 ? test : test.skip - Napi4Test('call thread safe function', (t) => { let i = 0 let value = 0 @@ -820,13 +845,19 @@ Napi4Test('throw error from thread safe function fatal mode', (t) => { return new Promise((resolve) => { p.on('exit', (code) => { t.is(code, 1) - t.true(stderr.toString('utf8').includes(`[Error: Generic tsfn error]`)) + const stderrMsg = stderr.toString('utf8') + console.info(stderrMsg) + t.true(stderrMsg.includes(`Error: Generic tsfn error`)) resolve() }) }) }) Napi4Test('await Promise in rust', async (t) => { + if (isWasiTest) { + t.pass() + return + } const fx = 20 const result = await asyncPlus100( new Promise((resolve) => { @@ -837,6 +868,10 @@ Napi4Test('await Promise in rust', async (t) => { }) Napi4Test('Promise should reject raw error in rust', async (t) => { + if (isWasiTest) { + t.pass() + return + } const fxError = new Error('What is Happy Planet') const err = await t.throwsAsync(() => asyncPlus100(Promise.reject(fxError))) t.is(err, fxError) @@ -855,6 +890,10 @@ Napi4Test('call ThreadsafeFunction with callback', async (t) => { }) Napi4Test('async call ThreadsafeFunction', async (t) => { + if (isWasiTest) { + t.pass() + return + } await t.notThrowsAsync(() => tsfnAsyncCall((err, arg1, arg2, arg3) => { t.is(err, null) @@ -867,6 +906,10 @@ Napi4Test('async call ThreadsafeFunction', async (t) => { }) test('Throw from ThreadsafeFunction JavaScript callback', async (t) => { + if (isWasiTest) { + t.pass() + return + } const errMsg = 'ThrowFromJavaScriptRawCallback' await t.throwsAsync( () => @@ -915,7 +958,11 @@ Napi4Test('accept ThreadsafeFunction tuple args', async (t) => { }) }) -test('threadsafe function return Promise and await in Rust', async (t) => { +Napi4Test('threadsafe function return Promise and await in Rust', async (t) => { + if (isWasiTest) { + t.pass() + return + } const value = await tsfnReturnPromise((err, value) => { if (err) { throw err @@ -959,7 +1006,11 @@ Napi4Test('object only from js', (t) => { }) }) -test('promise in either', async (t) => { +Napi4Test('promise in either', async (t) => { + if (isWasiTest) { + t.pass() + return + } t.is(await promiseInEither(1), false) t.is(await promiseInEither(20), true) t.is(await promiseInEither(Promise.resolve(1)), false) diff --git a/examples/napi/__tests__/worker-thread.spec.cjs b/examples/napi/__tests__/worker-thread.spec.ts similarity index 76% rename from examples/napi/__tests__/worker-thread.spec.cjs rename to examples/napi/__tests__/worker-thread.spec.ts index 8a93baec..4bb1d09b 100644 --- a/examples/napi/__tests__/worker-thread.spec.cjs +++ b/examples/napi/__tests__/worker-thread.spec.ts @@ -1,13 +1,19 @@ -const { join } = require('node:path') -const { Worker } = require('node:worker_threads') +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { Worker } from 'node:worker_threads' -const test = require('ava').default +import test from 'ava' -const { Animal, Kind, DEFAULT_COST } = require('../index.node') +const { Animal, Kind, DEFAULT_COST } = (await import('../index.js')).default + +const __dirname = join(fileURLToPath(import.meta.url), '..') // aarch64-unknown-linux-gnu is extremely slow in CI, skip it or it will timeout const t = - process.arch === 'arm64' && process.platform === 'linux' ? test.skip : test + (process.arch === 'arm64' && process.platform === 'linux') || + process.env.WASI_TEST + ? test.skip + : test const concurrency = process.platform === 'win32' || process.platform === 'darwin' || (process.platform === 'linux' && process.arch === 'x64') ? 50 : 10 @@ -15,9 +21,9 @@ t('should be able to require in worker thread', async (t) => { await Promise.all( Array.from({ length: concurrency }).map(() => { const w = new Worker(join(__dirname, 'worker.cjs'), { - execArgv: [] + execArgv: [], }) - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { w.postMessage({ type: 'require' }) w.on('message', (msg) => { t.is(msg, Animal.withKind(Kind.Cat).whoami() + DEFAULT_COST) @@ -39,9 +45,9 @@ t('custom GC works on worker_threads', async (t) => { await Promise.all( Array.from({ length: concurrency }).map(() => Promise.all([ - new Promise((resolve, reject) => { + new Promise((resolve, reject) => { const w = new Worker(join(__dirname, 'worker.cjs'), { - execArgv: [] + execArgv: [], }) w.postMessage({ type: 'async:buffer', @@ -56,9 +62,9 @@ t('custom GC works on worker_threads', async (t) => { }).then((w) => { return w.terminate() }), - new Promise((resolve, reject) => { + new Promise((resolve, reject) => { const w = new Worker(join(__dirname, 'worker.cjs'), { - execArgv: [] + execArgv: [], }) w.postMessage({ type: 'async:arraybuffer', @@ -82,9 +88,9 @@ t('should be able to new Class in worker thread concurrently', async (t) => { await Promise.all( Array.from({ length: concurrency }).map(() => { const w = new Worker(join(__dirname, 'worker.cjs'), { - execArgv: [] + execArgv: [], }) - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { w.postMessage({ type: 'constructor' }) w.on('message', (msg) => { t.is(msg, 'Ellie') diff --git a/examples/napi/electron-renderer/index.html b/examples/napi/electron-renderer/index.html index a84ee171..275509d9 100644 --- a/examples/napi/electron-renderer/index.html +++ b/examples/napi/electron-renderer/index.html @@ -1,13 +1,16 @@ - - - - - Electron test - - -
Electron test
- - - + + + + + + Electron test + + + +
Electron test
+ + + + \ No newline at end of file diff --git a/examples/napi/electron-renderer/index.js b/examples/napi/electron-renderer/index.js index 6e9f5c3e..c422774a 100644 --- a/examples/napi/electron-renderer/index.js +++ b/examples/napi/electron-renderer/index.js @@ -1,6 +1,6 @@ const { ipcRenderer } = require('electron') -const { callLongThreadsafeFunction } = require('../index') +const { callLongThreadsafeFunction } = require('../index.node') callLongThreadsafeFunction(() => {}) diff --git a/examples/napi/electron.cjs b/examples/napi/electron.cjs index 9f9ae8ae..64a39e42 100644 --- a/examples/napi/electron.cjs +++ b/examples/napi/electron.cjs @@ -1,15 +1,8 @@ -const assert = require('assert') -const { readFileSync } = require('fs') +const assert = require('node:assert') +const { readFileSync } = require('node:fs') const { app, BrowserWindow, ipcMain } = require('electron') -const { - readFileAsync, - callThreadsafeFunction, - withAbortController, - createExternalTypedArray, -} = require('./index') - const FILE_CONTENT = readFileSync(__filename, 'utf8') const createWindowAndReload = async () => { @@ -39,16 +32,30 @@ const createWindowAndReload = async () => { // reload to check if there is any crash win.reload() + // make sure the renderer process is still alive + ipcMain.once('pong', () => { + console.info('pong') + resolve() + }) + // Wait for a while to make sure if a crash happens, the 'resolve' function should be called after the crash setTimeout(() => { - // make sure the renderer process is still alive - ipcMain.once('pong', () => resolve()) win.webContents.send('ping') - }, 500) + console.info('ping') + }, 1000) }) } async function main() { + const { + default: { + readFileAsync, + callThreadsafeFunction, + withAbortController, + createExternalTypedArray, + }, + } = await import('./index.js') + const ctrl = new AbortController() const promise = withAbortController(1, 2, ctrl.signal) try { diff --git a/examples/napi/index.js b/examples/napi/index.js new file mode 100644 index 00000000..dccdb473 --- /dev/null +++ b/examples/napi/index.js @@ -0,0 +1,13 @@ +import { createRequire } from 'node:module' + +const require = createRequire(import.meta.url) + +let exports + +if (process.env.WASI_TEST) { + exports = await import('./index.wasi.mjs') +} else { + exports = require('./index.node') +} + +export default exports diff --git a/examples/napi/index.wasi.mjs b/examples/napi/index.wasi.mjs new file mode 100644 index 00000000..0d61c845 --- /dev/null +++ b/examples/napi/index.wasi.mjs @@ -0,0 +1,448 @@ +/* tslint:disable */ +/* eslint-disable */ +/* prettier-ignore */ + +/* auto-generated by NAPI-RS */ + +import * as __nodeFsPromises from 'node:fs/promises' +import * as __nodePath from 'node:path' +import { WASI as __nodeWASI } from 'node:wasi' +import { Worker } from 'node:worker_threads' +import * as __nodeURL from 'node:url' + +import { instantiateNapiModule as __emnapiInstantiateNapiModule } from '@emnapi/core' +import { getDefaultContext as __emnapiGetDefaultContext } from '@emnapi/runtime' + +const __wasi = new __nodeWASI({ + env: process.env, + preopens: { + '/': __nodePath.join(__nodeURL.fileURLToPath(import.meta.url), '..'), + } +}) + +const __dirname = __nodePath.join(__nodeURL.fileURLToPath(import.meta.url), '..') + +const __emnapiContext = __emnapiGetDefaultContext() + +const __sharedMemory = new WebAssembly.Memory({ + initial: 1024, + maximum: 10240, + shared: true, +}) + +const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = await __emnapiInstantiateNapiModule(__nodeFsPromises.readFile(__nodePath.join(__dirname, 'index.wasi-wasm32.wasm')), { + context: __emnapiContext, + asyncWorkPoolSize: 4, + wasi: __wasi, + onCreateWorker() { + return new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), { + env: process.env, + execArgv: ['--experimental-wasi-unstable-preview1'], + }) + }, + overwriteImports(importObject) { + importObject.env = { + ...importObject.env, + ...importObject.napi, + ...importObject.emnapi, + memory: __sharedMemory, + } + }, + beforeInit({ instance }) { + __napi_rs_initialize_modules(instance) + } +}) + +function __napi_rs_initialize_modules(__napiInstance) { + __napiInstance.exports['__napi_register__DEFAULT_COST_0']() + __napiInstance.exports['__napi_register__TYPE_SKIPPED_CONST_1']() + __napiInstance.exports['__napi_register__get_words_2']() + __napiInstance.exports['__napi_register__get_nums_3']() + __napiInstance.exports['__napi_register__sum_nums_4']() + __napiInstance.exports['__napi_register__to_js_obj_5']() + __napiInstance.exports['__napi_register__get_num_arr_6']() + __napiInstance.exports['__napi_register__get_nested_num_arr_7']() + __napiInstance.exports['__napi_register__read_file_async_8']() + __napiInstance.exports['__napi_register__async_multi_two_9']() + __napiInstance.exports['__napi_register__bigint_add_10']() + __napiInstance.exports['__napi_register__create_big_int_11']() + __napiInstance.exports['__napi_register__create_big_int_i64_12']() + __napiInstance.exports['__napi_register__bigint_get_u64_as_string_13']() + __napiInstance.exports['__napi_register__bigint_from_i64_14']() + __napiInstance.exports['__napi_register__bigint_from_i128_15']() + __napiInstance.exports['__napi_register__get_cwd_16']() + __napiInstance.exports['__napi_register__option_end_17']() + __napiInstance.exports['__napi_register__option_start_18']() + __napiInstance.exports['__napi_register__option_start_end_19']() + __napiInstance.exports['__napi_register__option_only_20']() + __napiInstance.exports['__napi_register__read_file_21']() + __napiInstance.exports['__napi_register__return_js_function_22']() + __napiInstance.exports['__napi_register__callback_return_promise_23']() + __napiInstance.exports['__napi_register__callback_return_promise_and_spawn_24']() + __napiInstance.exports['__napi_register__capture_error_in_callback_25']() + __napiInstance.exports['__napi_register__Animal_struct_26']() + __napiInstance.exports['__napi_register__Animal_impl_27']() + __napiInstance.exports['__napi_register__Dog_struct_28']() + __napiInstance.exports['__napi_register__Bird_struct_29']() + __napiInstance.exports['__napi_register__Bird_impl_30']() + __napiInstance.exports['__napi_register__Blake2bHasher_struct_31']() + __napiInstance.exports['__napi_register__Blake2bHasher_impl_32']() + __napiInstance.exports['__napi_register__Blake2bHasher_impl_33']() + __napiInstance.exports['__napi_register__Blake2bKey_struct_34']() + __napiInstance.exports['__napi_register__Context_struct_35']() + __napiInstance.exports['__napi_register__Context_impl_36']() + __napiInstance.exports['__napi_register__AnimalWithDefaultConstructor_struct_37']() + __napiInstance.exports['__napi_register__NinjaTurtle_struct_38']() + __napiInstance.exports['__napi_register__NinjaTurtle_impl_39']() + __napiInstance.exports['__napi_register__JsAssets_struct_40']() + __napiInstance.exports['__napi_register__JsAssets_impl_41']() + __napiInstance.exports['__napi_register__JsAsset_struct_42']() + __napiInstance.exports['__napi_register__JsAsset_impl_43']() + __napiInstance.exports['__napi_register__Optional_struct_44']() + __napiInstance.exports['__napi_register__Optional_impl_45']() + __napiInstance.exports['__napi_register__create_object_with_class_field_46']() + __napiInstance.exports['__napi_register__receive_object_with_class_field_47']() + __napiInstance.exports['__napi_register__NotWritableClass_struct_48']() + __napiInstance.exports['__napi_register__NotWritableClass_impl_49']() + __napiInstance.exports['__napi_register__CustomFinalize_struct_50']() + __napiInstance.exports['__napi_register__CustomFinalize_impl_51']() + __napiInstance.exports['__napi_register__Width_struct_52']() + __napiInstance.exports['__napi_register__plus_one_53']() + __napiInstance.exports['__napi_register__GetterSetterWithClosures_struct_54']() + __napiInstance.exports['__napi_register__GetterSetterWithClosures_impl_55']() + __napiInstance.exports['__napi_register__ClassWithFactory_struct_56']() + __napiInstance.exports['__napi_register__ClassWithFactory_impl_57']() + __napiInstance.exports['__napi_register__Selector_struct_58']() + __napiInstance.exports['__napi_register__date_to_number_59']() + __napiInstance.exports['__napi_register__chrono_date_to_millis_60']() + __napiInstance.exports['__napi_register__chrono_date_add_1_minute_61']() + __napiInstance.exports['__napi_register__chrono_native_date_time_62']() + __napiInstance.exports['__napi_register__chrono_native_date_time_return_63']() + __napiInstance.exports['__napi_register__either_string_or_number_64']() + __napiInstance.exports['__napi_register__return_either_65']() + __napiInstance.exports['__napi_register__either3_66']() + __napiInstance.exports['__napi_register__either4_67']() + __napiInstance.exports['__napi_register__JsClassForEither_struct_68']() + __napiInstance.exports['__napi_register__JsClassForEither_impl_69']() + __napiInstance.exports['__napi_register__AnotherClassForEither_struct_70']() + __napiInstance.exports['__napi_register__AnotherClassForEither_impl_71']() + __napiInstance.exports['__napi_register__receive_class_or_number_72']() + __napiInstance.exports['__napi_register__receive_mut_class_or_number_73']() + __napiInstance.exports['__napi_register__receive_different_class_74']() + __napiInstance.exports['__napi_register__return_either_class_75']() + __napiInstance.exports['__napi_register__either_from_option_76']() + __napiInstance.exports['__napi_register__either_from_objects_77']() + __napiInstance.exports['__napi_register__either_bool_or_function_78']() + __napiInstance.exports['__napi_register__promise_in_either_79']() + __napiInstance.exports['__napi_register__Kind_80']() + __napiInstance.exports['__napi_register__Empty_81']() + __napiInstance.exports['__napi_register__Status_82']() + __napiInstance.exports['__napi_register__CustomNumEnum_83']() + __napiInstance.exports['__napi_register__enum_to_i32_84']() + __napiInstance.exports['__napi_register__SkippedEnums_85']() + __napiInstance.exports['__napi_register__throw_error_86']() + __napiInstance.exports['__napi_register__panic_87']() + __napiInstance.exports['__napi_register__receive_string_88']() + __napiInstance.exports['__napi_register__custom_status_code_89']() + __napiInstance.exports['__napi_register__throw_async_error_90']() + __napiInstance.exports['__napi_register__create_external_91']() + __napiInstance.exports['__napi_register__create_external_string_92']() + __napiInstance.exports['__napi_register__get_external_93']() + __napiInstance.exports['__napi_register__mutate_external_94']() + __napiInstance.exports['__napi_register__validate_array_95']() + __napiInstance.exports['__napi_register__validate_buffer_96']() + __napiInstance.exports['__napi_register__validate_typed_array_97']() + __napiInstance.exports['__napi_register__validate_bigint_98']() + __napiInstance.exports['__napi_register__validate_boolean_99']() + __napiInstance.exports['__napi_register__validate_date_100']() + __napiInstance.exports['__napi_register__validate_date_time_101']() + __napiInstance.exports['__napi_register__validate_external_102']() + __napiInstance.exports['__napi_register__validate_function_103']() + __napiInstance.exports['__napi_register__validate_hash_map_104']() + __napiInstance.exports['__napi_register__validate_null_105']() + __napiInstance.exports['__napi_register__validate_undefined_106']() + __napiInstance.exports['__napi_register__validate_number_107']() + __napiInstance.exports['__napi_register__validate_promise_108']() + __napiInstance.exports['__napi_register__validate_string_109']() + __napiInstance.exports['__napi_register__validate_symbol_110']() + __napiInstance.exports['__napi_register__validate_optional_111']() + __napiInstance.exports['__napi_register__return_undefined_if_invalid_112']() + __napiInstance.exports['__napi_register__return_undefined_if_invalid_promise_113']() + __napiInstance.exports['__napi_register__ts_rename_114']() + __napiInstance.exports['__napi_register__override_individual_arg_on_function_115']() + __napiInstance.exports['__napi_register__override_individual_arg_on_function_with_cb_arg_116']() + __napiInstance.exports['__napi_register__Fib_struct_117']() + __napiInstance.exports['__napi_register__Fib_impl_118']() + __napiInstance.exports['__napi_register__Fib_impl_119']() + __napiInstance.exports['__napi_register__Fib2_struct_120']() + __napiInstance.exports['__napi_register__Fib2_impl_121']() + __napiInstance.exports['__napi_register__Fib2_impl_122']() + __napiInstance.exports['__napi_register__Fib3_struct_123']() + __napiInstance.exports['__napi_register__Fib3_impl_124']() + __napiInstance.exports['__napi_register__ALIGNMENT_125']() + __napiInstance.exports['__napi_register__xxh64_126']() + __napiInstance.exports['__napi_register__xxh128_127']() + __napiInstance.exports['__napi_register__Xxh3_struct_128']() + __napiInstance.exports['__napi_register__Xxh3_impl_129']() + __napiInstance.exports['__napi_register__xxh2_plus_130']() + __napiInstance.exports['__napi_register__xxh3_xxh64_alias_131']() + __napiInstance.exports['__napi_register__xxh64_alias_132']() + __napiInstance.exports['__napi_register__get_mapping_133']() + __napiInstance.exports['__napi_register__sum_mapping_134']() + __napiInstance.exports['__napi_register__map_option_135']() + __napiInstance.exports['__napi_register__return_null_136']() + __napiInstance.exports['__napi_register__return_undefined_137']() + __napiInstance.exports['__napi_register__add_138']() + __napiInstance.exports['__napi_register__fibonacci_139']() + __napiInstance.exports['__napi_register__list_obj_keys_140']() + __napiInstance.exports['__napi_register__create_obj_141']() + __napiInstance.exports['__napi_register__get_global_142']() + __napiInstance.exports['__napi_register__get_undefined_143']() + __napiInstance.exports['__napi_register__get_null_144']() + __napiInstance.exports['__napi_register__receive_all_optional_object_145']() + __napiInstance.exports['__napi_register__AliasedEnum_146']() + __napiInstance.exports['__napi_register__fn_received_aliased_147']() + __napiInstance.exports['__napi_register__receive_strict_object_148']() + __napiInstance.exports['__napi_register__get_str_from_object_149']() + __napiInstance.exports['__napi_register__create_obj_with_property_150']() + __napiInstance.exports['__napi_register__getter_from_obj_151']() + __napiInstance.exports['__napi_register__receive_object_only_from_js_152']() + __napiInstance.exports['__napi_register__async_plus_100_153']() + __napiInstance.exports['__napi_register__JsRepo_struct_154']() + __napiInstance.exports['__napi_register__JsRepo_impl_155']() + __napiInstance.exports['__napi_register__JsRemote_struct_156']() + __napiInstance.exports['__napi_register__JsRemote_impl_157']() + __napiInstance.exports['__napi_register__CSSRuleList_struct_158']() + __napiInstance.exports['__napi_register__CSSRuleList_impl_159']() + __napiInstance.exports['__napi_register__CSSStyleSheet_struct_160']() + __napiInstance.exports['__napi_register__AnotherCSSStyleSheet_struct_161']() + __napiInstance.exports['__napi_register__AnotherCSSStyleSheet_impl_162']() + __napiInstance.exports['__napi_register__CSSStyleSheet_impl_163']() + __napiInstance.exports['__napi_register__read_package_json_164']() + __napiInstance.exports['__napi_register__get_package_json_name_165']() + __napiInstance.exports['__napi_register__test_serde_roundtrip_166']() + __napiInstance.exports['__napi_register__test_serde_big_number_precision_167']() + __napiInstance.exports['__napi_register__return_from_shared_crate_168']() + __napiInstance.exports['__napi_register__contains_169']() + __napiInstance.exports['__napi_register__concat_str_170']() + __napiInstance.exports['__napi_register__concat_utf16_171']() + __napiInstance.exports['__napi_register__concat_latin1_172']() + __napiInstance.exports['__napi_register__roundtrip_str_173']() + __napiInstance.exports['__napi_register__set_symbol_in_obj_174']() + __napiInstance.exports['__napi_register__create_symbol_175']() + __napiInstance.exports['__napi_register__create_symbol_for_176']() + __napiInstance.exports['__napi_register__DelaySum_impl_177']() + __napiInstance.exports['__napi_register__without_abort_controller_178']() + __napiInstance.exports['__napi_register__with_abort_controller_179']() + __napiInstance.exports['__napi_register__call_threadsafe_function_180']() + __napiInstance.exports['__napi_register__call_long_threadsafe_function_181']() + __napiInstance.exports['__napi_register__threadsafe_function_throw_error_182']() + __napiInstance.exports['__napi_register__threadsafe_function_fatal_mode_183']() + __napiInstance.exports['__napi_register__threadsafe_function_fatal_mode_error_184']() + __napiInstance.exports['__napi_register__threadsafe_function_closure_capture_185']() + __napiInstance.exports['__napi_register__tsfn_call_with_callback_186']() + __napiInstance.exports['__napi_register__tsfn_async_call_187']() + __napiInstance.exports['__napi_register__accept_threadsafe_function_188']() + __napiInstance.exports['__napi_register__accept_threadsafe_function_fatal_189']() + __napiInstance.exports['__napi_register__accept_threadsafe_function_tuple_args_190']() + __napiInstance.exports['__napi_register__tsfn_return_promise_191']() + __napiInstance.exports['__napi_register__tsfn_return_promise_timeout_192']() + __napiInstance.exports['__napi_register__tsfn_throw_from_js_193']() + __napiInstance.exports['__napi_register__get_buffer_194']() + __napiInstance.exports['__napi_register__append_buffer_195']() + __napiInstance.exports['__napi_register__get_empty_buffer_196']() + __napiInstance.exports['__napi_register__convert_u32_array_197']() + __napiInstance.exports['__napi_register__create_external_typed_array_198']() + __napiInstance.exports['__napi_register__mutate_typed_array_199']() + __napiInstance.exports['__napi_register__deref_uint8_array_200']() + __napiInstance.exports['__napi_register__buffer_pass_through_201']() + __napiInstance.exports['__napi_register__array_buffer_pass_through_202']() + __napiInstance.exports['__napi_register__AsyncBuffer_impl_203']() + __napiInstance.exports['__napi_register__async_reduce_buffer_204']() + __napiInstance.exports['__napi_register__run_script_205']() +} + +const binding = __napiModule.exports +const { Animal, AnimalWithDefaultConstructor, AnotherClassForEither, AnotherCssStyleSheet, AnotherCSSStyleSheet, Asset, JsAsset, Assets, JsAssets, Bird, Blake2BHasher, Blake2bHasher, Blake2BKey, Blake2bKey, ClassWithFactory, Context, CssRuleList, CSSRuleList, CssStyleSheet, CSSStyleSheet, CustomFinalize, Dog, Fib, Fib2, Fib3, GetterSetterWithClosures, JsClassForEither, JsRemote, JsRepo, NinjaTurtle, NotWritableClass, Optional, Selector, Width, acceptThreadsafeFunction, acceptThreadsafeFunctionFatal, acceptThreadsafeFunctionTupleArgs, add, ALIAS, AliasedEnum, appendBuffer, arrayBufferPassThrough, asyncMultiTwo, asyncPlus100, asyncReduceBuffer, bigintAdd, bigintFromI128, bigintFromI64, bigintGetU64AsString, bufferPassThrough, callbackReturnPromise, callbackReturnPromiseAndSpawn, callLongThreadsafeFunction, callThreadsafeFunction, captureErrorInCallback, chronoDateAdd1Minute, chronoDateToMillis, chronoNativeDateTime, chronoNativeDateTimeReturn, concatLatin1, concatStr, concatUtf16, contains, convertU32Array, createBigInt, createBigIntI64, createExternal, createExternalString, createExternalTypedArray, createObj, createObjectWithClassField, createObjWithProperty, createSymbol, createSymbolFor, CustomNumEnum, customStatusCode, dateToNumber, DEFAULT_COST, derefUint8Array, either3, either4, eitherBoolOrFunction, eitherFromObjects, eitherFromOption, eitherStringOrNumber, Empty, enumToI32, fibonacci, fnReceivedAliased, getBuffer, getCwd, getEmptyBuffer, getExternal, getGlobal, getMapping, getNestedNumArr, getNull, getNumArr, getNums, getPackageJsonName, getStrFromObject, getterFromObj, getUndefined, getWords, Kind, listObjKeys, mapOption, mutateExternal, mutateTypedArray, optionEnd, optionOnly, optionStart, optionStartEnd, overrideIndividualArgOnFunction, overrideIndividualArgOnFunctionWithCbArg, panic, plusOne, promiseInEither, readFile, readFileAsync, readPackageJson, receiveAllOptionalObject, receiveClassOrNumber, receiveDifferentClass, receiveMutClassOrNumber, receiveObjectOnlyFromJs, receiveObjectWithClassField, receiveStrictObject, receiveString, returnEither, returnEitherClass, returnFromSharedCrate, returnJsFunction, returnNull, returnUndefined, returnUndefinedIfInvalid, returnUndefinedIfInvalidPromise, roundtripStr, runScript, setSymbolInObj, Status, sumMapping, sumNums, testSerdeBigNumberPrecision, testSerdeRoundtrip, threadsafeFunctionClosureCapture, threadsafeFunctionFatalMode, threadsafeFunctionFatalModeError, threadsafeFunctionThrowError, throwAsyncError, throwError, toJsObj, tsfnAsyncCall, tsfnCallWithCallback, tsfnReturnPromise, tsfnReturnPromiseTimeout, tsfnThrowFromJs, tsRename, validateArray, validateBigint, validateBoolean, validateBuffer, validateDate, validateDateTime, validateExternal, validateFunction, validateHashMap, validateNull, validateNumber, validateOptional, validatePromise, validateString, validateSymbol, validateTypedArray, validateUndefined, withAbortController, withoutAbortController, xxh64Alias, xxh2, xxh3 } = binding +export { + Animal, + AnimalWithDefaultConstructor, + AnotherClassForEither, + AnotherCssStyleSheet, + AnotherCSSStyleSheet, + Asset, + JsAsset, + Assets, + JsAssets, + Bird, + Blake2BHasher, + Blake2bHasher, + Blake2BKey, + Blake2bKey, + ClassWithFactory, + Context, + CssRuleList, + CSSRuleList, + CssStyleSheet, + CSSStyleSheet, + CustomFinalize, + Dog, + Fib, + Fib2, + Fib3, + GetterSetterWithClosures, + JsClassForEither, + JsRemote, + JsRepo, + NinjaTurtle, + NotWritableClass, + Optional, + Selector, + Width, + acceptThreadsafeFunction, + acceptThreadsafeFunctionFatal, + acceptThreadsafeFunctionTupleArgs, + add, + ALIAS, + AliasedEnum, + appendBuffer, + arrayBufferPassThrough, + asyncMultiTwo, + asyncPlus100, + asyncReduceBuffer, + bigintAdd, + bigintFromI128, + bigintFromI64, + bigintGetU64AsString, + bufferPassThrough, + callbackReturnPromise, + callbackReturnPromiseAndSpawn, + callLongThreadsafeFunction, + callThreadsafeFunction, + captureErrorInCallback, + chronoDateAdd1Minute, + chronoDateToMillis, + chronoNativeDateTime, + chronoNativeDateTimeReturn, + concatLatin1, + concatStr, + concatUtf16, + contains, + convertU32Array, + createBigInt, + createBigIntI64, + createExternal, + createExternalString, + createExternalTypedArray, + createObj, + createObjectWithClassField, + createObjWithProperty, + createSymbol, + createSymbolFor, + CustomNumEnum, + customStatusCode, + dateToNumber, + DEFAULT_COST, + derefUint8Array, + either3, + either4, + eitherBoolOrFunction, + eitherFromObjects, + eitherFromOption, + eitherStringOrNumber, + Empty, + enumToI32, + fibonacci, + fnReceivedAliased, + getBuffer, + getCwd, + getEmptyBuffer, + getExternal, + getGlobal, + getMapping, + getNestedNumArr, + getNull, + getNumArr, + getNums, + getPackageJsonName, + getStrFromObject, + getterFromObj, + getUndefined, + getWords, + Kind, + listObjKeys, + mapOption, + mutateExternal, + mutateTypedArray, + optionEnd, + optionOnly, + optionStart, + optionStartEnd, + overrideIndividualArgOnFunction, + overrideIndividualArgOnFunctionWithCbArg, + panic, + plusOne, + promiseInEither, + readFile, + readFileAsync, + readPackageJson, + receiveAllOptionalObject, + receiveClassOrNumber, + receiveDifferentClass, + receiveMutClassOrNumber, + receiveObjectOnlyFromJs, + receiveObjectWithClassField, + receiveStrictObject, + receiveString, + returnEither, + returnEitherClass, + returnFromSharedCrate, + returnJsFunction, + returnNull, + returnUndefined, + returnUndefinedIfInvalid, + returnUndefinedIfInvalidPromise, + roundtripStr, + runScript, + setSymbolInObj, + Status, + sumMapping, + sumNums, + testSerdeBigNumberPrecision, + testSerdeRoundtrip, + threadsafeFunctionClosureCapture, + threadsafeFunctionFatalMode, + threadsafeFunctionFatalModeError, + threadsafeFunctionThrowError, + throwAsyncError, + throwError, + toJsObj, + tsfnAsyncCall, + tsfnCallWithCallback, + tsfnReturnPromise, + tsfnReturnPromiseTimeout, + tsfnThrowFromJs, + tsRename, + validateArray, + validateBigint, + validateBoolean, + validateBuffer, + validateDate, + validateDateTime, + validateExternal, + validateFunction, + validateHashMap, + validateNull, + validateNumber, + validateOptional, + validatePromise, + validateString, + validateSymbol, + validateTypedArray, + validateUndefined, + withAbortController, + withoutAbortController, + xxh64Alias, + xxh2, + xxh3 +} diff --git a/examples/napi/package.json b/examples/napi/package.json index 3fe0bbd2..12d23751 100644 --- a/examples/napi/package.json +++ b/examples/napi/package.json @@ -3,11 +3,11 @@ "private": true, "version": "0.0.0", "type": "module", - "main": "./index.node", + "main": "./index.js", "types": "./index.d.ts", "scripts": { - "build": "napi-raw build --no-js", - "test": "cross-env TS_NODE_PROJECT=./tsconfig.json node --es-module-specifier-resolution=node --loader ts-node/esm/transpile-only ../../node_modules/ava/entrypoints/cli.mjs" + "build": "napi-raw build", + "test": "cross-env TS_NODE_PROJECT=./tsconfig.json node --es-module-specifier-resolution=node --loader ts-node/esm/transpile-only --experimental-wasi-unstable-preview1 ../../node_modules/ava/entrypoints/cli.mjs" }, "devDependencies": { "@napi-rs/cli": "workspace:*", @@ -25,11 +25,15 @@ "cjs": true }, "files": [ - "__tests__/**/*.spec.ts", - "__tests__/**/*.spec.cts", - "__tests__/**/*.spec.js", - "__tests__/**/*.spec.cjs" + "__tests__/**/*.spec.{ts,cts,js,cjs,mjs}" ], "timeout": "10m" + }, + "dependencies": { + "@emnapi/core": "0.43.1", + "@tybys/wasm-util": "^0.8.0", + "@types/lodash": "^4.14.191", + "lodash": "^4.17.21", + "sinon": "^15.0.1" } } diff --git a/examples/napi/src/async.rs b/examples/napi/src/async.rs index 5220ecfc..6d762107 100644 --- a/examples/napi/src/async.rs +++ b/examples/napi/src/async.rs @@ -1,18 +1,29 @@ +#[cfg(not(target_arch = "wasm32"))] use futures::prelude::*; use napi::bindgen_prelude::*; -use napi::tokio::{self, fs}; +use napi::tokio; +#[cfg(not(target_arch = "wasm32"))] +use napi::tokio::fs; #[napi] async fn read_file_async(path: String) -> Result { - fs::read(path) - .map(|r| match r { - Ok(content) => Ok(content.into()), - Err(e) => Err(Error::new( - Status::GenericFailure, - format!("failed to read file, {}", e), - )), - }) - .await + #[cfg(not(target_arch = "wasm32"))] + { + fs::read(path) + .map(|r| match r { + Ok(content) => Ok(content.into()), + Err(e) => Err(Error::new( + Status::GenericFailure, + format!("failed to read file, {}", e), + )), + }) + .await + } + #[cfg(target_arch = "wasm32")] + { + let conetent = std::fs::read(path)?; + Ok(conetent.into()) + } } #[napi] diff --git a/examples/napi/tsconfig.esm.json b/examples/napi/tsconfig.esm.json new file mode 100644 index 00000000..a3abe66d --- /dev/null +++ b/examples/napi/tsconfig.esm.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ESNext" + } +} diff --git a/examples/napi/tsconfig.json b/examples/napi/tsconfig.json index dd161b20..1d513f26 100644 --- a/examples/napi/tsconfig.json +++ b/examples/napi/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../tsconfig.json", "include": ["."], "compilerOptions": { + "moduleResolution": "node", "outDir": "./dist", "rootDir": ".", "target": "ESNext", @@ -11,5 +12,11 @@ "types": ["bun-types"], "importHelpers": false }, - "exclude": ["dist", "electron.cjs", "electron-renderer", "node_modules"] + "exclude": [ + "dist", + "electron.js", + "electron-renderer", + "index.js", + "index.wasi.mjs" + ] } diff --git a/examples/napi/wasi-worker.mjs b/examples/napi/wasi-worker.mjs new file mode 100644 index 00000000..d23c9501 --- /dev/null +++ b/examples/napi/wasi-worker.mjs @@ -0,0 +1,51 @@ +import fs from "node:fs"; +import { createRequire } from "node:module"; +import { parentPort, Worker } from "node:worker_threads"; + +import { instantiateNapiModuleSync, MessageHandler } from "@emnapi/core"; +import { WASI } from "@tybys/wasm-util"; + +const require = createRequire(import.meta.url); + +if (parentPort) { + parentPort.on("message", (data) => { + globalThis.onmessage({ data }); + }); +} + +Object.assign(globalThis, { + self: globalThis, + require, + Worker, + importScripts: function (f) { + ;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f); + }, + postMessage: function (msg) { + if (parentPort) { + parentPort.postMessage(msg); + } + }, +}); + +const handler = new MessageHandler({ + onLoad({ wasmModule, wasmMemory }) { + const wasi = new WASI({ fs }); + + return instantiateNapiModuleSync(wasmModule, { + childThread: true, + wasi, + overwriteImports(importObject) { + importObject.env = { + ...importObject.env, + ...importObject.napi, + ...importObject.emnapi, + memory: wasmMemory + }; + }, + }); + }, +}); + +globalThis.onmessage = function (e) { + handler.handle(e); +}; diff --git a/package.json b/package.json index f8950f2f..6d9d6e69 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "c8": "^8.0.0", "cross-env": "^7.0.3", "electron": "^27.0.0", - "esbuild": "^0.19.0", + "esbuild": "^0.19.5", "eslint": "^8.45.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.27.5", diff --git a/triples/generate-triple-list.ts b/triples/generate-triple-list.ts index 6a3f313d..e1f1da2c 100644 --- a/triples/generate-triple-list.ts +++ b/triples/generate-triple-list.ts @@ -23,7 +23,7 @@ const tripleLists: { [key: string]: { platform?: string } } = RAW_LIST.trim() .split('\n') .filter((line) => !line.startsWith('wasm') && line.trim().length) .map(parseTriple) - .reduce((acc, cur) => { + .reduce((acc: Record, cur) => { acc[cur.triple] = cur return acc }, {}) diff --git a/triples/tsconfig.json b/triples/tsconfig.json new file mode 100644 index 00000000..c0edd92c --- /dev/null +++ b/triples/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true + }, + "include": ["."] +} diff --git a/tsconfig.root-lint.json b/tsconfig.root-lint.json index 79782f3b..bf852398 100644 --- a/tsconfig.root-lint.json +++ b/tsconfig.root-lint.json @@ -5,6 +5,9 @@ "./triples/index.js", "./memory-testing/*.js", "./memory-testing/*.mjs", - "./crates/cli/index.js" + "./crates/cli/index.js", + "./examples/**/*.js", + "./examples/**/*.mjs", + "./examples/**/*.cjs" ] } diff --git a/yarn.lock b/yarn.lock index 9214d7ae..9941dadd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -125,156 +125,174 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/android-arm64@npm:0.19.0" +"@emnapi/core@npm:0.43.1": + version: 0.43.1 + resolution: "@emnapi/core@npm:0.43.1" + dependencies: + tslib: ^2.4.0 + checksum: 5bd6bce73883ef4db9347c853dfecb7851cd8b60de21099ffe8be5fec7383df0f73c3e702a1f15f37e43493a766320a1d506296925b02fe88b265031d820a94a + languageName: node + linkType: hard + +"@emnapi/runtime@npm:0.43.1": + version: 0.43.1 + resolution: "@emnapi/runtime@npm:0.43.1" + dependencies: + tslib: ^2.4.0 + checksum: 61ebf7346d745f87648b5a4373aa80aed7c731526615544253cbbcb50f1d0cc1159ca6504b6c67ce0df55d6afdd65ae272f988d03d01d568308ffc9f1f7dbfbb + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-arm64@npm:0.19.5" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/android-arm@npm:0.19.0" +"@esbuild/android-arm@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-arm@npm:0.19.5" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/android-x64@npm:0.19.0" +"@esbuild/android-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-x64@npm:0.19.5" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/darwin-arm64@npm:0.19.0" +"@esbuild/darwin-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/darwin-arm64@npm:0.19.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/darwin-x64@npm:0.19.0" +"@esbuild/darwin-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/darwin-x64@npm:0.19.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/freebsd-arm64@npm:0.19.0" +"@esbuild/freebsd-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/freebsd-arm64@npm:0.19.5" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/freebsd-x64@npm:0.19.0" +"@esbuild/freebsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/freebsd-x64@npm:0.19.5" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-arm64@npm:0.19.0" +"@esbuild/linux-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-arm64@npm:0.19.5" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-arm@npm:0.19.0" +"@esbuild/linux-arm@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-arm@npm:0.19.5" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-ia32@npm:0.19.0" +"@esbuild/linux-ia32@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-ia32@npm:0.19.5" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-loong64@npm:0.19.0" +"@esbuild/linux-loong64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-loong64@npm:0.19.5" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-mips64el@npm:0.19.0" +"@esbuild/linux-mips64el@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-mips64el@npm:0.19.5" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-ppc64@npm:0.19.0" +"@esbuild/linux-ppc64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-ppc64@npm:0.19.5" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-riscv64@npm:0.19.0" +"@esbuild/linux-riscv64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-riscv64@npm:0.19.5" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-s390x@npm:0.19.0" +"@esbuild/linux-s390x@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-s390x@npm:0.19.5" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/linux-x64@npm:0.19.0" +"@esbuild/linux-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-x64@npm:0.19.5" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/netbsd-x64@npm:0.19.0" +"@esbuild/netbsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/netbsd-x64@npm:0.19.5" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/openbsd-x64@npm:0.19.0" +"@esbuild/openbsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/openbsd-x64@npm:0.19.5" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/sunos-x64@npm:0.19.0" +"@esbuild/sunos-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/sunos-x64@npm:0.19.5" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/win32-arm64@npm:0.19.0" +"@esbuild/win32-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-arm64@npm:0.19.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/win32-ia32@npm:0.19.0" +"@esbuild/win32-ia32@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-ia32@npm:0.19.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.19.0": - version: 0.19.0 - resolution: "@esbuild/win32-x64@npm:0.19.0" +"@esbuild/win32-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-x64@npm:0.19.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -335,7 +353,9 @@ __metadata: version: 0.0.0-use.local resolution: "@examples/napi@workspace:examples/napi" dependencies: + "@emnapi/core": 0.43.1 "@napi-rs/cli": "workspace:*" + "@tybys/wasm-util": ^0.8.0 "@types/lodash": ^4.14.195 ava: ^5.3.1 cross-env: 7.0.3 @@ -498,7 +518,11 @@ __metadata: version: 0.0.0-use.local resolution: "@napi-rs/cli@workspace:cli" dependencies: + "@emnapi/core": 0.43.1 + "@emnapi/runtime": 0.43.1 "@octokit/rest": ^20.0.1 + "@tybys/wasm-util": 0.8.0 + "@types/debug": ^4.1.7 "@types/inquirer": ^9.0.3 "@types/js-yaml": ^4.0.5 "@types/lodash-es": ^4.17.8 @@ -506,14 +530,29 @@ __metadata: clipanion: ^3.2.1 colorette: ^2.0.20 debug: ^4.3.4 - esbuild: ^0.19.0 + emnapi: 0.43.1 + env-paths: ^3.0.0 + esbuild: ^0.19.5 inquirer: ^9.2.8 js-yaml: ^4.1.0 lodash-es: ^4.17.21 prettier: ^3.0.0 + toml: ^3.0.0 ts-node: ^10.9.1 + tslib: ^2.6.1 typanion: ^3.13.0 typescript: ^5.1.6 + peerDependencies: + "@emnapi/runtime": 0.43.1 + "@tybys/wasm-util": 0.8.0 + emnapi: 0.43.1 + peerDependenciesMeta: + "@emnapi/runtime": + optional: true + "@tybys/wasm-util": + optional: true + emnapi: + optional: true bin: napi: ./dist/cli.js napi-raw: ./cli.mjs @@ -1281,6 +1320,15 @@ __metadata: languageName: node linkType: hard +"@tybys/wasm-util@npm:0.8.0, @tybys/wasm-util@npm:^0.8.0": + version: 0.8.0 + resolution: "@tybys/wasm-util@npm:0.8.0" + dependencies: + tslib: ^2.4.0 + checksum: ce110aa721abe0c31f93c25c0abcc621bcc03a30f1927fe940e13456ef30438f140ec436dfe6d2a288814299d68215b071e986bca8ed97dfc3108f80ad214093 + languageName: node + linkType: hard + "@types/cacheable-request@npm:^6.0.1": version: 6.0.3 resolution: "@types/cacheable-request@npm:6.0.3" @@ -1293,7 +1341,7 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:^4.1.8": +"@types/debug@npm:^4.1.7, @types/debug@npm:^4.1.8": version: 4.1.8 resolution: "@types/debug@npm:4.1.8" dependencies: @@ -1421,16 +1469,16 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:^20.4.2": - version: 20.4.5 - resolution: "@types/node@npm:20.4.5" - checksum: 36a0304a8dc346a1b2d2edac4c4633eecf70875793d61a5274d0df052d7a7af7a8e34f29884eac4fbd094c4f0201477dcb39c0ecd3307ca141688806538d1138 + version: 20.4.4 + resolution: "@types/node@npm:20.4.4" + checksum: 43f3c4a8acc38ae753e15a0e79bae0447d255b3742fa87f8e065d7b9d20ecb0e03d6c5b46c00d5d26f4552160381a00255f49205595a8ee48c2423e00263c930 languageName: node linkType: hard "@types/node@npm:^18.11.18": - version: 18.17.1 - resolution: "@types/node@npm:18.17.1" - checksum: 56201bda9a2d05d68602df63b4e67b0545ac8c6d0280bd5fb31701350a978a577a027501fbf49db99bf177f2242ebd1244896bfd35e89042d5bd7dfebff28d4e + version: 18.17.0 + resolution: "@types/node@npm:18.17.0" + checksum: 3a43c5c5541342751b514485144818a515fac5427f663066068eaacbe8a108cbe1207aae75ec89d34c3b32414c334aad84e9083cf7fcf3ebfd970adc871314a4 languageName: node linkType: hard @@ -1508,14 +1556,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.0.0": - version: 6.2.1 - resolution: "@typescript-eslint/eslint-plugin@npm:6.2.1" + version: 6.2.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.2.0" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.2.1 - "@typescript-eslint/type-utils": 6.2.1 - "@typescript-eslint/utils": 6.2.1 - "@typescript-eslint/visitor-keys": 6.2.1 + "@typescript-eslint/scope-manager": 6.2.0 + "@typescript-eslint/type-utils": 6.2.0 + "@typescript-eslint/utils": 6.2.0 + "@typescript-eslint/visitor-keys": 6.2.0 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -1529,44 +1577,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: e73f3fe36519d895037d223f3ddf200b97e17bcde9390984118c38733add1edf996357c809ec2db92cec61bc7c9e5a3d9a583e0d0f92fa9c3919b68716a27b37 + checksum: 1ef46b1c2e3e2013f66b4982dcfb9e198a3824cc1503b843e553201a108a3cb6e4adfb2c486158c89d993e5e4b9d99aeb2af28297e43da98c4750dae8f5131b5 languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.0.0": - version: 6.2.1 - resolution: "@typescript-eslint/parser@npm:6.2.1" + version: 6.2.0 + resolution: "@typescript-eslint/parser@npm:6.2.0" dependencies: - "@typescript-eslint/scope-manager": 6.2.1 - "@typescript-eslint/types": 6.2.1 - "@typescript-eslint/typescript-estree": 6.2.1 - "@typescript-eslint/visitor-keys": 6.2.1 + "@typescript-eslint/scope-manager": 6.2.0 + "@typescript-eslint/types": 6.2.0 + "@typescript-eslint/typescript-estree": 6.2.0 + "@typescript-eslint/visitor-keys": 6.2.0 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: cf4768cbfc696ce1d4b15ae55b3d2b52761e91a4a80e738cf3a75c501c2257d735cd6e462567965069d0d693a8cf5463ab9e8b97c36c6ed1fccd3c1c09855bdb + checksum: ba79674f2d4599a24c7afa8f18ec28243b80df39f82a4a6b7a4ce7c584ec37d4ade40a3aa058d597a5cbf71647a40d0995866748d14cf4b52d8ad4420d10f669 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.2.1": - version: 6.2.1 - resolution: "@typescript-eslint/scope-manager@npm:6.2.1" +"@typescript-eslint/scope-manager@npm:6.2.0": + version: 6.2.0 + resolution: "@typescript-eslint/scope-manager@npm:6.2.0" dependencies: - "@typescript-eslint/types": 6.2.1 - "@typescript-eslint/visitor-keys": 6.2.1 - checksum: 3bb461678c7e729895c5ac16781ec7d66efc6ffa944bb49693ce8e9560f9a6cac70929157c0fc0875b2829ae19a5cdabb97973ddcfb7e81c16e22cdd5d39e3fd + "@typescript-eslint/types": 6.2.0 + "@typescript-eslint/visitor-keys": 6.2.0 + checksum: 75a650a3ede78bf841a3bf3f4880b94a06aa4c420f399a6fb9faee19a2e5998f7e330a13f78e07c4958413345bab58b0593f09fa163a77e8f6353012e795660c languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.2.1": - version: 6.2.1 - resolution: "@typescript-eslint/type-utils@npm:6.2.1" +"@typescript-eslint/type-utils@npm:6.2.0": + version: 6.2.0 + resolution: "@typescript-eslint/type-utils@npm:6.2.0" dependencies: - "@typescript-eslint/typescript-estree": 6.2.1 - "@typescript-eslint/utils": 6.2.1 + "@typescript-eslint/typescript-estree": 6.2.0 + "@typescript-eslint/utils": 6.2.0 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -1574,23 +1622,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 7f8d80f03e6ddc1838307a2a4df61dc4bd8400efb9dcc7316063ae293fce54afad238404a0c25cd2cdaceee73ae514f254b850bd7ff11e2def700d5d6b90af05 + checksum: 9adb542fb3c49bf5c1fecca98549bee3fcfd28a0ceee5227817a1ceb0841b912e322f58ba1b3ca98a47fc998cbec0a3d69cacb9cf9ac4be1d133b11bb9d53aae languageName: node linkType: hard -"@typescript-eslint/types@npm:6.2.1": - version: 6.2.1 - resolution: "@typescript-eslint/types@npm:6.2.1" - checksum: 388d32f15a9db8ad5d80794caf9ab280d6e5a428efdf4f6a6dfc4069afe4d19da32d628acf638e4c5b92ee77a9a18eecf728a778a3b91cc8a24484af579fc9cf +"@typescript-eslint/types@npm:6.2.0": + version: 6.2.0 + resolution: "@typescript-eslint/types@npm:6.2.0" + checksum: 81878866cf7f49dbc335cce05adfbd994f348e2ebe9538fd6e934fa82e44186c16b2112b8d5f9f4c528ea127be157185be5e35e4913db4880d20ac495785baaf languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.2.1": - version: 6.2.1 - resolution: "@typescript-eslint/typescript-estree@npm:6.2.1" +"@typescript-eslint/typescript-estree@npm:6.2.0": + version: 6.2.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.2.0" dependencies: - "@typescript-eslint/types": 6.2.1 - "@typescript-eslint/visitor-keys": 6.2.1 + "@typescript-eslint/types": 6.2.0 + "@typescript-eslint/visitor-keys": 6.2.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -1599,34 +1647,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 3d9beeb5e36b8827de5c160ed8e5c111dd66ca00671b183409b051e242b291480679b900bb74aaf4895dcae49497037567d3fcbbe67fa9930786ddd01c685f04 + checksum: 5bfd5bf09feff6c4807cfa65cf407dd0249f7d487d6820941dd05999ee35cacdabaacadf23c92b90b57920025e93088e93924bc8df41f393ac0366538eb2902f languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.2.1": - version: 6.2.1 - resolution: "@typescript-eslint/utils@npm:6.2.1" +"@typescript-eslint/utils@npm:6.2.0": + version: 6.2.0 + resolution: "@typescript-eslint/utils@npm:6.2.0" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.2.1 - "@typescript-eslint/types": 6.2.1 - "@typescript-eslint/typescript-estree": 6.2.1 + "@typescript-eslint/scope-manager": 6.2.0 + "@typescript-eslint/types": 6.2.0 + "@typescript-eslint/typescript-estree": 6.2.0 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: d16356a633f39d988a9af159da15e28c6a28fa47abce372061c79cf186d193d148e1c32862c9702ff87e2a06f7a2f82773e4b56320a39f432f4b1a989f8005ad + checksum: 54f062412a8ce23554ca4063d275327981640426b1ecd1073d30dd8b9464ff7af68b8f9f6272033bad9307815d56f2f922faa8a995421efdccd6165dd62557e1 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.2.1": - version: 6.2.1 - resolution: "@typescript-eslint/visitor-keys@npm:6.2.1" +"@typescript-eslint/visitor-keys@npm:6.2.0": + version: 6.2.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.2.0" dependencies: - "@typescript-eslint/types": 6.2.1 + "@typescript-eslint/types": 6.2.0 eslint-visitor-keys: ^3.4.1 - checksum: c05a1c45129f2cf9a8c49dadc3da10b675232e59b69dfe9fdc0bfb45d3be077ceff78097baf50e502dab3e71ce9fd799d2015e356a4be2787ee10c6c7a44ea8a + checksum: b400c657c7e5c65b289304f6f5cee6536f23b3441306f82aff2d2e047e13770330715d4f7b29e734b0b2dab6030e41028894d5cd441696115bfea43ad18b2c54 languageName: node linkType: hard @@ -3357,6 +3405,18 @@ __metadata: languageName: node linkType: hard +"emnapi@npm:0.43.1": + version: 0.43.1 + resolution: "emnapi@npm:0.43.1" + peerDependencies: + node-addon-api: ">= 6.1.0" + peerDependenciesMeta: + node-addon-api: + optional: true + checksum: 0b5940adaa8f165fdd3cdbc155d6514bd32b449732a0746bfb0dbd190816f16f942a59d32d3d9a978b391bf86df941496ef0c9502de94e10bd8ba79ea5afa730 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -3405,6 +3465,13 @@ __metadata: languageName: node linkType: hard +"env-paths@npm:^3.0.0": + version: 3.0.0 + resolution: "env-paths@npm:3.0.0" + checksum: b2b0a0d0d9931a13d279c22ed94d78648a1cc5f408f05d47ff3e0c1616f0aa0c38fb33deec5e5be50497225d500607d57f9c8652c4d39c2f2b7608cd45768128 + languageName: node + linkType: hard + "envinfo@npm:7.8.1": version: 7.8.1 resolution: "envinfo@npm:7.8.1" @@ -3515,32 +3582,32 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.19.0": - version: 0.19.0 - resolution: "esbuild@npm:0.19.0" +"esbuild@npm:^0.19.5": + version: 0.19.5 + resolution: "esbuild@npm:0.19.5" dependencies: - "@esbuild/android-arm": 0.19.0 - "@esbuild/android-arm64": 0.19.0 - "@esbuild/android-x64": 0.19.0 - "@esbuild/darwin-arm64": 0.19.0 - "@esbuild/darwin-x64": 0.19.0 - "@esbuild/freebsd-arm64": 0.19.0 - "@esbuild/freebsd-x64": 0.19.0 - "@esbuild/linux-arm": 0.19.0 - "@esbuild/linux-arm64": 0.19.0 - "@esbuild/linux-ia32": 0.19.0 - "@esbuild/linux-loong64": 0.19.0 - "@esbuild/linux-mips64el": 0.19.0 - "@esbuild/linux-ppc64": 0.19.0 - "@esbuild/linux-riscv64": 0.19.0 - "@esbuild/linux-s390x": 0.19.0 - "@esbuild/linux-x64": 0.19.0 - "@esbuild/netbsd-x64": 0.19.0 - "@esbuild/openbsd-x64": 0.19.0 - "@esbuild/sunos-x64": 0.19.0 - "@esbuild/win32-arm64": 0.19.0 - "@esbuild/win32-ia32": 0.19.0 - "@esbuild/win32-x64": 0.19.0 + "@esbuild/android-arm": 0.19.5 + "@esbuild/android-arm64": 0.19.5 + "@esbuild/android-x64": 0.19.5 + "@esbuild/darwin-arm64": 0.19.5 + "@esbuild/darwin-x64": 0.19.5 + "@esbuild/freebsd-arm64": 0.19.5 + "@esbuild/freebsd-x64": 0.19.5 + "@esbuild/linux-arm": 0.19.5 + "@esbuild/linux-arm64": 0.19.5 + "@esbuild/linux-ia32": 0.19.5 + "@esbuild/linux-loong64": 0.19.5 + "@esbuild/linux-mips64el": 0.19.5 + "@esbuild/linux-ppc64": 0.19.5 + "@esbuild/linux-riscv64": 0.19.5 + "@esbuild/linux-s390x": 0.19.5 + "@esbuild/linux-x64": 0.19.5 + "@esbuild/netbsd-x64": 0.19.5 + "@esbuild/openbsd-x64": 0.19.5 + "@esbuild/sunos-x64": 0.19.5 + "@esbuild/win32-arm64": 0.19.5 + "@esbuild/win32-ia32": 0.19.5 + "@esbuild/win32-x64": 0.19.5 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -3588,7 +3655,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 77ef2e57a94d1b88657fb6cd79c3ad6e3161823fd1b615f2ce4b71f163755b85e98cb5b565ed6c38db1f788c52c092b5534caa6800178de99a25de0671f92186 + checksum: 5a0227cf6ffffa3076714d88230af1dfdd2fc363d91bd712a81fb91230c315a395e2c9b7588eee62986aeebf4999804b9b1b59eeab8e2457184eb0056bfe20c8 languageName: node linkType: hard @@ -6530,7 +6597,7 @@ __metadata: c8: ^8.0.0 cross-env: ^7.0.3 electron: ^27.0.0 - esbuild: ^0.19.0 + esbuild: ^0.19.5 eslint: ^8.45.0 eslint-config-prettier: ^9.0.0 eslint-plugin-import: ^2.27.5 @@ -8903,6 +8970,13 @@ __metadata: languageName: node linkType: hard +"toml@npm:^3.0.0": + version: 3.0.0 + resolution: "toml@npm:3.0.0" + checksum: 5d7f1d8413ad7780e9bdecce8ea4c3f5130dd53b0a4f2e90b93340979a137739879d7b9ce2ce05c938b8cc828897fe9e95085197342a1377dd8850bf5125f15f + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -8987,7 +9061,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0, tslib@npm:^2.6.0": +"tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0, tslib@npm:^2.6.0, tslib@npm:^2.6.1": version: 2.6.1 resolution: "tslib@npm:2.6.1" checksum: b0d176d176487905b66ae4d5856647df50e37beea7571c53b8d10ba9222c074b81f1410fb91da13debaf2cbc970663609068bdebafa844ea9d69b146527c38fe