@napi-rs/cli 3.10.6 → 3.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/wasi.md CHANGED
@@ -539,6 +539,67 @@ pre-created pool, spawning is only a message to an already-running worker,
539
539
  and if the pool is exhausted the fallback allocates a fresh worker that
540
540
  boots once the spawning parent returns to its event loop.
541
541
 
542
+ ## Thread pool preload
543
+
544
+ The threaded Node loader (`<binary>.wasi.cjs`) creates its emnapi worker pool
545
+ empty (`reuseWorker: true`): emnapi's own preload (`reuseWorker.size > 0`)
546
+ cannot run on a synchronous CommonJS load. Without help, every pool thread a
547
+ `MultiThread` runtime spawns on its first async call would first boot a Worker
548
+ and load the wasm into it.
549
+
550
+ An addon built with `napi-async-runtime` exports
551
+ `napi_wasm_runtime_pool_workers() -> u32` on `wasm32-wasip1-threads`: the pool
552
+ threads the runtime will still spawn. That is the configured `MultiThread`
553
+ `worker_threads`, or 0 under `CurrentThread` (also the wasm default before any
554
+ configure), and 0 once the runtime has started (its first async call, or a
555
+ runtime-backed call during module registration): the started runtime already
556
+ spawned all its pool threads and never adds more. So a reconcile after first
557
+ use only releases idle Workers; a thread that starts later (a timer thread, a
558
+ uv thread, a restarted runtime) creates its Worker on demand. It reads an
559
+ atomic and takes no lock, and it comes with the scheduler, so
560
+ `default-features = false` builds have it too. The loader keeps that many
561
+ Workers idle in the pool:
562
+
563
+ - once, right after a successful load (after `#[module_init]` configured the
564
+ runtime);
565
+ - after every successful `configureAsyncRuntime`, when `napi.wasm.asyncRuntime`
566
+ is on. The loader replaces that export with a wrapper (same name, `this`,
567
+ arguments and return value) that calls the original and then reconciles. It
568
+ is matched by name, like the host install above. A configure that throws
569
+ (for example because the runtime already started) propagates and leaves the
570
+ pool alone;
571
+ - whenever you call
572
+ `binding[Symbol.for('napi.rs.wasi.reconcileThreadPool')]()`, published
573
+ non-enumerable and read-only next to the dispose symbol. Use it after
574
+ changing the configuration some other way. Like `napi.rs.wasi.dispose`, the
575
+ symbol lives on the CommonJS loader object. The generated ESM entry
576
+ re-exports named exports only, so an ESM consumer reaches it through
577
+ `createRequire(import.meta.url)('<pkg>-wasm32-wasi')` or the local
578
+ `./<name>.wasi.cjs`.
579
+
580
+ A reconcile creates each missing Worker through `onCreateWorker` (so it is
581
+ tracked, unref'd and gets the crash flags) and starts its load without waiting
582
+ for it; a thread spawn later pops a Worker that is already booting. It
583
+ terminates the idle Workers above the count, newest first, the way a spawn
584
+ takes them. Workers a spawn already took are not in the pool and are left
585
+ alone, so the count only covers idle Workers. A reconcile never throws and
586
+ never waits. It does nothing after a thread crash, once disposal started, or
587
+ for an addon without the export.
588
+
589
+ Two things to know:
590
+
591
+ - A preloaded Worker that fails to load still latches the binding as crashed,
592
+ like any pool Worker: the worker cannot tell a preload from a thread spawn,
593
+ so `dispose()` rejects afterwards. This is by design. The failed Worker is
594
+ taken out of the pool, so a later spawn creates a fresh one.
595
+ - `NAPI_RS_ASYNC_WORK_POOL_SIZE` (or `UV_THREADPOOL_SIZE`, default 4) sizes the
596
+ uv async-work threads, which take their Workers from the same reuse pool. A
597
+ preloaded Worker can therefore end up running a uv thread instead of a
598
+ runtime thread; the runtime thread then creates its own.
599
+
600
+ The browser loaders keep their fixed pre-created pool (see above), and the
601
+ threadless and deferred loaders have no pool.
602
+
542
603
  ## Detecting the threaded target from Rust
543
604
 
544
605
  rustc gives you nothing to tell the two WASI targets apart. `rustc --print
@@ -869,3 +930,10 @@ only through the worker's `'error'` or `'exit'` event, which needs a turn of
869
930
  its event loop, so a cleanup wait already in progress keeps waiting. The same
870
931
  holds before `beforeInit`: a thread spawned while the wasm initializes gets a
871
932
  worker with no view.
933
+
934
+ After a crash, the threaded Node loader's `dispose()` only terminates the pool
935
+ workers and rejects, and from then on it drops the calls into wasm that emnapi
936
+ deferred through the context's `setImmediate` (threadsafe-function finalizers,
937
+ handle closes, the finalizer queue). A worker terminated while it held napi's
938
+ heap-sync lock leaves that lock set, so such a call would free memory on the
939
+ JavaScript thread and spin on the lock for good.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napi-rs/cli",
3
- "version": "3.10.6",
3
+ "version": "3.10.7",
4
4
  "description": "Cli tools for napi-rs",
5
5
  "author": "LongYinan <lynweklm@gmail.com>",
6
6
  "homepage": "https://napi.rs/",