asm.js code minified with babel-plugin-minify-dead-code-elimination causes "asm.js type error: initializer of exported object literal must be name of function" error in Firefox
- Dominant language
- JavaScript
- Stars
- 4.4k
- Forks
- 217
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
asm.js code minified with the "babel-plugin-minify-dead-code-elimination plugin causes an `asm.js type error: initializer of exported object literal must be name of function` error in Firefox.
**NOTE: Even those this console message says "error", the code will still run correctly. However, Firefox will use its regular JS JIT instead of its asm.js-optimized JIT since the code's is no longer valid asm.js syntax.**
**To Reproduce**
Minimal code to reproduce the bug
```js
function AsmTest(stdlib, foreign, buffer) {
"use asm";
function foo() { return 0; }
return { foo: foo };
}
```
You can reproduce the error using this JS Fiddle example:
1. Load https://jsfiddle.net/1kcf69g3/ in Firefox.
2. Click the `Run` button.
3. Open Firefox's DevTools console using `Shift`+`Ctrl`+`I` on Windows or Linux or `Shift`+`Command`+`I` on macOS.
4. Filter the console output for "asm.js".
You will see two asm.js messages, the first when Firefox JITs the `GoodAsmTest()` function and second when Firefox JITs the `BadAsmTest()` function:
```
Successfully compiled asm.js code (total compilation time 0ms)
asm.js type error: initializer of exported object literal must be name of function
```
**NOTE: You must keep the DevTools console closed when you run the script!** If you open the DevTools console before you run the script, Firefox disables its JIT and you will see a console message like `asm.js type error: Disabled by lack of compiler support` or `asm.js type error: Asm.js optimizer disabled because debugger is active` instead of the `asm.js type error: initializer of exported object literal must be name of function` JIT error.
**Actual Output**
```js
function AsmTest() {
"use asm";
return {
foo: function () {
return 0;
}
};
}
```
The problem is that babel-minify is converting a standalone function definition into a function object in the `AsmTest()` function's `return` statement. asm.js requires that `use asm` functions return an object literal whose property values are function _identifiers_, not function _objects_:
http://asmjs.org/spec/latest/#validateexport-s
**Expected Output**
```js
function AsmTest(stdlib, foreign, buffer) {
"use asm";
function foo() {
return 0;
}
return {
foo: foo
};
}
```
**Configuration**
How are you using babel-minify?
Here is a live example of the bug in the Babel REPL with the `babel-plugin-minify-dead-code-elimination` plugin added:
https://babeljs.io/repl/#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&corejs=3.6&spec=false&loose=false&code_lz=GYVwdgxgLglg9mABAQQM4FsAqBTVUAUeAJgDYwBGANIsHAE7YwDmY15Iww2dAlIgN4AoRIgBEIVNkQBDDKIDcwmuGjwktOPj79EDKCDpIADPMQBfJXoNIdGgFw04cc4rNA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=false&presets=env%2Creact%2Cstage-2&prettier=false&targets=&version=7.15.3&externalPlugins=babel-plugin-minify-dead-code-elimination%400.5.1&assumptions=%7B%7D
**You must manually add the `babel-plugin-minify-dead-code-elimination` plugin.**
**Possible solution**
This problem could be avoided if babel-minify ignored `use asm` functions, as suggested in https://github.com/babel/minify/issues/599, or didn't run the the `babel-plugin-minify-dead-code-elimination` plugin on `use asm` functions.
**Additional context**
Here are multiple bug reports about this asm.js error in webtorrent.js caused by babel-minify:
https://github.com/webtorrent/webtorrent/issues/1830
https://github.com/webtorrent/webtorrent/issues/1252
https://github.com/webtorrent/webtorrent/issues/281
The unminified version of webtorrent.js and a version minified by [Terser](https://terser.org/) load in Firefox without problem. But the version minified by babel-minify (including webtorrent's official [webtorrent.min.js](https://github.com/webtorrent/webtorrent/blob/1499cbfc143bba8733a9cd426877260fbd39c059/webtorrent.min.js) version) have the error.
Here is the minified output from [Terser](https://terser.org/) (which you can test yourself in the [Terser REPL](https://try.terser.org/), which doesn't cause this asm.js error because it retains the standalone function `f`:
```
(function(n,o,u){"use asm";function f(){return 0}return{foo:f}})().foo();
```
Contributor guide
Assessment
This issue has not been assessed yet.