I previously tried an approach to scope bindings from var to scope but
it didn't catch all cases. This is evident in this bug:
https://phabricator.babeljs.io/T2892
Where even after transforming a const to a var we still get an error
that it's read-only.
This approach will go through and delete every existing let and const
binding and creates a new one with the kind "var"
As mentioned on the task https://phabricator.babeljs.io/T7179 having
this cache on the AST leads to all sorts of portability and reuse
bugs.
This moves the cache into a clearable WeakMap which will fix the
following:
1. Moving the AST between different babel versions or tools will not
lead into sharing potentially outdated cached information
2. `.clear()` can be called on the cache by a plugin to clear
potentially outdated information. This is helpful when implementing two
seperate pipelines that should not share information.
I think the next step (which is harder, I tried) is to isolate cache and
make it live on a transform or pipeline level state (like the `hub`).
The reason it is hard is because the `babel-traverse` main API -- although
requires the state object to be passed -- not many callers do. To fix
this we should release a patch version that warns about this and fix all
the internal callers. Next couple of releases we can start throwing when
no state is passed (or we can create our own state).
Original PR: https://github.com/babel/babel/pull/2469. Seems this got
lost in the v6 changes.
- - -
Without this, the only way to replace the arrow function is to either
manually override its `node.body`, or duplicate the arrow:
```js
// Old
ArrowFunctionExpression: function (node) {
node.body = t.blockStatement(...);
// Or
return t.ArrowFunctionExpression(
node.params,
t.blockStatement(...),
node.async
);
}
// New
ArrowFunctionExpression: function() {
this.get("body").replaceWith(t.blockStatement(...));
}
```
As an artificat of compiling methods to named function expressions the
function name is being considered a "local" binding in the function
body. This means that we will throw errors anytime someone would want to
create a new local binding with the same name.
This is solved by assigning a symbol to function Identifiers that
indicates that they should not be considered local bindings.