@bytecodealliance/jco 1.10.2 → 1.11.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 (52) hide show
  1. package/package.json +18 -6
  2. package/src/cmd/componentize.js +64 -18
  3. package/src/cmd/opt.js +233 -202
  4. package/src/cmd/run.js +117 -73
  5. package/src/cmd/transpile.js +643 -530
  6. package/src/cmd/wasm-tools.js +130 -95
  7. package/src/jco.js +5 -1
  8. package/obj/interfaces/local-wasm-tools-tools.d.ts +0 -52
  9. package/obj/interfaces/wasi-cli-environment.d.ts +0 -2
  10. package/obj/interfaces/wasi-cli-exit.d.ts +0 -3
  11. package/obj/interfaces/wasi-cli-stderr.d.ts +0 -3
  12. package/obj/interfaces/wasi-cli-stdin.d.ts +0 -3
  13. package/obj/interfaces/wasi-cli-stdout.d.ts +0 -3
  14. package/obj/interfaces/wasi-cli-terminal-input.d.ts +0 -8
  15. package/obj/interfaces/wasi-cli-terminal-output.d.ts +0 -8
  16. package/obj/interfaces/wasi-cli-terminal-stderr.d.ts +0 -3
  17. package/obj/interfaces/wasi-cli-terminal-stdin.d.ts +0 -3
  18. package/obj/interfaces/wasi-cli-terminal-stdout.d.ts +0 -3
  19. package/obj/interfaces/wasi-clocks-wall-clock.d.ts +0 -5
  20. package/obj/interfaces/wasi-filesystem-preopens.d.ts +0 -3
  21. package/obj/interfaces/wasi-filesystem-types.d.ts +0 -164
  22. package/obj/interfaces/wasi-io-error.d.ts +0 -8
  23. package/obj/interfaces/wasi-io-streams.d.ts +0 -30
  24. package/obj/interfaces/wasi-random-random.d.ts +0 -2
  25. package/obj/js-component-bindgen-component.core.wasm +0 -0
  26. package/obj/js-component-bindgen-component.core2.wasm +0 -0
  27. package/obj/js-component-bindgen-component.d.ts +0 -116
  28. package/obj/js-component-bindgen-component.js +0 -4302
  29. package/obj/wasm-tools.core.wasm +0 -0
  30. package/obj/wasm-tools.core2.wasm +0 -0
  31. package/obj/wasm-tools.d.ts +0 -20
  32. package/obj/wasm-tools.js +0 -4369
  33. package/src/api.d.ts +0 -42
  34. package/src/api.d.ts.map +0 -1
  35. package/src/browser.d.ts +0 -4
  36. package/src/browser.d.ts.map +0 -1
  37. package/src/cmd/componentize.d.ts +0 -2
  38. package/src/cmd/componentize.d.ts.map +0 -1
  39. package/src/cmd/opt.d.ts +0 -20
  40. package/src/cmd/opt.d.ts.map +0 -1
  41. package/src/cmd/run.d.ts +0 -3
  42. package/src/cmd/run.d.ts.map +0 -1
  43. package/src/cmd/transpile.d.ts +0 -89
  44. package/src/cmd/transpile.d.ts.map +0 -1
  45. package/src/cmd/wasm-tools.d.ts +0 -8
  46. package/src/cmd/wasm-tools.d.ts.map +0 -1
  47. package/src/common.d.ts +0 -16
  48. package/src/common.d.ts.map +0 -1
  49. package/src/jco.d.ts +0 -3
  50. package/src/jco.d.ts.map +0 -1
  51. package/src/ora-shim.d.ts +0 -7
  52. package/src/ora-shim.d.ts.map +0 -1
@@ -1,43 +1,62 @@
1
- import { $init, generate, generateTypes } from '../../obj/js-component-bindgen-component.js';
2
- import { writeFile } from 'node:fs/promises';
1
+ import { platform } from 'node:process';
2
+ import { writeFile, stat } from 'node:fs/promises';
3
3
  import { mkdir } from 'node:fs/promises';
4
4
  import { dirname, extname, basename, resolve } from 'node:path';
5
+
5
6
  import c from 'chalk-template';
6
- import { readFile, sizeStr, table, spawnIOTmp, setShowSpinner, getShowSpinner } from '../common.js';
7
- import { optimizeComponent } from './opt.js';
8
7
  import { minify } from 'terser';
9
8
  import { fileURLToPath } from 'url';
10
- import { $init as wasmToolsInit, tools } from "../../obj/wasm-tools.js";
9
+
10
+ import {
11
+ $init,
12
+ generate,
13
+ generateTypes,
14
+ } from '../../obj/js-component-bindgen-component.js';
15
+ import {
16
+ readFile,
17
+ sizeStr,
18
+ table,
19
+ spawnIOTmp,
20
+ setShowSpinner,
21
+ getShowSpinner,
22
+ } from '../common.js';
23
+ import { optimizeComponent } from './opt.js';
24
+ import { $init as wasmToolsInit, tools } from '../../obj/wasm-tools.js';
11
25
  const { componentEmbed, componentNew } = tools;
26
+
12
27
  import ora from '#ora';
13
- import { platform } from 'node:process';
14
28
 
15
29
  const isWindows = platform === 'win32';
16
30
 
17
31
  const ASYNC_WASI_IMPORTS = [
18
- "wasi:io/poll#poll",
19
- "wasi:io/poll#[method]pollable.block",
20
- "wasi:io/streams#[method]input-stream.blocking-read",
21
- "wasi:io/streams#[method]input-stream.blocking-skip",
22
- "wasi:io/streams#[method]output-stream.blocking-flush",
23
- "wasi:io/streams#[method]output-stream.blocking-write-and-flush",
24
- "wasi:io/streams#[method]output-stream.blocking-write-zeroes-and-flush",
25
- "wasi:io/streams#[method]output-stream.blocking-splice",
32
+ 'wasi:io/poll#poll',
33
+ 'wasi:io/poll#[method]pollable.block',
34
+ 'wasi:io/streams#[method]input-stream.blocking-read',
35
+ 'wasi:io/streams#[method]input-stream.blocking-skip',
36
+ 'wasi:io/streams#[method]output-stream.blocking-flush',
37
+ 'wasi:io/streams#[method]output-stream.blocking-write-and-flush',
38
+ 'wasi:io/streams#[method]output-stream.blocking-write-zeroes-and-flush',
39
+ 'wasi:io/streams#[method]output-stream.blocking-splice',
26
40
  ];
27
41
 
