@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytecodealliance/jco",
3
- "version": "1.10.2",
3
+ "version": "1.11.0",
4
4
  "description": "JavaScript tooling for working with WebAssembly Components",
5
5
  "author": "Guy Bedford",
6
6
  "bin": {
@@ -38,10 +38,14 @@
38
38
  "@typescript-eslint/eslint-plugin": "^8.2.0",
39
39
  "@typescript-eslint/parser": "^8.2.0",
40
40
  "eslint": "^9.9.0",
41
+ "eslint-config-prettier": "^10.1.1",
42
+ "eslint-plugin-prettier": "^5.2.3",
41
43
  "mime": "^4.0.4",
42
- "mocha": "^10.7.0",
44
+ "prettier": "^3.5.3",
43
45
  "puppeteer": "^24.0.1",
44
- "typescript": "^5.5.4"
46
+ "smol-toml": "^1.3.1",
47
+ "typescript": "^5.5.4",
48
+ "vitest": "^3.0.7"
45
49
  },
46
50
  "repository": {
47
51
  "type": "git",
@@ -61,9 +65,10 @@
61
65
  "build": "cargo xtask build debug",
62
66
  "build:release": "cargo xtask build release",
63
67
  "build:types:preview2-shim": "cargo xtask generate wasi-types",
64
- "lint": "eslint -c eslintrc.cjs src/**/*.js packages/*/lib/**/*.js",
65
- "test:lts": "mocha -u tdd test/test.js --timeout 240000",
66
- "test": "node --experimental-wasm-jspi --stack-trace-limit=100 node_modules/mocha/bin/mocha.js -u tdd test/test.js --timeout 240000",
68
+ "lint": "eslint -c eslintrc.mjs src/**/*.js packages/*/lib/**/*.js",
69
+ "lint:fix": "npm run lint -- --fix",
70
+ "test": "vitest run -c test/vitest.ts",
71
+ "test:lts": "vitest run -c test/vitest.lts.ts",
67
72
  "prepublishOnly": "cargo xtask build release && npm run test"
68
73
  },
69
74
  "files": [
@@ -75,6 +80,13 @@
75
80
  "obj/interfaces"
76
81
  ],
77
82
  "workspaces": [
83
+ ".",
84
+ "examples/components/add",
85
+ "examples/components/http-hello-world",
86
+ "examples/components/node-fetch",
87
+ "examples/components/string-reverse",
88
+ "examples/components/string-reverse-upper",
89
+ "examples/components/webidl-book-library",
78
90
  "packages/preview2-shim"
79
91
  ]
80
92
  }
@@ -1,23 +1,69 @@
1
1
  import { readFile, writeFile } from 'node:fs/promises';
2
2
  import { resolve, basename } from 'node:path';
3
+
3
4
  import c from 'chalk-template';
4
5
 
