Add option to block-scoping to slow on throw code (#5236)
The let/const plugin can add closures where you don't expect them. This is undesirable in some perf-sensitive projects (ex: React). I added an option that throws whenever the plugin adds a function (as opposed to simply renaming variables when converting to var).
This commit is contained in:
@@ -14,12 +14,26 @@ npm install --save-dev babel-plugin-transform-es2015-block-scoping
|
||||
|
||||
**.babelrc**
|
||||
|
||||
Without options:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": ["transform-es2015-block-scoping"]
|
||||
}
|
||||
```
|
||||
|
||||
With options:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": [
|
||||
["transform-es2015-block-scoping", {
|
||||
"throwIfClosureRequired": true
|
||||
}]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Via CLI
|
||||
|
||||
```sh
|
||||
@@ -33,3 +47,15 @@ require("babel-core").transform("code", {
|
||||
plugins: ["transform-es2015-block-scoping"]
|
||||
});
|
||||
```
|
||||
|
||||
## Options `throwIfClosureRequired`
|
||||
|
||||
In cases such as the following it's impossible to rewrite let/const without adding an additional function and closure while transforming:
|
||||
|
||||
```javascript
|
||||
for (let i = 0; i < 5; i++) {
|
||||
setTimeout(() => console.log(i), 1);
|
||||
}
|
||||
```
|
||||
|
||||
In extremely performance-sensitive code, this can be undesirable. If `"throwIfClosureRequired": true` is set, Babel throws when transforming these patterns instead of automatically adding an additional function.
|
||||
|
||||
@@ -360,6 +360,12 @@ class BlockScoping {
|
||||
}
|
||||
|
||||
wrapClosure() {
|
||||
if (this.file.opts.throwIfClosureRequired) {
|
||||
throw this.blockPath.buildCodeFrameError(
|
||||
"Compiling let/const in this block would add a closure " +
|
||||
"(throwIfClosureRequired)."
|
||||
);
|
||||
}
|
||||
const block = this.block;
|
||||
|
||||
const outsideRefs = this.outsideLetReferences;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const l = i;
|
||||
setTimeout(function() {
|
||||
console.log(l);
|
||||
}, 1);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Compiling let/const in this block would add a closure (throwIfClosureRequired)."
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
function test() {
|
||||
let foo = "bar";
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
function test() {
|
||||
var foo = "bar";
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-es2015-block-scoping", { "throwIfClosureRequired": true }], "syntax-jsx", "transform-react-jsx", "transform-es2015-block-scoped-functions", "transform-es2015-arrow-functions"]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
function foo() {
|
||||
switch (2) {
|
||||
case 0: {
|
||||
if (true) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stuff = new Map();
|
||||
const data = 0;
|
||||
stuff.forEach(() => {
|
||||
const d = data;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Compiling let/const in this block would add a closure (throwIfClosureRequired)."
|
||||
}
|
||||
Reference in New Issue
Block a user