28
42
  const ASYNC_WASI_EXPORTS = [
29
- "wasi:cli/run#run",
30
- "wasi:http/incoming-handler#handle",
43
+ 'wasi:cli/run#run',
44
+ 'wasi:http/incoming-handler#handle',
31
45
  ];
32
46
 
33
- export async function types (witPath, opts) {
34
- const files = await typesComponent(witPath, opts);
35
- await writeFiles(files, opts.quiet ? false : 'Generated Type Files');
47
+ export async function types(witPath, opts) {
48
+ const files = await typesComponent(witPath, opts);
49
+ await writeFiles(files, opts.quiet ? false : 'Generated Type Files');
36
50
  }
37
51
 
38
- export async function guestTypes (witPath, opts) {
39
- const files = await typesComponent(witPath, { ...opts, guest: true });
40
- await writeFiles(files, opts.quiet ? false : 'Generated Guest Typescript Definition Files (.d.ts)');
52
+ export async function guestTypes(witPath, opts) {
53
+ const files = await typesComponent(witPath, { ...opts, guest: true });
54
+ await writeFiles(
55
+ files,
56
+ opts.quiet
57
+ ? false
58
+ : 'Generated Guest Typescript Definition Files (.d.ts)'
59
+ );
41
60
  }
42
61
 
43
62
  /**
@@ -56,114 +75,165 @@ export async function guestTypes (witPath, opts) {
56
75
  * }} opts
57
76
  * @returns {Promise<{ [filename: string]: Uint8Array }>}
58
77
  */
59
- export async function typesComponent (witPath, opts) {
60
- await $init;
61
- const name = opts.name || (opts.worldName
62
- ? opts.worldName.split(':').pop().split('/').pop()
63
- : basename(witPath.slice(0, -extname(witPath).length || Infinity)));
64
- let instantiation;
65
- if (opts.instantiation) {
66
- instantiation = { tag: opts.instantiation };
67
- }
68
- let outDir = (opts.outDir ?? '').replace(/\\/g, '/');
69
- if (!outDir.endsWith('/') && outDir !== '')
70
- outDir += '/';
71
-
72
- let features = null;
73
- if (opts.allFeatures) {
74
- features = { tag: 'all' };
75
- } else if (Array.isArray(opts.feature)) {
76
- features = { tag: 'list', val: opts.feature };
77
- }
78
-
79
- if (opts.asyncWasiImports)
80
- opts.asyncImports = ASYNC_WASI_IMPORTS.concat(opts.asyncImports || []);
81
- if (opts.asyncWasiExports)
82
- opts.asyncExports = ASYNC_WASI_EXPORTS.concat(opts.asyncExports || []);
83
-
84
- const asyncMode = !opts.asyncMode || opts.asyncMode === 'sync' ?
85
- null :
86
- {
87
- tag: opts.asyncMode,
88
- val: {
89
- imports: opts.asyncImports || [],
90
- exports: opts.asyncExports || [],
91
- },
92
- };
93
-
94
- return Object.fromEntries(generateTypes(name, {
95
- wit: { tag: 'path', val: (isWindows ? '//?/' : '') + resolve(witPath) },
96
- instantiation,
97
- tlaCompat: opts.tlaCompat ?? false,
98
- world: opts.worldName,
99
- features,
100
- guest: opts.guest ?? false,
101
- asyncMode,
102
- }).map(([name, file]) => [`${outDir}${name}`, file]));
78
+ export async function typesComponent(witPath, opts) {
79
+ await $init;
80
+ const name =
81
+ opts.name ||
82
+ (opts.worldName
83
+ ? opts.worldName.split(':').pop().split('/').pop()
84
+ : basename(witPath.slice(0, -extname(witPath).length || Infinity)));
85
+ let instantiation;
86
+ if (opts.instantiation) {
87
+ instantiation = { tag: opts.instantiation };
88
+ }
89
+ let outDir = (opts.outDir ?? '').replace(/\\/g, '/');
90
+ if (!outDir.endsWith('/') && outDir !== '') outDir += '/';
91
+
92
+ let features = null;
93
+ if (opts.allFeatures) {
94
+ features = { tag: 'all' };
95
+ } else if (Array.isArray(opts.feature)) {
96
+ features = { tag: 'list', val: opts.feature };
97
+ }
98
+
99
+ if (opts.asyncWasiImports)
100
+ opts.asyncImports = ASYNC_WASI_IMPORTS.concat(opts.asyncImports || []);
101
+ if (opts.asyncWasiExports)
102
+ opts.asyncExports = ASYNC_WASI_EXPORTS.concat(opts.asyncExports || []);
103
+
104
+ const asyncMode =
105
+ !opts.asyncMode || opts.asyncMode === 'sync'
106
+ ? null
107
+ : {
108
+ tag: opts.asyncMode,
109
+ val: {
110
+ imports: opts.asyncImports || [],
111
+ exports: opts.asyncExports || [],
112
+ },
113
+ };
114
+
115
+ let types;
116
+ const absWitPath = resolve(witPath);
117
+ try {
118
+ types = generateTypes(name, {
119
+ wit: { tag: 'path', val: (isWindows ? '//?/' : '') + absWitPath },
120
+ instantiation,
121
+ tlaCompat: opts.tlaCompat ?? false,
122
+ world: opts.worldName,
123
+ features,
124
+ guest: opts.guest ?? false,
125
+ asyncMode,
126
+ }).map(([name, file]) => [`${outDir}${name}`, file]);
127
+ } catch (err) {
128
+ if (err.toString().includes('does not match previous package name')) {
129
+ const hint = await printWITLayoutHint(absWitPath);
130
+ if (err.message) {
131
+ err.message += `\n${hint}`;
132
+ }
133
+ throw err;
134
+ }
135
+ throw err;
136
+ }
137
+
138
+ return Object.fromEntries(types);
139
+ }
140
+
141
+ /**
142
+ * Print a hint about WIT folder layout
143
+ *
144
+ * @param {(string, any) => void} consoleFn
145
+ */
146
+ async function printWITLayoutHint(witPath) {
147
+ const pathMeta = await stat(witPath);
148
+ let output = '\n';
149
+ if (!pathMeta.isFile() && !pathMeta.isDirectory()) {
150
+ output += c`{yellow.bold warning} The supplited WIT path [${witPath}] is neither a file or directory.\n`;
151
+ return output;
152
+ }
153
+ const ftype = pathMeta.isDirectory() ? 'directory' : 'file';
154
+ output += c`{yellow.bold warning} Your WIT ${ftype} [${witPath}] may be laid out incorrectly\n`;
155
+ output += c`{yellow.bold warning} Keep in mind the following rules:\n`;
156
+ output += c`{yellow.bold warning} - Top level WIT files are in the same package (i.e. "ns:pkg" in "wit/*.wit")\n`;
157
+ output += c`{yellow.bold warning} - All package dependencies should be in "wit/deps" (i.e. "some:dep" in "wit/deps/some-dep.wit"\n`;
158
+ return output;
103
159
  }
104
160
 
105
161
  async function writeFiles(files, summaryTitle) {
106
- await Promise.all(Object.entries(files).map(async ([name, file]) => {
107
- await mkdir(dirname(name), { recursive: true });
108
- await writeFile(name, file);
109
- }));
110
- if (!summaryTitle)
111
- return;
112
- console.log(c`
162
+ await Promise.all(
163
+ Object.entries(files).map(async ([name, file]) => {
164
+ await mkdir(dirname(name), { recursive: true });
165
+ await writeFile(name, file);
166
+ })
167
+ );
168
+ if (!summaryTitle) return;
169
+ console.log(c`
113
170
  {bold ${summaryTitle}:}
114
171
 
115
- ${table(Object.entries(files).map(([name, source]) => [
116
- c` - {italic ${name}} `,
117
- c`{black.italic ${sizeStr(source.length)}}`
118
- ]))}`);
172
+ ${table(
173
+ Object.entries(files).map(([name, source]) => [
174
+ c` - {italic ${name}} `,
175
+ c`{black.italic ${sizeStr(source.length)}}`,
176
+ ])
177
+ )}`);
119
178
  }
120
179
 
121
- export async function transpile (componentPath, opts, program) {
122
- const varIdx = program?.parent.rawArgs.indexOf('--');
123
- if (varIdx !== undefined && varIdx !== -1)
124
- opts.optArgs = program.parent.rawArgs.slice(varIdx + 1);
125
-
126
- let component;
127
- if (!opts.stub) {
128
- component = await readFile(componentPath);
129
- } else {
130
- await wasmToolsInit;
131
- component = componentNew(componentEmbed({
132
- dummy: true,
133
- witPath: (isWindows ? '//?/' : '') + resolve(componentPath)
134
- }), []);
135
- }
136
-
137
- if (!opts.quiet)
138
- setShowSpinner(true);
139
- if (!opts.name)
140
- opts.name = basename(componentPath.slice(0, -extname(componentPath).length || Infinity));
141
- if (opts.map)
142
- opts.map = Object.fromEntries(opts.map.map(mapping => mapping.split('=')));
143
-
144
- if (opts.asyncWasiImports)
145
- opts.asyncImports = ASYNC_WASI_IMPORTS.concat(opts.asyncImports || []);
146
- if (opts.asyncWasiExports)
147
- opts.asyncExports = ASYNC_WASI_EXPORTS.concat(opts.asyncExports || []);
148
-
149
- const { files } = await transpileComponent(component, opts);
150
- await writeFiles(files, opts.quiet ? false : 'Transpiled JS Component Files');
180
+ export async function transpile(componentPath, opts, program) {
181
+ const varIdx = program?.parent.rawArgs.indexOf('--');
182
+ if (varIdx !== undefined && varIdx !== -1)
183
+ opts.optArgs = program.parent.rawArgs.slice(varIdx + 1);
184
+
185
+ let component;
186
+ if (!opts.stub) {
187
+ component = await readFile(componentPath);
188
+ } else {
189
+ await wasmToolsInit;
190
+ component = componentNew(
191
+ componentEmbed({
192
+ dummy: true,
193
+ witPath: (isWindows ? '//?/' : '') + resolve(componentPath),
194
+ }),
195
+ []
196
+ );
197
+ }
198
+
199
+ if (!opts.quiet) setShowSpinner(true);
200
+ if (!opts.name)
201
+ opts.name = basename(
202
+ componentPath.slice(0, -extname(componentPath).length || Infinity)
203
+ );
204
+ if (opts.map)
205
+ opts.map = Object.fromEntries(
206
+ opts.map.map((mapping) => mapping.split('='))
207
+ );
208
+
209
+ if (opts.asyncWasiImports)
210
+ opts.asyncImports = ASYNC_WASI_IMPORTS.concat(opts.asyncImports || []);
211
+ if (opts.asyncWasiExports)
212
+ opts.asyncExports = ASYNC_WASI_EXPORTS.concat(opts.asyncExports || []);
213
+
214
+ const { files } = await transpileComponent(component, opts);
215
+ await writeFiles(
216
+ files,
217
+ opts.quiet ? false : 'Transpiled JS Component Files'
218
+ );
151
219
  }
152
220
 
153
221
  /**
154
222
  * @param {Uint8Array} source
155
223
  * @returns {Promise<Uint8Array>}
156
224
  */
157
- async function wasm2Js (source) {
158
- const wasm2jsPath = fileURLToPath(import.meta.resolve('binaryen/bin/wasm2js'));
159
-
160
- try {
161
- return await spawnIOTmp(wasm2jsPath, source, ['-Oz', '-o']);
162
- } catch (e) {
163
- if (e.toString().includes('BasicBlock requested'))
164
- return wasm2Js(source);
165
- throw e;
166
- }
225
+ async function wasm2Js(source) {
226
+ const wasm2jsPath = fileURLToPath(
227
+ import.meta.resolve('binaryen/bin/wasm2js')
228
+ );
229
+
230
+ try {
231
+ return await spawnIOTmp(wasm2jsPath, source, ['-Oz', '-o']);
232
+ } catch (e) {
233
+ if (e.toString().includes('BasicBlock requested'))
234
+ return wasm2Js(source);
235
+ throw e;
236
+ }
167
237
  }
168
238
 
169
239
  /**
@@ -193,178 +263,198 @@ async function wasm2Js (source) {
193
263
  * }} opts
194
264
  * @returns {Promise<{ files: { [filename: string]: Uint8Array }, imports: string[], exports: [string, 'function' | 'instance'][] }>}
195
265
  */
196
- export async function transpileComponent (component, opts = {}) {
197
- await $init;
198
- if (opts.instantiation) opts.wasiShim = false;
199
-
200
- let spinner;
201
- const showSpinner = getShowSpinner();
202
-
203
- if (opts.optimize) {
204
- if (showSpinner) setShowSpinner(true);
205
- ({ component } = await optimizeComponent(component, opts));
206
- }
207
-
208
- if (opts.wasiShim !== false) {
209
- opts.map = Object.assign({
210
- 'wasi:cli/*': '@bytecodealliance/preview2-shim/cli#*',
211
- 'wasi:clocks/*': '@bytecodealliance/preview2-shim/clocks#*',
212
- 'wasi:filesystem/*': '@bytecodealliance/preview2-shim/filesystem#*',
213
- 'wasi:http/*': '@bytecodealliance/preview2-shim/http#*',
214
- 'wasi:io/*': '@bytecodealliance/preview2-shim/io#*',
215
- 'wasi:random/*': '@bytecodealliance/preview2-shim/random#*',
216
- 'wasi:sockets/*': '@bytecodealliance/preview2-shim/sockets#*',
217
- }, opts.map || {});
218
- }
219
-
220
- let instantiation = null;
221
-
222
- // Let's define `instantiation` from `--instantiation` if it's present.
223
- if (opts.instantiation) {
224
- instantiation = { tag: opts.instantiation };
225
- }
226
- // Otherwise, if `--js` is present, an `instantiate` function is required.
227
- else if (opts.js) {
228
- instantiation = { tag: 'async' };
229
- }
230
-
231
- const asyncMode = !opts.asyncMode || opts.asyncMode === 'sync' ?
232
- null :
233
- {
234
- tag: opts.asyncMode,
235
- val: {
236
- imports: opts.asyncImports || [],
237
- exports: opts.asyncExports || [],
238
- },
239
- };
240
-
241
- let { files, imports, exports } = generate(component, {
242
- name: opts.name ?? 'component',
243
- map: Object.entries(opts.map ?? {}),
244
- instantiation,
245
- asyncMode,
246
- importBindings: opts.importBindings ? { tag: opts.importBindings } : null,
247
- validLiftingOptimization: opts.validLiftingOptimization ?? false,
248
- tracing: opts.tracing ?? false,
249
- noNodejsCompat: opts.nodejsCompat === false,
250
- noTypescript: opts.typescript === false,
251
- tlaCompat: opts.tlaCompat ?? false,
252
- base64Cutoff: opts.js ? 0 : opts.base64Cutoff ?? 5000,
253
- noNamespacedExports: opts.namespacedExports === false,
254
- multiMemory: opts.multiMemory === true,
255
- idlImports: opts.experimentalIdlImports === true,
256
- });
257
-
258
- let outDir = (opts.outDir ?? '').replace(/\\/g, '/');
259
- if (!outDir.endsWith('/') && outDir !== '')
260
- outDir += '/';
261
- files = files.map(([name, source]) => [`${outDir}${name}`, source]);
262
-
263
- const jsFile = files.find(([name]) => name.endsWith('.js'));
264
-
265
- // Generate code for the `--js` option.
266
- //
267
- // `--js` can be called with or without `--instantiation`. The generated code
268
- // isn't exactly the same!
269
- //
270
- // `--js` needs an `instantiate` function to work, so it might look like
271
- // `--instantiation` is always implied, but actually no. It is correct
272
- // that when `--js` is present, an `instantiate` function _is_ generated,
273
- // but it doesn't mean that we expect the function to be used, it's simply
274
- // not exported, plus `instantiate` is automatically called (if `--tla-compat`
275
- // is `false`). When `--instantiation` is missing, functions are exported
276
- // with the `export` directive, and imports are imported with the `import`
277
- // directive. When `--instantiation` is present, there is no `export` and no
278
- // `import`: only a single exported `instantiate` function.
279
- //
280
- // Basically, we get this:
281
- //
282
- // * `--js` only:
283
- // * `instantiate` is renamed to `_instantiate`,
284
- // * A new `instantiate` function is created, that calls `_instantiate` with
285
- // the correct imports (which are ASM.js code) and returns the exports,
286
- // * A new `$init` function is created, that calls `instantiate` and maps
287
- // the returned exports to their respective trampolines,
288
- // * Trampolines are exported,
289
- // * `$init` is called automatically.
290
- //
291
- // * `--js` with `--tla-compat`:
292
- // * Same as with `--js` only, except that `$init` is exported instead of
293
- // being called immediately.
294
- //
295
- // * `--js` with `--instantiation[=async]`:
296
- // * `instantiate` is renamed to `_instantiate`,
297
- // * A new `instantiate` function is created, that calls `_instantiate` with
298
- // the correct imports (which are ASM.js code) and returns the exports,
299
- // * `instantiate` is exported.
300
- //
301
- // * `--js` with `--instantiation=sync`:
302
- // * Same as `--js` with `--instantiation[=async]`, except that
303
- // `_instantiate` and `instantiate` are non-async.
304
- //
305
- // Be careful with the variables: `opts.instantiation` reflects the presence
306
- // or the absence of the `--instantiation` flag, whilst `instantiation`
307
- // reflects how the `instantiate` function must be generated. We also use
308
- // `instantiation` to know whether the generated code must be async or
309
- // non-async.
310
- if (opts.js) {
311
- const withInstantiation = opts.instantiation !== undefined;
312
- const async_ = instantiation.tag == 'async' ? 'async ' : '';
313
- const await_ = instantiation.tag == 'async' ? 'await ' : '';
314
-
315
- // Format the previously generated code.
316
- const source = Buffer.from(jsFile[1]).toString('utf8')
317
- // update imports manging to match emscripten asm
318
- .replace(/exports(\d+)\['([^']+)']/g, (_, i, s) => `exports${i}['${asmMangle(s)}']`)
319
- .replace(/export (async )?function instantiate/, '$1function _instantiate') ;
320
-
321
- // Collect all Wasm files.
322
- const wasmFiles = files.filter(([name]) => name.endsWith('.wasm'));
323
- files = files.filter(([name]) => !name.endsWith('.wasm'));
324
-
325
- // Configure the spinner.
326
- let completed = 0;
327
- const spinnerText = () => c`{cyan ${completed} / ${wasmFiles.length}} Running Binaryen wasm2js on Wasm core modules (this takes a while)...\n`;
328
- if (showSpinner) {
329
- spinner = ora({
330
- color: 'cyan',
331
- spinner: 'bouncingBar'
332
- }).start();
333
- spinner.text = spinnerText();
266
+ export async function transpileComponent(component, opts = {}) {
267
+ await $init;
268
+ if (opts.instantiation) opts.wasiShim = false;
269
+
270
+ let spinner;
271
+ const showSpinner = getShowSpinner();
272
+
273
+ if (opts.optimize) {
274
+ if (showSpinner) setShowSpinner(true);
275
+ ({ component } = await optimizeComponent(component, opts));
334
276
  }
335
277
 
336
- // Compile all Wasm modules into ASM.js codes.
337
- try {
338
- const asmFiles = await Promise.all(wasmFiles.map(async ([, source]) => {
339
- const output = (await wasm2Js(source)).toString('utf8');
340
- if (spinner) {
341
- completed++;
342
- spinner.text = spinnerText();
278
+ if (opts.wasiShim !== false) {
279
+ opts.map = Object.assign(
280
+ {
281
+ 'wasi:cli/*': '@bytecodealliance/preview2-shim/cli#*',
282
+ 'wasi:clocks/*': '@bytecodealliance/preview2-shim/clocks#*',
283
+ 'wasi:filesystem/*':
284
+ '@bytecodealliance/preview2-shim/filesystem#*',
285
+ 'wasi:http/*': '@bytecodealliance/preview2-shim/http#*',
286
+ 'wasi:io/*': '@bytecodealliance/preview2-shim/io#*',
287
+ 'wasi:random/*': '@bytecodealliance/preview2-shim/random#*',
288
+ 'wasi:sockets/*': '@bytecodealliance/preview2-shim/sockets#*',
289
+ },
290
+ opts.map || {}
291
+ );
292
+ }
293
+
294
+ let instantiation = null;
295
+
296
+ // Let's define `instantiation` from `--instantiation` if it's present.
297
+ if (opts.instantiation) {
298
+ instantiation = { tag: opts.instantiation };
299
+ }
300
+ // Otherwise, if `--js` is present, an `instantiate` function is required.
301
+ else if (opts.js) {
302
+ instantiation = { tag: 'async' };
303
+ }
304
+
305
+ const asyncMode =
306
+ !opts.asyncMode || opts.asyncMode === 'sync'
307
+ ? null
308
+ : {
309
+ tag: opts.asyncMode,
310
+ val: {
311
+ imports: opts.asyncImports || [],
312
+ exports: opts.asyncExports || [],
313
+ },
314
+ };
315
+
316
+ let { files, imports, exports } = generate(component, {
317
+ name: opts.name ?? 'component',
318
+ map: Object.entries(opts.map ?? {}),
319
+ instantiation,
320
+ asyncMode,
321
+ importBindings: opts.importBindings
322
+ ? { tag: opts.importBindings }
323
+ : null,
324
+ validLiftingOptimization: opts.validLiftingOptimization ?? false,
325
+ tracing: opts.tracing ?? false,
326
+ noNodejsCompat: opts.nodejsCompat === false,
327
+ noTypescript: opts.typescript === false,
328
+ tlaCompat: opts.tlaCompat ?? false,
329
+ base64Cutoff: opts.js ? 0 : (opts.base64Cutoff ?? 5000),
330
+ noNamespacedExports: opts.namespacedExports === false,
331
+ multiMemory: opts.multiMemory === true,
332
+ idlImports: opts.experimentalIdlImports === true,
333
+ });
334
+
335
+ let outDir = (opts.outDir ?? '').replace(/\\/g, '/');
336
+ if (!outDir.endsWith('/') && outDir !== '') outDir += '/';
337
+ files = files.map(([name, source]) => [`${outDir}${name}`, source]);
338
+
339
+ const jsFile = files.find(([name]) => name.endsWith('.js'));
340
+
341
+ // Generate code for the `--js` option.
342
+ //
343
+ // `--js` can be called with or without `--instantiation`. The generated code
344
+ // isn't exactly the same!
345
+ //
346
+ // `--js` needs an `instantiate` function to work, so it might look like
347
+ // `--instantiation` is always implied, but actually no. It is correct
348
+ // that when `--js` is present, an `instantiate` function _is_ generated,
349
+ // but it doesn't mean that we expect the function to be used, it's simply
350
+ // not exported, plus `instantiate` is automatically called (if `--tla-compat`
351
+ // is `false`). When `--instantiation` is missing, functions are exported
352
+ // with the `export` directive, and imports are imported with the `import`
353
+ // directive. When `--instantiation` is present, there is no `export` and no
354
+ // `import`: only a single exported `instantiate` function.
355
+ //
356
+ // Basically, we get this:
357
+ //
358
+ // * `--js` only:
359
+ // * `instantiate` is renamed to `_instantiate`,
360
+ // * A new `instantiate` function is created, that calls `_instantiate` with
361
+ // the correct imports (which are ASM.js code) and returns the exports,
362
+ // * A new `$init` function is created, that calls `instantiate` and maps
363
+ // the returned exports to their respective trampolines,
364
+ // * Trampolines are exported,
365
+ // * `$init` is called automatically.
366
+ //
367
+ // * `--js` with `--tla-compat`:
368
+ // * Same as with `--js` only, except that `$init` is exported instead of
369
+ // being called immediately.
370
+ //
371
+ // * `--js` with `--instantiation[=async]`:
372
+ // * `instantiate` is renamed to `_instantiate`,
373
+ // * A new `instantiate` function is created, that calls `_instantiate` with
374
+ // the correct imports (which are ASM.js code) and returns the exports,
375
+ // * `instantiate` is exported.
376
+ //
377
+ // * `--js` with `--instantiation=sync`:
378
+ // * Same as `--js` with `--instantiation[=async]`, except that
379
+ // `_instantiate` and `instantiate` are non-async.
380
+ //
381
+ // Be careful with the variables: `opts.instantiation` reflects the presence
382
+ // or the absence of the `--instantiation` flag, whilst `instantiation`
383
+ // reflects how the `instantiate` function must be generated. We also use
384
+ // `instantiation` to know whether the generated code must be async or
385
+ // non-async.
386
+ if (opts.js) {
387
+ const withInstantiation = opts.instantiation !== undefined;
388
+ const async_ = instantiation.tag == 'async' ? 'async ' : '';
389
+ const await_ = instantiation.tag == 'async' ? 'await ' : '';
390
+
391
+ // Format the previously generated code.
392
+ const source = Buffer.from(jsFile[1])
393
+ .toString('utf8')
394
+ // update imports manging to match emscripten asm
395
+ .replace(
396
+ /exports(\d+)\['([^']+)']/g,
397
+ (_, i, s) => `exports${i}['${asmMangle(s)}']`
398
+ )
399
+ .replace(
400
+ /export (async )?function instantiate/,
401
+ '$1function _instantiate'
402
+ );
403
+
404
+ // Collect all Wasm files.
405
+ const wasmFiles = files.filter(([name]) => name.endsWith('.wasm'));
406
+ files = files.filter(([name]) => !name.endsWith('.wasm'));
407
+
408
+ // Configure the spinner.
409
+ let completed = 0;
410
+ const spinnerText = () =>
411
+ c`{cyan ${completed} / ${wasmFiles.length}} Running Binaryen wasm2js on Wasm core modules (this takes a while)...\n`;
412
+ if (showSpinner) {
413
+ spinner = ora({
414
+ color: 'cyan',
415
+ spinner: 'bouncingBar',
416
+ }).start();
417
+ spinner.text = spinnerText();
343
418
  }
344
- return output;
345
- }));
346
419
 
347
- const asms = asmFiles.map((asm, nth) => `function asm${nth}(imports) {
420
+ // Compile all Wasm modules into ASM.js codes.
421
+ try {
422
+ const asmFiles = await Promise.all(
423
+ wasmFiles.map(async ([, source]) => {
424
+ const output = (await wasm2Js(source)).toString('utf8');
425
+ if (spinner) {
426
+ completed++;
427
+ spinner.text = spinnerText();
428
+ }
429
+ return output;
430
+ })
431
+ );
432
+
433
+ const asms = asmFiles
434
+ .map(
435
+ (asm, nth) => `function asm${nth}(imports) {
348
436
  ${
349
- // strip and replace the asm instantiation wrapper
350
- asm
351
- .replace(/import \* as [^ ]+ from '[^']*';/g, '')
352
- .replace('function asmFunc(imports) {', '')
353
- .replace(/export var ([^ ]+) = ([^. ]+)\.([^ ]+);/g, '')
354
- .replace(/var retasmFunc = [\s\S]*$/, '')
355
- .replace(/var memasmFunc = new ArrayBuffer\(0\);/g, '')
356
- .replace('memory.grow = __wasm_memory_grow;', '')
357
- .trim()
358
- }`)
359
- .join(',\n');
360
-
361
- // The `instantiate` function.
362
- const instantiateFunction =
363
- `${
364
- withInstantiation ? 'export ' : ''
365
- }${async_}function instantiate(imports) {
437
+ // strip and replace the asm instantiation wrapper
438
+ asm
439
+ .replace(/import \* as [^ ]+ from '[^']*';/g, '')
440
+ .replace('function asmFunc(imports) {', '')
441
+ .replace(/export var ([^ ]+) = ([^. ]+)\.([^ ]+);/g, '')
442
+ .replace(/var retasmFunc = [\s\S]*$/, '')
443
+ .replace(/var memasmFunc = new ArrayBuffer\(0\);/g, '')
444
+ .replace('memory.grow = __wasm_memory_grow;', '')
445
+ .trim()
446
+ }`
447
+ )
448
+ .join(',\n');
449
+
450
+ // The `instantiate` function.
451
+ const instantiateFunction = `${
452
+ withInstantiation ? 'export ' : ''
453
+ }${async_}function instantiate(imports) {
366
454
  const wasm_file_to_asm_index = {
367
- ${wasmFiles.map(([path], nth) => `'${basename(path)}': ${nth}`).join(',\n ')}
455
+ ${wasmFiles
456
+ .map(([path], nth) => `'${basename(path)}': ${nth}`)
457
+ .join(',\n ')}
368
458
  };
369
459
 
370
460
  return ${await_}_instantiate(
@@ -374,90 +464,80 @@ export async function transpileComponent (component, opts = {}) {
374
464
  );
375
465
  }`;
376
466
 
377
- // If `--js` is used without `--instantiation`.
378
- let importDirectives = '';
379
- let exportDirectives = '';
380
- let exportTrampolines = '';
381
- let autoInstantiate = '';
382
-
383
- if (!withInstantiation) {
384
- importDirectives = imports
385
- .map((import_file, nth) => `import * as import${nth} from '${import_file}';`)
386
- .join('\n');
387
-
388
- if (exports.length > 0 || opts.tlaCompat) {
389
- exportDirectives =
390
- `export {
467
+ // If `--js` is used without `--instantiation`.
468
+ let importDirectives = '';
469
+ let exportDirectives = '';
470
+ let exportTrampolines = '';
471
+ let autoInstantiate = '';
472
+
473
+ if (!withInstantiation) {
474
+ importDirectives = imports
475
+ .map(
476
+ (import_file, nth) =>
477
+ `import * as import${nth} from '${import_file}';`
478
+ )
479
+ .join('\n');
480
+
481
+ if (exports.length > 0 || opts.tlaCompat) {
482
+ exportDirectives = `export {
391
483
  ${
392
- // Exporting `$init` must come first to not break the transpiling tests.
393
- (opts.tlaCompat) ? ' $init,\n' : ''
394
- }${
395
- exports
396
- .map(([name]) => {
397
- if (name === asmMangle(name)){
398
- return ` ${name},`;
399
- } else {
400
- return ` ${asmMangle(name)} as '${name}',`;
484
+ // Exporting `$init` must come first to not break the transpiling tests.
485
+ opts.tlaCompat ? ' $init,\n' : ''
486
+ }${exports
487
+ .map(([name]) => {
488
+ if (name === asmMangle(name)) {
489
+ return ` ${name},`;
490
+ } else {
491
+ return ` ${asmMangle(name)} as '${name}',`;
492
+ }
493
+ })
494
+ .join('\n')}
495
+ }`;
401
496
  }
402
- })
403
- .join('\n')
404
- }
405
- }`
406
- }
407
497
 
408
- exportTrampolines =
409
- `let ${
410
- exports
411
- .filter(([, ty]) => ty === 'function')
412
- .map(([name]) => `_${asmMangle(name)}`)
413
- .join(', ')
414
- };
415
- ${
416
- exports
417
- .map(([name, ty]) => {
418
- if (ty === 'function') {
419
- return `\nfunction ${asmMangle(name)} () {
498
+ exportTrampolines = `let ${exports
499
+ .filter(([, ty]) => ty === 'function')
500
+ .map(([name]) => `_${asmMangle(name)}`)
501
+ .join(', ')};
502
+ ${exports
503
+ .map(([name, ty]) => {
504
+ if (ty === 'function') {
505
+ return `\nfunction ${asmMangle(name)} () {
420
506
  return _${asmMangle(name)}.apply(this, arguments);
421
507
  }`;
422
- } else {
423
- return `\nlet ${asmMangle(name)};`;
424
- }
425
- })
426
- .join('\n')
427
- }`;
428
-
429
- autoInstantiate =
430
- `${async_}function $init() {
508
+ } else {
509
+ return `\nlet ${asmMangle(name)};`;
510
+ }
511
+ })
512
+ .join('\n')}`;
513
+
514
+ autoInstantiate = `${async_}function $init() {
431
515
  ( {
432
- ${
433
- exports
434
- .map( ([name, ty]) => {
435
- if (ty === 'function') {
436
- return ` '${ name }': _${ asmMangle(name) },`;
437
- } else if (asmMangle(name) === name) {
438
- return ` ${ name },`;
439
- } else {
440
- return ` '${ name }': ${ asmMangle(name) },`;
441
- }
442
- })
443
- .join('\n')
444
- }
516
+ ${exports
517
+ .map(([name, ty]) => {
518
+ if (ty === 'function') {
519
+ return ` '${name}': _${asmMangle(name)},`;
520
+ } else if (asmMangle(name) === name) {
521
+ return ` ${name},`;
522
+ } else {
523
+ return ` '${name}': ${asmMangle(name)},`;
524
+ }
525
+ })
526
+ .join('\n')}
445
527
  } = ${await_}instantiate(
446
528
  {
447
- ${
448
- imports
449
- .map((import_file, nth) => ` '${import_file}': import${ nth },`)
450
- .join('\n')
451
- }
529
+ ${imports
530
+ .map((import_file, nth) => ` '${import_file}': import${nth},`)
531
+ .join('\n')}
452
532
  }
453
533
  ) )
454
534
  }
455
535
 
456
- ${ opts.tlaCompat ? '' : `${await_}$init();`}`;
457
- }
536
+ ${opts.tlaCompat ? '' : `${await_}$init();`}`;
537
+ }
458
538
 
459
- // Prepare the final generated code.
460
- const outSource = `${importDirectives}
539
+ // Prepare the final generated code.
540
+ const outSource = `${importDirectives}
461
541
 
462
542
  ${source}
463
543
 
@@ -471,192 +551,225 @@ ${exportDirectives}
471
551
 
472
552
  ${autoInstantiate}`;
473
553
 
474
- // Save the final generated code.
475
- jsFile[1] = Buffer.from(outSource);
554
+ // Save the final generated code.
555
+ jsFile[1] = Buffer.from(outSource);
556
+ } finally {
557
+ if (spinner) {
558
+ spinner.stop();
559
+ }
560
+ }
476
561
  }
477
- finally {
478
- if (spinner) {
479
- spinner.stop();
480
- }
562
+
563
+ if (opts.minify) {
564
+ ({ code: jsFile[1] } = await minify(
565
+ Buffer.from(jsFile[1]).toString('utf8'),
566
+ {
567
+ module: true,
568
+ compress: {
569
+ ecma: 9,
570
+ unsafe: true,
571
+ },
572
+ mangle: {
573
+ keep_classnames: true,
574
+ },
575
+ }
576
+ ));
481
577
  }
482
- }
483
-
484
- if (opts.minify) {
485
- ({ code: jsFile[1] } = await minify(Buffer.from(jsFile[1]).toString('utf8'), {
486
- module: true,
487
- compress: {
488
- ecma: 9,
489
- unsafe: true
490
- },
491
- mangle: {
492
- keep_classnames: true
493
- }
494
- }));
495
- }
496
-
497
- return { files: Object.fromEntries(files), imports, exports };
578
+
579
+ return { files: Object.fromEntries(files), imports, exports };
498
580
  }
499
581
 
500
582
  // emscripten asm mangles specifiers to be valid identifiers
501
583
  // for imports to match up we must do the same
502
584
  // See https://github.com/WebAssembly/binaryen/blob/main/src/asmjs/asmangle.cpp
503
- function asmMangle (name) {
504
- if (name === '')
505
- return '$';
506
-
507
- let mightBeKeyword = true;
508
- let i = 1;
509
-
510
- // Names must start with a character, $ or _
511
- switch (name[0]) {
512
- case '0':
513
- case '1':
514
- case '2':
515
- case '3':
516
- case '4':
517
- case '5':
518
- case '6':
519
- case '7':
520
- case '8':
521
- case '9': {
522
- name = '$' + name;
523
- i = 2;
524
- // fallthrough
525
- }
526
- case '$':
527
- case '_': {
528
- mightBeKeyword = false;
529
- break;
530
- }
531
- default: {
532
- let chNum = name.charCodeAt(0);
533
- if (!(chNum >= 97 && chNum <= 122) && !(chNum >= 65 && chNum <= 90)) {
534
- name = '$' + name.substr(1);
535
- mightBeKeyword = false;
536
- }
585
+ function asmMangle(name) {
586
+ if (name === '') return '$';
587
+
588
+ let mightBeKeyword = true;
589
+ let i = 1;
590
+
591
+ // Names must start with a character, $ or _
592
+ switch (name[0]) {
593
+ case '0':
594
+ case '1':
595
+ case '2':
596
+ case '3':
597
+ case '4':
598
+ case '5':
599
+ case '6':
600
+ case '7':
601
+ case '8':
602
+ case '9': {
603
+ name = '$' + name;
604
+ i = 2;
605
+ // fallthrough
606
+ }
607
+ case '$':
608
+ case '_': {
609
+ mightBeKeyword = false;
610
+ break;
611
+ }
612
+ default: {
613
+ let chNum = name.charCodeAt(0);
614
+ if (
615
+ !(chNum >= 97 && chNum <= 122) &&
616
+ !(chNum >= 65 && chNum <= 90)
617
+ ) {
618
+ name = '$' + name.substr(1);
619
+ mightBeKeyword = false;
620
+ }
621
+ }
537
622
  }
538
- }
539
-
540
- // Names must contain only characters, digits, $ or _
541
- let len = name.length;
542
- for (; i < len; ++i) {
543
- switch (name[i]) {
544
- case '0':
545
- case '1':
546
- case '2':
547
- case '3':
548
- case '4':
549
- case '5':
550
- case '6':
551
- case '7':
552
- case '8':
553
- case '9':
554
- case '$':
555
- case '_': {
556
- mightBeKeyword = false;
557
- break;
558
- }
559
- default: {
560
- let chNum = name.charCodeAt(i);
561
- if (!(chNum >= 97 && chNum <= 122) && !(chNum >= 65 && chNum <= 90)) {
562
- name = name.substr(0, i) + '_' + name.substr(i + 1);
563
- mightBeKeyword = false;
623
+
624
+ // Names must contain only characters, digits, $ or _
625
+ let len = name.length;
626
+ for (; i < len; ++i) {
627
+ switch (name[i]) {
628
+ case '0':
629
+ case '1':
630
+ case '2':
631
+ case '3':
632
+ case '4':
633
+ case '5':
634
+ case '6':
635
+ case '7':
636
+ case '8':
637
+ case '9':
638
+ case '$':
639
+ case '_': {
640
+ mightBeKeyword = false;
641
+ break;
642
+ }
643
+ default: {
644
+ let chNum = name.charCodeAt(i);
645
+ if (
646
+ !(chNum >= 97 && chNum <= 122) &&
647
+ !(chNum >= 65 && chNum <= 90)
648
+ ) {
649
+ name = name.substr(0, i) + '_' + name.substr(i + 1);
650
+ mightBeKeyword = false;
651
+ }
652
+ }
564
653
  }
565
- }
566
654
  }
567
- }
568
655
 
569
- // Names must not collide with keywords
570
- if (mightBeKeyword && len >= 2 && len <= 10) {
571
- switch (name[0]) {
572
- case 'a': {
573
- if (name == "arguments")
574
- return name + '_';
575
- break;
576
- }
577
- case 'b': {
578
- if (name == "break")
579
- return name + '_';
580
- break;
581
- }
582
- case 'c': {
583
- if (name == "case" || name == "continue" || name == "catch" ||
584
- name == "const" || name == "class")
585
- return name + '_';
586
- break;
587
- }
588
- case 'd': {
589
- if (name == "do" || name == "default" || name == "debugger")
590
- return name + '_';
591
- break;
592
- }
593
- case 'e': {
594
- if (name == "else" || name == "enum" || name == "eval" || // to be sure
595
- name == "export" || name == "extends")
596
- return name + '_';
597
- break;
598
- }
599
- case 'f': {
600
- if (name == "for" || name == "false" || name == "finally" ||
601
- name == "function")
602
- return name + '_';
603
- break;
604
- }
605
- case 'i': {
606
- if (name == "if" || name == "in" || name == "import" ||
607
- name == "interface" || name == "implements" ||
608
- name == "instanceof")
609
- return name + '_';
610
- break;
611
- }
612
- case 'l': {
613
- if (name == "let")
614
- return name + '_';
615
- break;
616
- }
617
- case 'n': {
618
- if (name == "new" || name == "null")
619
- return name + '_';
620
- break;
621
- }
622
- case 'p': {
623
- if (name == "public" || name == "package" || name == "private" ||
624
- name == "protected")
625
- return name + '_';
626
- break;
627
- }
628
- case 'r': {
629
- if (name == "return")
630
- return name + '_';
631
- break;
632
- }
633
- case 's': {
634
- if (name == "super" || name == "static" || name == "switch")
635
- return name + '_';
636
- break;
637
- }
638
- case 't': {
639
- if (name == "try" || name == "this" || name == "true" ||
640
- name == "throw" || name == "typeof")
641
- return name + '_';
642
- break;
643
- }
644
- case 'v': {
645
- if (name == "var" || name == "void")
646
- return name + '_';
647
- break;
648
- }
649
- case 'w': {
650
- if (name == "with" || name == "while")
651
- return name + '_';
652
- break;
653
- }
654
- case 'y': {
655
- if (name == "yield")
656
- return name + '_';
657
- break;
658
- }
656
+ // Names must not collide with keywords
657
+ if (mightBeKeyword && len >= 2 && len <= 10) {
658
+ switch (name[0]) {
659
+ case 'a': {
660
+ if (name == 'arguments') return name + '_';
661
+ break;
662
+ }
663
+ case 'b': {
664
+ if (name == 'break') return name + '_';
665
+ break;
666
+ }
667
+ case 'c': {
668
+ if (
669
+ name == 'case' ||
670
+ name == 'continue' ||
671
+ name == 'catch' ||
672
+ name == 'const' ||
673
+ name == 'class'
674
+ )
675
+ return name + '_';
676
+ break;
677
+ }
678
+ case 'd': {
679
+ if (name == 'do' || name == 'default' || name == 'debugger')
680
+ return name + '_';
681
+ break;
682
+ }
683
+ case 'e': {
684
+ if (
685
+ name == 'else' ||
686
+ name == 'enum' ||
687
+ name == 'eval' || // to be sure
688
+ name == 'export' ||
689
+ name == 'extends'
690
+ )
691
+ return name + '_';
692
+ break;
693
+ }
694
+ case 'f': {
695
+ if (
696
+ name == 'for' ||
697
+ name == 'false' ||
698
+ name == 'finally' ||
699
+ name == 'function'
700
+ )
701
+ return name + '_';
702
+ break;
703
+ }
704
+ case 'i': {
705
+ if (
706
+ name == 'if' ||
707
+ name == 'in' ||
708
+ name == 'import' ||
709
+ name == 'interface' ||
710
+ name == 'implements' ||
711
+ name == 'instanceof'
712
+ )
713
+ return name + '_';
714
+ break;
715
+ }
716
+ case 'l': {
717
+ if (name == 'let') return name + '_';
718
+ break;
719
+ }
720
+ case 'n': {
721
+ if (name == 'new' || name == 'null') return name + '_';
722
+ break;
723
+ }
724
+ case 'p': {
725
+ if (
726
+ name == 'public' ||
727
+ name == 'package' ||
728
+ name == 'private' ||
729
+ name == 'protected'
730
+ )
731
+ return name + '_';
732
+ break;
733
+ }
734
+ case 'r': {
735
+ if (name == 'return') return name + '_';
736
+ break;
737
+ }
738
+ case 's': {
739
+ if (name == 'super' || name == 'static' || name == 'switch')
740
+ return name + '_';
741
+ break;
742
+ }
743
+ case 't': {
744
+ if (
745
+ name == 'try' ||
746
+ name == 'this' ||
747
+ name == 'true' ||
748
+ name == 'throw' ||
749
+ name == 'typeof'
750
+ )
751
+ return name + '_';
752
+ break;
753
+ }
754
+ case 'v': {
755
+ if (name == 'var' || name == 'void') return name + '_';
756
+ break;
757
+ }
758
+ case 'w': {
759
+ if (name == 'with' || name == 'while') return name + '_';
760
+ break;
761
+ }
762
+ case 'y': {
763
+ if (name == 'yield') return name + '_';
764
+ break;
765
+ }
766
+ }
659
767
  }
660
- }
661
- return name;
768
+ return name;
769
+ }
770
+
771
+ // see: https://github.com/vitest-dev/vitest/issues/6953#issuecomment-2505310022
772
+ if (typeof __vite_ssr_import_meta__ !== 'undefined') {
773
+ __vite_ssr_import_meta__.resolve = (path) =>
774
+ 'file://' + globalCreateRequire(import.meta.url).resolve(path);
662
775
  }