@napi-rs/cli 3.9.0 → 3.10.0

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.
Files changed (39) hide show
  1. package/README.md +17 -4
  2. package/dist/cli.js +10359 -8729
  3. package/dist/index.cjs +10381 -8751
  4. package/dist/index.d.cts +83 -16
  5. package/dist/index.d.ts +83 -16
  6. package/dist/index.js +10359 -8729
  7. package/docs/wasi.md +318 -4
  8. package/package.json +5 -6
  9. package/src/api/__tests__/__snapshots__/templates.spec.ts.md +4003 -53
  10. package/src/api/__tests__/__snapshots__/templates.spec.ts.snap +0 -0
  11. package/src/api/__tests__/build-regressions.spec.ts +210 -3
  12. package/src/api/__tests__/build.spec.ts +2333 -3
  13. package/src/api/__tests__/create-npm-dirs.spec.ts +105 -3
  14. package/src/api/__tests__/pre-publish.spec.ts +153 -1
  15. package/src/api/__tests__/templates.spec.ts +1309 -1
  16. package/src/api/build.ts +756 -30
  17. package/src/api/create-npm-dirs.ts +23 -10
  18. package/src/api/new.ts +13 -18
  19. package/src/api/pre-publish.ts +34 -11
  20. package/src/api/rename.ts +10 -21
  21. package/src/api/templates/binding-target.ts +176 -0
  22. package/src/api/templates/index.ts +1 -0
  23. package/src/api/templates/js-binding.ts +54 -10
  24. package/src/api/templates/load-wasi-template.ts +661 -58
  25. package/src/api/templates/wasi-worker-template.ts +36 -31
  26. package/src/commands/build.ts +1 -1
  27. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +18 -28
  28. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
  29. package/src/utils/__tests__/misc.spec.ts +4 -0
  30. package/src/utils/__tests__/reconciliation.spec.ts +676 -0
  31. package/src/utils/__tests__/serialize.spec.ts +55 -0
  32. package/src/utils/__tests__/target.spec.ts +221 -0
  33. package/src/utils/__tests__/typegen.spec.ts +115 -0
  34. package/src/utils/config.ts +50 -0
  35. package/src/utils/index.ts +1 -0
  36. package/src/utils/misc.ts +351 -79
  37. package/src/utils/serialize.ts +47 -0
  38. package/src/utils/target.ts +150 -1
  39. package/src/utils/typegen.ts +608 -42
@@ -1,4 +1,6 @@
1
- import { execSync } from 'node:child_process'
1
+ import { execFileSync, execSync } from 'node:child_process'
2
+ import { readFileSync } from 'node:fs'
3
+ import { join } from 'node:path'
2
4
 
3
5
  export type Platform = NodeJS.Platform | 'wasm' | 'wasi' | 'openharmony'
4
6
 
@@ -156,6 +158,153 @@ export function wasiTargetHasThreads(
156
158
  return getWasiTarget(target)?.flavor === 'threads'
157
159
  }
158
160
 
