Issue 1:
Bug Report

I would like to work on a fix!

Current Behavior

scope.crawl() does not add references to bindings correctly in some cases. In particular I get the bug when referencing a class inside a class method.

Input Code

regiontog/babel@master...bug/missing-references-after-crawl

const path = getPath("class a { build() { return new a(); } }");
path.scope.crawl();
const referencePaths = path.scope.bindings.a.referencePaths;
expect(referencePaths).toHaveLength(1);

Expected behavior/code

I expect the binding a to have 1 reference inside the scope of the build class method after a crawl. The binding has 1 reference before the crawl call is made.

Environment

System:
OS: Linux 5.4 Arch Linux
Binaries:
Node: 13.3.0 - /usr/bin/node
Yarn: 1.21.0 - /usr/bin/yarn
npm: 6.12.1 - /usr/bin/npm
Monorepos:
Lerna: 3.19.0
npmPackages:
@babel/cli: ^7.7.0 => 7.7.5
@babel/core: ^7.7.2 => 7.7.5
@babel/eslint-plugin-development: ^1.0.1 => 1.0.1
@babel/plugin-proposal-class-properties: ^7.7.0 => 7.7.4
@babel/plugin-proposal-export-namespace-from: ^7.5.2 => 7.7.4
@babel/plugin-proposal-nullish-coalescing-operator: ^7.4.4 => 7.7.4
@babel/plugin-proposal-numeric-separator: ^7.2.0 => 7.7.4
@babel/plugin-proposal-object-rest-spread: ^7.7.4 => 7.7.4
@babel/plugin-proposal-optional-chaining: ^7.6.0 => 7.7.5
@babel/plugin-transform-flow-strip-types: ^7.7.4 => 7.7.4
@babel/plugin-transform-for-of: ^7.7.4 => 7.7.4
@babel/plugin-transform-modules-commonjs: ^7.7.0 => 7.7.5
@babel/plugin-transform-runtime: ^7.6.2 => 7.7.6
@babel/preset-env: ^7.7.1 => 7.7.6
@babel/preset-flow: ^7.0.0 => 7.7.4
@babel/register: ^7.7.0 => 7.7.4
@babel/runtime: ^7.7.2 => 7.7.6
babel-eslint: ^11.0.0-beta.2 => 11.0.0-beta.2
babel-jest: ^24.9.0 => 24.9.0
babel-plugin-transform-charcodes: ^0.2.0 => 0.2.0
eslint: ^6.0.1 => 6.7.2
eslint-config-babel: ^9.0.0 => 9.0.0
gulp-babel: ^8.0.0 => 8.0.0
jest: ^24.9.0 => 24.9.0
lerna: ^3.19.0 => 3.19.0
rollup-plugin-babel: ^4.0.0 => 4.3.3

How you are using Babel: API

Possible Solution

It seems suspect to me to add the reference to a binding in the references own scope here

Additional context/Screenshots

Output of test linked above:

scope › binding paths › reference paths after crawl

expect(received).toHaveLength(expected)

Expected length: 1
Received length: 0
Received array: []

276 | path.scope.crawl();
277 | const referencePaths = path.scope.bindings.a.referencePaths;
> 278 | expect(referencePaths).toHaveLength(1);
| ^
279 | });
280 | });
281 |

at Object.<anonymous> (packages/babel-traverse/test/scope.js:278:30)

Issue 2:
Copying from babel/notes#19, many other issues linked there

Issue

The order that you specify plugins/presets in a config matters in Babel. User's shouldn't have to change their config to make it compile correctly (or get a weird error message about how a plugin isn't enabled when it's just in the "wrong" order).

From the https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy repo

Simpler example: if you specify a plugin only modifies ES2015 classes and you make that run after the plugin that transforms classes, then it won't run at all because at that point the classes will have been transformed into a function already.

{ plugins: ["modify-es2015-classes", "transform-es2015-classes"] } // works

{ plugins: ["transform-es2015-classes", "modify-es2015-classes"] } // fails

How can we make Babel automatically know how to order the plugins for the user, or at least give a clearer error message? Or how can we let the user opt-in to a specific ordering?

Duplicate plugins in a config

What if a user includes "es2015", "env", "latest", and "transform-arrow-functions"? That includes the arrow function transform 4 times! It would be nice to have a nice error message to explain that there's duplicate functionality or that you have a plugin that isn't already on.

Possible Solution: Capabilities Discovery

Plugins provide a function to state the capabilities it provides and which it needs.

This includes both syntax and built-ins

This is important to fix plugin ordering automatically in Babel itself. If the classes plugin transpiles classes and decorators run over classes, then with this information Babel will know to make decorators run first.

This could mean exposing a method in plugins called hasCapability('capability-here')

// minify-plugin.js
// return true or false based on if the target environment natively supports arrows
// or if the plugin that compiles arrow functions is enabled
if (hasCapability('es2015-arrow-function') {
// output an arrow function
} else {
// output a function expression
}

Other ideas

Allow plugins to have multiple priorities (and a lower priority can error out to signal that a plugin should move before or after)

Explicit ordering of before/after by users (sounds like passPerPreset) (#3793, #3281).

Testing

A test can be to randomly sort the plugins in preset-env/es2015/presets and check if the output is the same. Also tests for specific issues we know about (decorators and class properties)

Other Benefits

Users shouldn't need to care about what order plugins are specified

This would also provide better error messages: "your native environment doesn't support this syntax and you haven't added the correct plugin to transform it: here are some options and how to install"

Minify can also take advantage of this by having multiple outputs based on the target environment (output arrow functions (ES6) if available)