In this release: multiple improvements to the react-constant-elements
plugin by @STRML, some codegen optimizations, and lots of bug fixes! Thanks to @loganfsmyth for the release + reviews!
Shoutouts to @xtina-starr, @finkef, @chitchu, @yongxu, @jwbay, @hex13 for their first PRs! π
Check out GitHub for the whole changelog.
I'll be writing up the 7.0 post (our current progress) soon so look out for that! We want to do whatever we can to make it easy for both end-users and plugin/tool authors to upgrade seamlessly: whether it be a beta period for the release, a 7.0 upgrade guide, codemods if necessary, a bot to automatically upgrade your OSS project from 6 to 7, or any other suggestions you can give us!
Since not everyone realises, I wanted to re-iterate again that our team is still a small group of volunteers. There's no company sponsor or even anyone working on it full time.
We'd love for you to contribute (especially not code!), so please reach out to us! More designers, technical writers/editors, and teachers for our website would be amazing.
And in other news, Babel has been accepted as a Rails Girls Summer of Code project as well as waiting to hear back as a mentor organization for Google Summer of Code!
π New Featureβ
#5236 transform-es2015-block-scoping
: Add option throwIfClosureRequired
to throw on slow code. (@spicyj)β
{
"plugins": [
["transform-es2015-block-scoping", {
"throwIfClosureRequired": true
}]
]
}
In cases such as the following, it is impossible to rewrite let/const without adding an additional function and closure while transforming:
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.
#4812 transform-react-constant-elements
: Support pure expressions (@STRML)β
Adds a path.isPure()
check to the plugin.
The expression will remain in the hoisted code, even though it could be statically evaluated. UglifyJS/Babili will take care of that in many cases.
In
const OFFSET = 3;
var Foo = React.createClass({
render: function () {
return (
<div tabIndex={OFFSET + 1} />
);
}
});
Out
const OFFSET = 3;
var _ref = <div tabIndex={OFFSET + 1} />;
var Foo = React.createClass({
render: function () {
return _ref;
}
});
Deopt
As noted in facebook/react#3226, it's not safe to reuse elements with mutable props.
<div style={
{ width: 100 }
} />
#5288 babel-preset-flow
: Add new preset (@thejameskyle)β
babel-preset-flow
just includes transform-flow-strip-types
.
Before (still valid)
{
"plugins": ["transform-flow-strip-types"]
}
After
{
"presets": ["flow"]
}
FYI: the React preset still includes the flow plugin by default (we might change it when TS support is added)
Thanks to @simnalamburt for giving us the package name!
#5230 babel-traverse
: Add extra sibling methods (@chitchu)β
For plugin authors: there's already a path.getSibling(number)
, so we're adding a few helper methods.
path.getPrevSibling(); // path.getSibling(path.parentPath.key - 1)
path.getNextSibling(); // path.getSibling(path.parentPath.key + 1)
path.getAllPrevSiblings(); // returns Array<NodePath> of previous siblings
path.getAllNextSiblings();// returns Array<NodePath> of next siblings
π Bug Fixesβ
Because almost every bug fix can be an opportunity to learn more about JavaScript and how the tool that you use works, I would check out some of the PRs!
#5298 Fix loose transform-es2015-for-of
with label. (@jridgewell)β
b: for (let c of d()) { // previously, the label was completely dropped
for (let e of f()) {
continue b;
}
}
#5153 transform-react-constant-elements
: Hoisting fixes (@STRML)β
Better hoisting inside variable declarations
Input
function render() {
const bar = "bar", renderFoo = () => <foo bar={bar} baz={baz} />, baz = "baz";
return renderFoo();
}
Output
function render() {
const bar = "bar",
renderFoo = () => _ref2,
baz = "baz",
_ref2 = <foo bar={bar} baz={baz} />;
return renderFoo();
}
Hoisting with Higher Order Components
Input
const HOC = component => component;
const Parent = () => (
<div className="parent">
<Child/>
</div>
);
export default Parent;
let Child = () => (
<div className="child">
ChildTextContent
</div>
);
Child = HOC(Child);
Output
const HOC = component => component;
const Parent = () => _ref;
export default Parent;
var _ref2 = <div className="child">
ChildTextContent
</div>;
let Child = () => _ref2;
Child = HOC(Child);
var _ref = <div className="parent">
<Child />
</div>;
#5143 transform-react-constant-elements
: Fix PathHoister
hoisting JSX member expressions on this
(@STRML)β
<this.component />
was previously hoisted outside its own function (doesn't make sense because otherwise this
would be undefined
)
function render() {
this.component = "div";
return () => <this.component />;
}
function render() {
this.component = "div";
var _ref = <this.component />;
return () => _ref;
}
#5030 transform-do-expressions
: Prevent multiple return statements in a loop when replacing expressions. (@existentialism)β
let p
let a = do {
while (p = p.parentPath) {
if (a) {
'a'
} else {
'b'
}
}
};
let p;
let a = function () {
var _ret;
while (p = p.parentPath) {
if (a) {
_ret = 'a';
} else {
_ret = 'b';
}
}
return _ret; // previously had an extra return
}();
#5260 babel-register
: Fix a TypeError with the cache. (@xtuc)β
#5206 babel-traverse
: Deopt evaluation of undefined with a local binding (@boopathi)β
If undefined
, NaN
, Infinity
are redefined, deopt.
#5195 babel-plugin-transform-runtime
: Don't compile certain symbol properties. (@taion)β
Don't pull in the individual Symbol.asyncIterator
/Symbol.observable
polyfills and pull in the full Symbol
polyfill instead.
#5258 babel
: Check if it is installed globally and displays correct cli message. (@xtina-starr)β
Now if you install babel
the error message will display either -g
or not.
#5270 babel-generator
: Emit parens for await of ternary expressions. (@erikdesjardins)β
async function asdf() {
await (1 ? 2 : 3);
}
#5193 babel-generator
: Fix missing parens when FunctionExpression
is a tag in a template string. (@existentialism)β
(() => {})``;
(function(){}``);
#5235 transform-es2015-modules-commonjs
: Limit export node default assignment stack size #4323. (@mattste)β
An interesting issue when importing/exporting a lot!
import { foo, foo1, foo2 ... } from "foo"; // assume ... is 100 imports/exports
export { foo, foo1, foo2 ... }
Part of the generated code looks like:
exports.Foo6 = exports.Foo5 = ...
Thus with a file that exports a lot of modules it creates so many nested assignment nodes in the AST the code generator errors with Maximum call stack size exceeded
.
The solution is to break up the expression into sets of 100.
Output
exports.foo100 = undefined; // split by 100
exports.foo99 = exports.foo98 = ... exports.foo1 = exports.foo = undefined
#5255 babel-generator
: Use trim
instead of lodash/trimEnd
for codegen performance (@jwbay)β
lodash/trimEnd
executes a regex against potentially massive strings which can freeze node. (106ms vs. 5ms)
#5050 babel-traverse
: Rewrite Hub
as an interface (@yongxu)β
This was reverted due to an incompatible change to babel-core
There are a few cases where babel-traverse
can't be used standalone so this removes some code that tied babel-traverse
to babel-core
's implementation.
π Committers: 20β
- Andres Suarez (zertosh)
- Ben Alpert (spicyj)
- Boopathi Rajaa (boopathi)
- Brian Ng (existentialism)
- Christina (xtina-starr) First PR!
- Erik Desjardins (erikdesjardins)
- Fabian Finke (finkef) First PR!
- Henry Zhu (hzoo)
- Jimmy Jia (taion)
- Justin Ridgewell (jridgewell)
- Logan Smyth (loganfsmyth)
- Matt Stewart (mattste)
- Samuel Reed (STRML)
- Sergey Rubanov (chicoxyzzy)
- Sven SAULEAU (xtuc)
- Vicente Jr Yuchitcho (chitchu) First PR!
- Yongxu Ren (yongxu) First PR!
- jwbay First PR!
- james kyle (thejameskyle)
- Εukasz LityΕski (hex13) First PR!
Check out Github for the whole changelog!