Create File class for babel helpers (#10575)
* add test * fix: pass File to helper traverser * pass babel.File to helpers.ensure
This commit is contained in:
parent
748897be07
commit
4bf36e64da
@ -2,6 +2,7 @@ import * as helpers from "@babel/helpers";
|
||||
import generator from "@babel/generator";
|
||||
import template from "@babel/template";
|
||||
import * as t from "@babel/types";
|
||||
import File from "../transformation/file/file";
|
||||
|
||||
// Wrapped to avoid wasting time parsing this when almost no-one uses
|
||||
// build-external-helpers.
|
||||
@ -136,6 +137,7 @@ function buildHelpers(body, namespace, whitelist) {
|
||||
|
||||
const ref = (refs[name] = getHelperReference(name));
|
||||
|
||||
helpers.ensure(name, File);
|
||||
const { nodes } = helpers.get(name, getHelperReference, ref);
|
||||
|
||||
body.push(...nodes);
|
||||
|
||||
@ -174,7 +174,7 @@ export default class File {
|
||||
}
|
||||
|
||||
// make sure that the helper exists
|
||||
helpers.ensure(name);
|
||||
helpers.ensure(name, File);
|
||||
|
||||
const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
|
||||
name,
|
||||
|
||||
@ -13,6 +13,7 @@ function makePath(path) {
|
||||
return parts.reverse().join(".");
|
||||
}
|
||||
|
||||
let fileClass = undefined;
|
||||
/**
|
||||
* Given a file AST for a given helper, get a bunch of metadata about it so that Babel can quickly render
|
||||
* the helper is whatever context it is needed in.
|
||||
@ -29,7 +30,7 @@ function getHelperMetadata(file) {
|
||||
const importPaths = [];
|
||||
const importBindingsReferences = [];
|
||||
|
||||
traverse(file, {
|
||||
const dependencyVisitor = {
|
||||
ImportDeclaration(child) {
|
||||
const name = child.node.source.value;
|
||||
if (!helpers[name]) {
|
||||
@ -72,9 +73,9 @@ function getHelperMetadata(file) {
|
||||
|
||||
child.skip();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
traverse(file, {
|
||||
const referenceVisitor = {
|
||||
Program(path) {
|
||||
const bindings = path.scope.getAllBindings();
|
||||
|
||||
@ -111,7 +112,10 @@ function getHelperMetadata(file) {
|
||||
exportBindingAssignments.push(makePath(child));
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
traverse(file.ast, dependencyVisitor, file.scope);
|
||||
traverse(file.ast, referenceVisitor, file.scope);
|
||||
|
||||
if (!exportPath) throw new Error("Helpers must default-export something.");
|
||||
|
||||
@ -170,7 +174,7 @@ function permuteHelperAST(file, metadata, id, localBindings, getDependency) {
|
||||
toRename[exportName] = id.name;
|
||||
}
|
||||
|
||||
traverse(file, {
|
||||
const visitor = {
|
||||
Program(path) {
|
||||
// We need to compute these in advance because removing nodes would
|
||||
// invalidate the paths.
|
||||
@ -223,7 +227,8 @@ function permuteHelperAST(file, metadata, id, localBindings, getDependency) {
|
||||
// actually doing the traversal.
|
||||
path.stop();
|
||||
},
|
||||
});
|
||||
};
|
||||
traverse(file.ast, visitor, file.scope);
|
||||
}
|
||||
|
||||
const helperData = Object.create(null);
|
||||
@ -238,7 +243,16 @@ function loadHelper(name) {
|
||||
}
|
||||
|
||||
const fn = () => {
|
||||
return t.file(helper.ast());
|
||||
const file = { ast: t.file(helper.ast()) };
|
||||
if (fileClass) {
|
||||
return new fileClass(
|
||||
{
|
||||
filename: `babel-helper://${name}`,
|
||||
},
|
||||
file,
|
||||
);
|
||||
}
|
||||
return file;
|
||||
};
|
||||
|
||||
const metadata = getHelperMetadata(fn());
|
||||
@ -249,7 +263,7 @@ function loadHelper(name) {
|
||||
permuteHelperAST(file, metadata, id, localBindings, getDependency);
|
||||
|
||||
return {
|
||||
nodes: file.program.body,
|
||||
nodes: file.ast.program.body,
|
||||
globals: metadata.globals,
|
||||
};
|
||||
},
|
||||
@ -280,7 +294,12 @@ export function getDependencies(name: string): $ReadOnlyArray<string> {
|
||||
return Array.from(loadHelper(name).dependencies.values());
|
||||
}
|
||||
|
||||
export function ensure(name: string) {
|
||||
export function ensure(name: string, newFileClass?) {
|
||||
if (!fileClass) {
|
||||
// optional fileClass used to wrap helper snippets into File instance,
|
||||
// offering `path.hub` support during traversal
|
||||
fileClass = newFileClass;
|
||||
}
|
||||
loadHelper(name);
|
||||
}
|
||||
|
||||
|
||||
1
packages/babel-helpers/test/fixtures/regression/9496/input.js
vendored
Normal file
1
packages/babel-helpers/test/fixtures/regression/9496/input.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
REPLACE_ME;
|
||||
3
packages/babel-helpers/test/fixtures/regression/9496/options.json
vendored
Normal file
3
packages/babel-helpers/test/fixtures/regression/9496/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": ["./plugin"]
|
||||
}
|
||||
3
packages/babel-helpers/test/fixtures/regression/9496/output.js
vendored
Normal file
3
packages/babel-helpers/test/fixtures/regression/9496/output.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
function _$_9496_main_hub_is_found() {}
|
||||
|
||||
_$_9496_main_hub_is_found;
|
||||
22
packages/babel-helpers/test/fixtures/regression/9496/plugin.js
vendored
Normal file
22
packages/babel-helpers/test/fixtures/regression/9496/plugin.js
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
const defineHelper = require("../../../helpers/define-helper").default;
|
||||
|
||||
const main = defineHelper(__dirname, "main", `
|
||||
export default function helper() {}
|
||||
`);
|
||||
|
||||
module.exports = function() {
|
||||
return {
|
||||
visitor: {
|
||||
Identifier(path) {
|
||||
if (path.node.name !== "REPLACE_ME") {
|
||||
if (path.hub) {
|
||||
path.node.name += "_hub_is_found";
|
||||
}
|
||||
return;
|
||||
}
|
||||
const helper = this.addHelper(main);
|
||||
path.replaceWith(helper);
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
@ -134,6 +134,7 @@ function buildHelper(
|
||||
|
||||
if (!esm) {
|
||||
bindings = [];
|
||||
helpers.ensure(helperName, babel.File);
|
||||
for (const dep of helpers.getDependencies(helperName)) {
|
||||
const id = (dependencies[dep] = t.identifier(t.toIdentifier(dep)));
|
||||
tree.body.push(template.statement.ast`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user