packages/babel-core/src/transformation/block-hoist-plugin.js
// @flow
import sortBy from "lodash/sortBy";
import loadConfig, { type Plugin } from "../config";
let LOADED_PLUGIN: Plugin | void;
export default function loadBlockHoistPlugin(): Plugin {
if (!LOADED_PLUGIN) {
// Lazy-init the internal plugin to remove the init-time circular
// dependency between plugins being passed @babel/core's export object,
// which loads this file, and this 'loadConfig' loading plugins.
const config = loadConfig.sync({
babelrc: false,
configFile: false,
plugins: [blockHoistPlugin],
});
LOADED_PLUGIN = config ? config.passes[0][0] : undefined;
if (!LOADED_PLUGIN) throw new Error("Assertion failure");
}
return LOADED_PLUGIN;
}
const blockHoistPlugin = {
/**
* [Please add a description.]
*
* Priority:
*
* - 0 We want this to be at the **very** bottom
* - 1 Default node position
* - 2 Priority over normal nodes
* - 3 We want this to be at the **very** top
* - 4 Reserved for the helpers used to implement module imports.
*/
name: "internal.blockHoist",
visitor: {
Block: {
exit({ node }) {
let hasChange = false;
for (let i = 0; i < node.body.length; i++) {
const bodyNode = node.body[i];
if (bodyNode?._blockHoist != null) {
hasChange = true;
break;
}
}
if (!hasChange) return;
node.body = sortBy(node.body, function (bodyNode) {
let priority = bodyNode?._blockHoist;
if (priority == null) priority = 1;
if (priority === true) priority = 2;
// Higher priorities should move toward the top.
return -1 * priority;
});
},
},
},
};