@napi-rs/cli 3.10.4 → 3.10.5

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/build.md CHANGED
@@ -58,3 +58,4 @@ new NapiCli().build({
58
58
  | features | --features,-F | string[] | false | | Space-separated list of features to activate |
59
59
  | allFeatures | --all-features | boolean | false | | Activate all available features |
60
60
  | noDefaultFeatures | --no-default-features | boolean | false | | Do not activate the `default` feature |
61
+ | ohosSign | --ohos-sign | boolean | false | true | Whether to self-sign the built binary for OpenHarmony targets by injecting a `.codesign` fs-verity section, so the `.so` can be loaded on HarmonyOS devices. Only works with `*-unknown-linux-ohos` targets |
package/docs/wasi.md CHANGED
@@ -390,12 +390,16 @@ override the default in either direction:
390
390
 
391
391
  ## Shared async runtime hosts
392
392
 
393
- `CurrentThread` is the only async-runtime flavor on WebAssembly, for both
394
- `wasm32-wasip1` and `wasm32-wasip1-threads`. An addon built with the
395
- `napi-async-runtime` crate therefore makes no progress until a JavaScript task
396
- host publishes its runnable turns, and its timers never fire until a timer host
397
- relays them. Set `napi.wasm.asyncRuntime` and the generated loaders install
398
- both for you:
393
+ `CurrentThread` is the default async-runtime flavor on every WebAssembly
394
+ target, and the only flavor on threadless `wasm32-wasip1`. On
395
+ `wasm32-wasip1-threads` an addon may select `MultiThread` instead — always an
396
+ explicit host act, never a default (see the crate's "Running MultiThread on
397
+ `wasm32-wasip1-threads`" section).
398
+
399
+ A `CurrentThread` addon built with the `napi-async-runtime` crate makes no
400
+ progress until a JavaScript task host publishes its runnable turns, and its
401
+ timers never fire until a timer host relays them. Set `napi.wasm.asyncRuntime`
402
+ and the generated loaders install both for you:
399
403
 
400
404
  ```json
401
405
  {
@@ -407,8 +411,16 @@ both for you:
407
411
  }
408
412
  ```
409
413
 
410
- This affects WASI output only. Native `.node` bindings run the `MultiThread`
411
- flavor on real threads and need no JavaScript host.
414
+ This affects WASI output only. Native `.node` bindings default to the
415
+ `MultiThread` flavor on real threads and need no JavaScript host.
416
+
417
+ Keep the flag on even for a `wasm32-wasip1-threads` addon that configures
418
+ `MultiThread`. The loaders cannot see the flavor, so they install both hosts
419
+ unconditionally — and a `MultiThread` runtime never uses either: its futures
420
+ run on the Rayon pool instead of published host turns, and its timers come from
421
+ the executor-owned heap plus a timekeeper thread. The installed task host is an
422
+ unref'd threadsafe function, so it does not hold the event loop open. That is
423
+ what lets one artifact choose its flavor at runtime.
412
424
 
413
425
  With the flag on:
414
426
 
@@ -526,3 +538,132 @@ would never boot and the caller would deadlock waiting for it. With a
526
538
  pre-created pool, spawning is only a message to an already-running worker,
527
539
  and if the pool is exhausted the fallback allocates a fresh worker that
528
540
  boots once the spawning parent returns to its event loop.
541
+
542
+ ## Detecting the threaded target from Rust
543
+
544
+ rustc gives you nothing to tell the two WASI targets apart. `rustc --print
545
+ cfg` emits an _identical_ set for `wasm32-wasip1` and
546
+ `wasm32-wasip1-threads` — same `target_arch`, same `target_os`, same
547
+ `target_env = "p1"` — and `target_feature = "atomics"` is set for neither,
548
+ because the wasm `atomics` feature is still unstable and the stable channel
549
+ keeps unstable target features out of the cfg set
550
+ ([rust-lang/rust#77839](https://github.com/rust-lang/rust/issues/77839)).
551
+ Passing `-C target-feature=+atomics` does not change that: rustc warns that
552
+ the feature is unstable and the cfg still does not appear. Only the exact
553
+ cargo `TARGET` answers the question, and only a build script can read it.
554
+
555
+ An addon crate gets the answer for free. `napi_build::setup()` emits
556
+ `cfg(napi_wasi_threads)` when — and only when — the crate is being compiled
557
+ for `wasm32-wasip1-threads`, so the addon can write:
558
+
559
+ ```rust
560
+ #[cfg(napi_wasi_threads)]
561
+ const WORKERS: usize = 4;
562
+ #[cfg(not(napi_wasi_threads))]
563
+ const WORKERS: usize = 1;
564
+ ```
565
+
566
+ `setup()` also prints the matching `cargo::rustc-check-cfg` line on _every_
567
+ target, so `#[cfg(napi_wasi_threads)]` is a known cfg everywhere and never
568
+ trips the `unexpected_cfgs` lint on the targets where it is not set.
569
+
570
+ A build-script cfg is crate-local: it reaches the crate whose `build.rs`
571
+ printed it and nothing else. Another crate in the same graph that needs the
572
+ distinction therefore needs its own build script — which is why `napi` and
573
+ `napi-async-runtime` each carry one:
574
+
575
+ ```rust
576
+ // build.rs
577
+ fn main() {
578
+ println!("cargo::rustc-check-cfg=cfg(my_wasi_threads)");
579
+ if std::env::var("TARGET").as_deref() == Ok("wasm32-wasip1-threads") {
580
+ println!("cargo::rustc-cfg=my_wasi_threads");
581
+ }
582
+ }
583
+ ```
584
+
585
+ Use the older single-colon `cargo:` form if the crate's `rust-version` is
586
+ below 1.77.
587
+
588
+ Absence has to be the conservative branch. The cfg is permission to use
589
+ shared memory and real threads, never a requirement that something be
590
+ configured: a plain `cargo build`, `cargo test`, or rust-analyzer run — no
591
+ `napi build`, no CLI, no `RUSTFLAGS` — must still compile a correct crate on
592
+ the `not(...)` side. Nothing outside the build script can set it, so a
593
+ mistake there is silent.
594
+
595
+ ### Third-party locks
596
+
597
+ `parking_lot_core`, the lock core under `parking_lot` and `dashmap`, does not
598
+ follow this rule, and an addon can pull it in without ever naming it. Its
599
+ only threaded-wasm parker is gated on the crate's `nightly` feature _and_
600
+ `target_feature = "atomics"` (0.9.12, `src/thread_parker/mod.rs:69`), so on
601
+ stable the cascade falls through to the wasm stub, whose `prepare_park` is
602
+ `panic!("Parking not supported on this platform")`
603
+ (`src/thread_parker/wasm.rs:26`). The build succeeds and the addon dies at the
604
+ first _contended_ lock, on a target whose `std` has fully working threads.
605
+
606
+ Upstream
607
+ [Amanieu/parking_lot#529](https://github.com/Amanieu/parking_lot/pull/529)
608
+ adds a `std::sync::Mutex` and `Condvar` parker for WASI, but its selection arm
609
+ keys on `target_feature = "atomics"` as well, so it cannot be reached on
610
+ stable either. Until that is resolved there are two options:
611
+
612
+ - Keep `parking_lot` and `dashmap` out of the `wasm32-wasip1-threads`
613
+ dependency graph, or
614
+ - route the whole graph through a `parking_lot_core` that detects the triple
615
+ in its own `build.rs`, exactly as above. napi-rs maintains that fork and
616
+ publishes it as `lock_api-napi` 0.4.15, `parking_lot_core-napi` 0.9.13 and
617
+ `parking_lot-napi` 0.12.6; each keeps the upstream `[lib] name`, so
618
+ `use parking_lot::Mutex` still compiles. A transitive user such as
619
+ `dashmap` is only reachable through `[patch.crates-io]`, and the only
620
+ form cargo accepts is a git pin on the fork's `wasi-threads-parker`
621
+ branch, which still carries the _upstream_ package names. Pin the exact
622
+ revision rather than the branch, so the lock stays reproducible:
623
+
624
+ ```toml
625
+ [patch.crates-io.parking_lot_core]
626
+ git = "https://github.com/napi-rs/parking_lot"
627
+ rev = "ac046ba44e72159e90e36b7323b1058ba1d48ad2"
628
+ ```
629
+
630
+ The published `*-napi` crates cannot be named in such an entry. Cargo
631
+ rejects a crates.io package replacing another crates.io package, because
632
+ a patch must point to a different source:
633
+
634
+ ```toml
635
+ [patch.crates-io]
636
+ parking_lot_core = { package = "parking_lot_core-napi", version = "0.9.13" }
637
+ ```
638
+
639
+ ```text
640
+ error: patch for `parking_lot_core-napi` points to the same source, but
641
+ patches must point to different sources
642
+ ```
643
+
644
+ Over a path or git source the entry resolves, and is then dropped. Cargo
645
+ does honour `package =` — it selects that package from the replacement
646
+ source — but the selected package keeps its own name, and a dependency on
647
+ `parking_lot_core` is satisfied only by a package named
648
+ `parking_lot_core`. The fork's `master` carries the renamed manifests
649
+ (`name = "parking_lot_core-napi"`), so pointing the rename at it gives:
650
+
651
+ ```toml
652
+ [patch.crates-io.parking_lot_core]
653
+ git = "https://github.com/napi-rs/parking_lot"
654
+ rev = "e243c6c43832c151bce2887fcb209b5b8b72ac61" # master
655
+ package = "parking_lot_core-napi"
656
+ ```
657
+
658
+ ```text
659
+ warning: patch `parking_lot_core-napi v0.9.13 (…?rev=e243c6c4…)` was not
660
+ used in the crate graph
661
+ ```
662
+
663
+ The lock then records it under `[[patch.unused]]` and `dashmap` keeps
664
+ building against stock `parking_lot_core` 0.9.12 — the panicking parker.
665
+
666
+ Verified on the patched core: a contended probe under `wasmtime run -S
667
+ threads` — `Mutex`, `Condvar`, `RwLock`, `park_until`, `notify_all`, `DashMap`
668
+ — reports `ALL OK` with zero parking stubs left in the module, and rolldown's
669
+ threaded WASI artifact passed its stability lane 3 of 3.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napi-rs/cli",
3
- "version": "3.10.4",
3
+ "version": "3.10.5",
4
4
  "description": "Cli tools for napi-rs",
5
5
  "author": "LongYinan <lynweklm@gmail.com>",
6
6
  "homepage": "https://napi.rs/",
@@ -87,7 +87,7 @@
87
87
  "emnapi": "^2.0.0-alpha.4",
88
88
  "empathic": "^2.0.1",
89
89
  "env-paths": "^4.0.0",
90
- "oxc-parser": "^0.150.0",
90
+ "oxc-parser": "^0.151.0",
91
91
  "tsdown": "^0.23.0",
92
92
  "tslib": "^2.8.1"
93
93
  },