@napi-rs/cli 3.7.3 → 3.8.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 (51) hide show
  1. package/README.md +33 -0
  2. package/cli.mjs +9 -12
  3. package/dist/cli.js +9277 -1313
  4. package/dist/index.cjs +9266 -1302
  5. package/dist/index.d.cts +176 -158
  6. package/dist/index.d.ts +176 -158
  7. package/dist/index.js +9277 -1313
  8. package/docs/artifacts.md +33 -0
  9. package/docs/build.md +58 -0
  10. package/docs/create-npm-dirs.md +32 -0
  11. package/docs/new.md +39 -0
  12. package/docs/pre-publish.md +37 -0
  13. package/docs/rename.md +37 -0
  14. package/docs/universalize.md +31 -0
  15. package/docs/version.md +31 -0
  16. package/docs/wasi.md +161 -0
  17. package/package.json +11 -10
  18. package/src/api/__tests__/__snapshots__/templates.spec.ts.md +1019 -114
  19. package/src/api/__tests__/__snapshots__/templates.spec.ts.snap +0 -0
  20. package/src/api/__tests__/artifacts.spec.ts +17 -0
  21. package/src/api/__tests__/create-npm-dirs.spec.ts +14 -15
  22. package/src/api/__tests__/new.spec.ts +41 -5
  23. package/src/api/artifacts.ts +934 -108
  24. package/src/api/build.ts +1325 -194
  25. package/src/api/create-npm-dirs.ts +472 -101
  26. package/src/api/new.ts +354 -35
  27. package/src/api/pre-publish.ts +2845 -99
  28. package/src/api/rename.ts +1638 -124
  29. package/src/api/templates/js-binding.ts +216 -38
  30. package/src/api/templates/load-wasi-template.ts +1641 -111
  31. package/src/api/templates/wasi-worker-template.ts +32 -3
  32. package/src/commands/rename.ts +8 -3
  33. package/src/def/artifacts.ts +2 -2
  34. package/src/utils/__tests__/__fixtures__/optional-napi-derive/Cargo.toml +3 -0
  35. package/src/utils/__tests__/__fixtures__/optional-napi-derive/main-crate/Cargo.toml +8 -0
  36. package/src/utils/__tests__/__fixtures__/optional-napi-derive/main-crate/src/lib.rs +1 -0
  37. package/src/utils/__tests__/__fixtures__/optional-napi-derive/napi-derive/Cargo.toml +5 -0
  38. package/src/utils/__tests__/__fixtures__/optional-napi-derive/napi-derive/src/lib.rs +1 -0
  39. package/src/utils/__tests__/__fixtures__/optional-napi-derive/with-optional-derive/Cargo.toml +11 -0
  40. package/src/utils/__tests__/__fixtures__/optional-napi-derive/with-optional-derive/src/lib.rs +1 -0
  41. package/src/utils/__tests__/__snapshots__/target.spec.ts.md +2 -2
  42. package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
  43. package/src/utils/__tests__/metadata.spec.ts +43 -2
  44. package/src/utils/__tests__/misc.spec.ts +124 -3
  45. package/src/utils/__tests__/version.spec.ts +47 -1
  46. package/src/utils/config.ts +15 -2
  47. package/src/utils/metadata.ts +206 -7
  48. package/src/utils/misc.ts +6079 -0
  49. package/src/utils/target.ts +66 -8
  50. package/src/utils/typegen.ts +1223 -63
  51. package/src/utils/version.ts +96 -0
