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).
This syntax allows you to specify whether a type variable can appear in
a covariant or contravariant position, and is super useful for, say,
Promise.
Right now this is hacked in jankily, but in the next major release we
should stop using Identifier nodes for type parameters.
The untransformed `let` keyword causes problems for older parsers. I
understand using `let` instead of `var` ensures each getter function has
its own binding for the KEY variable, but the same can be accomplished
(with less code) using a `.forEach` callback function, and this way
there's no need to worry about generating a unique name for the `key`
variable.
When convert a const, let or any other block-bound binding to a var we
forget to update the scope info. This confuses other transforms that may
come after this as to which scope does the binding belongs to.
This also uncovered an issue where duplicate block-scoped bindings were allowed
to co-exist.