66 lines
1.7 KiB
JavaScript
66 lines
1.7 KiB
JavaScript
// @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({
|
|
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 && bodyNode._blockHoist != null) {
|
|
hasChange = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasChange) return;
|
|
|
|
node.body = sortBy(node.body, function(bodyNode) {
|
|
let priority = bodyNode && bodyNode._blockHoist;
|
|
if (priority == null) priority = 1;
|
|
if (priority === true) priority = 2;
|
|
|
|
// Higher priorities should move toward the top.
|
|
return -1 * priority;
|
|
});
|
|
},
|
|
},
|
|
},
|
|
};
|