// @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; }); }, }, }, };