5
- export async function componentize (jsSource, opts) {
6
- const { componentize: componentizeFn } = await eval('import("@bytecodealliance/componentize-js")');
7
- if (opts.disable?.includes('all')) {
8
- opts.disable = ['stdio', 'random', 'clocks', 'http'];
9
- }
10
- const source = await readFile(jsSource, 'utf8');
11
- const { component } = await componentizeFn(source, {
12
- enableAot: opts.aot,
13
- wevalBin: opts.wevalBin,
14
- sourceName: basename(jsSource),
15
- witPath: resolve(opts.wit),
16
- worldName: opts.worldName,
17
- disableFeatures: opts.disable,
18
- enableFeatures: opts.enable,
19
- preview2Adapter: opts.preview2Adapter,
20
- });
21
- await writeFile(opts.out, component);
22
- console.log(c`{green OK} Successfully written {bold ${opts.out}}.`);
6
+ export async function componentize(jsSource, opts) {
7
+ const { componentize: componentizeFn } = await eval(
8
+ 'import("@bytecodealliance/componentize-js")'
9
+ );
10
+ if (opts.disable?.includes('all')) {
11
+ opts.disable = ['stdio', 'random', 'clocks', 'http'];
12
+ }
13
+ const source = await readFile(jsSource, 'utf8');
14
+
15
+ const witPath = resolve(opts.wit);
16
+ const sourceName = basename(jsSource);
17
+
18
+ let component;
19
+ try {
20
+ const result = await componentizeFn(source, {
21
+ enableAot: opts.aot,
22
+ aotMinStackSizeBytes: opts.aotMinStackSizeBytes,
23
+ wevalBin: opts.wevalBin,
24
+ sourceName,
25
+ witPath,
26
+ worldName: opts.worldName,
27
+ disableFeatures: opts.disable,
28
+ enableFeatures: opts.enable,
29
+ preview2Adapter: opts.preview2Adapter,
30
+ debugBuild: opts.debugStarlingmonkeyBuild,
31
+ });
32
+ component = result.component;
33
+ } catch (err) {
34
+ // Detect package resolution issues that usually mean a misconfigured "witPath"
35
+ if (err.toString().includes('no known packages')) {
36
+ const isFile = await stat(witPath).then((s) => s.isFile());
37
+ if (isFile) {
38
+ const hint = await printWITPathHint(witPath);
39
+ if (err.message) {
40
+ err.message += `\n${hint}`;
41
+ }
42
+ }
43
+ }
44
+ throw err;
45
+ }
46
+
47
+ await writeFile(opts.out, component);
48
+
49
+ console.log(c`{green OK} Successfully written {bold ${opts.out}}.`);
50
+ }
51
+
52
+ /**
53
+ * Print a hint about the witPath option that may be incorrect
54
+ *
55
+ * @param {string} witPath - witPath option that was used (which is a path that resolves to a file or directory)
56
+ * @returns {string} user-visible, highlighted output that can be printed
57
+ */
58
+ async function printWITPathHint(witPath) {
59
+ const pathMeta = await stat(witPath);
60
+ let output = '\n';
61
+ if (!pathMeta.isFile() && !pathMeta.isDirectory()) {
62
+ output += c`{yellow.bold warning} The supplited WIT path [${witPath}] is neither a file or directory.\n`;
63
+ return output;
64
+ }
65
+ output += c`{yellow.bold warning} Your WIT path option [${witPath}] may be incorrect\n`;
66
+ output += c`{yellow.bold warning} When using a world with dependencies, you must pass the enclosing WIT folder, not a single file.\n`;
67
+ output += c`{yellow.bold warning} (e.g. 'wit/', rather than 'wit/component.wit').\n`;
68
+ return output;
23
69
  }
package/src/cmd/opt.js CHANGED
@@ -1,61 +1,61 @@
1
- import { $init, tools } from "../../obj/wasm-tools.js";
1
+ import { $init, tools } from '../../obj/wasm-tools.js';
2
2
  const { metadataShow, print } = tools;
3
- import { writeFile } from "fs/promises";
4
- import { fileURLToPath } from "url";
5
- import c from "chalk-template";
3
+ import { writeFile } from 'fs/promises';
4
+ import { fileURLToPath } from 'url';
5
+ import c from 'chalk-template';
6
6
  import {
7
- readFile,
8
- sizeStr,
9
- fixedDigitDisplay,
10
- table,
11
- spawnIOTmp,
12
- setShowSpinner,
13
- getShowSpinner,
14
- } from "../common.js";
15
- import ora from "#ora";
7
+ readFile,
8
+ sizeStr,
9
+ fixedDigitDisplay,
10
+ table,
11
+ spawnIOTmp,
12
+ setShowSpinner,
13
+ getShowSpinner,
14
+ } from '../common.js';
15
+ import ora from '#ora';
16
16
 
