Skip to content

wasm2js: Mangle import names for JS #2267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,33 @@ as a translation of
)
```

You can also tell wasm2js to optimize, using the normal optimization flags
wasm-opt and other tools receive (such as `-Os`). For optimal code size,
you should both optimize and run a JavaScript minifier afterwards.
wasm2js's output is in ES6 module format - basically, it converts a wasm
module into an ES6 module (to run on older browsers and Node.js versions
you can use Babel etc. to convert it to ES5). Let's look at a full example
of calling that hello world wast; first, create the main JS file:

Things to keep in mind with wasm2js's output:
```javascript
// main.mjs
import { add } from "./hello_world.mjs";
console.log('the sum of 1 and 2 is:', add(1, 2));
```

The run this (note that you need a new enough Node.js with ES6 module
support):

```shell
$ bin/wasm2js test/hello_world.wast -o hello_world.mjs
$ node --experimental-modules main.mjs
the sum of 1 and 2 is: 3
```

Things keep to in mind with wasm2js's output:

* It is not possible to match WebAssemblty semantics 100% precisely with fast
* You should run wasm2js with optimizations for release builds, using `-O`
or another optimization level. That will optimize along the entire pipeline
(wasm and JS). It won't do everything a JS minifer would, though, like
minify whitespace, so you should still run a normal JS minifer afterwards.
* It is not possible to match WebAssembly semantics 100% precisely with fast
JavaScript code. For example, every load and store may trap, and to make
JavaScript do the same we'd need to add checks everywhere, which would be
large and slow. Instead, wasm2js assumes loads and stores do not trap, that
Expand Down
4 changes: 4 additions & 0 deletions scripts/test/mod.ule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

export function ba_se() {
console.log('"mod.ule"."ba.se"');
}
5 changes: 2 additions & 3 deletions scripts/test/node-esm-loader.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ export function resolve(specifier, parentModuleURL = baseURL, defaultResolve) {
format: 'builtin'
};
}
// Resolve the 'spectest' and 'env' modules to our custom implementations of
// various builtins.
if (specifier == 'spectest' || specifier == 'env') {
// Resolve special modules used in our test suite.
if (specifier == 'spectest' || specifier == 'env' || specifier == 'mod.ule') {
const resolved = new URL('./scripts/test/' + specifier + '.js', parentModuleURL);
return {
url: resolved.href,
Expand Down
5 changes: 3 additions & 2 deletions src/wasm2js.h
Original file line number Diff line number Diff line change
Expand Up @@ -2087,7 +2087,8 @@ void Wasm2JSGlue::emitPreES6() {
}
baseModuleMap[base] = module;

out << "import { " << base.str << " } from '" << module.str << "';\n";
out << "import { " << asmangle(base.str) << " } from '" << module.str
<< "';\n";
};

ImportInfo imports(wasm);
Expand Down Expand Up @@ -2185,7 +2186,7 @@ void Wasm2JSGlue::emitPostES6() {
if (ABI::wasm2js::isScratchMemoryHelper(import->base)) {
return;
}
out << "," << import->base.str;
out << "," << asmangle(import->base.str);
});
out << "},mem" << moduleName.str << ");\n";

Expand Down
37 changes: 37 additions & 0 deletions test/wasm2js/dot_import.2asm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ba_se } from 'mod.ule';

function asmFunc(global, env, buffer) {
var HEAP8 = new global.Int8Array(buffer);
var HEAP16 = new global.Int16Array(buffer);
var HEAP32 = new global.Int32Array(buffer);
var HEAPU8 = new global.Uint8Array(buffer);
var HEAPU16 = new global.Uint16Array(buffer);
var HEAPU32 = new global.Uint32Array(buffer);
var HEAPF32 = new global.Float32Array(buffer);
var HEAPF64 = new global.Float64Array(buffer);
var Math_imul = global.Math.imul;
var Math_fround = global.Math.fround;
var Math_abs = global.Math.abs;
var Math_clz32 = global.Math.clz32;
var Math_min = global.Math.min;
var Math_max = global.Math.max;
var Math_floor = global.Math.floor;
var Math_ceil = global.Math.ceil;
var Math_sqrt = global.Math.sqrt;
var abort = env.abort;
var nan = global.NaN;
var infinity = global.Infinity;
var base = env.ba_se;
function $0() {
base();
}

var FUNCTION_TABLE = [];
return {
"exported": $0
};
}

var memasmFunc = new ArrayBuffer(65536);
var retasmFunc = asmFunc({Math,Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,NaN,Infinity}, {abort:function() { throw new Error('abort'); },ba_se},memasmFunc);
export var exported = retasmFunc.exported;
37 changes: 37 additions & 0 deletions test/wasm2js/dot_import.2asm.js.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ba_se } from 'mod.ule';

function asmFunc(global, env, buffer) {
var HEAP8 = new global.Int8Array(buffer);
var HEAP16 = new global.Int16Array(buffer);
var HEAP32 = new global.Int32Array(buffer);
var HEAPU8 = new global.Uint8Array(buffer);
var HEAPU16 = new global.Uint16Array(buffer);
var HEAPU32 = new global.Uint32Array(buffer);
var HEAPF32 = new global.Float32Array(buffer);
var HEAPF64 = new global.Float64Array(buffer);
var Math_imul = global.Math.imul;
var Math_fround = global.Math.fround;
var Math_abs = global.Math.abs;
var Math_clz32 = global.Math.clz32;
var Math_min = global.Math.min;
var Math_max = global.Math.max;
var Math_floor = global.Math.floor;
var Math_ceil = global.Math.ceil;
var Math_sqrt = global.Math.sqrt;
var abort = env.abort;
var nan = global.NaN;
var infinity = global.Infinity;
var base = env.ba_se;
function $0() {
base();
}

var FUNCTION_TABLE = [];
return {
"exported": $0
};
}

var memasmFunc = new ArrayBuffer(65536);
var retasmFunc = asmFunc({Math,Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,NaN,Infinity}, {abort:function() { throw new Error('abort'); },ba_se},memasmFunc);
export var exported = retasmFunc.exported;
6 changes: 6 additions & 0 deletions test/wasm2js/dot_import.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(module
(import "mod.ule" "ba.se" (func $base))
(func "exported"
(call $base)
)
)