161
+ function readTextFileOrNull(path: string): string | null {
162
+ try {
163
+ return readFileSync(path, 'utf8')
164
+ } catch {
165
+ return null
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Detect the major version of a wasi-sdk installation.
171
+ *
172
+ * wasi-libc dropped the unused `int op` parameter from
173
+ * `__wasilibc_futex_wait_atomic_wait` and `__wasilibc_futex_wait_maybe_busy`,
174
+ * and wasi-sdk 34 is the first release that ships the 3-argument signature.
175
+ * Static archives compiled against the two signatures cannot be mixed, so the
176
+ * emnapi archives have to be picked by wasi-sdk version, not by target triple
177
+ * alone.
178
+ *
179
+ * `<wasiSdkPath>/VERSION` is the primary signal: every release ships it and
180
+ * its first line is the version (`27.0`, `33.0+m`, `34.0`, ...). The
181
+ * `wasi/version.h` header carrying `__wasi_sdk_major__` only appears from
182
+ * wasi-sdk 30 onwards, so it stays a fallback for trees without a `VERSION`.
183
+ *
184
+ * Returns `null` when neither signal is readable or parseable. Detection must
185
+ * never throw: an unknown wasi-sdk degrades to the legacy archives instead of
186
+ * failing the build.
187
+ */
188
+ export function wasiSdkMajorVersion(wasiSdkPath: string): number | null {
189
+ const version = readTextFileOrNull(join(wasiSdkPath, 'VERSION'))
190
+ if (version) {
191
+ // `33.0+m` and friends carry a build suffix, so only the leading integer
192
+ // of the first line is meaningful.
193
+ const major = /^\s*(\d+)/.exec(version.split('\n', 1)[0])
194
+ if (major) {
195
+ return Number(major[1])
196
+ }
197
+ }
198
+ const versionHeader = readTextFileOrNull(
199
+ join(
200
+ wasiSdkPath,
201
+ 'share',
202
+ 'wasi-sysroot',
203
+ 'include',
204
+ 'wasm32-wasip1-threads',
205
+ 'wasi',
206
+ 'version.h',
207
+ ),
208
+ )
209
+ if (versionHeader) {
210
+ const major = /^\s*#\s*define\s+__wasi_sdk_major__\s+(\d+)/m.exec(
211
+ versionHeader,
212
+ )
213
+ if (major) {
214
+ return Number(major[1])
215
+ }
216
+ }
217
+ return null
218
+ }
219
+
220
+ /**
221
+ * Archive member that only exists in a wasi-libc carrying the 3-argument
222
+ * futex ABI.
223
+ *
224
+ * wasi-libc moved the wasi-threads futex helpers out of `__wait.c` and into a
225
+ * new `futex.c` in the same change that dropped the unused `int op` parameter
226
+ * (WebAssembly/wasi-libc#846). `__wait.c` still exists afterwards for other
227
+ * symbols, so the presence of `futex.c` — not the absence of `__wait.c` — is
228
+ * what separates the two ABIs.
229
+ */
230
+ const NEW_FUTEX_ABI_ARCHIVE_MEMBER = 'futex.c.obj'
231
+
232
+ /**
233
+ * Path to the wasi-libc that cargo links when no wasi-sdk is configured.
234
+ *
235
+ * Without `WASI_SDK_PATH` the target links through `rust-lld` against the
236
+ * wasi-libc bundled with the Rust standard library, so that copy — not a
237
+ * wasi-sdk — decides the futex ABI.
238
+ *
239
+ * `cwd` must be the directory Cargo is spawned in, because that is what
240
+ * selects the toolchain.
241
+ *
242
+ * Returns `null` when `rustc` cannot be queried or the target is not
243
+ * installed. Never throws: an undetectable sysroot degrades to the legacy
244
+ * archives.
245
+ */
246
+ export function rustBundledWasiLibc(
247
+ wasiTarget: string,
248
+ cwd?: string,
249
+ ): string | null {
250
+ let sysroot: string
251
+ try {
252
+ // `rustc` is a rustup shim: it resolves `rust-toolchain.toml` and any
253
+ // directory override from its working directory. Cargo is spawned with
254
+ // the build cwd, so the probe must use the same one or it can read a
255
+ // different toolchain's wasi-libc than the one that gets linked.
256
+ // `RUSTC` and `CARGO_BUILD_RUSTC` bypass the shim entirely; Cargo gives
257
+ // `RUSTC` precedence, so do the same. `build.rustc` from the project's
258
+ // `.cargo/config.toml` stays out of reach without invoking cargo itself.
259
+ sysroot = execFileSync(
260
+ process.env.RUSTC ?? process.env.CARGO_BUILD_RUSTC ?? 'rustc',
261
+ ['--print', 'sysroot'],
262
+ {
263
+ cwd,
264
+ env: process.env,
265
+ stdio: ['ignore', 'pipe', 'ignore'],
266
+ },
267
+ )
268
+ .toString('utf8')
269
+ .trim()
270
+ } catch {
271
+ return null
272
+ }
273
+ if (!sysroot) {
274
+ return null
275
+ }
276
+ return join(
277
+ sysroot,
278
+ 'lib',
279
+ 'rustlib',
280
+ wasiTarget,
281
+ 'lib',
282
+ 'self-contained',
283
+ 'libc.a',
284
+ )
285
+ }
286
+
287
+ /**
288
+ * Whether a wasi-libc archive carries the 3-argument futex ABI.
289
+ *
290
+ * Returns `null` when the archive cannot be read, so callers can tell
291
+ * "definitely the legacy ABI" apart from "could not tell".
292
+ */
293
+ export function wasiLibcHasNewFutexAbi(
294
+ libcArchivePath: string | null,
295
+ ): boolean | null {
296
+ if (!libcArchivePath) {
297
+ return null
298
+ }
299
+ let archive: Buffer
300
+ try {
301
+ archive = readFileSync(libcArchivePath)
302
+ } catch {
303
+ return null
304
+ }
305
+ return archive.includes(NEW_FUTEX_ABI_ARCHIVE_MEMBER, 0, 'latin1')
306
+ }
307
+
159
308
  /**
160
309
  * A triple is a specific format for specifying a target architecture.
161
310
  * Triples may be referred to as a target triple which is the architecture for the artifact produced, and the host triple which is the architecture that the compiler is running on.