Cleanup template-literals transform (#5748)

Avoid `Array#shift`s and prefer `const`s when possible.
This commit is contained in:
Justin Ridgewell 2017-05-19 14:57:15 -04:00 committed by Henry Zhu
parent a52d34023c
commit 09229db794

View File

@ -1,82 +1,70 @@
export default function ({ types: t }) {
function isString(node) {
return t.isLiteral(node) && typeof node.value === "string";
}
function buildBinaryExpression(left, right) {
return t.binaryExpression("+", left, right);
}
return {
visitor: {
TaggedTemplateExpression(path, state) {
const { node } = path;
const quasi = node.quasi;
let args = [];
const { quasi } = node;
let strings = [];
let raw = [];
const strings = [];
const raws = [];
for (const elem of (quasi.quasis: Array)) {
const value = elem.value.cooked == null
const { raw, cooked } = elem.value;
const value = cooked == null
? path.scope.buildUndefinedNode()
: t.stringLiteral(elem.value.cooked);
strings.push(value);
raw.push(t.stringLiteral(elem.value.raw));
}
: t.stringLiteral(cooked);
strings = t.arrayExpression(strings);
raw = t.arrayExpression(raw);
strings.push(value);
raws.push(t.stringLiteral(raw));
}
let templateName = "taggedTemplateLiteral";
if (state.opts.loose) templateName += "Loose";
const templateObject = state.file.addTemplateObject(templateName, strings, raw);
args.push(templateObject);
const templateObject = state.file.addTemplateObject(
templateName,
t.arrayExpression(strings),
t.arrayExpression(raws)
);
args = args.concat(quasi.expressions);
const args = [templateObject].concat(quasi.expressions);
path.replaceWith(t.callExpression(node.tag, args));
},
TemplateLiteral(path, state) {
let nodes: Array<Object> = [];
const nodes = [];
const expressions = path.get("expressions");
let index = 0;
for (const elem of (path.node.quasis: Array)) {
nodes.push(t.stringLiteral(elem.value.cooked));
if (elem.value.cooked) {
nodes.push(t.stringLiteral(elem.value.cooked));
}
const expr = expressions.shift();
if (expr) {
if (index < expressions.length) {
const expr = expressions[index++];
const node = expr.node;
if (state.opts.spec && !expr.isBaseType("string") && !expr.isBaseType("number")) {
nodes.push(t.callExpression(t.identifier("String"), [expr.node]));
} else {
nodes.push(expr.node);
nodes.push(t.callExpression(t.identifier("String"), [node]));
} else if (!t.isStringLiteral(node, { value: "" })) {
nodes.push(node);
}
}
}
// filter out empty string literals
nodes = nodes.filter((n) => !t.isLiteral(n, { value: "" }));
// since `+` is left-to-right associative
// ensure the first node is a string if first/second isn't
if (!isString(nodes[0]) && !isString(nodes[1])) {
if (!t.isStringLiteral(nodes[0]) && !t.isStringLiteral(nodes[1])) {
nodes.unshift(t.stringLiteral(""));
}
if (nodes.length > 1) {
let root = buildBinaryExpression(nodes.shift(), nodes.shift());
for (const node of nodes) {
root = buildBinaryExpression(root, node);
}
path.replaceWith(root);
} else {
path.replaceWith(nodes[0]);
let root = nodes[0];
for (let i = 1; i < nodes.length; i++) {
root = t.binaryExpression("+", root, nodes[i]);
}
path.replaceWith(root);
},
},
};