@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.
- package/package.json +18 -6
- package/src/cmd/componentize.js +64 -18
- package/src/cmd/opt.js +233 -202
- package/src/cmd/run.js +117 -73
- package/src/cmd/transpile.js +643 -530
- package/src/cmd/wasm-tools.js +130 -95
- package/src/jco.js +5 -1
- package/obj/interfaces/local-wasm-tools-tools.d.ts +0 -52
- package/obj/interfaces/wasi-cli-environment.d.ts +0 -2
- package/obj/interfaces/wasi-cli-exit.d.ts +0 -3
- package/obj/interfaces/wasi-cli-stderr.d.ts +0 -3
- package/obj/interfaces/wasi-cli-stdin.d.ts +0 -3
- package/obj/interfaces/wasi-cli-stdout.d.ts +0 -3
- package/obj/interfaces/wasi-cli-terminal-input.d.ts +0 -8
- package/obj/interfaces/wasi-cli-terminal-output.d.ts +0 -8
- package/obj/interfaces/wasi-cli-terminal-stderr.d.ts +0 -3
- package/obj/interfaces/wasi-cli-terminal-stdin.d.ts +0 -3
- package/obj/interfaces/wasi-cli-terminal-stdout.d.ts +0 -3
- package/obj/interfaces/wasi-clocks-wall-clock.d.ts +0 -5
- package/obj/interfaces/wasi-filesystem-preopens.d.ts +0 -3
- package/obj/interfaces/wasi-filesystem-types.d.ts +0 -164
- package/obj/interfaces/wasi-io-error.d.ts +0 -8
- package/obj/interfaces/wasi-io-streams.d.ts +0 -30
- package/obj/interfaces/wasi-random-random.d.ts +0 -2
- package/obj/js-component-bindgen-component.core.wasm +0 -0
- package/obj/js-component-bindgen-component.core2.wasm +0 -0
- package/obj/js-component-bindgen-component.d.ts +0 -116
- package/obj/js-component-bindgen-component.js +0 -4302
- package/obj/wasm-tools.core.wasm +0 -0
- package/obj/wasm-tools.core2.wasm +0 -0
- package/obj/wasm-tools.d.ts +0 -20
- package/obj/wasm-tools.js +0 -4369
- package/src/api.d.ts +0 -42
- package/src/api.d.ts.map +0 -1
- package/src/browser.d.ts +0 -4
- package/src/browser.d.ts.map +0 -1
- package/src/cmd/componentize.d.ts +0 -2
- package/src/cmd/componentize.d.ts.map +0 -1
- package/src/cmd/opt.d.ts +0 -20
- package/src/cmd/opt.d.ts.map +0 -1
- package/src/cmd/run.d.ts +0 -3
- package/src/cmd/run.d.ts.map +0 -1
- package/src/cmd/transpile.d.ts +0 -89
- package/src/cmd/transpile.d.ts.map +0 -1
- package/src/cmd/wasm-tools.d.ts +0 -8
- package/src/cmd/wasm-tools.d.ts.map +0 -1
- package/src/common.d.ts +0 -16
- package/src/common.d.ts.map +0 -1
- package/src/jco.d.ts +0 -3
- package/src/jco.d.ts.map +0 -1
- package/src/ora-shim.d.ts +0 -7
- package/src/ora-shim.d.ts.map +0 -1
package/src/cmd/transpile.js
CHANGED
|
@@ -1,43 +1,62 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
30
|
-
|
|
43
|
+
'wasi:cli/run#run',
|
|
44
|
+
'wasi:http/incoming-handler#handle',
|
|
31
45
|
];
|
|
32
46
|
|
|
33
|
-
export async function types
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
outDir
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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(
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
|
|
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
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}`
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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
|
|
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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
-
|
|
393
|
-
|
|
394
|
-
}${
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
-
|
|
449
|
-
|
|
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
|
-
${
|
|
457
|
-
|
|
536
|
+
${opts.tlaCompat ? '' : `${await_}$init();`}`;
|
|
537
|
+
}
|
|
458
538
|
|
|
459
|
-
|
|
460
|
-
|
|
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
|
-
|
|
475
|
-
|
|
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
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
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
|
-
|
|
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
|
}
|