17
17
  export async function opt(componentPath, opts, program) {
18
- await $init;
19
- const varIdx = program.parent.rawArgs.indexOf("--");
20
- if (varIdx !== -1) opts.optArgs = program.parent.rawArgs.slice(varIdx + 1);
21
- const componentBytes = await readFile(componentPath);
18
+ await $init;
19
+ const varIdx = program.parent.rawArgs.indexOf('--');
20
+ if (varIdx !== -1) opts.optArgs = program.parent.rawArgs.slice(varIdx + 1);
21
+ const componentBytes = await readFile(componentPath);
22
22
 
23
- if (!opts.quiet) setShowSpinner(true);
24
- const optPromise = optimizeComponent(componentBytes, opts);
25
- const { component, compressionInfo } = await optPromise;
23
+ if (!opts.quiet) setShowSpinner(true);
24
+ const optPromise = optimizeComponent(componentBytes, opts);
25
+ const { component, compressionInfo } = await optPromise;
26
26
 
27
- await writeFile(opts.output, component);
27
+ await writeFile(opts.output, component);
28
28
 
29
- let totalBeforeBytes = 0,
30
- totalAfterBytes = 0;
29
+ let totalBeforeBytes = 0,
30
+ totalAfterBytes = 0;
31
31
 
32
- if (!opts.quiet)
33
- console.log(c`
32
+ if (!opts.quiet)
33
+ console.log(c`
34
34
  {bold Optimized WebAssembly Component Internal Core Modules:}
35
35
 
36
36
  ${table(
37
- [
38
- ...compressionInfo.map(({ beforeBytes, afterBytes }, i) => {
39
- totalBeforeBytes += beforeBytes;
40
- totalAfterBytes += afterBytes;
41
- return [
42
- ` - Core Module ${i + 1}: `,
43
- sizeStr(beforeBytes),
44
- " -> ",
45
- c`{cyan ${sizeStr(afterBytes)}} `,
46
- `(${fixedDigitDisplay((afterBytes / beforeBytes) * 100, 2)}%)`,
47
- ];
48
- }),
49
- ["", "", "", "", ""],
50
37
  [
51
- ` = Total: `,
52
- `${sizeStr(totalBeforeBytes)}`,
53
- ` => `,
54
- c`{cyan ${sizeStr(totalAfterBytes)}} `,
55
- `(${fixedDigitDisplay((totalAfterBytes / totalBeforeBytes) * 100, 2)}%)`,
38
+ ...compressionInfo.map(({ beforeBytes, afterBytes }, i) => {
39
+ totalBeforeBytes += beforeBytes;
40
+ totalAfterBytes += afterBytes;
41
+ return [
42
+ ` - Core Module ${i + 1}: `,
43
+ sizeStr(beforeBytes),
44
+ ' -> ',
45
+ c`{cyan ${sizeStr(afterBytes)}} `,
46
+ `(${fixedDigitDisplay((afterBytes / beforeBytes) * 100, 2)}%)`,
47
+ ];
48
+ }),
49
+ ['', '', '', '', ''],
50
+ [
51
+ ` = Total: `,
52
+ `${sizeStr(totalBeforeBytes)}`,
53
+ ` => `,
54
+ c`{cyan ${sizeStr(totalAfterBytes)}} `,
55
+ `(${fixedDigitDisplay((totalAfterBytes / totalBeforeBytes) * 100, 2)}%)`,
56
+ ],
56
57
  ],
57
- ],
58
- [, , , , "right"]
58
+ [, , , , 'right']
59
59
  )}`);
60
60
  }
61
61
 
@@ -65,12 +65,12 @@ ${table(
65
65
  * @returns {number}
66
66
  */
67
67
  function byteLengthLEB128(val) {
68
- let len = 0;
69
- do {
70
- val >>>= 7;
71
- len++;
72
- } while (val !== 0);
73
- return len;
68
+ let len = 0;
69
+ do {
70
+ val >>>= 7;
71
+ len++;
72
+ } while (val !== 0);
73
+ return len;
74
74
  }
75
75
 
76
76
  /**
@@ -80,165 +80,190 @@ function byteLengthLEB128(val) {
80
80
  * @returns {Promise<{ component: Uint8Array, compressionInfo: { beforeBytes: number, afterBytes: number }[] >}
81
81
  */
82
82
  export async function optimizeComponent(componentBytes, opts) {
83
- await $init;
84
- const showSpinner = getShowSpinner();
85
- let spinner;
86
- try {
87
- let componentMetadata = metadataShow(componentBytes);
88
- componentMetadata.forEach((metadata, index) => {
89
- // add index to the metadata object
90
- metadata.index = index;
91
- const size = metadata.range[1] - metadata.range[0];
92
- // compute previous LEB128 encoding length
93
- metadata.prevLEBLen = byteLengthLEB128(size);
94
- });
95
- const coreModules = componentMetadata
96
- .filter(({ metaType }) => metaType.tag === "module");
83
+ await $init;
84
+ const showSpinner = getShowSpinner();
85
+ let spinner;
86
+ try {
87
+ let componentMetadata = metadataShow(componentBytes);
88
+ componentMetadata.forEach((metadata, index) => {
89
+ // add index to the metadata object
90
+ metadata.index = index;
91
+ const size = metadata.range[1] - metadata.range[0];
92
+ // compute previous LEB128 encoding length
93
+ metadata.prevLEBLen = byteLengthLEB128(size);
94
+ });
95
+ const coreModules = componentMetadata.filter(
96
+ ({ metaType }) => metaType.tag === 'module'
97
+ );
97
98
 
98
- // log number of core Wasm modules to be run with wasm-opt
99
- let completed = 0;
100
- const spinnerText = () =>
101
- c`{cyan ${completed} / ${coreModules.length}} Running Binaryen on WebAssembly Component Internal Core Modules \n`;
102
- if (showSpinner) {
103
- spinner = ora({
104
- color: "cyan",
105
- spinner: "bouncingBar",
106
- }).start();
107
- spinner.text = spinnerText();
108
- }
99
+ // log number of core Wasm modules to be run with wasm-opt
100
+ let completed = 0;
101
+ const spinnerText = () =>
102
+ c`{cyan ${completed} / ${coreModules.length}} Running Binaryen on WebAssembly Component Internal Core Modules \n`;
103
+ if (showSpinner) {
104
+ spinner = ora({
105
+ color: 'cyan',
106
+ spinner: 'bouncingBar',
107
+ }).start();
108
+ spinner.text = spinnerText();
109
+ }
109
110
 
110
- // gather the options for wasm-opt. optionally, adding the asyncify flag
111
- const args = opts?.optArgs ?
112
- [...opts.optArgs] :
113
- ['-Oz', '--low-memory-unused', '--enable-bulk-memory', '--strip-debug'];
114
- if (opts?.asyncify) args.push('--asyncify');
111
+ // gather the options for wasm-opt. optionally, adding the asyncify flag
112
+ const args = opts?.optArgs
113
+ ? [...opts.optArgs]
114
+ : [
115
+ '-Oz',
116
+ '--low-memory-unused',
117
+ '--enable-bulk-memory',
118
+ '--strip-debug',
119
+ ];
120
+ if (opts?.asyncify) args.push('--asyncify');
115
121
 
122
+ // process core Wasm modules with wasm-opt
123
+ await Promise.all(
124
+ coreModules.map(async (metadata) => {
125
+ if (metadata.metaType.tag === 'module') {
126
+ // store the wasm-opt processed module in the metadata
127
+ metadata.optimized = await wasmOpt(
128
+ componentBytes.subarray(
129
+ metadata.range[0],
130
+ metadata.range[1]
131
+ ),
132
+ args
133
+ );
116
134
 
117
- // process core Wasm modules with wasm-opt
118
- await Promise.all(
119
- coreModules.map(async (metadata) => {
120
- if (metadata.metaType.tag === "module") {
121
- // store the wasm-opt processed module in the metadata
122
- metadata.optimized = await wasmOpt(
123
- componentBytes.subarray(metadata.range[0], metadata.range[1]),
124
- args);
135
+ // compute the size change, including the change to
136
+ // the LEB128 encoding of the size change
137
+ const prevModuleSize =
138
+ metadata.range[1] - metadata.range[0];
139
+ const newModuleSize = metadata.optimized.byteLength;
140
+ metadata.newLEBLen = byteLengthLEB128(newModuleSize);
141
+ metadata.sizeChange = newModuleSize - prevModuleSize;
125
142
 
126
- // compute the size change, including the change to
127
- // the LEB128 encoding of the size change
128
- const prevModuleSize = metadata.range[1] - metadata.range[0];
129
- const newModuleSize = metadata.optimized.byteLength;
130
- metadata.newLEBLen = byteLengthLEB128(newModuleSize);
131
- metadata.sizeChange = newModuleSize - prevModuleSize;
143
+ if (spinner) {
144
+ completed++;
145
+ spinner.text = spinnerText();
146
+ }
147
+ }
148
+ })
149
+ );
132
150
 
133
- if (spinner) {
134
- completed++;
135
- spinner.text = spinnerText();
136
- }
137
- }
138
- }));
151
+ // organize components in modules into tree parent and children
152
+ const nodes = componentMetadata.slice(1);
153
+ const getChildren = (parentIndex) => {
154
+ const children = [];
155
+ for (let i = 0; i < nodes.length; i++) {
156
+ const metadata = nodes[i];
157
+ if (metadata.parentIndex === parentIndex) {
158
+ nodes.splice(i, 1); // remove from nodes
159
+ i--;
160
+ metadata.children = getChildren(metadata.index);
161
+ metadata.sizeChange = metadata.children.reduce(
162
+ (total, { prevLEBLen, newLEBLen, sizeChange }) => {
163
+ return sizeChange
164
+ ? total + sizeChange + newLEBLen - prevLEBLen
165
+ : total;
166
+ },
167
+ metadata.sizeChange || 0
168
+ );
169
+ const prevSize = metadata.range[1] - metadata.range[0];
170
+ metadata.newLEBLen = byteLengthLEB128(
171
+ prevSize + metadata.sizeChange
172
+ );
173
+ children.push(metadata);
174
+ }
175
+ }
176
+ return children;
177
+ };
178
+ const componentTree = getChildren(0);
139
179
 
140
- // organize components in modules into tree parent and children
141
- const nodes = componentMetadata.slice(1);
142
- const getChildren = (parentIndex) => {
143
- const children = [];
144
- for (let i = 0; i < nodes.length; i++) {
145
- const metadata = nodes[i];
146
- if (metadata.parentIndex === parentIndex) {
147
- nodes.splice(i, 1); // remove from nodes
148
- i--;
149
- metadata.children = getChildren(metadata.index);
150
- metadata.sizeChange = metadata.children
151
- .reduce((total, {prevLEBLen, newLEBLen, sizeChange}) => {
152
- return sizeChange ?
153
- total + sizeChange + newLEBLen - prevLEBLen :
154
- total;
180
+ // compute the total size change in the component binary
181
+ const sizeChange = componentTree.reduce(
182
+ (total, { prevLEBLen, newLEBLen, sizeChange }) => {
183
+ return total + (sizeChange || 0) + newLEBLen - prevLEBLen;
155
184
  },
156
- metadata.sizeChange || 0);
157
- const prevSize = metadata.range[1] - metadata.range[0];
158
- metadata.newLEBLen = byteLengthLEB128(prevSize + metadata.sizeChange);
159
- children.push(metadata);
160
- }
161
- }
162
- return children;
163
- };
164
- const componentTree = getChildren(0);
185
+ 0
186
+ );
187
+
188
+ let outComponentBytes = new Uint8Array(
189
+ componentBytes.byteLength + sizeChange
190
+ );
191
+ let nextReadPos = 0,
192
+ nextWritePos = 0;
165
193
 
166
- // compute the total size change in the component binary
167
- const sizeChange = componentTree
168
- .reduce((total, {prevLEBLen, newLEBLen, sizeChange}) => {
169
- return total + (sizeChange || 0) + newLEBLen - prevLEBLen;
170
- }, 0);
194
+ const write = ({
195
+ prevLEBLen,
196
+ range,
197
+ optimized,
198
+ children,
199
+ sizeChange,
200
+ }) => {
201
+ // write from the last read to the LEB byte start
202
+ outComponentBytes.set(
203
+ componentBytes.subarray(nextReadPos, range[0] - prevLEBLen),
204
+ nextWritePos
205
+ );
206
+ nextWritePos += range[0] - prevLEBLen - nextReadPos;
171
207
 
172
- let outComponentBytes = new Uint8Array(
173
- componentBytes.byteLength + sizeChange);
174
- let nextReadPos = 0, nextWritePos = 0;
208
+ // write the new LEB bytes
209
+ let val = range[1] - range[0] + sizeChange;
210
+ do {
211
+ const byte = val & 0x7f;
212
+ val >>>= 7;
213
+ outComponentBytes[nextWritePos++] =
214
+ val === 0 ? byte : byte | 0x80;
215
+ } while (val !== 0);
175
216
 
176
- const write = ({prevLEBLen, range, optimized, children, sizeChange}) => {
177
- // write from the last read to the LEB byte start
178
- outComponentBytes.set(
179
- componentBytes.subarray(nextReadPos, range[0] - prevLEBLen),
180
- nextWritePos
181
- );
182
- nextWritePos += range[0] - prevLEBLen - nextReadPos;
217
+ if (optimized) {
218
+ // write the core module
219
+ outComponentBytes.set(optimized, nextWritePos);
220
+ nextReadPos = range[1];
221
+ nextWritePos += optimized.byteLength;
222
+ } else if (children.length > 0) {
223
+ // write child components / modules
224
+ nextReadPos = range[0];
225
+ children.forEach(write);
226
+ } else {
227
+ // write component
228
+ outComponentBytes.set(
229
+ componentBytes.subarray(range[0], range[1]),
230
+ nextWritePos
231
+ );
232
+ nextReadPos = range[1];
233
+ nextWritePos += range[1] - range[0];
234
+ }
235
+ };
183
236
 
184
- // write the new LEB bytes
185
- let val = range[1] - range[0] + sizeChange;
186
- do {
187
- const byte = val & 0x7f;
188
- val >>>= 7;
189
- outComponentBytes[nextWritePos++] = val === 0 ? byte : byte | 0x80;
190
- } while (val !== 0);
237
+ // write each top-level component / module
238
+ componentTree.forEach(write);
191
239
 
192
- if (optimized) {
193
- // write the core module
194
- outComponentBytes.set(optimized, nextWritePos);
195
- nextReadPos = range[1];
196
- nextWritePos += optimized.byteLength;
197
- } else if (children.length > 0) {
198
- // write child components / modules
199
- nextReadPos = range[0];
200
- children.forEach(write);
201
- } else {
202
- // write component
240
+ // write remaining
203
241
  outComponentBytes.set(
204
- componentBytes.subarray(range[0], range[1]),
205
- nextWritePos
242
+ componentBytes.subarray(nextReadPos),
243
+ nextWritePos
206
244
  );
207
- nextReadPos = range[1];
208
- nextWritePos += range[1] - range[0];
209
- }
210
- };
211
-
212
- // write each top-level component / module
213
- componentTree.forEach(write);
214
245
 
215
- // write remaining
216
- outComponentBytes.set(
217
- componentBytes.subarray(nextReadPos),
218
- nextWritePos
219
- );
246
+ // verify it still parses ok
247
+ if (!opts?.noVerify) {
248
+ try {
249
+ await print(outComponentBytes);
250
+ } catch (e) {
251
+ throw new Error(
252
+ `Internal error performing optimization.\n${e.message}`
253
+ );
254
+ }
255
+ }
220
256
 
221
- // verify it still parses ok
222
- if (!opts?.noVerify) {
223
- try {
224
- await print(outComponentBytes);
225
- } catch (e) {
226
- throw new Error(
227
- `Internal error performing optimization.\n${e.message}`
228
- );
229
- }
257
+ return {
258
+ component: outComponentBytes,
259
+ compressionInfo: coreModules.map(({ range, optimized }) => ({
260
+ beforeBytes: range[1] - range[0],
261
+ afterBytes: optimized?.byteLength,
262
+ })),
263
+ };
264
+ } finally {
265
+ if (spinner) spinner.stop();
230
266
  }
231
-
232
- return {
233
- component: outComponentBytes,
234
- compressionInfo: coreModules.map(({range, optimized}) => ({
235
- beforeBytes: range[1] - range[0],
236
- afterBytes: optimized?.byteLength,
237
- })),
238
- };
239
- } finally {
240
- if (spinner) spinner.stop();
241
- }
242
267
  }
243
268
 
244
269
  /**
@@ -247,15 +272,21 @@ export async function optimizeComponent(componentBytes, opts) {
247
272
  * @returns {Promise<Uint8Array>}
248
273
  */
249
274
  async function wasmOpt(source, args) {
250
- const wasmOptPath = fileURLToPath(
251
- import.meta.resolve("binaryen/bin/wasm-opt")
252
- );
275
+ const wasmOptPath = fileURLToPath(
276
+ import.meta.resolve('binaryen/bin/wasm-opt')
277
+ );
278
+
279
+ try {
280
+ return await spawnIOTmp(wasmOptPath, source, [...args, '-o']);
281
+ } catch (e) {
282
+ if (e.toString().includes('BasicBlock requested'))
283
+ return wasmOpt(source, args);
284
+ throw e;
285
+ }
286
+ }
253
287
 
254
- try {
255
- return await spawnIOTmp(wasmOptPath, source, [...args, "-o"]);
256
- } catch (e) {
257
- if (e.toString().includes("BasicBlock requested"))
258
- return wasmOpt(source, args);
259
- throw e;
260
- }
288
+ // see: https://github.com/vitest-dev/vitest/issues/6953#issuecomment-2505310022
289
+ if (typeof __vite_ssr_import_meta__ !== 'undefined') {
290
+ __vite_ssr_import_meta__.resolve = (path) =>
291
+ 'file://' + globalCreateRequire(import.meta.url).resolve(path);
261
292
  }