@bytecodealliance/jco 0.13.2 → 0.14.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/README.md +23 -21
- package/lib/wasi_snapshot_preview1.command.wasm +0 -0
- package/lib/wasi_snapshot_preview1.reactor.wasm +0 -0
- package/obj/interfaces/wasi-filesystem-types.d.ts +4 -9
- package/obj/interfaces/wasi-io-error.d.ts +6 -0
- package/obj/interfaces/wasi-io-streams.d.ts +2 -4
- package/obj/js-component-bindgen-component.component.wasm +0 -0
- 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 +27 -18
- package/obj/js-component-bindgen-component.js +849 -784
- package/obj/wasm-tools.component.wasm +0 -0
- package/obj/wasm-tools.core.wasm +0 -0
- package/obj/wasm-tools.core2.wasm +0 -0
- package/obj/wasm-tools.d.ts +18 -17
- package/obj/wasm-tools.js +779 -751
- package/package.json +3 -3
- package/src/api.d.ts +42 -0
- package/src/api.d.ts.map +1 -0
- package/src/browser.d.ts +4 -0
- package/src/browser.d.ts.map +1 -0
- package/src/cmd/componentize.d.ts +2 -0
- package/src/cmd/componentize.d.ts.map +1 -0
- package/src/cmd/componentize.js +1 -0
- package/src/cmd/opt.d.ts +15 -0
- package/src/cmd/opt.d.ts.map +1 -0
- package/src/cmd/run.d.ts +2 -0
- package/src/cmd/run.d.ts.map +1 -0
- package/src/cmd/run.js +23 -6
- package/src/cmd/transpile.d.ts +44 -0
- package/src/cmd/transpile.d.ts.map +1 -0
- package/src/cmd/transpile.js +206 -45
- package/src/cmd/wasm-tools.d.ts +8 -0
- package/src/cmd/wasm-tools.d.ts.map +1 -0
- package/src/cmd/wasm-tools.js +3 -2
- package/src/common.d.ts +16 -0
- package/src/common.d.ts.map +1 -0
- package/src/common.js +3 -0
- package/src/jco.d.ts +3 -0
- package/src/jco.d.ts.map +1 -0
- package/src/jco.js +9 -4
- package/src/ora-shim.d.ts +7 -0
- package/src/ora-shim.d.ts.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bytecodealliance/jco",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "JavaScript tooling for working with WebAssembly Components",
|
|
5
5
|
"author": "Guy Bedford",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"type": "module",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@bytecodealliance/preview2-shim": "0.0
|
|
21
|
+
"@bytecodealliance/preview2-shim": "0.14.0",
|
|
22
22
|
"binaryen": "^111.0.0",
|
|
23
23
|
"chalk-template": "^0.4.0",
|
|
24
24
|
"commander": "^9.4.1",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"terser": "^5.16.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@bytecodealliance/componentize-js": "^0.4.
|
|
30
|
+
"@bytecodealliance/componentize-js": "^0.4.1",
|
|
31
31
|
"@types/node": "^18.11.17",
|
|
32
32
|
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
|
33
33
|
"@typescript-eslint/parser": "^5.41.0",
|
package/src/api.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {Parameters<import('../obj/wasm-tools.js').print>[0]} binary
|
|
3
|
+
* @return {Promise<ReturnType<import('../obj/wasm-tools.js').print>>}
|
|
4
|
+
*/
|
|
5
|
+
export function print(binary: Parameters<import('../obj/wasm-tools.js').print>[0]): Promise<ReturnType<import('../obj/wasm-tools.js').print>>;
|
|
6
|
+
/**
|
|
7
|
+
* @param {Parameters<import('../obj/wasm-tools.js').parse>[0]} wat
|
|
8
|
+
* @return {Promise<ReturnType<import('../obj/wasm-tools.js').parse>>}
|
|
9
|
+
*/
|
|
10
|
+
export function parse(wat: Parameters<import('../obj/wasm-tools.js').parse>[0]): Promise<ReturnType<import('../obj/wasm-tools.js').parse>>;
|
|
11
|
+
/**
|
|
12
|
+
* @param {Parameters<import('../obj/wasm-tools.js').componentWit>[0]} binary
|
|
13
|
+
* @return {Promise<ReturnType<import('../obj/wasm-tools.js').componentWit>>}
|
|
14
|
+
*/
|
|
15
|
+
export function componentWit(binary: Parameters<import('../obj/wasm-tools.js').componentWit>[0]): Promise<ReturnType<import('../obj/wasm-tools.js').componentWit>>;
|
|
16
|
+
/**
|
|
17
|
+
* @param {Parameters<import('../obj/wasm-tools.js').componentNew>[0]} binary
|
|
18
|
+
* @param {Parameters<import('../obj/wasm-tools.js').componentNew>[1]} adapters
|
|
19
|
+
* @return {Promise<ReturnType<import('../obj/wasm-tools.js').componentNew>>}
|
|
20
|
+
*/
|
|
21
|
+
export function componentNew(binary: Parameters<import('../obj/wasm-tools.js').componentNew>[0], adapters: Parameters<import('../obj/wasm-tools.js').componentNew>[1]): Promise<ReturnType<import('../obj/wasm-tools.js').componentNew>>;
|
|
22
|
+
/**
|
|
23
|
+
* @param {Parameters<import('../obj/wasm-tools.js').componentEmbed>[0]} embedOpts
|
|
24
|
+
* @return {Promise<ReturnType<import('../obj/wasm-tools.js').componentEmbed>>}
|
|
25
|
+
*/
|
|
26
|
+
export function componentEmbed(embedOpts: Parameters<import('../obj/wasm-tools.js').componentEmbed>[0]): Promise<ReturnType<import('../obj/wasm-tools.js').componentEmbed>>;
|
|
27
|
+
/**
|
|
28
|
+
* @param {Parameters<import('../obj/wasm-tools.js').metadataAdd>[0]} binary
|
|
29
|
+
* @param {Parameters<import('../obj/wasm-tools.js').metadataAdd>[1]} metadata
|
|
30
|
+
* @return {Promise<ReturnType<import('../obj/wasm-tools.js').metadataAdd>>}
|
|
31
|
+
*/
|
|
32
|
+
export function metadataAdd(binary: Parameters<import('../obj/wasm-tools.js').metadataAdd>[0], metadata: Parameters<import('../obj/wasm-tools.js').metadataAdd>[1]): Promise<ReturnType<import('../obj/wasm-tools.js').metadataAdd>>;
|
|
33
|
+
/**
|
|
34
|
+
* @param {Parameters<import('../obj/wasm-tools.js').metadataShow>[0]} binary
|
|
35
|
+
* @return {Promise<ReturnType<import('../obj/wasm-tools.js').metadataShow>>}
|
|
36
|
+
*/
|
|
37
|
+
export function metadataShow(binary: Parameters<import('../obj/wasm-tools.js').metadataShow>[0]): Promise<ReturnType<import('../obj/wasm-tools.js').metadataShow>>;
|
|
38
|
+
export function preview1AdapterCommandPath(): URL;
|
|
39
|
+
export function preview1AdapterReactorPath(): URL;
|
|
40
|
+
export { optimizeComponent as opt } from "./cmd/opt.js";
|
|
41
|
+
export { transpileComponent as transpile } from "./cmd/transpile.js";
|
|
42
|
+
//# sourceMappingURL=api.d.ts.map
|
package/src/api.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["api.js"],"names":[],"mappings":"AAKA;;;GAGG;AACH,8BAHW,WAAW,OAAO,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAClD,QAAQ,WAAW,OAAO,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAKpE;AACD;;;GAGG;AACH,2BAHW,WAAW,OAAO,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAClD,QAAQ,WAAW,OAAO,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAKpE;AACD;;;GAGG;AACH,qCAHW,WAAW,OAAO,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GACzD,QAAQ,WAAW,OAAO,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAK3E;AACD;;;;GAIG;AACH,qCAJW,WAAW,OAAO,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,YAC1D,WAAW,OAAO,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GACzD,QAAQ,WAAW,OAAO,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAK3E;AACD;;;GAGG;AACH,0CAHW,WAAW,OAAO,sBAAsB,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,GAC3D,QAAQ,WAAW,OAAO,sBAAsB,EAAE,cAAc,CAAC,CAAC,CAK7E;AACD;;;;GAIG;AACH,oCAJW,WAAW,OAAO,sBAAsB,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,YACzD,WAAW,OAAO,sBAAsB,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GACxD,QAAQ,WAAW,OAAO,sBAAsB,EAAE,WAAW,CAAC,CAAC,CAK1E;AACD;;;GAGG;AACH,qCAHW,WAAW,OAAO,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GACzD,QAAQ,WAAW,OAAO,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAK3E;AACD,kDAEC;AACD,kDAEC"}
|
package/src/browser.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["browser.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"componentize.d.ts","sourceRoot":"","sources":["componentize.js"],"names":[],"mappings":"AAIA,sEAkBC"}
|
package/src/cmd/componentize.js
CHANGED
package/src/cmd/opt.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function opt(componentPath: any, opts: any, program: any): Promise<void>;
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {Uint8Array} componentBytes
|
|
5
|
+
* @param {{ quiet: boolean, optArgs?: string[] }} options?
|
|
6
|
+
* @returns {Promise<{ component: Uint8Array, compressionInfo: { beforeBytes: number, afterBytes: number }[] >}
|
|
7
|
+
*/
|
|
8
|
+
export function optimizeComponent(componentBytes: Uint8Array, opts: any): Promise<{
|
|
9
|
+
component: Uint8Array;
|
|
10
|
+
compressionInfo: {
|
|
11
|
+
beforeBytes: number;
|
|
12
|
+
afterBytes: number;
|
|
13
|
+
}[];
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=opt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opt.d.ts","sourceRoot":"","sources":["opt.js"],"names":[],"mappings":"AAeA,gFAoCC;AAED;;;;;GAKG;AACH,kDAJW,UAAU,cAER,QAAQ;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,eAAe,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAA,CAAE,CA8E7G"}
|
package/src/cmd/run.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["run.js"],"names":[],"mappings":"AASA,6EA+FC"}
|
package/src/cmd/run.js
CHANGED
|
@@ -4,15 +4,20 @@ import { rm, stat, mkdir, writeFile, symlink } from 'node:fs/promises';
|
|
|
4
4
|
import { basename, resolve, extname } from 'node:path';
|
|
5
5
|
import { fork } from 'node:child_process';
|
|
6
6
|
import process from 'node:process';
|
|
7
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
8
8
|
import c from 'chalk-template';
|
|
9
9
|
|
|
10
|
-
export async function run (componentPath, args) {
|
|
10
|
+
export async function run (componentPath, args, opts) {
|
|
11
11
|
// Ensure that `args` is an array
|
|
12
12
|
args = [...args];
|
|
13
13
|
|
|
14
|
+
const jcoImport = opts.jcoImport ? resolve(opts.jcoImport) : null;
|
|
15
|
+
|
|
14
16
|
const name = basename(componentPath.slice(0, -extname(componentPath).length || Infinity));
|
|
15
|
-
const outDir = await getTmpDir();
|
|
17
|
+
const outDir = opts.jcoDir || await getTmpDir();
|
|
18
|
+
if (opts.jcoDir) {
|
|
19
|
+
await mkdir(outDir, { recursive: true });
|
|
20
|
+
}
|
|
16
21
|
try {
|
|
17
22
|
try {
|
|
18
23
|
await transpile(componentPath, {
|
|
@@ -20,7 +25,8 @@ export async function run (componentPath, args) {
|
|
|
20
25
|
quiet: true,
|
|
21
26
|
noTypescript: true,
|
|
22
27
|
wasiShim: true,
|
|
23
|
-
outDir
|
|
28
|
+
outDir,
|
|
29
|
+
tracing: opts.jcoTrace
|
|
24
30
|
});
|
|
25
31
|
}
|
|
26
32
|
catch (e) {
|
|
@@ -46,14 +52,22 @@ export async function run (componentPath, args) {
|
|
|
46
52
|
|
|
47
53
|
const modulesDir = resolve(outDir, 'node_modules', '@bytecodealliance');
|
|
48
54
|
await mkdir(modulesDir, { recursive: true });
|
|
49
|
-
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
await symlink(preview2ShimPath, resolve(modulesDir, 'preview2-shim'), 'dir');
|
|
58
|
+
} catch (e) {
|
|
59
|
+
if (e.code !== 'EEXIST')
|
|
60
|
+
throw e;
|
|
61
|
+
}
|
|
50
62
|
|
|
51
63
|
const runPath = resolve(outDir, '_run.js');
|
|
52
64
|
await writeFile(runPath, `
|
|
65
|
+
${jcoImport ? `import ${JSON.stringify(pathToFileURL(jcoImport))}` : ''}
|
|
53
66
|
function logInvalidCommand () {
|
|
54
67
|
console.error('Not a valid command component to execute, make sure it was built to a command adapter and with the same version.');
|
|
55
68
|
}
|
|
56
69
|
try {
|
|
70
|
+
process.argv[1] = "${name}";
|
|
57
71
|
const mod = await import('./${name}.js');
|
|
58
72
|
if (!mod.run || !mod.run.run) {
|
|
59
73
|
logInvalidCommand();
|
|
@@ -61,6 +75,8 @@ export async function run (componentPath, args) {
|
|
|
61
75
|
}
|
|
62
76
|
try {
|
|
63
77
|
mod.run.run();
|
|
78
|
+
// TODO: figure out stdout flush!
|
|
79
|
+
setTimeout(() => {});
|
|
64
80
|
}
|
|
65
81
|
catch (e) {
|
|
66
82
|
console.error(e);
|
|
@@ -82,7 +98,8 @@ export async function run (componentPath, args) {
|
|
|
82
98
|
}
|
|
83
99
|
finally {
|
|
84
100
|
try {
|
|
85
|
-
|
|
101
|
+
if (!opts.jcoDir)
|
|
102
|
+
await rm(outDir, { recursive: true });
|
|
86
103
|
} catch {}
|
|
87
104
|
}
|
|
88
105
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function transpile(componentPath: any, opts: any, program: any): Promise<void>;
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {Uint8Array} component
|
|
5
|
+
* @param {{
|
|
6
|
+
* name: string,
|
|
7
|
+
* instantiation?: 'async' | 'sync',
|
|
8
|
+
* map?: Record<string, string>,
|
|
9
|
+
* validLiftingOptimization?: bool,
|
|
10
|
+
* tracing?: bool,
|
|
11
|
+
* noNodejsCompat?: bool,
|
|
12
|
+
* tlaCompat?: bool,
|
|
13
|
+
* base64Cutoff?: bool,
|
|
14
|
+
* js?: bool,
|
|
15
|
+
* minify?: bool,
|
|
16
|
+
* optimize?: bool,
|
|
17
|
+
* noNamespacedExports?: bool,
|
|
18
|
+
* optArgs?: string[],
|
|
19
|
+
* }} opts
|
|
20
|
+
* @returns {Promise<{ files: { [filename: string]: Uint8Array }, imports: string[], exports: [string, 'function' | 'instance'][] }>}
|
|
21
|
+
*/
|
|
22
|
+
export function transpileComponent(component: Uint8Array, opts?: {
|
|
23
|
+
name: string;
|
|
24
|
+
instantiation?: 'async' | 'sync';
|
|
25
|
+
map?: Record<string, string>;
|
|
26
|
+
validLiftingOptimization?: bool;
|
|
27
|
+
tracing?: bool;
|
|
28
|
+
noNodejsCompat?: bool;
|
|
29
|
+
tlaCompat?: bool;
|
|
30
|
+
base64Cutoff?: bool;
|
|
31
|
+
js?: bool;
|
|
32
|
+
minify?: bool;
|
|
33
|
+
optimize?: bool;
|
|
34
|
+
noNamespacedExports?: bool;
|
|
35
|
+
optArgs?: string[];
|
|
36
|
+
}): Promise<{
|
|
37
|
+
files: {
|
|
38
|
+
[filename: string]: Uint8Array;
|
|
39
|
+
};
|
|
40
|
+
imports: string[];
|
|
41
|
+
exports: [string, 'function' | 'instance'][];
|
|
42
|
+
}>;
|
|
43
|
+
import { minify } from "terser";
|
|
44
|
+
//# sourceMappingURL=transpile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transpile.d.ts","sourceRoot":"","sources":["transpile.js"],"names":[],"mappings":"AAWA,sFA2BC;AAuBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,8CAlBW,UAAU;UAEV,MAAM;oBACI,OAAO,GAAG,MAAM;UAC1B,OAAO,MAAM,EAAE,MAAM,CAAC;;;;;;;;;;cAUlB,MAAM,EAAE;;;;;aAEoD,MAAM,EAAE;aAAW,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC,EAAE;GA4IhI"}
|
package/src/cmd/transpile.js
CHANGED
|
@@ -46,7 +46,7 @@ try {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* @param {Uint8Array} source
|
|
49
|
+
* @param {Uint8Array} source
|
|
50
50
|
* @returns {Promise<Uint8Array>}
|
|
51
51
|
*/
|
|
52
52
|
async function wasm2Js (source) {
|
|
@@ -60,22 +60,23 @@ async function wasm2Js (source) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
64
|
-
* @param {Uint8Array} component
|
|
63
|
+
*
|
|
64
|
+
* @param {Uint8Array} component
|
|
65
65
|
* @param {{
|
|
66
66
|
* name: string,
|
|
67
|
-
* instantiation?:
|
|
67
|
+
* instantiation?: 'async' | 'sync',
|
|
68
68
|
* map?: Record<string, string>,
|
|
69
69
|
* validLiftingOptimization?: bool,
|
|
70
70
|
* tracing?: bool,
|
|
71
|
-
*
|
|
71
|
+
* nodejsCompat?: bool,
|
|
72
72
|
* tlaCompat?: bool,
|
|
73
73
|
* base64Cutoff?: bool,
|
|
74
74
|
* js?: bool,
|
|
75
75
|
* minify?: bool,
|
|
76
76
|
* optimize?: bool,
|
|
77
|
+
* namespacedExports?: bool,
|
|
77
78
|
* optArgs?: string[],
|
|
78
|
-
* }} opts
|
|
79
|
+
* }} opts
|
|
79
80
|
* @returns {Promise<{ files: { [filename: string]: Uint8Array }, imports: string[], exports: [string, 'function' | 'instance'][] }>}
|
|
80
81
|
*/
|
|
81
82
|
export async function transpileComponent (component, opts = {}) {
|
|
@@ -103,16 +104,28 @@ export async function transpileComponent (component, opts = {}) {
|
|
|
103
104
|
}, opts.map || {});
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
let instantiation = null;
|
|
108
|
+
|
|
109
|
+
// Let's define `instantiation` from `--instantiation` if it's present.
|
|
110
|
+
if (opts.instantiation) {
|
|
111
|
+
instantiation = { tag: opts.instantiation };
|
|
112
|
+
}
|
|
113
|
+
// Otherwise, if `--js` is present, an `instantiate` function is required.
|
|
114
|
+
else if (opts.js) {
|
|
115
|
+
instantiation = { tag: 'async' };
|
|
116
|
+
}
|
|
117
|
+
|
|
106
118
|
let { files, imports, exports } = generate(component, {
|
|
107
119
|
name: opts.name ?? 'component',
|
|
108
120
|
map: Object.entries(opts.map ?? {}),
|
|
109
|
-
instantiation
|
|
121
|
+
instantiation,
|
|
110
122
|
validLiftingOptimization: opts.validLiftingOptimization ?? false,
|
|
111
123
|
tracing: opts.tracing ?? false,
|
|
112
124
|
noNodejsCompat: !(opts.nodejsCompat ?? true),
|
|
113
125
|
noTypescript: opts.noTypescript || false,
|
|
114
126
|
tlaCompat: opts.tlaCompat ?? false,
|
|
115
|
-
base64Cutoff: opts.js ? 0 : opts.base64Cutoff ?? 5000
|
|
127
|
+
base64Cutoff: opts.js ? 0 : opts.base64Cutoff ?? 5000,
|
|
128
|
+
noNamespacedExports: opts.namespacedExports === false,
|
|
116
129
|
});
|
|
117
130
|
|
|
118
131
|
let outDir = (opts.outDir ?? '').replace(/\\/g, '/');
|
|
@@ -122,16 +135,67 @@ export async function transpileComponent (component, opts = {}) {
|
|
|
122
135
|
|
|
123
136
|
const jsFile = files.find(([name]) => name.endsWith('.js'));
|
|
124
137
|
|
|
138
|
+
// Generate code for the `--js` option.
|
|
139
|
+
//
|
|
140
|
+
// `--js` can be called with or without `--instantiation`. The generated code
|
|
141
|
+
// isn't exactly the same!
|
|
142
|
+
//
|
|
143
|
+
// `--js` needs an `instantiate` function to work, so it might look like
|
|
144
|
+
// `--instantiation` is always implied, but actually no. It is correct
|
|
145
|
+
// that when `--js` is present, an `instantiate` function _is_ generated,
|
|
146
|
+
// but it doesn't mean that we expect the function to be used, it's simply
|
|
147
|
+
// not exported, plus `instantiate` is automatically called (if `--tla-compat`
|
|
148
|
+
// is `false`). When `--instantiation` is missing, functions are exported
|
|
149
|
+
// with the `export` directive, and imports are imported with the `import`
|
|
150
|
+
// directive. When `--instantiation` is present, there is no `export` and no
|
|
151
|
+
// `import`: only a single exported `instantiate` function.
|
|
152
|
+
//
|
|
153
|
+
// Basically, we get this:
|
|
154
|
+
//
|
|
155
|
+
// * `--js` only:
|
|
156
|
+
// * `instantiate` is renamed to `_instantiate`,
|
|
157
|
+
// * A new `instantiate` function is created, that calls `_instantiate` with
|
|
158
|
+
// the correct imports (which are ASM.js code) and returns the exports,
|
|
159
|
+
// * A new `$init` function is created, that calls `instantiate` and maps
|
|
160
|
+
// the returned exports to their respective trampolines,
|
|
161
|
+
// * Trampolines are exported,
|
|
162
|
+
// * `$init` is called automatically.
|
|
163
|
+
//
|
|
164
|
+
// * `--js` with `--tla-compat`:
|
|
165
|
+
// * Same as with `--js` only, except that `$init` is exported instead of
|
|
166
|
+
// being called immediately.
|
|
167
|
+
//
|
|
168
|
+
// * `--js` with `--instantiation[=async]`:
|
|
169
|
+
// * `instantiate` is renamed to `_instantiate`,
|
|
170
|
+
// * A new `instantiate` function is created, that calls `_instantiate` with
|
|
171
|
+
// the correct imports (which are ASM.js code) and returns the exports,
|
|
172
|
+
// * `instantiate` is exported.
|
|
173
|
+
//
|
|
174
|
+
// * `--js` with `--instantiation=sync`:
|
|
175
|
+
// * Same as `--js` with `--instantiation[=async]`, except that
|
|
176
|
+
// `_instantiate` and `instantiate` are non-async.
|
|
177
|
+
//
|
|
178
|
+
// Be careful with the variables: `opts.instantiation` reflects the presence
|
|
179
|
+
// or the absence of the `--instantiation` flag, whilst `instantiation`
|
|
180
|
+
// reflects how the `instantiate` function must be generated. We also use
|
|
181
|
+
// `instantiation` to know whether the generated code must be async or
|
|
182
|
+
// non-async.
|
|
125
183
|
if (opts.js) {
|
|
184
|
+
const withInstantiation = opts.instantiation !== undefined;
|
|
185
|
+
const async_ = instantiation.tag == 'async' ? 'async ' : '';
|
|
186
|
+
const await_ = instantiation.tag == 'async' ? 'await ' : '';
|
|
187
|
+
|
|
188
|
+
// Format the previously generated code.
|
|
126
189
|
const source = Buffer.from(jsFile[1]).toString('utf8')
|
|
127
190
|
// update imports manging to match emscripten asm
|
|
128
|
-
.replace(/exports(\d+)\['([^']+)']/g, (_, i, s) => `exports${i}['${asmMangle(s)}']`)
|
|
129
|
-
|
|
191
|
+
.replace(/exports(\d+)\['([^']+)']/g, (_, i, s) => `exports${i}['${asmMangle(s)}']`)
|
|
192
|
+
.replace(/export (async )?function instantiate/, '$1function _instantiate') ;
|
|
193
|
+
|
|
194
|
+
// Collect all Wasm files.
|
|
130
195
|
const wasmFiles = files.filter(([name]) => name.endsWith('.wasm'));
|
|
131
196
|
files = files.filter(([name]) => !name.endsWith('.wasm'));
|
|
132
197
|
|
|
133
|
-
//
|
|
134
|
-
|
|
198
|
+
// Configure the spinner.
|
|
135
199
|
let completed = 0;
|
|
136
200
|
const spinnerText = () => c`{cyan ${completed} / ${wasmFiles.length}} Running Binaryen wasm2js on Wasm core modules (this takes a while)...\n`;
|
|
137
201
|
if (showSpinner) {
|
|
@@ -142,6 +206,7 @@ export async function transpileComponent (component, opts = {}) {
|
|
|
142
206
|
spinner.text = spinnerText();
|
|
143
207
|
}
|
|
144
208
|
|
|
209
|
+
// Compile all Wasm modules into ASM.js codes.
|
|
145
210
|
try {
|
|
146
211
|
const asmFiles = await Promise.all(wasmFiles.map(async ([, source]) => {
|
|
147
212
|
const output = (await wasm2Js(source)).toString('utf8');
|
|
@@ -152,44 +217,140 @@ export async function transpileComponent (component, opts = {}) {
|
|
|
152
217
|
return output;
|
|
153
218
|
}));
|
|
154
219
|
|
|
155
|
-
const asms = asmFiles.map((asm,
|
|
220
|
+
const asms = asmFiles.map((asm, nth) => `function asm${nth}(imports) {
|
|
156
221
|
${
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
222
|
+
// strip and replace the asm instantiation wrapper
|
|
223
|
+
asm
|
|
224
|
+
.replace(/import \* as [^ ]+ from '[^']*';/g, '')
|
|
225
|
+
.replace('function asmFunc(imports) {', '')
|
|
226
|
+
.replace(/export var ([^ ]+) = ([^. ]+)\.([^ ]+);/g, '')
|
|
227
|
+
.replace(/var retasmFunc = [\s\S]*$/, '')
|
|
228
|
+
.replace(/var memasmFunc = new ArrayBuffer\(0\);/g, '')
|
|
229
|
+
.replace('memory.grow = __wasm_memory_grow;', '')
|
|
230
|
+
.trim()
|
|
231
|
+
}`)
|
|
232
|
+
.join(',\n');
|
|
233
|
+
|
|
234
|
+
// The `instantiate` function.
|
|
235
|
+
const instantiateFunction =
|
|
236
|
+
`${
|
|
237
|
+
withInstantiation ? 'export ' : ''
|
|
238
|
+
}${async_}function instantiate(imports) {
|
|
239
|
+
const wasm_file_to_asm_index = {
|
|
240
|
+
${wasmFiles.map(([path], nth) => `'${basename(path)}': ${nth}`).join(',\n ')}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
return ${await_}_instantiate(
|
|
244
|
+
module_name => wasm_file_to_asm_index[module_name],
|
|
245
|
+
imports,
|
|
246
|
+
(module_index, imports) => ({ exports: asmInit[module_index](imports) })
|
|
247
|
+
);
|
|
248
|
+
}`;
|
|
249
|
+
|
|
250
|
+
// If `--js` is used without `--instantiation`.
|
|
251
|
+
let importDirectives = '';
|
|
252
|
+
let exportDirectives = '';
|
|
253
|
+
let exportTrampolines = '';
|
|
254
|
+
let autoInstantiate = '';
|
|
255
|
+
|
|
256
|
+
if (!withInstantiation) {
|
|
257
|
+
importDirectives = imports
|
|
258
|
+
.map((import_file, nth) => `import * as import${nth} from '${import_file}';`)
|
|
259
|
+
.join('\n');
|
|
260
|
+
|
|
261
|
+
if (exports.length > 0 || opts.tlaCompat) {
|
|
262
|
+
exportDirectives =
|
|
263
|
+
`export {
|
|
264
|
+
${
|
|
265
|
+
// Exporting `$init` must come first to not break the transpiling tests.
|
|
266
|
+
(opts.tlaCompat) ? ' $init,\n' : ''
|
|
267
|
+
}${
|
|
268
|
+
exports
|
|
269
|
+
.map(([name]) => {
|
|
270
|
+
if (name === asmMangle(name)) {
|
|
271
|
+
return ` ${name},`;
|
|
272
|
+
} else {
|
|
273
|
+
return ` ${asmMangle(name)} as '${name}',`;
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
.join('\n')
|
|
277
|
+
}
|
|
278
|
+
}`
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
exportTrampolines =
|
|
282
|
+
`let ${
|
|
283
|
+
exports
|
|
284
|
+
.filter(([, ty]) => ty === 'function')
|
|
285
|
+
.map(([name]) => `_${asmMangle(name)}`)
|
|
286
|
+
.join(', ')
|
|
287
|
+
};
|
|
288
|
+
${
|
|
289
|
+
exports
|
|
290
|
+
.map(([name, ty]) => {
|
|
291
|
+
if (ty === 'function') {
|
|
292
|
+
return `\nfunction ${asmMangle(name)} () {
|
|
293
|
+
return _${asmMangle(name)}.apply(this, arguments);
|
|
294
|
+
}`;
|
|
295
|
+
} else {
|
|
296
|
+
return `\nlet ${asmMangle(name)};`;
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
.join('\n')
|
|
300
|
+
}`;
|
|
301
|
+
|
|
302
|
+
autoInstantiate =
|
|
303
|
+
`${async_}function $init() {
|
|
304
|
+
( {
|
|
305
|
+
${
|
|
306
|
+
exports
|
|
307
|
+
.map( ([name, ty]) => {
|
|
308
|
+
if (ty === 'function') {
|
|
309
|
+
return ` '${ name }': _${ asmMangle(name) },`;
|
|
310
|
+
} else if (asmMangle(name) === name) {
|
|
311
|
+
return ` ${ name },`;
|
|
312
|
+
} else {
|
|
313
|
+
return ` '${ name }': ${ asmMangle(name) },`;
|
|
314
|
+
}
|
|
315
|
+
})
|
|
316
|
+
.join('\n')
|
|
317
|
+
}
|
|
318
|
+
} = ${await_}instantiate(
|
|
319
|
+
{
|
|
320
|
+
${
|
|
321
|
+
imports
|
|
322
|
+
.map((import_file, nth) => ` '${import_file}': import${ nth },`)
|
|
323
|
+
.join('\n')
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
) )
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
${ opts.tlaCompat ? '' : `${await_}$init();`}`;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Prepare the final generated code.
|
|
333
|
+
const outSource = `${importDirectives}
|
|
334
|
+
|
|
335
|
+
${source}
|
|
177
336
|
|
|
178
337
|
const asmInit = [${asms}];
|
|
179
338
|
|
|
180
|
-
${
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
${imports.map((impt, i) => ` '${impt}': import${i},`).join('\n')}
|
|
184
|
-
}, (i, imports) => ({ exports: asmInit[i](imports) })));
|
|
185
|
-
})();${exports.length > 0 ? `\nexport { ${exports.map(([name]) => name === asmMangle(name) ? `${name}` : `${asmMangle(name)} as "${name}"`).join(', ')} }` : ''}
|
|
186
|
-
${opts.tlaCompat ? '' : '\nawait $init;\n'}`;
|
|
339
|
+
${exportTrampolines}
|
|
340
|
+
|
|
341
|
+
${instantiateFunction}
|
|
187
342
|
|
|
343
|
+
${exportDirectives}
|
|
344
|
+
|
|
345
|
+
${autoInstantiate}`;
|
|
346
|
+
|
|
347
|
+
// Save the final generated code.
|
|
188
348
|
jsFile[1] = Buffer.from(outSource);
|
|
189
349
|
}
|
|
190
350
|
finally {
|
|
191
|
-
if (spinner)
|
|
351
|
+
if (spinner) {
|
|
192
352
|
spinner.stop();
|
|
353
|
+
}
|
|
193
354
|
}
|
|
194
355
|
}
|
|
195
356
|
|
|
@@ -215,10 +376,10 @@ ${opts.tlaCompat ? '' : '\nawait $init;\n'}`;
|
|
|
215
376
|
function asmMangle (name) {
|
|
216
377
|
if (name === '')
|
|
217
378
|
return '$';
|
|
218
|
-
|
|
379
|
+
|
|
219
380
|
let mightBeKeyword = true;
|
|
220
381
|
let i = 1;
|
|
221
|
-
|
|
382
|
+
|
|
222
383
|
// Names must start with a character, $ or _
|
|
223
384
|
switch (name[0]) {
|
|
224
385
|
case '0':
|
|
@@ -248,7 +409,7 @@ function asmMangle (name) {
|
|
|
248
409
|
}
|
|
249
410
|
}
|
|
250
411
|
}
|
|
251
|
-
|
|
412
|
+
|
|
252
413
|
// Names must contain only characters, digits, $ or _
|
|
253
414
|
let len = name.length;
|
|
254
415
|
for (; i < len; ++i) {
|
|
@@ -277,7 +438,7 @@ function asmMangle (name) {
|
|
|
277
438
|
}
|
|
278
439
|
}
|
|
279
440
|
}
|
|
280
|
-
|
|
441
|
+
|
|
281
442
|
// Names must not collide with keywords
|
|
282
443
|
if (mightBeKeyword && len >= 2 && len <= 10) {
|
|
283
444
|
switch (name[0]) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function parse(file: any, opts: any): Promise<void>;
|
|
2
|
+
export function print(file: any, opts: any): Promise<void>;
|
|
3
|
+
export function componentWit(file: any, opts: any): Promise<void>;
|
|
4
|
+
export function componentNew(file: any, opts: any): Promise<void>;
|
|
5
|
+
export function componentEmbed(file: any, opts: any): Promise<void>;
|
|
6
|
+
export function metadataAdd(file: any, opts: any): Promise<void>;
|
|
7
|
+
export function metadataShow(file: any, opts: any): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=wasm-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm-tools.d.ts","sourceRoot":"","sources":["wasm-tools.js"],"names":[],"mappings":"AAOA,2DAKC;AAED,2DASC;AAED,kEASC;AAED,kEAsBC;AAED,oEAaC;AAED,iEAUC;AAED,kEAiCC"}
|
package/src/cmd/wasm-tools.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { writeFile } from "node:fs/promises";
|
|
2
|
-
import { readFile } from '../common.js';
|
|
2
|
+
import { readFile, isWindows } from '../common.js';
|
|
3
3
|
import { $init, tools } from "../../obj/wasm-tools.js";
|
|
4
4
|
const { print: printFn, parse: parseFn, componentWit: componentWitFn, componentNew: componentNewFn, componentEmbed: componentEmbedFn, metadataAdd: metadataAddFn, metadataShow: metadataShowFn } = tools;
|
|
5
5
|
import { resolve, basename, extname } from 'node:path';
|
|
6
6
|
import c from 'chalk-template';
|
|
7
|
+
import { platform } from 'node:process';
|
|
7
8
|
|
|
8
9
|
export async function parse(file, opts) {
|
|
9
10
|
await $init;
|
|
@@ -68,7 +69,7 @@ export async function componentEmbed(file, opts) {
|
|
|
68
69
|
});
|
|
69
70
|
const source = file ? await readFile(file) : null;
|
|
70
71
|
opts.binary = source;
|
|
71
|
-
opts.witPath = resolve(opts.wit);
|
|
72
|
+
opts.witPath = (isWindows ? '//?/' : '') + resolve(opts.wit);
|
|
72
73
|
const output = componentEmbedFn(opts);
|
|
73
74
|
await writeFile(opts.output, output);
|
|
74
75
|
}
|
package/src/common.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function setShowSpinner(val: any): void;
|
|
2
|
+
export function getShowSpinner(): boolean;
|
|
3
|
+
export function sizeStr(num: any): string;
|
|
4
|
+
export function fixedDigitDisplay(num: any, maxChars: any): string;
|
|
5
|
+
export function table(data: any, align?: any[]): string;
|
|
6
|
+
/**
|
|
7
|
+
* Securely creates a temporary directory and returns its path.
|
|
8
|
+
*
|
|
9
|
+
* The new directory is created using `fsPromises.mkdtemp()`.
|
|
10
|
+
*/
|
|
11
|
+
export function getTmpDir(): Promise<string>;
|
|
12
|
+
export function spawnIOTmp(cmd: any, input: any, args: any): Promise<Buffer>;
|
|
13
|
+
export const isWindows: boolean;
|
|
14
|
+
export { readFileCli as readFile };
|
|
15
|
+
declare function readFileCli(file: any, encoding: any): Promise<Buffer>;
|
|
16
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["common.js"],"names":[],"mappings":"AAWA,+CAEC;AACD,0CAIC;AAED,0CAOC;AAED,mEAaC;AAED,wDAcC;AAED;;;;GAIG;AACH,6CAEC;AAYD,6EA8BC;AArGD,gCAA8C;;AA6D9C,wEAOC"}
|