@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
@@ -9,11 +9,13 @@ Generated by [AVA](https://avajs.dev).
9
9
  > Snapshot 1
10
10
 
11
11
  `import {␊
12
+ emnapiAsyncWorkPlugin as __emnapiAsyncWorkPlugin,␊
13
+ emnapiTSFNPlugin as __emnapiTSFNPlugin,␊
12
14
  createOnMessage as __wasmCreateOnMessageForFsProxy,␊
13
- getDefaultContext as __emnapiGetDefaultContext,␊
14
15
  instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync,␊
15
16
  WASI as __WASI,␊
16
17
  } from '@napi-rs/wasm-runtime'␊
18
+ import { createContext as __emnapiCreateContext } from '@emnapi/runtime'␊
17
19
  ␊
18
20
  ␊
19
21
  ␊
@@ -22,8 +24,18 @@ Generated by [AVA](https://avajs.dev).
22
24
  })␊
23
25
  ␊
24
26
  const __wasmUrl = new URL('./test-wasi.wasm', import.meta.url).href␊
25
- const __emnapiContext = __emnapiGetDefaultContext()␊
26
- ␊
27
+ const __wasmResponse = await globalThis.fetch(__wasmUrl)␊
28
+ if (!__wasmResponse.ok) {␊
29
+ throw new Error(␊
30
+ 'Failed to fetch WASI module ' +␊
31
+ __wasmUrl +␊
32
+ ': ' +␊
33
+ __wasmResponse.status +␊
34
+ ' ' +␊
35
+ (__wasmResponse.statusText || 'Unknown Status'),␊
36
+ )␊
37
+ }␊
38
+ const __wasmFile = await __wasmResponse.arrayBuffer()␊
27
39
  ␊
28
40
  const __sharedMemory = new WebAssembly.Memory({␊
29
41
  initial: 4000,␊
@@ -31,41 +43,314 @@ Generated by [AVA](https://avajs.dev).
31
43
  shared: true,␊
32
44
  })␊
33
45
  ␊
34
- const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())␊
35
- ␊
36
- const {␊
37
- instance: __napiInstance,␊
38
- module: __wasiModule,␊
39
- napiModule: __napiModule,␊
40
- } = __emnapiInstantiateNapiModuleSync(__wasmFile, {␊
41
- context: __emnapiContext,␊
42
- asyncWorkPoolSize: 4,␊
43
- wasi: __wasi,␊
44
- onCreateWorker() {␊
45
- const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {␊
46
- type: 'module',␊
47
- })␊
46
+ let __emnapiContext␊
48
47
  ␊
48
+ const __wasiDisposeSymbol = Symbol.for('napi.rs.wasi.dispose')␊
49
+ const __wasiWorkers = new Set()␊
50
+ let __napiInstance␊
51
+ let __emnapiContextDestroyed = false␊
52
+ let __emnapiContextDestroyPromise␊
53
+ let __emnapiWasmEnvCleanupPrepared = false␊
54
+ let __wasiDisposed = false␊
55
+ let __wasiDisposePromise␊
56
+ let __completeWasiDisposal = function() {}␊
49
57
  ␊
50
- return worker␊
51
- },␊
52
- overwriteImports(importObject) {␊
53
- importObject.env = {␊
54
- ...importObject.env,␊
55
- ...importObject.napi,␊
56
- ...importObject.emnapi,␊
57
- memory: __sharedMemory,␊
58
- }␊
59
- return importObject␊
60
- },␊
61
- beforeInit({ instance }) {␊
62
- for (const name of Object.keys(instance.exports)) {␊
63
- if (name.startsWith('__napi_register__')) {␊
64
- instance.exports[name]()␊
58
+ function __isThenable(value) {␊
59
+ return (␊
60
+ value !== null &&␊
61
+ (typeof value === 'object' || typeof value === 'function') &&␊
62
+ typeof value.then === 'function'␊
63
+ )␊
64
+ }␊
65
+ ␊
66
+ function __createCleanupError(errors, message) {␊
67
+ if (errors.length === 1) {␊
68
+ return errors[0]␊
69
+ }␊
70
+ const __AggregateError = globalThis.AggregateError␊
71
+ if (typeof __AggregateError === 'function') {␊
72
+ return new __AggregateError(errors, message)␊
73
+ }␊
74
+ const error = new Error(message)␊
75
+ error.errors = errors␊
76
+ return error␊
77
+ }␊
78
+ ␊
79
+ function __attachCleanupErrors(error, cleanupErrors) {␊
80
+ if (cleanupErrors.length === 0) {␊
81
+ return error␊
82
+ }␊
83
+ const cleanupError = __createCleanupError(␊
84
+ cleanupErrors,␊
85
+ 'WASI binding cleanup failed',␊
86
+ )␊
87
+ try {␊
88
+ if (␊
89
+ error &&␊
90
+ (typeof error === 'object' || typeof error === 'function')␊
91
+ ) {␊
92
+ if (error.cause === undefined) {␊
93
+ error.cause = cleanupError␊
94
+ if (error.cause === cleanupError) {␊
95
+ return error␊
96
+ }␊
97
+ }␊
98
+ if (Array.isArray(error.cleanupErrors)) {␊
99
+ error.cleanupErrors.push(cleanupError)␊
100
+ return error␊
101
+ } else {␊
102
+ const attachedCleanupErrors = [cleanupError]␊
103
+ error.cleanupErrors = attachedCleanupErrors␊
104
+ if (error.cleanupErrors === attachedCleanupErrors) {␊
105
+ return error␊
106
+ }␊
65
107
  }␊
66
108
  }␊
67
- },␊
68
- })␊
109
+ } catch {}␊
110
+ const aggregate = __createCleanupError(␊
111
+ [error, cleanupError],␊
112
+ 'WASI binding initialization and cleanup failed',␊
113
+ )␊
114
+ try {␊
115
+ aggregate.cause = error␊
116
+ } catch {}␊
117
+ return aggregate␊
118
+ }␊
119
+ ␊
120
+ function __prepareWasmEnvCleanup() {␊
121
+ if (__emnapiWasmEnvCleanupPrepared) {␊
122
+ return␊
123
+ }␊
124
+ const prepare = __napiInstance?.exports?.napi_prepare_wasm_env_cleanup␊
125
+ if (typeof prepare === 'function') {␊
126
+ prepare()␊
127
+ }␊
128
+ __emnapiWasmEnvCleanupPrepared = true␊
129
+ }␊
130
+ ␊
131
+ function __destroyEmnapiContext() {␊
132
+ if (__emnapiContextDestroyed || __emnapiContext === undefined) {␊
133
+ __emnapiContextDestroyed = true␊
134
+ return␊
135
+ }␊
136
+ if (__emnapiContextDestroyPromise) {␊
137
+ return __emnapiContextDestroyPromise␊
138
+ }␊
139
+ ␊
140
+ __prepareWasmEnvCleanup()␊
141
+ const result = __emnapiContext.destroy()␊
142
+ if (!__isThenable(result)) {␊
143
+ __emnapiContextDestroyed = true␊
144
+ return␊
145
+ }␊
146
+ ␊
147
+ const destroyPromise = Promise.resolve(result).then(␊
148
+ (value) => {␊
149
+ __emnapiContextDestroyed = true␊
150
+ return value␊
151
+ },␊
152
+ (error) => {␊
153
+ __emnapiContextDestroyPromise = undefined␊
154
+ throw error␊
155
+ },␊
156
+ )␊
157
+ __emnapiContextDestroyPromise = destroyPromise␊
158
+ return destroyPromise␊
159
+ }␊
160
+ ␊
161
+ function __terminateWasiWorkers() {␊
162
+ const cleanupErrors = []␊
163
+ const pending = []␊
164
+ ␊
165
+ for (const worker of __wasiWorkers) {␊
166
+ let result␊
167
+ try {␊
168
+ result = worker.terminate()␊
169
+ } catch (error) {␊
170
+ cleanupErrors.push(error)␊
171
+ continue␊
172
+ }␊
173
+ if (__isThenable(result)) {␊
174
+ pending.push(␊
175
+ Promise.resolve(result).then(␊
176
+ () => {␊
177
+ __wasiWorkers.delete(worker)␊
178
+ },␊
179
+ (error) => {␊
180
+ cleanupErrors.push(error)␊
181
+ },␊
182
+ ),␊
183
+ )␊
184
+ } else {␊
185
+ __wasiWorkers.delete(worker)␊
186
+ }␊
187
+ }␊
188
+ ␊
189
+ const finish = () => {␊
190
+ if (cleanupErrors.length > 0) {␊
191
+ throw __createCleanupError(␊
192
+ cleanupErrors,␊
193
+ 'Failed to terminate WASI workers',␊
194
+ )␊
195
+ }␊
196
+ }␊
197
+ return pending.length > 0 ? Promise.all(pending).then(finish) : finish()␊
198
+ }␊
199
+ ␊
200
+ function __finishWasiDisposal() {␊
201
+ const workerResult = __terminateWasiWorkers()␊
202
+ if (__isThenable(workerResult)) {␊
203
+ return Promise.resolve(workerResult).then(__completeWasiDisposal)␊
204
+ }␊
205
+ return __completeWasiDisposal()␊
206
+ }␊
207
+ ␊
208
+ function __startWasiDisposal() {␊
209
+ const destroyResult = __destroyEmnapiContext()␊
210
+ if (__isThenable(destroyResult)) {␊
211
+ return Promise.resolve(destroyResult).then(__finishWasiDisposal)␊
212
+ }␊
213
+ return __finishWasiDisposal()␊
214
+ }␊
215
+ ␊
216
+ /**␊
217
+ * Disposes this generated WASI binding.␊
218
+ *␊
219
+ * Access this function with:␊
220
+ * binding[Symbol.for('napi.rs.wasi.dispose')]()␊
221
+ */␊
222
+ function __disposeWasiBinding() {␊
223
+ if (__wasiDisposePromise) {␊
224
+ return __wasiDisposePromise␊
225
+ }␊
226
+ if (__wasiDisposed) {␊
227
+ return Promise.resolve()␊
228
+ }␊
229
+ ␊
230
+ let resolveDispose␊
231
+ let rejectDispose␊
232
+ const disposePromise = new Promise((resolve, reject) => {␊
233
+ resolveDispose = resolve␊
234
+ rejectDispose = reject␊
235
+ })␊
236
+ __wasiDisposePromise = disposePromise␊
237
+ ␊
238
+ let result␊
239
+ try {␊
240
+ result = __startWasiDisposal()␊
241
+ } catch (error) {␊
242
+ __wasiDisposePromise = undefined␊
243
+ rejectDispose(error)␊
244
+ return disposePromise␊
245
+ }␊
246
+ ␊
247
+ Promise.resolve(result).then(␊
248
+ (value) => {␊
249
+ __wasiDisposed = true␊
250
+ resolveDispose(value)␊
251
+ },␊
252
+ (error) => {␊
253
+ __wasiDisposePromise = undefined␊
254
+ rejectDispose(error)␊
255
+ },␊
256
+ )␊
257
+ return disposePromise␊
258
+ }␊
259
+ ␊
260
+ function __publishWasiDispose(exports) {␊
261
+ Object.defineProperty(exports, __wasiDisposeSymbol, {␊
262
+ configurable: false,␊
263
+ enumerable: false,␊
264
+ value: __disposeWasiBinding,␊
265
+ writable: false,␊
266
+ })␊
267
+ }␊
268
+ ␊
269
+ function __finishWasiInitializationRollback(cleanupErrors) {␊
270
+ let workerResult␊
271
+ try {␊
272
+ workerResult = __terminateWasiWorkers()␊
273
+ } catch (cleanupError) {␊
274
+ cleanupErrors.push(cleanupError)␊
275
+ return cleanupErrors␊
276
+ }␊
277
+ if (__isThenable(workerResult)) {␊
278
+ return Promise.resolve(workerResult)␊
279
+ .catch((cleanupError) => {␊
280
+ cleanupErrors.push(cleanupError)␊
281
+ })␊
282
+ .then(() => cleanupErrors)␊
283
+ }␊
284
+ return cleanupErrors␊
285
+ }␊
286
+ ␊
287
+ function __rollbackWasiInitialization() {␊
288
+ const cleanupErrors = []␊
289
+ let destroyResult␊
290
+ try {␊
291
+ destroyResult = __destroyEmnapiContext()␊
292
+ } catch (cleanupError) {␊
293
+ cleanupErrors.push(cleanupError)␊
294
+ return __finishWasiInitializationRollback(cleanupErrors)␊
295
+ }␊
296
+ if (__isThenable(destroyResult)) {␊
297
+ return Promise.resolve(destroyResult)␊
298
+ .catch((cleanupError) => {␊
299
+ cleanupErrors.push(cleanupError)␊
300
+ })␊
301
+ .then(() => __finishWasiInitializationRollback(cleanupErrors))␊
302
+ }␊
303
+ return __finishWasiInitializationRollback(cleanupErrors)␊
304
+ }␊
305
+ ␊
306
+ let __wasiModule␊
307
+ let __napiModule␊
308
+ ␊
309
+ try {␊
310
+ __emnapiContext = __emnapiCreateContext({ autoDestroy: false })␊
311
+ __emnapiContext.suppressDestroy()␊
312
+ ␊
313
+ ;({␊
314
+ instance: __napiInstance,␊
315
+ module: __wasiModule,␊
316
+ napiModule: __napiModule,␊
317
+ } = __emnapiInstantiateNapiModuleSync(__wasmFile, {␊
318
+ context: __emnapiContext,␊
319
+ asyncWorkPoolSize: 4,␊
320
+ plugins: [__emnapiAsyncWorkPlugin, __emnapiTSFNPlugin],␊
321
+ wasi: __wasi,␊
322
+ onCreateWorker() {␊
323
+ const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {␊
324
+ type: 'module',␊
325
+ })␊
326
+ __wasiWorkers.add(worker)␊
327
+ ␊
328
+ ␊
329
+ return worker␊
330
+ },␊
331
+ overwriteImports(importObject) {␊
332
+ importObject.env = {␊
333
+ ...importObject.env,␊
334
+ ...importObject.napi,␊
335
+ ...importObject.emnapi,␊
336
+ memory: __sharedMemory,␊
337
+ }␊
338
+ return importObject␊
339
+ },␊
340
+ beforeInit({ instance }) {␊
341
+ __napiInstance = instance␊
342
+ for (const name of Object.keys(instance.exports)) {␊
343
+ if (name.startsWith('__napi_register__')) {␊
344
+ instance.exports[name]()␊
345
+ }␊
346
+ }␊
347
+ },␊
348
+ }))␊
349
+ __publishWasiDispose(__napiModule.exports)␊
350
+ } catch (error) {␊
351
+ const cleanupErrors = await __rollbackWasiInitialization()␊
352
+ throw __attachCleanupErrors(error, cleanupErrors)␊
353
+ }␊
69
354
  `
70
355
 
71
356
  ## createWasiBrowserBinding with errorEvent
@@ -73,11 +358,13 @@ Generated by [AVA](https://avajs.dev).
73
358
  > Snapshot 1
74
359
 
75
360
  `import {␊
361
+ emnapiAsyncWorkPlugin as __emnapiAsyncWorkPlugin,␊
362
+ emnapiTSFNPlugin as __emnapiTSFNPlugin,␊
76
363
  createOnMessage as __wasmCreateOnMessageForFsProxy,␊
77
- getDefaultContext as __emnapiGetDefaultContext,␊
78
364
  instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync,␊
79
365
  WASI as __WASI,␊
80
366
  } from '@napi-rs/wasm-runtime'␊
367
+ import { createContext as __emnapiCreateContext } from '@emnapi/runtime'␊
81
368
  ␊
82
369
  ␊
83
370
  ␊
@@ -86,8 +373,18 @@ Generated by [AVA](https://avajs.dev).
86
373
  })␊
87
374
  ␊
88
375
  const __wasmUrl = new URL('./test-wasi.wasm', import.meta.url).href␊
89
- const __emnapiContext = __emnapiGetDefaultContext()␊
90
- ␊
376
+ const __wasmResponse = await globalThis.fetch(__wasmUrl)␊
377
+ if (!__wasmResponse.ok) {␊
378
+ throw new Error(␊
379
+ 'Failed to fetch WASI module ' +␊
380
+ __wasmUrl +␊
381
+ ': ' +␊
382
+ __wasmResponse.status +␊
383
+ ' ' +␊
384
+ (__wasmResponse.statusText || 'Unknown Status'),␊
385
+ )␊
386
+ }␊
387
+ const __wasmFile = await __wasmResponse.arrayBuffer()␊
91
388
  ␊
92
389
  const __sharedMemory = new WebAssembly.Memory({␊
93
390
  initial: 4000,␊
@@ -95,46 +392,327 @@ Generated by [AVA](https://avajs.dev).
95
392
  shared: true,␊
96
393
  })␊
97
394
  ␊
98
- const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())␊
99
- ␊
100
- const {␊
101
- instance: __napiInstance,␊
102
- module: __wasiModule,␊
103
- napiModule: __napiModule,␊
104
- } = __emnapiInstantiateNapiModuleSync(__wasmFile, {␊
105
- context: __emnapiContext,␊
106
- asyncWorkPoolSize: 4,␊
107
- wasi: __wasi,␊
108
- onCreateWorker() {␊
109
- const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {␊
110
- type: 'module',␊
111
- })␊
395
+ let __emnapiContext␊
396
+ ␊
397
+ const __wasiDisposeSymbol = Symbol.for('napi.rs.wasi.dispose')␊
398
+ const __wasiWorkers = new Set()␊
399
+ let __napiInstance␊
400
+ let __emnapiContextDestroyed = false␊
401
+ let __emnapiContextDestroyPromise␊
402
+ let __emnapiWasmEnvCleanupPrepared = false␊
403
+ let __wasiDisposed = false␊
404
+ let __wasiDisposePromise␊
405
+ let __completeWasiDisposal = function() {}␊
406
+ ␊
407
+ function __isThenable(value) {␊
408
+ return (␊
409
+ value !== null &&␊
410
+ (typeof value === 'object' || typeof value === 'function') &&␊
411
+ typeof value.then === 'function'␊
412
+ )␊
413
+ }␊
112
414
  ␊
113
- worker.addEventListener('message', (event) => {␊
114
- if (event.data && typeof event.data === 'object' && event.data.type === 'error') {␊
115
- window.dispatchEvent(new CustomEvent('napi-rs-worker-error', { detail: event.data }))␊
415
+ function __createCleanupError(errors, message) {␊
416
+ if (errors.length === 1) {␊
417
+ return errors[0]␊
418
+ }␊
419
+ const __AggregateError = globalThis.AggregateError␊
420
+ if (typeof __AggregateError === 'function') {␊
421
+ return new __AggregateError(errors, message)␊
422
+ }␊
423
+ const error = new Error(message)␊
424
+ error.errors = errors␊
425
+ return error␊
426
+ }␊
427
+ ␊
428
+ function __attachCleanupErrors(error, cleanupErrors) {␊
429
+ if (cleanupErrors.length === 0) {␊
430
+ return error␊
431
+ }␊
432
+ const cleanupError = __createCleanupError(␊
433
+ cleanupErrors,␊
434
+ 'WASI binding cleanup failed',␊
435
+ )␊
436
+ try {␊
437
+ if (␊
438
+ error &&␊
439
+ (typeof error === 'object' || typeof error === 'function')␊
440
+ ) {␊
441
+ if (error.cause === undefined) {␊
442
+ error.cause = cleanupError␊
443
+ if (error.cause === cleanupError) {␊
444
+ return error␊
445
+ }␊
116
446
  }␊
117
- })␊
447
+ if (Array.isArray(error.cleanupErrors)) {␊
448
+ error.cleanupErrors.push(cleanupError)␊
449
+ return error␊
450
+ } else {␊
451
+ const attachedCleanupErrors = [cleanupError]␊
452
+ error.cleanupErrors = attachedCleanupErrors␊
453
+ if (error.cleanupErrors === attachedCleanupErrors) {␊
454
+ return error␊
455
+ }␊
456
+ }␊
457
+ }␊
458
+ } catch {}␊
459
+ const aggregate = __createCleanupError(␊
460
+ [error, cleanupError],␊
461
+ 'WASI binding initialization and cleanup failed',␊
462
+ )␊
463
+ try {␊
464
+ aggregate.cause = error␊
465
+ } catch {}␊
466
+ return aggregate␊
467
+ }␊
118
468
  ␊
119
- return worker␊
120
- },␊
121
- overwriteImports(importObject) {␊
122
- importObject.env = {␊
123
- ...importObject.env,␊
124
- ...importObject.napi,␊
125
- ...importObject.emnapi,␊
126
- memory: __sharedMemory,␊
469
+ function __prepareWasmEnvCleanup() {␊
470
+ if (__emnapiWasmEnvCleanupPrepared) {␊
471
+ return␊
472
+ }␊
473
+ const prepare = __napiInstance?.exports?.napi_prepare_wasm_env_cleanup␊
474
+ if (typeof prepare === 'function') {␊
475
+ prepare()␊
476
+ }␊
477
+ __emnapiWasmEnvCleanupPrepared = true␊
478
+ }␊
479
+ ␊
480
+ function __destroyEmnapiContext() {␊
481
+ if (__emnapiContextDestroyed || __emnapiContext === undefined) {␊
482
+ __emnapiContextDestroyed = true␊
483
+ return␊
484
+ }␊
485
+ if (__emnapiContextDestroyPromise) {␊
486
+ return __emnapiContextDestroyPromise␊
487
+ }␊
488
+ ␊
489
+ __prepareWasmEnvCleanup()␊
490
+ const result = __emnapiContext.destroy()␊
491
+ if (!__isThenable(result)) {␊
492
+ __emnapiContextDestroyed = true␊
493
+ return␊
494
+ }␊
495
+ ␊
496
+ const destroyPromise = Promise.resolve(result).then(␊
497
+ (value) => {␊
498
+ __emnapiContextDestroyed = true␊
499
+ return value␊
500
+ },␊
501
+ (error) => {␊
502
+ __emnapiContextDestroyPromise = undefined␊
503
+ throw error␊
504
+ },␊
505
+ )␊
506
+ __emnapiContextDestroyPromise = destroyPromise␊
507
+ return destroyPromise␊
508
+ }␊
509
+ ␊
510
+ function __terminateWasiWorkers() {␊
511
+ const cleanupErrors = []␊
512
+ const pending = []␊
513
+ ␊
514
+ for (const worker of __wasiWorkers) {␊
515
+ let result␊
516
+ try {␊
517
+ result = worker.terminate()␊
518
+ } catch (error) {␊
519
+ cleanupErrors.push(error)␊
520
+ continue␊
127
521
  }␊
128
- return importObject␊
129
- },␊
130
- beforeInit({ instance }) {␊
131
- for (const name of Object.keys(instance.exports)) {␊
132
- if (name.startsWith('__napi_register__')) {␊
133
- instance.exports[name]()␊
134
- }␊
522
+ if (__isThenable(result)) {␊
523
+ pending.push(␊
524
+ Promise.resolve(result).then(␊
525
+ () => {␊
526
+ __wasiWorkers.delete(worker)␊
527
+ },␊
528
+ (error) => {␊
529
+ cleanupErrors.push(error)␊
530
+ },␊
531
+ ),␊
532
+ )␊
533
+ } else {␊
534
+ __wasiWorkers.delete(worker)␊
135
535
  }␊
136
- },␊
137
- })␊
536
+ }␊
537
+ ␊
538
+ const finish = () => {␊
539
+ if (cleanupErrors.length > 0) {␊
540
+ throw __createCleanupError(␊
541
+ cleanupErrors,␊
542
+ 'Failed to terminate WASI workers',␊
543
+ )␊
544
+ }␊
545
+ }␊
546
+ return pending.length > 0 ? Promise.all(pending).then(finish) : finish()␊
547
+ }␊
548
+ ␊
549
+ function __finishWasiDisposal() {␊
550
+ const workerResult = __terminateWasiWorkers()␊
551
+ if (__isThenable(workerResult)) {␊
552
+ return Promise.resolve(workerResult).then(__completeWasiDisposal)␊
553
+ }␊
554
+ return __completeWasiDisposal()␊
555
+ }␊
556
+ ␊
557
+ function __startWasiDisposal() {␊
558
+ const destroyResult = __destroyEmnapiContext()␊
559
+ if (__isThenable(destroyResult)) {␊
560
+ return Promise.resolve(destroyResult).then(__finishWasiDisposal)␊
561
+ }␊
562
+ return __finishWasiDisposal()␊
563
+ }␊
564
+ ␊
565
+ /**␊
566
+ * Disposes this generated WASI binding.␊
567
+ *␊
568
+ * Access this function with:␊
569
+ * binding[Symbol.for('napi.rs.wasi.dispose')]()␊
570
+ */␊
571
+ function __disposeWasiBinding() {␊
572
+ if (__wasiDisposePromise) {␊
573
+ return __wasiDisposePromise␊
574
+ }␊
575
+ if (__wasiDisposed) {␊
576
+ return Promise.resolve()␊
577
+ }␊
578
+ ␊
579
+ let resolveDispose␊
580
+ let rejectDispose␊
581
+ const disposePromise = new Promise((resolve, reject) => {␊
582
+ resolveDispose = resolve␊
583
+ rejectDispose = reject␊
584
+ })␊
585
+ __wasiDisposePromise = disposePromise␊
586
+ ␊
587
+ let result␊
588
+ try {␊
589
+ result = __startWasiDisposal()␊
590
+ } catch (error) {␊
591
+ __wasiDisposePromise = undefined␊
592
+ rejectDispose(error)␊
593
+ return disposePromise␊
594
+ }␊
595
+ ␊
596
+ Promise.resolve(result).then(␊
597
+ (value) => {␊
598
+ __wasiDisposed = true␊
599
+ resolveDispose(value)␊
600
+ },␊
601
+ (error) => {␊
602
+ __wasiDisposePromise = undefined␊
603
+ rejectDispose(error)␊
604
+ },␊
605
+ )␊
606
+ return disposePromise␊
607
+ }␊
608
+ ␊
609
+ function __publishWasiDispose(exports) {␊
610
+ Object.defineProperty(exports, __wasiDisposeSymbol, {␊
611
+ configurable: false,␊
612
+ enumerable: false,␊
613
+ value: __disposeWasiBinding,␊
614
+ writable: false,␊
615
+ })␊
616
+ }␊
617
+ ␊
618
+ function __finishWasiInitializationRollback(cleanupErrors) {␊
619
+ let workerResult␊
620
+ try {␊
621
+ workerResult = __terminateWasiWorkers()␊
622
+ } catch (cleanupError) {␊
623
+ cleanupErrors.push(cleanupError)␊
624
+ return cleanupErrors␊
625
+ }␊
626
+ if (__isThenable(workerResult)) {␊
627
+ return Promise.resolve(workerResult)␊
628
+ .catch((cleanupError) => {␊
629
+ cleanupErrors.push(cleanupError)␊
630
+ })␊
631
+ .then(() => cleanupErrors)␊
632
+ }␊
633
+ return cleanupErrors␊
634
+ }␊
635
+ ␊
636
+ function __rollbackWasiInitialization() {␊
637
+ const cleanupErrors = []␊
638
+ let destroyResult␊
639
+ try {␊
640
+ destroyResult = __destroyEmnapiContext()␊
641
+ } catch (cleanupError) {␊
642
+ cleanupErrors.push(cleanupError)␊
643
+ return __finishWasiInitializationRollback(cleanupErrors)␊
644
+ }␊
645
+ if (__isThenable(destroyResult)) {␊
646
+ return Promise.resolve(destroyResult)␊
647
+ .catch((cleanupError) => {␊
648
+ cleanupErrors.push(cleanupError)␊
649
+ })␊
650
+ .then(() => __finishWasiInitializationRollback(cleanupErrors))␊
651
+ }␊
652
+ return __finishWasiInitializationRollback(cleanupErrors)␊
653
+ }␊
654
+ ␊
655
+ let __wasiModule␊
656
+ let __napiModule␊
657
+ ␊
658
+ try {␊
659
+ __emnapiContext = __emnapiCreateContext({ autoDestroy: false })␊
660
+ __emnapiContext.suppressDestroy()␊
661
+ ␊
662
+ ;({␊
663
+ instance: __napiInstance,␊
664
+ module: __wasiModule,␊
665
+ napiModule: __napiModule,␊
666
+ } = __emnapiInstantiateNapiModuleSync(__wasmFile, {␊
667
+ context: __emnapiContext,␊
668
+ asyncWorkPoolSize: 4,␊
669
+ plugins: [__emnapiAsyncWorkPlugin, __emnapiTSFNPlugin],␊
670
+ wasi: __wasi,␊
671
+ onCreateWorker() {␊
672
+ const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {␊
673
+ type: 'module',␊
674
+ })␊
675
+ __wasiWorkers.add(worker)␊
676
+ ␊
677
+ worker.addEventListener('message', (event) => {␊
678
+ if (event.data && typeof event.data === 'object' && event.data.type === 'error') {␊
679
+ const __CustomEvent = globalThis.CustomEvent␊
680
+ if (␊
681
+ typeof globalThis.dispatchEvent === 'function' &&␊
682
+ typeof __CustomEvent === 'function'␊
683
+ ) {␊
684
+ globalThis.dispatchEvent(␊
685
+ new __CustomEvent('napi-rs-worker-error', { detail: event.data }),␊
686
+ )␊
687
+ }␊
688
+ }␊
689
+ })␊
690
+ ␊
691
+ return worker␊
692
+ },␊
693
+ overwriteImports(importObject) {␊
694
+ importObject.env = {␊
695
+ ...importObject.env,␊
696
+ ...importObject.napi,␊
697
+ ...importObject.emnapi,␊
698
+ memory: __sharedMemory,␊
699
+ }␊
700
+ return importObject␊
701
+ },␊
702
+ beforeInit({ instance }) {␊
703
+ __napiInstance = instance␊
704
+ for (const name of Object.keys(instance.exports)) {␊
705
+ if (name.startsWith('__napi_register__')) {␊
706
+ instance.exports[name]()␊
707
+ }␊
708
+ }␊
709
+ },␊
710
+ }))␊
711
+ __publishWasiDispose(__napiModule.exports)␊
712
+ } catch (error) {␊
713
+ const cleanupErrors = await __rollbackWasiInitialization()␊
714
+ throw __attachCleanupErrors(error, cleanupErrors)␊
715
+ }␊
138
716
  `
139
717
 
140
718
  ## createWasiBrowserBinding with errorEvent and fs
@@ -142,11 +720,13 @@ Generated by [AVA](https://avajs.dev).
142
720
  > Snapshot 1
143
721
 
144
722
  `import {␊
723
+ emnapiAsyncWorkPlugin as __emnapiAsyncWorkPlugin,␊
724
+ emnapiTSFNPlugin as __emnapiTSFNPlugin,␊
145
725
  createOnMessage as __wasmCreateOnMessageForFsProxy,␊
146
- getDefaultContext as __emnapiGetDefaultContext,␊
147
726
  instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync,␊
148
727
  WASI as __WASI,␊
149
728
  } from '@napi-rs/wasm-runtime'␊
729
+ import { createContext as __emnapiCreateContext } from '@emnapi/runtime'␊
150
730
  import { memfs } from '@napi-rs/wasm-runtime/fs'␊
151
731
  ␊
152
732
  ␊
@@ -161,8 +741,18 @@ Generated by [AVA](https://avajs.dev).
161
741
  })␊
162
742
  ␊
163
743
  const __wasmUrl = new URL('./test-wasi.wasm', import.meta.url).href␊
164
- const __emnapiContext = __emnapiGetDefaultContext()␊
165
- ␊
744
+ const __wasmResponse = await globalThis.fetch(__wasmUrl)␊
745
+ if (!__wasmResponse.ok) {␊
746
+ throw new Error(␊
747
+ 'Failed to fetch WASI module ' +␊
748
+ __wasmUrl +␊
749
+ ': ' +␊
750
+ __wasmResponse.status +␊
751
+ ' ' +␊
752
+ (__wasmResponse.statusText || 'Unknown Status'),␊
753
+ )␊
754
+ }␊
755
+ const __wasmFile = await __wasmResponse.arrayBuffer()␊
166
756
  ␊
167
757
  const __sharedMemory = new WebAssembly.Memory({␊
168
758
  initial: 4000,␊
@@ -170,54 +760,341 @@ Generated by [AVA](https://avajs.dev).
170
760
  shared: true,␊
171
761
  })␊
172
762
  ␊
173
- const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())␊
174
- ␊
175
- const {␊
176
- instance: __napiInstance,␊
177
- module: __wasiModule,␊
178
- napiModule: __napiModule,␊
179
- } = __emnapiInstantiateNapiModuleSync(__wasmFile, {␊
180
- context: __emnapiContext,␊
181
- asyncWorkPoolSize: 4,␊
182
- wasi: __wasi,␊
183
- onCreateWorker() {␊
184
- const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {␊
185
- type: 'module',␊
186
- })␊
187
- worker.addEventListener('message', __wasmCreateOnMessageForFsProxy(__fs))␊
763
+ let __emnapiContext␊
764
+ ␊
765
+ const __wasiDisposeSymbol = Symbol.for('napi.rs.wasi.dispose')␊
766
+ const __wasiWorkers = new Set()␊
767
+ let __napiInstance␊
768
+ let __emnapiContextDestroyed = false␊
769
+ let __emnapiContextDestroyPromise␊
770
+ let __emnapiWasmEnvCleanupPrepared = false␊
771
+ let __wasiDisposed = false␊
772
+ let __wasiDisposePromise␊
773
+ let __completeWasiDisposal = function() {}␊
774
+ ␊
775
+ function __isThenable(value) {␊
776
+ return (␊
777
+ value !== null &&␊
778
+ (typeof value === 'object' || typeof value === 'function') &&␊
779
+ typeof value.then === 'function'␊
780
+ )␊
781
+ }␊
782
+ ␊
783
+ function __createCleanupError(errors, message) {␊
784
+ if (errors.length === 1) {␊
785
+ return errors[0]␊
786
+ }␊
787
+ const __AggregateError = globalThis.AggregateError␊
788
+ if (typeof __AggregateError === 'function') {␊
789
+ return new __AggregateError(errors, message)␊
790
+ }␊
791
+ const error = new Error(message)␊
792
+ error.errors = errors␊
793
+ return error␊
794
+ }␊
188
795
  ␊
189
- worker.addEventListener('message', (event) => {␊
190
- if (event.data && typeof event.data === 'object' && event.data.type === 'error') {␊
191
- window.dispatchEvent(new CustomEvent('napi-rs-worker-error', { detail: event.data }))␊
796
+ function __attachCleanupErrors(error, cleanupErrors) {␊
797
+ if (cleanupErrors.length === 0) {␊
798
+ return error␊
799
+ }␊
800
+ const cleanupError = __createCleanupError(␊
801
+ cleanupErrors,␊
802
+ 'WASI binding cleanup failed',␊
803
+ )␊
804
+ try {␊
805
+ if (␊
806
+ error &&␊
807
+ (typeof error === 'object' || typeof error === 'function')␊
808
+ ) {␊
809
+ if (error.cause === undefined) {␊
810
+ error.cause = cleanupError␊
811
+ if (error.cause === cleanupError) {␊
812
+ return error␊
813
+ }␊
192
814
  }␊
193
- })␊
815
+ if (Array.isArray(error.cleanupErrors)) {␊
816
+ error.cleanupErrors.push(cleanupError)␊
817
+ return error␊
818
+ } else {␊
819
+ const attachedCleanupErrors = [cleanupError]␊
820
+ error.cleanupErrors = attachedCleanupErrors␊
821
+ if (error.cleanupErrors === attachedCleanupErrors) {␊
822
+ return error␊
823
+ }␊
824
+ }␊
825
+ }␊
826
+ } catch {}␊
827
+ const aggregate = __createCleanupError(␊
828
+ [error, cleanupError],␊
829
+ 'WASI binding initialization and cleanup failed',␊
830
+ )␊
831
+ try {␊
832
+ aggregate.cause = error␊
833
+ } catch {}␊
834
+ return aggregate␊
835
+ }␊
194
836
  ␊
195
- return worker␊
196
- },␊
197
- overwriteImports(importObject) {␊
198
- importObject.env = {␊
199
- ...importObject.env,␊
200
- ...importObject.napi,␊
201
- ...importObject.emnapi,␊
202
- memory: __sharedMemory,␊
837
+ function __prepareWasmEnvCleanup() {␊
838
+ if (__emnapiWasmEnvCleanupPrepared) {␊
839
+ return␊
840
+ }␊
841
+ const prepare = __napiInstance?.exports?.napi_prepare_wasm_env_cleanup␊
842
+ if (typeof prepare === 'function') {␊
843
+ prepare()␊
844
+ }␊
845
+ __emnapiWasmEnvCleanupPrepared = true␊
846
+ }␊
847
+ ␊
848
+ function __destroyEmnapiContext() {␊
849
+ if (__emnapiContextDestroyed || __emnapiContext === undefined) {␊
850
+ __emnapiContextDestroyed = true␊
851
+ return␊
852
+ }␊
853
+ if (__emnapiContextDestroyPromise) {␊
854
+ return __emnapiContextDestroyPromise␊
855
+ }␊
856
+ ␊
857
+ __prepareWasmEnvCleanup()␊
858
+ const result = __emnapiContext.destroy()␊
859
+ if (!__isThenable(result)) {␊
860
+ __emnapiContextDestroyed = true␊
861
+ return␊
862
+ }␊
863
+ ␊
864
+ const destroyPromise = Promise.resolve(result).then(␊
865
+ (value) => {␊
866
+ __emnapiContextDestroyed = true␊
867
+ return value␊
868
+ },␊
869
+ (error) => {␊
870
+ __emnapiContextDestroyPromise = undefined␊
871
+ throw error␊
872
+ },␊
873
+ )␊
874
+ __emnapiContextDestroyPromise = destroyPromise␊
875
+ return destroyPromise␊
876
+ }␊
877
+ ␊
878
+ function __terminateWasiWorkers() {␊
879
+ const cleanupErrors = []␊
880
+ const pending = []␊
881
+ ␊
882
+ for (const worker of __wasiWorkers) {␊
883
+ let result␊
884
+ try {␊
885
+ result = worker.terminate()␊
886
+ } catch (error) {␊
887
+ cleanupErrors.push(error)␊
888
+ continue␊
203
889
  }␊
204
- return importObject␊
205
- },␊
206
- beforeInit({ instance }) {␊
207
- for (const name of Object.keys(instance.exports)) {␊
208
- if (name.startsWith('__napi_register__')) {␊
209
- instance.exports[name]()␊
210
- }␊
890
+ if (__isThenable(result)) {␊
891
+ pending.push(␊
892
+ Promise.resolve(result).then(␊
893
+ () => {␊
894
+ __wasiWorkers.delete(worker)␊
895
+ },␊
896
+ (error) => {␊
897
+ cleanupErrors.push(error)␊
898
+ },␊
899
+ ),␊
900
+ )␊
901
+ } else {␊
902
+ __wasiWorkers.delete(worker)␊
211
903
  }␊
212
- },␊
213
- })␊
904
+ }␊
905
+ ␊
906
+ const finish = () => {␊
907
+ if (cleanupErrors.length > 0) {␊
908
+ throw __createCleanupError(␊
909
+ cleanupErrors,␊
910
+ 'Failed to terminate WASI workers',␊
911
+ )␊
912
+ }␊
913
+ }␊
914
+ return pending.length > 0 ? Promise.all(pending).then(finish) : finish()␊
915
+ }␊
916
+ ␊
917
+ function __finishWasiDisposal() {␊
918
+ const workerResult = __terminateWasiWorkers()␊
919
+ if (__isThenable(workerResult)) {␊
920
+ return Promise.resolve(workerResult).then(__completeWasiDisposal)␊
921
+ }␊
922
+ return __completeWasiDisposal()␊
923
+ }␊
924
+ ␊
925
+ function __startWasiDisposal() {␊
926
+ const destroyResult = __destroyEmnapiContext()␊
927
+ if (__isThenable(destroyResult)) {␊
928
+ return Promise.resolve(destroyResult).then(__finishWasiDisposal)␊
929
+ }␊
930
+ return __finishWasiDisposal()␊
931
+ }␊
932
+ ␊
933
+ /**␊
934
+ * Disposes this generated WASI binding.␊
935
+ *␊
936
+ * Access this function with:␊
937
+ * binding[Symbol.for('napi.rs.wasi.dispose')]()␊
938
+ */␊
939
+ function __disposeWasiBinding() {␊
940
+ if (__wasiDisposePromise) {␊
941
+ return __wasiDisposePromise␊
942
+ }␊
943
+ if (__wasiDisposed) {␊
944
+ return Promise.resolve()␊
945
+ }␊
946
+ ␊
947
+ let resolveDispose␊
948
+ let rejectDispose␊
949
+ const disposePromise = new Promise((resolve, reject) => {␊
950
+ resolveDispose = resolve␊
951
+ rejectDispose = reject␊
952
+ })␊
953
+ __wasiDisposePromise = disposePromise␊
954
+ ␊
955
+ let result␊
956
+ try {␊
957
+ result = __startWasiDisposal()␊
958
+ } catch (error) {␊
959
+ __wasiDisposePromise = undefined␊
960
+ rejectDispose(error)␊
961
+ return disposePromise␊
962
+ }␊
963
+ ␊
964
+ Promise.resolve(result).then(␊
965
+ (value) => {␊
966
+ __wasiDisposed = true␊
967
+ resolveDispose(value)␊
968
+ },␊
969
+ (error) => {␊
970
+ __wasiDisposePromise = undefined␊
971
+ rejectDispose(error)␊
972
+ },␊
973
+ )␊
974
+ return disposePromise␊
975
+ }␊
976
+ ␊
977
+ function __publishWasiDispose(exports) {␊
978
+ Object.defineProperty(exports, __wasiDisposeSymbol, {␊
979
+ configurable: false,␊
980
+ enumerable: false,␊
981
+ value: __disposeWasiBinding,␊
982
+ writable: false,␊
983
+ })␊
984
+ }␊
985
+ ␊
986
+ function __finishWasiInitializationRollback(cleanupErrors) {␊
987
+ let workerResult␊
988
+ try {␊
989
+ workerResult = __terminateWasiWorkers()␊
990
+ } catch (cleanupError) {␊
991
+ cleanupErrors.push(cleanupError)␊
992
+ return cleanupErrors␊
993
+ }␊
994
+ if (__isThenable(workerResult)) {␊
995
+ return Promise.resolve(workerResult)␊
996
+ .catch((cleanupError) => {␊
997
+ cleanupErrors.push(cleanupError)␊
998
+ })␊
999
+ .then(() => cleanupErrors)␊
1000
+ }␊
1001
+ return cleanupErrors␊
1002
+ }␊
1003
+ ␊
1004
+ function __rollbackWasiInitialization() {␊
1005
+ const cleanupErrors = []␊
1006
+ let destroyResult␊
1007
+ try {␊
1008
+ destroyResult = __destroyEmnapiContext()␊
1009
+ } catch (cleanupError) {␊
1010
+ cleanupErrors.push(cleanupError)␊
1011
+ return __finishWasiInitializationRollback(cleanupErrors)␊
1012
+ }␊
1013
+ if (__isThenable(destroyResult)) {␊
1014
+ return Promise.resolve(destroyResult)␊
1015
+ .catch((cleanupError) => {␊
1016
+ cleanupErrors.push(cleanupError)␊
1017
+ })␊
1018
+ .then(() => __finishWasiInitializationRollback(cleanupErrors))␊
1019
+ }␊
1020
+ return __finishWasiInitializationRollback(cleanupErrors)␊
1021
+ }␊
1022
+ ␊
1023
+ let __wasiModule␊
1024
+ let __napiModule␊
1025
+ ␊
1026
+ try {␊
1027
+ __emnapiContext = __emnapiCreateContext({ autoDestroy: false })␊
1028
+ __emnapiContext.suppressDestroy()␊
1029
+ ␊
1030
+ ;({␊
1031
+ instance: __napiInstance,␊
1032
+ module: __wasiModule,␊
1033
+ napiModule: __napiModule,␊
1034
+ } = __emnapiInstantiateNapiModuleSync(__wasmFile, {␊
1035
+ context: __emnapiContext,␊
1036
+ asyncWorkPoolSize: 4,␊
1037
+ plugins: [__emnapiAsyncWorkPlugin, __emnapiTSFNPlugin],␊
1038
+ wasi: __wasi,␊
1039
+ onCreateWorker() {␊
1040
+ const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {␊
1041
+ type: 'module',␊
1042
+ })␊
1043
+ __wasiWorkers.add(worker)␊
1044
+ worker.addEventListener('message', __wasmCreateOnMessageForFsProxy(__fs))␊
1045
+ ␊
1046
+ worker.addEventListener('message', (event) => {␊
1047
+ if (event.data && typeof event.data === 'object' && event.data.type === 'error') {␊
1048
+ const __CustomEvent = globalThis.CustomEvent␊
1049
+ if (␊
1050
+ typeof globalThis.dispatchEvent === 'function' &&␊
1051
+ typeof __CustomEvent === 'function'␊
1052
+ ) {␊
1053
+ globalThis.dispatchEvent(␊
1054
+ new __CustomEvent('napi-rs-worker-error', { detail: event.data }),␊
1055
+ )␊
1056
+ }␊
1057
+ }␊
1058
+ })␊
1059
+ ␊
1060
+ return worker␊
1061
+ },␊
1062
+ overwriteImports(importObject) {␊
1063
+ importObject.env = {␊
1064
+ ...importObject.env,␊
1065
+ ...importObject.napi,␊
1066
+ ...importObject.emnapi,␊
1067
+ memory: __sharedMemory,␊
1068
+ }␊
1069
+ return importObject␊
1070
+ },␊
1071
+ beforeInit({ instance }) {␊
1072
+ __napiInstance = instance␊
1073
+ for (const name of Object.keys(instance.exports)) {␊
1074
+ if (name.startsWith('__napi_register__')) {␊
1075
+ instance.exports[name]()␊
1076
+ }␊
1077
+ }␊
1078
+ },␊
1079
+ }))␊
1080
+ __publishWasiDispose(__napiModule.exports)␊
1081
+ } catch (error) {␊
1082
+ const cleanupErrors = await __rollbackWasiInitialization()␊
1083
+ throw __attachCleanupErrors(error, cleanupErrors)␊
1084
+ }␊
214
1085
  `
215
1086
 
216
1087
  ## createWasiBrowserWorkerBinding default
217
1088
 
218
1089
  > Snapshot 1
219
1090
 
220
- `import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'␊
1091
+ `import {␊
1092
+ instantiateNapiModuleSync,␊
1093
+ MessageHandler,␊
1094
+ WASI,␊
1095
+ emnapiAsyncWorkPlugin,␊
1096
+ emnapiTSFNPlugin,␊
1097
+ } from '@napi-rs/wasm-runtime'␊
221
1098
  ␊
222
1099
  const handler = new MessageHandler({␊
223
1100
  onLoad({ wasmModule, wasmMemory }) {␊
@@ -235,6 +1112,11 @@ Generated by [AVA](https://avajs.dev).
235
1112
  return instantiateNapiModuleSync(wasmModule, {␊
236
1113
  childThread: true,␊
237
1114
  wasi,␊
1115
+ // The wasm links a "basic" emnapi archive (no C async-work /␊
1116
+ // threadsafe-function implementations), so every thread that␊
1117
+ // instantiates it must provide the JavaScript implementations␊
1118
+ // through the emnapi plugins.␊
1119
+ plugins: [emnapiAsyncWorkPlugin, emnapiTSFNPlugin],␊
238
1120
  overwriteImports(importObject) {␊
239
1121
  importObject.env = {␊
240
1122
  ...importObject.env,␊
@@ -257,7 +1139,13 @@ Generated by [AVA](https://avajs.dev).
257
1139
 
258
1140
  > Snapshot 1
259
1141
 
260
- `import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'␊
1142
+ `import {␊
1143
+ instantiateNapiModuleSync,␊
1144
+ MessageHandler,␊
1145
+ WASI,␊
1146
+ emnapiAsyncWorkPlugin,␊
1147
+ emnapiTSFNPlugin,␊
1148
+ } from '@napi-rs/wasm-runtime'␊
261
1149
  ␊
262
1150
  const errorOutputs = []␊
263
1151
  ␊
@@ -278,6 +1166,11 @@ Generated by [AVA](https://avajs.dev).
278
1166
  return instantiateNapiModuleSync(wasmModule, {␊
279
1167
  childThread: true,␊
280
1168
  wasi,␊
1169
+ // The wasm links a "basic" emnapi archive (no C async-work /␊
1170
+ // threadsafe-function implementations), so every thread that␊
1171
+ // instantiates it must provide the JavaScript implementations␊
1172
+ // through the emnapi plugins.␊
1173
+ plugins: [emnapiAsyncWorkPlugin, emnapiTSFNPlugin],␊
281
1174
  overwriteImports(importObject) {␊
282
1175
  importObject.env = {␊
283
1176
  ...importObject.env,␊
@@ -303,7 +1196,14 @@ Generated by [AVA](https://avajs.dev).
303
1196
 
304
1197
  > Snapshot 1
305
1198
 
306
- `import { instantiateNapiModuleSync, MessageHandler, WASI, createFsProxy } from '@napi-rs/wasm-runtime'␊
1199
+ `import {␊
1200
+ instantiateNapiModuleSync,␊
1201
+ MessageHandler,␊
1202
+ WASI,␊
1203
+ createFsProxy,␊
1204
+ emnapiAsyncWorkPlugin,␊
1205
+ emnapiTSFNPlugin,␊
1206
+ } from '@napi-rs/wasm-runtime'␊
307
1207
  import { memfsExported as __memfsExported } from '@napi-rs/wasm-runtime/fs'␊
308
1208
  ␊
309
1209
  const fs = createFsProxy(__memfsExported)␊
@@ -331,6 +1231,11 @@ Generated by [AVA](https://avajs.dev).
331
1231
  return instantiateNapiModuleSync(wasmModule, {␊
332
1232
  childThread: true,␊
333
1233
  wasi,␊
1234
+ // The wasm links a "basic" emnapi archive (no C async-work /␊
1235
+ // threadsafe-function implementations), so every thread that␊
1236
+ // instantiates it must provide the JavaScript implementations␊
1237
+ // through the emnapi plugins.␊
1238
+ plugins: [emnapiAsyncWorkPlugin, emnapiTSFNPlugin],␊
334
1239
  overwriteImports(importObject) {␊
335
1240
  importObject.env = {␊
336
1241
  ...importObject.env,␊