@@ -1,3 +1,266 @@
1
+ const WASI_DISPOSE_SYMBOL = 'napi.rs.wasi.dispose'
2
+ const WASI_ROLLBACK_REGISTRY_SYMBOL = 'napi.rs.wasi.rollback.registry.v1'
3
+
4
+ const emnapiContextLifecycle = `
5
+ const __wasiDisposeSymbol = Symbol.for('${WASI_DISPOSE_SYMBOL}')
6
+ const __wasiWorkers = new Set()
7
+ let __napiInstance
8
+ let __emnapiContextDestroyed = false
9
+ let __emnapiContextDestroyPromise
10
+ let __emnapiWasmEnvCleanupPrepared = false
11
+ let __wasiDisposed = false
12
+ let __wasiDisposePromise
13
+ let __completeWasiDisposal = function() {}
14
+
15
+ function __isThenable(value) {
16
+ return (
17
+ value !== null &&
18
+ (typeof value === 'object' || typeof value === 'function') &&
19
+ typeof value.then === 'function'
20
+ )
21
+ }
22
+
23
+ function __createCleanupError(errors, message) {
24
+ if (errors.length === 1) {
25
+ return errors[0]
26
+ }
27
+ const __AggregateError = globalThis.AggregateError
28
+ if (typeof __AggregateError === 'function') {
29
+ return new __AggregateError(errors, message)
30
+ }
31
+ const error = new Error(message)
32
+ error.errors = errors
33
+ return error
34
+ }
35
+
36
+ function __attachCleanupErrors(error, cleanupErrors) {
37
+ if (cleanupErrors.length === 0) {
38
+ return error
39
+ }
40
+ const cleanupError = __createCleanupError(
41
+ cleanupErrors,
42
+ 'WASI binding cleanup failed',
43
+ )
44
+ try {
45
+ if (
46
+ error &&
47
+ (typeof error === 'object' || typeof error === 'function')
48
+ ) {
49
+ if (error.cause === undefined) {
50
+ error.cause = cleanupError
51
+ if (error.cause === cleanupError) {
52
+ return error
53
+ }
54
+ }
55
+ if (Array.isArray(error.cleanupErrors)) {
56
+ error.cleanupErrors.push(cleanupError)
57
+ return error
58
+ } else {
59
+ const attachedCleanupErrors = [cleanupError]
60
+ error.cleanupErrors = attachedCleanupErrors
61
+ if (error.cleanupErrors === attachedCleanupErrors) {
62
+ return error
63
+ }
64
+ }
65
+ }
66
+ } catch {}
67
+ const aggregate = __createCleanupError(
68
+ [error, cleanupError],
69
+ 'WASI binding initialization and cleanup failed',
70
+ )
71
+ try {
72
+ aggregate.cause = error
73
+ } catch {}
74
+ return aggregate
75
+ }
76
+
77
+ function __prepareWasmEnvCleanup() {
78
+ if (__emnapiWasmEnvCleanupPrepared) {
79
+ return
80
+ }
81
+ const prepare = __napiInstance?.exports?.napi_prepare_wasm_env_cleanup
82
+ if (typeof prepare === 'function') {
83
+ prepare()
84
+ }
85
+ __emnapiWasmEnvCleanupPrepared = true
86
+ }
87
+
88
+ function __destroyEmnapiContext() {
89
+ if (__emnapiContextDestroyed || __emnapiContext === undefined) {
90
+ __emnapiContextDestroyed = true
91
+ return
92
+ }
93
+ if (__emnapiContextDestroyPromise) {
94
+ return __emnapiContextDestroyPromise
95
+ }
96
+
97
+ __prepareWasmEnvCleanup()
98
+ const result = __emnapiContext.destroy()
99
+ if (!__isThenable(result)) {
100
+ __emnapiContextDestroyed = true
101
+ return
102
+ }
103
+
104
+ const destroyPromise = Promise.resolve(result).then(
105
+ (value) => {
106
+ __emnapiContextDestroyed = true
107
+ return value
108
+ },
109
+ (error) => {
110
+ __emnapiContextDestroyPromise = undefined
111
+ throw error
112
+ },
113
+ )
114
+ __emnapiContextDestroyPromise = destroyPromise
115
+ return destroyPromise
116
+ }
117
+
118
+ function __terminateWasiWorkers() {
119
+ const cleanupErrors = []
120
+ const pending = []
121
+
122
+ for (const worker of __wasiWorkers) {
123
+ let result
124
+ try {
125
+ result = worker.terminate()
126
+ } catch (error) {
127
+ cleanupErrors.push(error)
128
+ continue
129
+ }
130
+ if (__isThenable(result)) {
131
+ pending.push(
132
+ Promise.resolve(result).then(
133
+ () => {
134
+ __wasiWorkers.delete(worker)
135
+ },
136
+ (error) => {
137
+ cleanupErrors.push(error)
138
+ },
139
+ ),
140
+ )
141
+ } else {
142
+ __wasiWorkers.delete(worker)
143
+ }
144
+ }
145
+
146
+ const finish = () => {
147
+ if (cleanupErrors.length > 0) {
148
+ throw __createCleanupError(
149
+ cleanupErrors,
150
+ 'Failed to terminate WASI workers',
151
+ )
152
+ }
153
+ }
154
+ return pending.length > 0 ? Promise.all(pending).then(finish) : finish()
155
+ }
156
+
157
+ function __finishWasiDisposal() {
158
+ const workerResult = __terminateWasiWorkers()
159
+ if (__isThenable(workerResult)) {
160
+ return Promise.resolve(workerResult).then(__completeWasiDisposal)
161
+ }
162
+ return __completeWasiDisposal()
163
+ }
164
+
165
+ function __startWasiDisposal() {
166
+ const destroyResult = __destroyEmnapiContext()
167
+ if (__isThenable(destroyResult)) {
168
+ return Promise.resolve(destroyResult).then(__finishWasiDisposal)
169
+ }
170
+ return __finishWasiDisposal()
171
+ }
172
+
173
+ /**
174
+ * Disposes this generated WASI binding.
175
+ *
176
+ * Access this function with:
177
+ * binding[Symbol.for('${WASI_DISPOSE_SYMBOL}')]()
178
+ */
179
+ function __disposeWasiBinding() {
180
+ if (__wasiDisposePromise) {
181
+ return __wasiDisposePromise
182
+ }
183
+ if (__wasiDisposed) {
184
+ return Promise.resolve()
185
+ }
186
+
187
+ let resolveDispose
188
+ let rejectDispose
189
+ const disposePromise = new Promise((resolve, reject) => {
190
+ resolveDispose = resolve
191
+ rejectDispose = reject
192
+ })
193
+ __wasiDisposePromise = disposePromise
194
+
195
+ let result
196
+ try {
197
+ result = __startWasiDisposal()
198
+ } catch (error) {
199
+ __wasiDisposePromise = undefined
200
+ rejectDispose(error)
201
+ return disposePromise
202
+ }
203
+
204
+ Promise.resolve(result).then(
205
+ (value) => {
206
+ __wasiDisposed = true
207
+ resolveDispose(value)
208
+ },
209
+ (error) => {
210
+ __wasiDisposePromise = undefined
211
+ rejectDispose(error)
212
+ },
213
+ )
214
+ return disposePromise
215
+ }
216
+
217
+ function __publishWasiDispose(exports) {
218
+ Object.defineProperty(exports, __wasiDisposeSymbol, {
219
+ configurable: false,
220
+ enumerable: false,
221
+ value: __disposeWasiBinding,
222
+ writable: false,
223
+ })
224
+ }
225
+
226
+ function __finishWasiInitializationRollback(cleanupErrors) {
227
+ let workerResult
228
+ try {
229
+ workerResult = __terminateWasiWorkers()
230
+ } catch (cleanupError) {
231
+ cleanupErrors.push(cleanupError)
232
+ return cleanupErrors
233
+ }
234
+ if (__isThenable(workerResult)) {
235
+ return Promise.resolve(workerResult)
236
+ .catch((cleanupError) => {
237
+ cleanupErrors.push(cleanupError)
238
+ })
239
+ .then(() => cleanupErrors)
240
+ }
241
+ return cleanupErrors
242
+ }
243
+
244
+ function __rollbackWasiInitialization() {
245
+ const cleanupErrors = []
246
+ let destroyResult
247
+ try {
248
+ destroyResult = __destroyEmnapiContext()
249
+ } catch (cleanupError) {
250
+ cleanupErrors.push(cleanupError)
251
+ return __finishWasiInitializationRollback(cleanupErrors)
252
+ }
253
+ if (__isThenable(destroyResult)) {
254
+ return Promise.resolve(destroyResult)
255
+ .catch((cleanupError) => {
256
+ cleanupErrors.push(cleanupError)
257
+ })
258
+ .then(() => __finishWasiInitializationRollback(cleanupErrors))
259
+ }
260
+ return __finishWasiInitializationRollback(cleanupErrors)
261
+ }
262
+ `
263
+
1
264
  export const createWasiBrowserBinding = (
2
265
  wasiFilename: string,
3
266
  initialMemory = 4000,
@@ -6,6 +269,7 @@ export const createWasiBrowserBinding = (
6
269
  asyncInit = false,
7
270
  buffer = false,
8
271
  errorEvent = false,
272
+ threads = true,
9
273
  ) => {
10
274
  const fsImport = fs
11
275
  ? buffer
@@ -30,20 +294,28 @@ const __wasi = new __WASI({
30
294
  })`
31
295
 
32
296
  const workerFsHandler = fs
33
- ? ` worker.addEventListener('message', __wasmCreateOnMessageForFsProxy(__fs))\n`
297
+ ? ` worker.addEventListener('message', __wasmCreateOnMessageForFsProxy(__fs))\n`
34
298
  : ''
35
299
 
36
300
  const workerErrorHandler = errorEvent
37
- ? ` worker.addEventListener('message', (event) => {
38
- if (event.data && typeof event.data === 'object' && event.data.type === 'error') {
39
- window.dispatchEvent(new CustomEvent('napi-rs-worker-error', { detail: event.data }))
40
- }
41
- })
301
+ ? ` worker.addEventListener('message', (event) => {
302
+ if (event.data && typeof event.data === 'object' && event.data.type === 'error') {
303
+ const __CustomEvent = globalThis.CustomEvent
304
+ if (
305
+ typeof globalThis.dispatchEvent === 'function' &&
306
+ typeof __CustomEvent === 'function'
307
+ ) {
308
+ globalThis.dispatchEvent(
309
+ new __CustomEvent('napi-rs-worker-error', { detail: event.data }),
310
+ )
311
+ }
312
+ }
313
+ })
42
314
  `
43
315
  : ''
44
316
 
45
317
  const emnapiInjectBuffer = buffer
46
- ? '__emnapiContext.feature.Buffer = Buffer'
318
+ ? ' __emnapiContext.features.Buffer = Buffer\n'
47
319
  : ''
48
320
  const emnapiInstantiateImport = asyncInit
49
321
  ? `instantiateNapiModule as __emnapiInstantiateNapiModule`
@@ -51,71 +323,1171 @@ const __wasi = new __WASI({
51
323
  const emnapiInstantiateCall = asyncInit
52
324
  ? `await __emnapiInstantiateNapiModule`
53
325
  : `__emnapiInstantiateNapiModuleSync`
326
+ const workerRuntimeImport = threads
327
+ ? ` createOnMessage as __wasmCreateOnMessageForFsProxy,\n`
328
+ : ''
329
+ const memoryName = threads ? '__sharedMemory' : '__wasmMemory'
330
+ const asyncWorkPoolOption = ` asyncWorkPoolSize: ${threads ? 4 : 0},
331
+ `
332
+ // Every build links a "basic" emnapi archive without the C async-work and
333
+ // threadsafe-function implementations (the `emnapi-napi-rs(-mt)` archives shipped by the emnapi package), so the
334
+ // JavaScript implementations must be provided through the emnapi plugins in
335
+ // both threading modes. Without threads the C code would be unconditional
336
+ // `napi_generic_failure` stubs; with threads it would shadow the
337
+ // `@emnapi/core` threaded TSFN/async-work protocol the plugins implement.
338
+ const emnapiPluginImport = ` emnapiAsyncWorkPlugin as __emnapiAsyncWorkPlugin,\n emnapiTSFNPlugin as __emnapiTSFNPlugin,\n`
339
+ const emnapiPluginOption = ` plugins: [__emnapiAsyncWorkPlugin, __emnapiTSFNPlugin],\n`
340
+ const workerOption = threads
341
+ ? ` onCreateWorker() {
342
+ const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
343
+ type: 'module',
344
+ })
345
+ __wasiWorkers.add(worker)
346
+ ${workerFsHandler}
347
+ ${workerErrorHandler}
348
+ return worker
349
+ },
350
+ `
351
+ : ''
54
352
 
55
353
  return `import {
56
- createOnMessage as __wasmCreateOnMessageForFsProxy,
57
- getDefaultContext as __emnapiGetDefaultContext,
354
+ ${emnapiPluginImport}\
355
+ ${workerRuntimeImport}\
58
356
  ${emnapiInstantiateImport},
59
357
  WASI as __WASI,
60
358
  } from '@napi-rs/wasm-runtime'
359
+ import { createContext as __emnapiCreateContext } from '@emnapi/runtime'
61
360
  ${fsImport}
62
361
  ${bufferImport}
63
362
  ${wasiCreation}
64
363
 
65
364
  const __wasmUrl = new URL('./${wasiFilename}.wasm', import.meta.url).href
66
- const __emnapiContext = __emnapiGetDefaultContext()
67
- ${emnapiInjectBuffer}
365
+ const __wasmResponse = await globalThis.fetch(__wasmUrl)
366
+ if (!__wasmResponse.ok) {
367
+ throw new Error(
368
+ 'Failed to fetch WASI module ' +
369
+ __wasmUrl +
370
+ ': ' +
371
+ __wasmResponse.status +
372
+ ' ' +
373
+ (__wasmResponse.statusText || 'Unknown Status'),
374
+ )
375
+ }
376
+ const __wasmFile = await __wasmResponse.arrayBuffer()
68
377
 
69
- const __sharedMemory = new WebAssembly.Memory({
378
+ const ${memoryName} = new WebAssembly.Memory({
70
379
  initial: ${initialMemory},
71
380
  maximum: ${maximumMemory},
72
- shared: true,
381
+ ${threads ? ' shared: true,\n' : ''}\
73
382
  })
74
383
 
75
- const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())
384
+ let __emnapiContext
385
+ ${emnapiContextLifecycle}
386
+ let __wasiModule
387
+ let __napiModule
76
388
 
77
- const {
78
- instance: __napiInstance,
79
- module: __wasiModule,
80
- napiModule: __napiModule,
81
- } = ${emnapiInstantiateCall}(__wasmFile, {
82
- context: __emnapiContext,
83
- asyncWorkPoolSize: 4,
84
- wasi: __wasi,
85
- onCreateWorker() {
86
- const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
87
- type: 'module',
389
+ try {
390
+ __emnapiContext = __emnapiCreateContext({ autoDestroy: false })
391
+ __emnapiContext.suppressDestroy()
392
+ ${emnapiInjectBuffer}
393
+ ;({
394
+ instance: __napiInstance,
395
+ module: __wasiModule,
396
+ napiModule: __napiModule,
397
+ } = ${emnapiInstantiateCall}(__wasmFile, {
398
+ context: __emnapiContext,
399
+ ${asyncWorkPoolOption}\
400
+ ${emnapiPluginOption}\
401
+ wasi: __wasi,
402
+ ${workerOption}\
403
+ overwriteImports(importObject) {
404
+ importObject.env = {
405
+ ...importObject.env,
406
+ ...importObject.napi,
407
+ ...importObject.emnapi,
408
+ memory: ${memoryName},
409
+ }
410
+ return importObject
411
+ },
412
+ beforeInit({ instance }) {
413
+ __napiInstance = instance
414
+ for (const name of Object.keys(instance.exports)) {
415
+ if (name.startsWith('__napi_register__')) {
416
+ instance.exports[name]()
417
+ }
418
+ }
419
+ },
420
+ }))
421
+ __publishWasiDispose(__napiModule.exports)
422
+ } catch (error) {
423
+ const cleanupErrors = await __rollbackWasiInitialization()
424
+ throw __attachCleanupErrors(error, cleanupErrors)
425
+ }
426
+ `
427
+ }
428
+
429
+ export const createWasiDeferredBrowserBinding = (
430
+ wasiFilename: string,
431
+ // 64 MiB leaves headroom for JS/runtime state under workerd's 128 MiB
432
+ // isolate limit. The regular Node/browser loaders retain their historical
433
+ // 4,000-page default.
434
+ initialMemory = 1024,
435
+ maximumMemory = 65536,
436
+ buffer = false,
437
+ ) => {
438
+ const bufferImport = buffer ? `import { Buffer } from 'buffer'` : ''
439
+ const emnapiInjectBuffer = buffer
440
+ ? ' __emnapiContext.features.Buffer = Buffer\n'
441
+ : ''
442
+ return `import {
443
+ emnapiAsyncWorkPlugin as __emnapiAsyncWorkPlugin,
444
+ emnapiTSFNPlugin as __emnapiTSFNPlugin,
445
+ instantiateNapiModule as __emnapiInstantiateNapiModule,
446
+ WASI as __WASI,
447
+ } from '@napi-rs/wasm-runtime'
448
+ import { createContext as __emnapiCreateContext } from '@emnapi/runtime'
449
+ ${bufferImport}
450
+
451
+ /**
452
+ * Deferred, workerd-safe instantiation: no top-level I/O, no compile-from-bytes.
453
+ * Accepts ONLY a precompiled WebAssembly.Module, or a Promise resolving to one
454
+ * (e.g. \`import mod from './${wasiFilename}.wasm'\` under a CompiledWasm
455
+ * module rule / wrangler module import). Byte buffers, URLs and Response
456
+ * objects are rejected: they require dynamic Wasm compilation, which
457
+ * Cloudflare Workers disallows.
458
+ */
459
+ async function __resolveModule(__wasmInput) {
460
+ const __module = await __wasmInput
461
+ // Brand check, not \`instanceof\`: \`WebAssembly.Module.imports\` throws unless
462
+ // its argument is a genuine WebAssembly.Module, so prototype-spoofed byte
463
+ // buffers are rejected while cross-realm Module instances are accepted.
464
+ try {
465
+ WebAssembly.Module.imports(__module)
466
+ } catch {
467
+ throw new TypeError(
468
+ "instantiate() and createInstance() expect a precompiled WebAssembly.Module (or a Promise resolving to one), " +
469
+ "e.g. import mod from './${wasiFilename}.wasm' under a CompiledWasm module rule / wrangler module import. " +
470
+ "Byte buffers, URLs and Response objects require dynamic Wasm compilation, which Cloudflare Workers disallows.",
471
+ )
472
+ }
473
+ return __module
474
+ }
475
+
476
+ let __normalizedModules
477
+
478
+ function __rememberNormalizedModule(__module, __normalizedModule) {
479
+ if (!__normalizedModules) {
480
+ __normalizedModules = new WeakMap()
481
+ }
482
+ __normalizedModules.set(__module, __normalizedModule)
483
+ return __normalizedModule
484
+ }
485
+
486
+ async function __normalizeModuleForEmnapi(__module) {
487
+ if (__module instanceof WebAssembly.Module) {
488
+ return __module
489
+ }
490
+ if (__normalizedModules) {
491
+ const __normalizedModule = __normalizedModules.get(__module)
492
+ if (__normalizedModule) {
493
+ return __normalizedModule
494
+ }
495
+ }
496
+ // @emnapi/core currently performs realm-local \`instanceof\` checks after
497
+ // accepting the module. Structured cloning preserves compiled code without
498
+ // compiling bytes and produces a Module owned by the current realm.
499
+ if (typeof structuredClone === 'function') {
500
+ try {
501
+ const __normalizedModule = structuredClone(__module)
502
+ if (__normalizedModule instanceof WebAssembly.Module) {
503
+ return __rememberNormalizedModule(__module, __normalizedModule)
504
+ }
505
+ } catch {}
506
+ }
507
+ // MessageChannel uses the same structured-clone semantics and covers older
508
+ // browser/Node hosts that expose it but not the structuredClone function.
509
+ if (typeof MessageChannel === 'function') {
510
+ let __channel
511
+ try {
512
+ __channel = new MessageChannel()
513
+ const __normalizedModule = await new Promise((resolve, reject) => {
514
+ __channel.port1.onmessage = (event) => resolve(event.data)
515
+ __channel.port1.onmessageerror = () =>
516
+ reject(new TypeError('Failed to clone WebAssembly.Module'))
517
+ try {
518
+ __channel.port2.postMessage(__module)
519
+ } catch (error) {
520
+ reject(error)
521
+ }
522
+ })
523
+ if (__normalizedModule instanceof WebAssembly.Module) {
524
+ return __rememberNormalizedModule(__module, __normalizedModule)
525
+ }
526
+ } catch {
527
+ } finally {
528
+ try {
529
+ __channel?.port1.close()
530
+ } catch {}
531
+ try {
532
+ __channel?.port2.close()
533
+ } catch {}
534
+ }
535
+ }
536
+ // Last-resort compatibility for genuine, extensible foreign Modules.
537
+ try {
538
+ Object.setPrototypeOf(__module, WebAssembly.Module.prototype)
539
+ } catch {}
540
+ if (__module instanceof WebAssembly.Module) {
541
+ return __module
542
+ }
543
+ throw new TypeError(
544
+ 'This host cannot normalize a cross-realm WebAssembly.Module; ' +
545
+ 'provide structuredClone or MessageChannel support.',
546
+ )
547
+ }
548
+
549
+ function __captureEmnapiAutoDestroyListener(__process) {
550
+ if (
551
+ !__process ||
552
+ typeof __process.prependListener !== 'function' ||
553
+ typeof __process.removeListener !== 'function'
554
+ ) {
555
+ return
556
+ }
557
+ let __autoDestroyListener
558
+ const __captureListener = (__event, __listener) => {
559
+ if (__event === 'beforeExit' && __autoDestroyListener === undefined) {
560
+ __autoDestroyListener = __listener
561
+ }
562
+ }
563
+ try {
564
+ // Run before existing newListener hooks so a hook that registers its own
565
+ // beforeExit listener cannot be mistaken for emnapi's registration.
566
+ __process.prependListener('newListener', __captureListener)
567
+ } catch {
568
+ return
569
+ }
570
+ return () => {
571
+ try {
572
+ __process.removeListener('newListener', __captureListener)
573
+ } catch {}
574
+ if (__autoDestroyListener !== undefined) {
575
+ try {
576
+ __process.removeListener('beforeExit', __autoDestroyListener)
577
+ } catch {}
578
+ }
579
+ }
580
+ }
581
+
582
+ function __attachCleanupError(__error, __cleanupError) {
583
+ try {
584
+ if (
585
+ __error &&
586
+ (typeof __error === 'object' || typeof __error === 'function') &&
587
+ __error.cause === undefined
588
+ ) {
589
+ __error.cause = __cleanupError
590
+ }
591
+ } catch {}
592
+ }
593
+
594
+ function __createLifecycleReentryError(__operation) {
595
+ const __error = new Error(
596
+ __operation +
597
+ '() cannot run while an emnapi Context.destroy() call is still active; await the original cleanup promise instead.',
598
+ )
599
+ __error.code = 'ERR_NAPI_WASI_LIFECYCLE_REENTRY'
600
+ return __error
601
+ }
602
+
603
+ const __managedEmnapiContextDestroyers = new Set()
604
+ let __managedCleanupProcess
605
+ let __managedBeforeExitListener
606
+ let __managedDestroyPromise
607
+ let __managedDestroyersInFlight
608
+ let __managedBeforeExitRegistrationRetryCount = 0
609
+ let __managedBeforeExitRegistrationRetryScheduled = false
610
+ let __moduleLifecycleDestroyDepth = 0
611
+
612
+ function __removeManagedEmnapiCleanupListeners() {
613
+ const __process = __managedCleanupProcess
614
+ const __beforeExitListener = __managedBeforeExitListener
615
+ __managedCleanupProcess = undefined
616
+ __managedBeforeExitListener = undefined
617
+ __managedBeforeExitRegistrationRetryCount = 0
618
+ if (__process && __beforeExitListener) {
619
+ try {
620
+ __process.removeListener('beforeExit', __beforeExitListener)
621
+ } catch {}
622
+ }
623
+ }
624
+
625
+ function __scheduleManagedBeforeExitListenerRegistration() {
626
+ if (
627
+ !__managedCleanupProcess ||
628
+ __managedBeforeExitListener ||
629
+ __managedEmnapiContextDestroyers.size === 0 ||
630
+ __managedBeforeExitRegistrationRetryScheduled ||
631
+ __managedBeforeExitRegistrationRetryCount >= 3
632
+ ) {
633
+ return
634
+ }
635
+ __managedBeforeExitRegistrationRetryScheduled = true
636
+ __managedBeforeExitRegistrationRetryCount++
637
+ queueMicrotask(() => {
638
+ __managedBeforeExitRegistrationRetryScheduled = false
639
+ if (
640
+ !__managedCleanupProcess ||
641
+ __managedBeforeExitListener ||
642
+ __managedEmnapiContextDestroyers.size === 0
643
+ ) {
644
+ return
645
+ }
646
+ try {
647
+ __registerManagedBeforeExitListener()
648
+ } catch {}
649
+ })
650
+ }
651
+
652
+ function __registerManagedBeforeExitListener() {
653
+ if (!__managedCleanupProcess || __managedBeforeExitListener) {
654
+ return
655
+ }
656
+ try {
657
+ __managedCleanupProcess.once(
658
+ 'beforeExit',
659
+ __destroyManagedEmnapiContextsBeforeExit,
660
+ )
661
+ } catch (error) {
662
+ __scheduleManagedBeforeExitListenerRegistration()
663
+ throw error
664
+ }
665
+ __managedBeforeExitListener = __destroyManagedEmnapiContextsBeforeExit
666
+ __managedBeforeExitRegistrationRetryCount = 0
667
+ }
668
+
669
+ function __settleManagedEmnapiContextDestroy(__promise) {
670
+ if (__managedDestroyPromise === __promise) {
671
+ __managedDestroyPromise = undefined
672
+ __managedDestroyersInFlight = undefined
673
+ }
674
+ if (__managedEmnapiContextDestroyers.size === 0) {
675
+ __removeManagedEmnapiCleanupListeners()
676
+ return
677
+ }
678
+ try {
679
+ __registerManagedBeforeExitListener()
680
+ } catch {}
681
+ }
682
+
683
+ function __destroyManagedEmnapiContexts(__excludedDestroyers) {
684
+ if (__managedDestroyPromise) {
685
+ return __managedDestroyPromise
686
+ }
687
+ const __destroyers = Array.from(__managedEmnapiContextDestroyers).filter(
688
+ (__destroy) => !__excludedDestroyers?.has(__destroy),
689
+ )
690
+ if (__destroyers.length === 0) {
691
+ return Promise.resolve()
692
+ }
693
+ let __resolveDestroy
694
+ let __rejectDestroy
695
+ const __promise = new Promise((resolve, reject) => {
696
+ __resolveDestroy = resolve
697
+ __rejectDestroy = reject
698
+ })
699
+ __managedDestroyPromise = __promise
700
+ __managedDestroyersInFlight = new Set(__destroyers)
701
+ void Promise.all(
702
+ __destroyers.map((__destroy) => {
703
+ try {
704
+ return Promise.resolve(__destroy()).then(
705
+ () => ({ failed: false }),
706
+ (error) => ({ failed: true, error }),
707
+ )
708
+ } catch (error) {
709
+ return { failed: true, error }
710
+ }
711
+ }),
712
+ ).then((__results) => {
713
+ let __primaryError
714
+ let __failed = false
715
+ for (const __result of __results) {
716
+ if (!__result.failed) {
717
+ continue
718
+ }
719
+ if (!__failed) {
720
+ __failed = true
721
+ __primaryError = __result.error
722
+ } else {
723
+ __attachCleanupError(__primaryError, __result.error)
724
+ }
725
+ }
726
+ if (__failed) {
727
+ __rejectDestroy(__primaryError)
728
+ } else {
729
+ __resolveDestroy()
730
+ }
731
+ }, __rejectDestroy)
732
+ void __promise.then(
733
+ () => {
734
+ __settleManagedEmnapiContextDestroy(__promise)
735
+ },
736
+ () => {
737
+ __settleManagedEmnapiContextDestroy(__promise)
738
+ },
739
+ )
740
+ return __promise
741
+ }
742
+
743
+ async function __drainManagedEmnapiContexts(__excludedDestroyers) {
744
+ const __attemptedDestroyers = new Set(__excludedDestroyers)
745
+ let __primaryError
746
+ let __failed = false
747
+ while (true) {
748
+ let __promise = __managedDestroyPromise
749
+ let __destroyers = __managedDestroyersInFlight
750
+ if (!__promise) {
751
+ __promise = __destroyManagedEmnapiContexts(__attemptedDestroyers)
752
+ __destroyers = __managedDestroyersInFlight
753
+ if (!__destroyers) {
754
+ break
755
+ }
756
+ }
757
+ for (const __destroy of __destroyers) {
758
+ __attemptedDestroyers.add(__destroy)
759
+ }
760
+ try {
761
+ await __promise
762
+ } catch (error) {
763
+ if (!__failed) {
764
+ __failed = true
765
+ __primaryError = error
766
+ } else {
767
+ __attachCleanupError(__primaryError, error)
768
+ }
769
+ }
770
+ }
771
+ if (__failed) {
772
+ throw __primaryError
773
+ }
774
+ }
775
+
776
+ function __destroyManagedEmnapiContextsBeforeExit() {
777
+ // A once listener is consumed before Node invokes it, including when another
778
+ // cleanup batch is still pending.
779
+ __managedBeforeExitListener = undefined
780
+ if (__managedDestroyPromise) {
781
+ return
782
+ }
783
+ void __destroyManagedEmnapiContexts().catch((error) => {
784
+ queueMicrotask(() => {
785
+ throw error
88
786
  })
89
- ${workerFsHandler}
90
- ${workerErrorHandler}
91
- return worker
92
- },
93
- overwriteImports(importObject) {
94
- importObject.env = {
95
- ...importObject.env,
96
- ...importObject.napi,
97
- ...importObject.emnapi,
98
- memory: __sharedMemory,
99
- }
100
- return importObject
101
- },
102
- beforeInit({ instance }) {
103
- for (const name of Object.keys(instance.exports)) {
104
- if (name.startsWith('__napi_register__')) {
105
- instance.exports[name]()
787
+ })
788
+ }
789
+
790
+ function __registerManagedEmnapiContext(__process, __destroy) {
791
+ __managedEmnapiContextDestroyers.add(__destroy)
792
+ if (
793
+ !__managedCleanupProcess &&
794
+ __process &&
795
+ typeof __process.once === 'function' &&
796
+ typeof __process.removeListener === 'function'
797
+ ) {
798
+ __managedCleanupProcess = __process
799
+ }
800
+ let __registered = true
801
+ return () => {
802
+ if (!__registered) {
803
+ return
804
+ }
805
+ __registered = false
806
+ __managedEmnapiContextDestroyers.delete(__destroy)
807
+ if (__managedEmnapiContextDestroyers.size === 0) {
808
+ __removeManagedEmnapiCleanupListeners()
809
+ }
810
+ }
811
+ }
812
+
813
+ async function __createManagedEmnapiContext(__prepareEnvCleanup) {
814
+ const __process =
815
+ typeof process === 'object' && process !== null ? process : undefined
816
+ const __finishAutoDestroyCapture =
817
+ __captureEmnapiAutoDestroyListener(__process)
818
+ let __emnapiContext
819
+ let __contextInitializationError
820
+ let __contextInitializationFailed = false
821
+ try {
822
+ __emnapiContext = __emnapiCreateContext({ autoDestroy: false })
823
+ // emnapi 2.x still registers an unconditional process.once('beforeExit')
824
+ // auto-destroy listener on Node hosts, and suppressDestroy() only
825
+ // neutralizes its callback without removing it. This loader must stay
826
+ // side-effect free per instance, so the listener is captured and removed;
827
+ // suppressDestroy() remains the safety net when removal is unavailable.
828
+ __emnapiContext.suppressDestroy()
829
+ } catch (error) {
830
+ __contextInitializationError = error
831
+ __contextInitializationFailed = true
832
+ } finally {
833
+ // Remove only the exact emnapi callback captured above.
834
+ __finishAutoDestroyCapture?.()
835
+ }
836
+ if (__emnapiContext === undefined) {
837
+ throw __contextInitializationError
838
+ }
839
+ let __disposed = false
840
+ let __destroying = false
841
+ let __destroyPromise
842
+ let __cleanupRegistered = false
843
+ let __unregisterCleanup
844
+ const __destroy = (__blocksModuleLifecycle = false) => {
845
+ if (__disposed) {
846
+ return
847
+ }
848
+ if (__destroying) {
849
+ throw __createLifecycleReentryError('dispose')
850
+ }
851
+ if (__destroyPromise) {
852
+ return __destroyPromise
853
+ }
854
+ __destroying = true
855
+ let __result
856
+ const __finishDestroyInvocation = () => {
857
+ __destroying = false
858
+ }
859
+ const __finishModuleLifecycleDestroy = () => {
860
+ if (__blocksModuleLifecycle) {
861
+ __blocksModuleLifecycle = false
862
+ __moduleLifecycleDestroyDepth--
106
863
  }
107
864
  }
108
- },
109
- })
865
+ if (__blocksModuleLifecycle) {
866
+ __moduleLifecycleDestroyDepth++
867
+ }
868
+ try {
869
+ // Context.destroy() disables JS before cleanup hooks run, so settle
870
+ // runtime-owned promises while this environment can still call JS.
871
+ __prepareEnvCleanup?.()
872
+ __result = __emnapiContext.destroy()
873
+ } catch (error) {
874
+ __finishDestroyInvocation()
875
+ __finishModuleLifecycleDestroy()
876
+ throw error
877
+ }
878
+ let __then
879
+ try {
880
+ if (
881
+ __result !== null &&
882
+ (typeof __result === 'object' || typeof __result === 'function')
883
+ ) {
884
+ __then = __result.then
885
+ }
886
+ } catch (error) {
887
+ __finishDestroyInvocation()
888
+ __finishModuleLifecycleDestroy()
889
+ throw error
890
+ }
891
+ if (typeof __then === 'function') {
892
+ let __resolveResult
893
+ let __rejectResult
894
+ const __resultPromise = new Promise((resolve, reject) => {
895
+ __resolveResult = resolve
896
+ __rejectResult = reject
897
+ })
898
+ const __promise = __resultPromise.then(
899
+ (value) => {
900
+ __finishDestroyInvocation()
901
+ __finishModuleLifecycleDestroy()
902
+ __disposed = true
903
+ __destroyPromise = undefined
904
+ __unregisterCleanup?.()
905
+ return value
906
+ },
907
+ (error) => {
908
+ __finishDestroyInvocation()
909
+ __finishModuleLifecycleDestroy()
910
+ __destroyPromise = undefined
911
+ throw error
912
+ },
913
+ )
914
+ __destroyPromise = __promise
915
+ try {
916
+ Reflect.apply(__then, __result, [__resolveResult, __rejectResult])
917
+ } catch (error) {
918
+ __rejectResult(error)
919
+ }
920
+ return __promise
921
+ }
922
+ __finishDestroyInvocation()
923
+ __finishModuleLifecycleDestroy()
924
+ __disposed = true
925
+ __unregisterCleanup?.()
926
+ }
927
+ const __destroyForModuleLifecycle = () => __destroy(true)
928
+ const __registerCleanup = (
929
+ __beforeExitDestroy = __destroyForModuleLifecycle,
930
+ ) => {
931
+ if (__cleanupRegistered || __disposed) {
932
+ return
933
+ }
934
+ __unregisterCleanup = __registerManagedEmnapiContext(
935
+ __process,
936
+ __beforeExitDestroy,
937
+ )
938
+ __cleanupRegistered = true
939
+ __registerManagedBeforeExitListener()
940
+ }
941
+ if (__contextInitializationFailed) {
942
+ let __registrationError
943
+ let __registrationFailed = false
944
+ try {
945
+ __registerCleanup()
946
+ } catch (error) {
947
+ __attachCleanupError(__contextInitializationError, error)
948
+ __registrationError = error
949
+ __registrationFailed = true
950
+ }
951
+ try {
952
+ await __destroyForModuleLifecycle()
953
+ } catch (error) {
954
+ __attachCleanupError(
955
+ __registrationFailed
956
+ ? __registrationError
957
+ : __contextInitializationError,
958
+ error,
959
+ )
960
+ try {
961
+ __registerManagedBeforeExitListener()
962
+ } catch {}
963
+ }
964
+ throw __contextInitializationError
965
+ }
966
+ return {
967
+ context: __emnapiContext,
968
+ destroy: __destroy,
969
+ destroyForModuleLifecycle: __destroyForModuleLifecycle,
970
+ registerCleanup: __registerCleanup,
971
+ }
972
+ }
973
+
974
+ async function __createInstance(
975
+ __wasmInput,
976
+ __beforeExitDestroy,
977
+ __onManagedDestroyer,
978
+ ) {
979
+ const __module = await __resolveModule(__wasmInput)
980
+ const __emnapiModule = await __normalizeModuleForEmnapi(__module)
981
+ const __wasi = new __WASI({
982
+ version: 'preview1',
983
+ })
984
+ // The wasm module is linked with \`--import-memory\`, so a Memory must be
985
+ // provided. It is allocated here in function scope (workerd bans global
986
+ // scope allocation) and is not shared (no threads, no SharedArrayBuffer).
987
+ // Allocate it before the emnapi context so a host memory-limit failure cannot
988
+ // leak a context that never reaches instantiation.
989
+ const __wasmMemory = new WebAssembly.Memory({
990
+ initial: ${initialMemory},
991
+ maximum: ${maximumMemory},
992
+ })
993
+ let __lifecycleState = 'pending'
994
+ let __destroyEmnapiContext
995
+ let __destroyOwnedContext
996
+ let __destroyManagedOwnedContext
997
+ let __napiInstance
998
+ const __destroyBeforeExit = __beforeExitDestroy
999
+ ? async () => {
1000
+ if (__lifecycleState === 'failed') {
1001
+ await __destroyManagedOwnedContext()
1002
+ return
1003
+ }
1004
+ __lifecycleState = 'disposal'
1005
+ try {
1006
+ await __beforeExitDestroy()
1007
+ } catch (error) {
1008
+ if (__lifecycleState !== 'failed') {
1009
+ throw error
1010
+ }
1011
+ // The singleton's initialization rejection is already observable
1012
+ // through instantiate() and dispose(). Managed beforeExit cleanup
1013
+ // owns only context destruction, including retrying a failed rollback.
1014
+ await __destroyManagedOwnedContext()
1015
+ }
1016
+ }
1017
+ : undefined
1018
+ const {
1019
+ context: __emnapiContext,
1020
+ destroy,
1021
+ destroyForModuleLifecycle,
1022
+ registerCleanup: __registerCleanup,
1023
+ } = await __createManagedEmnapiContext(() => {
1024
+ const __prepareWasmEnvCleanup =
1025
+ __napiInstance?.exports.napi_prepare_wasm_env_cleanup
1026
+ if (typeof __prepareWasmEnvCleanup === 'function') {
1027
+ __prepareWasmEnvCleanup()
1028
+ }
1029
+ })
1030
+ __destroyEmnapiContext = destroy
1031
+ __destroyOwnedContext = () => __destroyEmnapiContext()
1032
+ __destroyManagedOwnedContext = destroyForModuleLifecycle
1033
+ try {
1034
+ if (__destroyBeforeExit) {
1035
+ __onManagedDestroyer(__destroyBeforeExit)
1036
+ await __registerCleanup(__destroyBeforeExit)
1037
+ }
1038
+ ${emnapiInjectBuffer}\
1039
+ let __napiModule
1040
+ ;({
1041
+ instance: __napiInstance,
1042
+ napiModule: __napiModule,
1043
+ } = await __emnapiInstantiateNapiModule(__emnapiModule, {
1044
+ context: __emnapiContext,
1045
+ asyncWorkPoolSize: 0,
1046
+ plugins: [__emnapiAsyncWorkPlugin, __emnapiTSFNPlugin],
1047
+ wasi: __wasi,
1048
+ overwriteImports(importObject) {
1049
+ importObject.env = {
1050
+ ...importObject.env,
1051
+ ...importObject.napi,
1052
+ ...importObject.emnapi,
1053
+ memory: __wasmMemory,
1054
+ }
1055
+ return importObject
1056
+ },
1057
+ beforeInit({ instance }) {
1058
+ __napiInstance = instance
1059
+ for (const name of Object.keys(instance.exports)) {
1060
+ if (name.startsWith('__napi_register__')) {
1061
+ instance.exports[name]()
1062
+ }
1063
+ }
1064
+ },
1065
+ }))
1066
+ if (__lifecycleState === 'pending') {
1067
+ __lifecycleState = 'succeeded'
1068
+ }
1069
+ return {
1070
+ exports: __napiModule.exports,
1071
+ async dispose() {
1072
+ if (__lifecycleState !== 'failed') {
1073
+ __lifecycleState = 'disposal'
1074
+ }
1075
+ return __beforeExitDestroy
1076
+ ? __destroyManagedOwnedContext()
1077
+ : __destroyOwnedContext()
1078
+ },
1079
+ }
1080
+ } catch (error) {
1081
+ __lifecycleState = 'failed'
1082
+ let __registrationError
1083
+ let __registrationFailed = false
1084
+ if (!__beforeExitDestroy) {
1085
+ try {
1086
+ // Independent instances are caller-owned while pending and after
1087
+ // success. Register only failed rollback so cleanup remains retryable.
1088
+ await __registerCleanup()
1089
+ } catch (registrationError) {
1090
+ __attachCleanupError(error, registrationError)
1091
+ __registrationError = registrationError
1092
+ __registrationFailed = true
1093
+ }
1094
+ }
1095
+ try {
1096
+ await __destroyManagedOwnedContext()
1097
+ } catch (disposeError) {
1098
+ // Initialization is the primary failure. Preserve it even if cleanup
1099
+ // also fails, while retaining the cleanup error when the value is
1100
+ // extensible and has no existing cause.
1101
+ __attachCleanupError(
1102
+ __registrationFailed ? __registrationError : error,
1103
+ disposeError,
1104
+ )
1105
+ try {
1106
+ __registerManagedBeforeExitListener()
1107
+ } catch {}
1108
+ }
1109
+ throw error
1110
+ }
1111
+ }
1112
+
1113
+ /**
1114
+ * Create an independent instance. Call dispose() when the instance is no
1115
+ * longer needed so emnapi cleanup hooks run deterministically.
1116
+ */
1117
+ export async function createInstance(__wasmInput) {
1118
+ return __createInstance(__wasmInput)
1119
+ }
1120
+
1121
+ let __defaultModulePromise
1122
+ let __defaultInstancePromise
1123
+ let __defaultDisposePromise
1124
+ let __defaultDisposalStarted = false
1125
+ const __defaultManagedDestroyers = new WeakMap()
1126
+ let __moduleDisposePromise
1127
+
1128
+ /**
1129
+ * Instantiate a module-local singleton. Concurrent and repeated calls
1130
+ * with the same module share one instance and one Memory allocation.
1131
+ */
1132
+ export function instantiate(__wasmInput) {
1133
+ const __modulePromise = __resolveModule(__wasmInput)
1134
+ if (__moduleLifecycleDestroyDepth !== 0) {
1135
+ void __modulePromise.catch(() => {})
1136
+ return Promise.reject(__createLifecycleReentryError('instantiate'))
1137
+ }
1138
+ if (__moduleDisposePromise) {
1139
+ void __modulePromise.catch(() => {})
1140
+ return __moduleDisposePromise.then(() => instantiate(__modulePromise))
1141
+ }
1142
+ if (__defaultDisposalStarted) {
1143
+ // Observe rejected input immediately, but preserve lifecycle ordering and
1144
+ // error precedence by instantiating only after disposal succeeds. A failed
1145
+ // disposal retains the old instance only so its cleanup can be retried.
1146
+ void __modulePromise.catch(() => {})
1147
+ const __disposePromise = __defaultDisposePromise ?? dispose()
1148
+ return __disposePromise.then(() => instantiate(__modulePromise))
1149
+ }
1150
+ if (!__defaultInstancePromise) {
1151
+ __defaultModulePromise = __modulePromise
1152
+ const __instancePromise = __modulePromise.then((__module) =>
1153
+ __createInstance(
1154
+ __module,
1155
+ __disposeDefaultInstance,
1156
+ (__managedDestroyer) => {
1157
+ __defaultManagedDestroyers.set(
1158
+ __instancePromise,
1159
+ __managedDestroyer,
1160
+ )
1161
+ },
1162
+ ),
1163
+ )
1164
+ __defaultInstancePromise = __instancePromise
1165
+ void __instancePromise.catch(() => {
1166
+ if (__defaultInstancePromise === __instancePromise) {
1167
+ __defaultInstancePromise = undefined
1168
+ __defaultModulePromise = undefined
1169
+ }
1170
+ })
1171
+ return __instancePromise.then((__instance) => __instance.exports)
1172
+ }
1173
+ const __defaultModulePromiseForCall = __defaultModulePromise
1174
+ const __defaultInstancePromiseForCall = __defaultInstancePromise
1175
+ return Promise.all([__defaultModulePromiseForCall, __modulePromise]).then(
1176
+ async ([__defaultModule, __module]) => {
1177
+ if (__defaultModule !== __module) {
1178
+ throw new Error(
1179
+ 'instantiate() already owns a different WebAssembly.Module; call dispose() first or use createInstance() for independent instances.',
1180
+ )
1181
+ }
1182
+ return (await __defaultInstancePromiseForCall).exports
1183
+ },
1184
+ )
1185
+ }
1186
+
1187
+ async function __disposeDefaultInstance(__onDestroy) {
1188
+ if (__defaultDisposePromise) {
1189
+ return __defaultDisposePromise
1190
+ }
1191
+ const __instancePromise = __defaultInstancePromise
1192
+ if (!__instancePromise) {
1193
+ __defaultDisposalStarted = false
1194
+ return
1195
+ }
1196
+ __defaultDisposalStarted = true
1197
+ const __disposePromise = (async () => {
1198
+ let __instance
1199
+ try {
1200
+ __instance = await __instancePromise
1201
+ } catch (error) {
1202
+ const __managedDestroyer =
1203
+ __defaultManagedDestroyers.get(__instancePromise)
1204
+ if (__managedDestroyer) {
1205
+ __onDestroy?.(__managedDestroyer)
1206
+ }
1207
+ __defaultManagedDestroyers.delete(__instancePromise)
1208
+ throw error
1209
+ }
1210
+ const __managedDestroyer =
1211
+ __defaultManagedDestroyers.get(__instancePromise)
1212
+ if (__managedDestroyer) {
1213
+ __onDestroy?.(__managedDestroyer)
1214
+ }
1215
+ await __instance.dispose()
1216
+ if (__defaultInstancePromise === __instancePromise) {
1217
+ __defaultInstancePromise = undefined
1218
+ __defaultModulePromise = undefined
1219
+ __defaultDisposalStarted = false
1220
+ }
1221
+ __defaultManagedDestroyers.delete(__instancePromise)
1222
+ })()
1223
+ __defaultDisposePromise = __disposePromise
1224
+ try {
1225
+ await __disposePromise
1226
+ } finally {
1227
+ if (__defaultDisposePromise === __disposePromise) {
1228
+ __defaultDisposePromise = undefined
1229
+ }
1230
+ }
1231
+ }
1232
+
1233
+ async function __dispose() {
1234
+ let __defaultDisposeError
1235
+ let __defaultDisposeFailed = false
1236
+ let __attemptedDefaultDestroyer
1237
+ try {
1238
+ await __disposeDefaultInstance((__destroyer) => {
1239
+ __attemptedDefaultDestroyer = __destroyer
1240
+ })
1241
+ } catch (error) {
1242
+ __defaultDisposeError = error
1243
+ __defaultDisposeFailed = true
1244
+ }
1245
+ const __excludedDestroyers = new Set()
1246
+ if (__defaultDisposeFailed && __attemptedDefaultDestroyer) {
1247
+ __excludedDestroyers.add(__attemptedDefaultDestroyer)
1248
+ }
1249
+ try {
1250
+ await __drainManagedEmnapiContexts(__excludedDestroyers)
1251
+ } catch (error) {
1252
+ if (!__defaultDisposeFailed) {
1253
+ throw error
1254
+ }
1255
+ if (error !== __defaultDisposeError) {
1256
+ __attachCleanupError(__defaultDisposeError, error)
1257
+ }
1258
+ }
1259
+ if (__defaultDisposeFailed) {
1260
+ throw __defaultDisposeError
1261
+ }
1262
+ }
1263
+
1264
+ /**
1265
+ * Dispose the singleton created by instantiate(). A later call may create a
1266
+ * fresh instance, including from a different module. This also retries cleanup
1267
+ * retained after a failed initialization rollback.
1268
+ */
1269
+ export function dispose() {
1270
+ if (__moduleLifecycleDestroyDepth !== 0) {
1271
+ return Promise.reject(__createLifecycleReentryError('dispose'))
1272
+ }
1273
+ if (__moduleDisposePromise) {
1274
+ return __moduleDisposePromise
1275
+ }
1276
+ let __resolveDispose
1277
+ let __rejectDispose
1278
+ const __promise = new Promise((resolve, reject) => {
1279
+ __resolveDispose = resolve
1280
+ __rejectDispose = reject
1281
+ })
1282
+ __moduleDisposePromise = __promise
1283
+ void __dispose().then(__resolveDispose, __rejectDispose)
1284
+ void __promise.then(
1285
+ () => {
1286
+ if (__moduleDisposePromise === __promise) {
1287
+ __moduleDisposePromise = undefined
1288
+ }
1289
+ },
1290
+ () => {
1291
+ if (__moduleDisposePromise === __promise) {
1292
+ __moduleDisposePromise = undefined
1293
+ }
1294
+ },
1295
+ )
1296
+ return __promise
1297
+ }
110
1298
  `
111
1299
  }
112
1300
 
1301
+ export const createWasiDeferredBrowserBindingTypeDef = (
1302
+ packageName: string,
1303
+ ) => `export type WasiBinding = typeof import('${packageName}')
1304
+
1305
+ export type WasiModuleInput =
1306
+ | WebAssembly.Module
1307
+ | PromiseLike<WebAssembly.Module>
1308
+
1309
+ export interface WasiInstance {
1310
+ readonly exports: WasiBinding
1311
+ dispose(): Promise<void>
1312
+ }
1313
+
1314
+ export function instantiate(wasmInput: WasiModuleInput): Promise<WasiBinding>
1315
+ export function createInstance(wasmInput: WasiModuleInput): Promise<WasiInstance>
1316
+ /** Dispose the singleton and retry retained failed-initialization cleanup. */
1317
+ export function dispose(): Promise<void>
1318
+ `
1319
+
113
1320
  export const createWasiBinding = (
114
1321
  wasmFileName: string,
115
1322
  packageName: string,
116
1323
  initialMemory = 4000,
117
1324
  maximumMemory = 65536,
118
- ) => `/* eslint-disable */
1325
+ threads = true,
1326
+ // `platformArchABI` of the flavor this loader belongs to; the fallback
1327
+ // package (`<packageName>-<platformArchABI>`) must ship the same flavor's
1328
+ // wasm artifact.
1329
+ platformArchABI = 'wasm32-wasi',
1330
+ packageWasmFileName = wasmFileName,
1331
+ ) => {
1332
+ const workerImports = threads
1333
+ ? `const { Worker } = require('node:worker_threads')
1334
+ `
1335
+ : ''
1336
+ const workerExecArgv = threads
1337
+ ? `
1338
+ function __getWasiWorkerExecArgv() {
1339
+ const __workerExecArgv = []
1340
+ for (let __index = 0; __index < process.execArgv.length; __index += 1) {
1341
+ const __arg = process.execArgv[__index]
1342
+ if (
1343
+ __arg === '--input-type' ||
1344
+ __arg === '--eval' ||
1345
+ __arg === '-e' ||
1346
+ __arg === '--print' ||
1347
+ __arg === '-p'
1348
+ ) {
1349
+ __index += 1
1350
+ continue
1351
+ }
1352
+ if (
1353
+ __arg.startsWith('--input-type=') ||
1354
+ __arg.startsWith('--eval=') ||
1355
+ __arg.startsWith('--print=')
1356
+ ) {
1357
+ continue
1358
+ }
1359
+ __workerExecArgv.push(__arg)
1360
+ }
1361
+ return __workerExecArgv
1362
+ }
1363
+
1364
+ function __isInvalidWasiWorkerExecArgv(errorMessage, argument) {
1365
+ const __equalsIndex = argument.indexOf('=')
1366
+ const __argumentName =
1367
+ __equalsIndex === -1 ? argument : argument.slice(0, __equalsIndex)
1368
+ return (
1369
+ errorMessage.includes(': ' + __argumentName + ',') ||
1370
+ errorMessage.includes(': ' + __argumentName + '=') ||
1371
+ errorMessage.endsWith(': ' + __argumentName) ||
1372
+ errorMessage.includes(', ' + __argumentName + ',') ||
1373
+ errorMessage.includes(', ' + __argumentName + '=') ||
1374
+ errorMessage.endsWith(', ' + __argumentName)
1375
+ )
1376
+ }
1377
+
1378
+ function __removeInvalidWasiWorkerExecArgv(execArgv, error) {
1379
+ if (typeof error.message !== 'string') {
1380
+ return
1381
+ }
1382
+ const __workerExecArgv = []
1383
+ let __removed = false
1384
+ for (let __index = 0; __index < execArgv.length; __index += 1) {
1385
+ const __arg = execArgv[__index]
1386
+ if (
1387
+ __arg.startsWith('-') &&
1388
+ __isInvalidWasiWorkerExecArgv(error.message, __arg)
1389
+ ) {
1390
+ __removed = true
1391
+ if (
1392
+ !__arg.includes('=') &&
1393
+ __index + 1 < execArgv.length &&
1394
+ !execArgv[__index + 1].startsWith('-')
1395
+ ) {
1396
+ __index += 1
1397
+ }
1398
+ continue
1399
+ }
1400
+ __workerExecArgv.push(__arg)
1401
+ }
1402
+ return __removed ? __workerExecArgv : undefined
1403
+ }
1404
+
1405
+ function __createWasiWorker(filename) {
1406
+ let __workerExecArgv = __getWasiWorkerExecArgv()
1407
+ while (true) {
1408
+ try {
1409
+ return new Worker(filename, {
1410
+ env: process.env,
1411
+ execArgv: __workerExecArgv,
1412
+ })
1413
+ } catch (error) {
1414
+ if (!error || error.code !== 'ERR_WORKER_INVALID_EXEC_ARGV') {
1415
+ throw error
1416
+ }
1417
+ const __nextWorkerExecArgv =
1418
+ __removeInvalidWasiWorkerExecArgv(__workerExecArgv, error)
1419
+ if (!__nextWorkerExecArgv) {
1420
+ throw error
1421
+ }
1422
+ __workerExecArgv = __nextWorkerExecArgv
1423
+ }
1424
+ }
1425
+ }
1426
+ `
1427
+ : ''
1428
+ const workerRuntimeImport = threads
1429
+ ? ` createOnMessage: __wasmCreateOnMessageForFsProxy,\n`
1430
+ : ''
1431
+ const memoryName = threads ? '__sharedMemory' : '__wasmMemory'
1432
+ const asyncWorkOptions = threads
1433
+ ? ` asyncWorkPoolSize: (function() {
1434
+ const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
1435
+ // NaN > 0 is false
1436
+ if (threadsSizeFromEnv > 0) {
1437
+ return threadsSizeFromEnv
1438
+ } else {
1439
+ return 4
1440
+ }
1441
+ })(),
1442
+ reuseWorker: true,
1443
+ plugins: [__emnapiAsyncWorkPlugin, __emnapiTSFNPlugin],
1444
+ `
1445
+ : ` asyncWorkPoolSize: 0,
1446
+ plugins: [__emnapiAsyncWorkPlugin, __emnapiTSFNPlugin],
1447
+ `
1448
+ // Every build links a "basic" emnapi archive without the C async-work and
1449
+ // threadsafe-function implementations (the `emnapi-napi-rs(-mt)` archives shipped by the emnapi package), so the
1450
+ // JavaScript implementations must be provided through the emnapi plugins in
1451
+ // both threading modes. Without threads the C code would be unconditional
1452
+ // `napi_generic_failure` stubs; with threads it would shadow the
1453
+ // `@emnapi/core` threaded TSFN/async-work protocol the plugins implement.
1454
+ const emnapiPluginRequire = ` emnapiAsyncWorkPlugin: __emnapiAsyncWorkPlugin,\n emnapiTSFNPlugin: __emnapiTSFNPlugin,\n`
1455
+ const workerOption = threads
1456
+ ? ` onCreateWorker() {
1457
+ const worker = __createWasiWorker(__nodePath.join(__dirname, 'wasi-worker.mjs'))
1458
+ __wasiWorkers.add(worker)
1459
+ worker.onmessage = ({ data }) => {
1460
+ __wasmCreateOnMessageForFsProxy(__nodeFs)(data)
1461
+ }
1462
+
1463
+ // The main thread of Node.js waits for all the active handles before exiting.
1464
+ // But Rust threads are never waited without \`thread::join\`.
1465
+ // So here we hack the code of Node.js to prevent the workers from being referenced (active).
1466
+ // According to https://github.com/nodejs/node/blob/19e0d472728c79d418b74bddff588bea70a403d0/lib/internal/worker.js#L415,
1467
+ // a worker is consist of two handles: kPublicPort and kHandle.
1468
+ {
1469
+ const kPublicPort = Object.getOwnPropertySymbols(worker).find(s =>
1470
+ s.toString().includes("kPublicPort")
1471
+ );
1472
+ if (kPublicPort) {
1473
+ worker[kPublicPort].ref = () => {};
1474
+ }
1475
+
1476
+ const kHandle = Object.getOwnPropertySymbols(worker).find(s =>
1477
+ s.toString().includes("kHandle")
1478
+ );
1479
+ if (kHandle) {
1480
+ worker[kHandle].ref = () => {};
1481
+ }
1482
+
1483
+ worker.unref();
1484
+ }
1485
+ return worker
1486
+ },
1487
+ `
1488
+ : ''
1489
+
1490
+ return `/* eslint-disable */
119
1491
  /* prettier-ignore */
120
1492
 
121
1493
  /* auto-generated by NAPI-RS */
@@ -123,13 +1495,15 @@ export const createWasiBinding = (
123
1495
  const __nodeFs = require('node:fs')
124
1496
  const __nodePath = require('node:path')
125
1497
  const { WASI: __nodeWASI } = require('node:wasi')
126
- const { Worker } = require('node:worker_threads')
1498
+ ${workerImports}\
127
1499
 
128
1500
  const {
129
- createOnMessage: __wasmCreateOnMessageForFsProxy,
130
- getDefaultContext: __emnapiGetDefaultContext,
1501
+ ${emnapiPluginRequire}\
1502
+ ${workerRuntimeImport}\
131
1503
  instantiateNapiModuleSync: __emnapiInstantiateNapiModuleSync,
132
1504
  } = require('@napi-rs/wasm-runtime')
1505
+ const { createContext: __emnapiCreateContext } = require('@emnapi/runtime')
1506
+ ${workerExecArgv}\
133
1507
 
134
1508
  const __rootDir = __nodePath.parse(process.cwd()).root
135
1509
 
@@ -141,12 +1515,10 @@ const __wasi = new __nodeWASI({
141
1515
  }
142
1516
  })
143
1517
 
144
- const __emnapiContext = __emnapiGetDefaultContext()
145
-
146
- const __sharedMemory = new WebAssembly.Memory({
1518
+ const ${memoryName} = new WebAssembly.Memory({
147
1519
  initial: ${initialMemory},
148
1520
  maximum: ${maximumMemory},
149
- shared: true,
1521
+ ${threads ? ' shared: true,\n' : ''}\
150
1522
  })
151
1523
 
152
1524
  let __wasmFilePath = __nodePath.join(__dirname, '${wasmFileName}.wasm')
@@ -155,73 +1527,231 @@ const __wasmDebugFilePath = __nodePath.join(__dirname, '${wasmFileName}.debug.wa
155
1527
  if (__nodeFs.existsSync(__wasmDebugFilePath)) {
156
1528
  __wasmFilePath = __wasmDebugFilePath
157
1529
  } else if (!__nodeFs.existsSync(__wasmFilePath)) {
158
- try {
159
- __wasmFilePath = require.resolve('${packageName}-wasm32-wasi/${wasmFileName}.wasm')
160
- } catch {
161
- throw new Error('Cannot find ${wasmFileName}.wasm file, and ${packageName}-wasm32-wasi package is not installed.')
1530
+ const __wasiPackageEntry = require.resolve('${packageName}-${platformArchABI}')
1531
+ const __packagedWasmFilePath = __nodePath.join(
1532
+ __nodePath.dirname(__wasiPackageEntry),
1533
+ '${packageWasmFileName}.wasm',
1534
+ )
1535
+ if (!__nodeFs.existsSync(__packagedWasmFilePath)) {
1536
+ throw new Error(
1537
+ '${packageName}-${platformArchABI} is installed but is missing ${packageWasmFileName}.wasm.',
1538
+ )
162
1539
  }
1540
+ __wasmFilePath = __packagedWasmFilePath
163
1541
  }
164
1542
 
165
- const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__wasmFilePath), {
166
- context: __emnapiContext,
167
- asyncWorkPoolSize: (function() {
168
- const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
169
- // NaN > 0 is false
170
- if (threadsSizeFromEnv > 0) {
171
- return threadsSizeFromEnv
172
- } else {
173
- return 4
174
- }
175
- })(),
176
- reuseWorker: true,
177
- wasi: __wasi,
178
- onCreateWorker() {
179
- const worker = new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
180
- env: process.env,
181
- })
182
- worker.onmessage = ({ data }) => {
183
- __wasmCreateOnMessageForFsProxy(__nodeFs)(data)
1543
+ const __wasmFile = __nodeFs.readFileSync(__wasmFilePath)
1544
+ let __emnapiContext
1545
+ ${emnapiContextLifecycle}
1546
+ const __wasiRollbackRegistrySymbol = Symbol.for('${WASI_ROLLBACK_REGISTRY_SYMBOL}')
1547
+ const __wasiRollbackRegistryKey =
1548
+ typeof __filename === 'string' ? __filename : __wasmFilePath
1549
+
1550
+ function __getWasiRollbackRegistry() {
1551
+ const existing = process[__wasiRollbackRegistrySymbol]
1552
+ if (existing !== undefined) {
1553
+ if (!(existing instanceof Map)) {
1554
+ throw new TypeError(
1555
+ 'The process-wide NAPI-RS WASI rollback registry is invalid',
1556
+ )
184
1557
  }
1558
+ return existing
1559
+ }
1560
+ const registry = new Map()
1561
+ Object.defineProperty(process, __wasiRollbackRegistrySymbol, {
1562
+ configurable: false,
1563
+ enumerable: false,
1564
+ value: registry,
1565
+ writable: false,
1566
+ })
1567
+ return registry
1568
+ }
185
1569
 
186
- // The main thread of Node.js waits for all the active handles before exiting.
187
- // But Rust threads are never waited without \`thread::join\`.
188
- // So here we hack the code of Node.js to prevent the workers from being referenced (active).
189
- // According to https://github.com/nodejs/node/blob/19e0d472728c79d418b74bddff588bea70a403d0/lib/internal/worker.js#L415,
190
- // a worker is consist of two handles: kPublicPort and kHandle.
191
- {
192
- const kPublicPort = Object.getOwnPropertySymbols(worker).find(s =>
193
- s.toString().includes("kPublicPort")
194
- );
195
- if (kPublicPort) {
196
- worker[kPublicPort].ref = () => {};
197
- }
1570
+ const __wasiRollbackRegistry = __getWasiRollbackRegistry()
198
1571
 
199
- const kHandle = Object.getOwnPropertySymbols(worker).find(s =>
200
- s.toString().includes("kHandle")
201
- );
202
- if (kHandle) {
203
- worker[kHandle].ref = () => {};
1572
+ function __completeWasiInitializationRollback(record, cleanupErrors) {
1573
+ try {
1574
+ if (cleanupErrors.length === 0) {
1575
+ if (
1576
+ __wasiRollbackRegistry.get(__wasiRollbackRegistryKey) === record
1577
+ ) {
1578
+ __wasiRollbackRegistry.delete(__wasiRollbackRegistryKey)
204
1579
  }
1580
+ return
1581
+ }
1582
+ record.error = __attachCleanupErrors(record.error, cleanupErrors)
1583
+ } catch (cleanupError) {
1584
+ try {
1585
+ record.error = __createCleanupError(
1586
+ [record.error, cleanupError],
1587
+ 'WASI binding initialization and cleanup failed',
1588
+ )
1589
+ } catch {}
1590
+ } finally {
1591
+ record.active = false
1592
+ record.promise = undefined
1593
+ }
1594
+ }
205
1595
 
206
- worker.unref();
1596
+ function __runWasiInitializationRollback(record) {
1597
+ if (record.active) {
1598
+ return
1599
+ }
1600
+ record.active = true
1601
+
1602
+ let rollbackResult
1603
+ try {
1604
+ rollbackResult = record.rollback()
1605
+ } catch (cleanupError) {
1606
+ __completeWasiInitializationRollback(record, [cleanupError])
1607
+ return
1608
+ }
1609
+
1610
+ if (!__isThenable(rollbackResult)) {
1611
+ __completeWasiInitializationRollback(record, rollbackResult)
1612
+ return
1613
+ }
1614
+
1615
+ record.promise = Promise.resolve(rollbackResult).then(
1616
+ (cleanupErrors) => {
1617
+ __completeWasiInitializationRollback(record, cleanupErrors)
1618
+ },
1619
+ (cleanupError) => {
1620
+ __completeWasiInitializationRollback(record, [cleanupError])
1621
+ },
1622
+ )
1623
+ }
1624
+
1625
+ const __pendingWasiRollback = __wasiRollbackRegistry.get(
1626
+ __wasiRollbackRegistryKey,
1627
+ )
1628
+ if (__pendingWasiRollback !== undefined) {
1629
+ __runWasiInitializationRollback(__pendingWasiRollback)
1630
+ throw __pendingWasiRollback.error
1631
+ }
1632
+
1633
+ let __wasiModule
1634
+ let __napiModule
1635
+ let __wasiExitListenerRegistered = false
1636
+
1637
+ function __removeWasiExitListener() {
1638
+ if (
1639
+ __wasiExitListenerRegistered &&
1640
+ typeof process.removeListener === 'function'
1641
+ ) {
1642
+ process.removeListener('exit', __disposeWasiBindingAtExit)
1643
+ }
1644
+ __wasiExitListenerRegistered = false
1645
+ }
1646
+
1647
+ function __disposeWasiBindingAtExit() {
1648
+ __wasiExitListenerRegistered = false
1649
+ try {
1650
+ const result = __disposeWasiBinding()
1651
+ if (__isThenable(result)) {
1652
+ void Promise.resolve(result).catch(() => {})
207
1653
  }
208
- return worker
209
- },
210
- overwriteImports(importObject) {
211
- importObject.env = {
212
- ...importObject.env,
213
- ...importObject.napi,
214
- ...importObject.emnapi,
215
- memory: __sharedMemory,
216
- }
217
- return importObject
218
- },
219
- beforeInit({ instance }) {
220
- for (const name of Object.keys(instance.exports)) {
221
- if (name.startsWith('__napi_register__')) {
222
- instance.exports[name]()
223
- }
1654
+ } catch {}
1655
+ }
1656
+
1657
+ function __registerWasiExitListener() {
1658
+ if (
1659
+ !__wasiExitListenerRegistered &&
1660
+ typeof process.once === 'function'
1661
+ ) {
1662
+ process.once('exit', __disposeWasiBindingAtExit)
1663
+ __wasiExitListenerRegistered = true
1664
+ }
1665
+ }
1666
+
1667
+ __completeWasiDisposal = __removeWasiExitListener
1668
+
1669
+ function __captureEmnapiAutoDestroyListener() {
1670
+ if (
1671
+ typeof process.prependListener !== 'function' ||
1672
+ typeof process.removeListener !== 'function'
1673
+ ) {
1674
+ return
1675
+ }
1676
+ let __autoDestroyListener
1677
+ const __captureListener = (__event, __listener) => {
1678
+ if (__event === 'beforeExit' && __autoDestroyListener === undefined) {
1679
+ __autoDestroyListener = __listener
224
1680
  }
225
- },
226
- })
1681
+ }
1682
+ try {
1683
+ // Run before existing newListener hooks so a hook that registers its own
1684
+ // beforeExit listener cannot be mistaken for emnapi's registration.
1685
+ process.prependListener('newListener', __captureListener)
1686
+ } catch {
1687
+ return
1688
+ }
1689
+ return () => {
1690
+ try {
1691
+ process.removeListener('newListener', __captureListener)
1692
+ } catch {}
1693
+ if (__autoDestroyListener !== undefined) {
1694
+ try {
1695
+ process.removeListener('beforeExit', __autoDestroyListener)
1696
+ } catch {}
1697
+ }
1698
+ }
1699
+ }
1700
+
1701
+ try {
1702
+ const __finishAutoDestroyCapture = __captureEmnapiAutoDestroyListener()
1703
+ try {
1704
+ __emnapiContext = __emnapiCreateContext({ autoDestroy: false })
1705
+ // emnapi 2.x still registers an unconditional once-listener for
1706
+ // beforeExit that auto-destroys the context, and suppressDestroy() only
1707
+ // neutralizes its callback without removing it. This loader owns cleanup
1708
+ // through its 'exit' listener, so emnapi's listener is captured and
1709
+ // removed; suppressDestroy() remains the safety net when removal fails.
1710
+ __emnapiContext.suppressDestroy()
1711
+ } finally {
1712
+ // Remove only the exact emnapi callback captured above.
1713
+ __finishAutoDestroyCapture?.()
1714
+ }
1715
+
1716
+ ;({
1717
+ instance: __napiInstance,
1718
+ module: __wasiModule,
1719
+ napiModule: __napiModule,
1720
+ } = __emnapiInstantiateNapiModuleSync(__wasmFile, {
1721
+ context: __emnapiContext,
1722
+ ${asyncWorkOptions}\
1723
+ wasi: __wasi,
1724
+ ${workerOption}\
1725
+ overwriteImports(importObject) {
1726
+ importObject.env = {
1727
+ ...importObject.env,
1728
+ ...importObject.napi,
1729
+ ...importObject.emnapi,
1730
+ memory: ${memoryName},
1731
+ }
1732
+ return importObject
1733
+ },
1734
+ beforeInit({ instance }) {
1735
+ __napiInstance = instance
1736
+ for (const name of Object.keys(instance.exports)) {
1737
+ if (name.startsWith('__napi_register__')) {
1738
+ instance.exports[name]()
1739
+ }
1740
+ }
1741
+ },
1742
+ }))
1743
+ __publishWasiDispose(__napiModule.exports)
1744
+ __registerWasiExitListener()
1745
+ } catch (error) {
1746
+ const rollback = {
1747
+ active: false,
1748
+ error,
1749
+ promise: undefined,
1750
+ rollback: __rollbackWasiInitialization,
1751
+ }
1752
+ __wasiRollbackRegistry.set(__wasiRollbackRegistryKey, rollback)
1753
+ __runWasiInitializationRollback(rollback)
1754
+ throw rollback.error
1755
+ }
227
1756
  `
1757
+ }