Add support for evaluating String.raw expressions (#5681)
* Add support for evaluating `String.raw` expressions * Dedupe evaluation code for template literal quasis * Check scoping in `String.raw` evaluation This addresses https://github.com/babel/babel/pull/5681#discussion_r114203497 * Ensure that `tag` is a MemberExpression in `String.raw` evaluation This addresses https://github.com/babel/babel/pull/5681#discussion_r114203555 * babel-traverse: Move evaluateQuasis() outside _evaluate()
This commit is contained in:
parent
b6b69c615a
commit
a330cf2b09
@ -89,25 +89,20 @@ function _evaluate(path, state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path.isTemplateLiteral()) {
|
if (path.isTemplateLiteral()) {
|
||||||
let str = "";
|
return evaluateQuasis(path, node.quasis, state);
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
const exprs = path.get("expressions");
|
|
||||||
|
|
||||||
for (const elem of (node.quasis: Array<Object>)) {
|
|
||||||
// not confident, evaluated an expression we don't like
|
|
||||||
if (!state.confident) break;
|
|
||||||
|
|
||||||
// add on cooked element
|
|
||||||
str += elem.value.cooked;
|
|
||||||
|
|
||||||
// add on interpolated expression if it's present
|
|
||||||
const expr = exprs[i++];
|
|
||||||
if (expr) str += String(evaluateCached(expr, state));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.confident) return;
|
if (path.isTaggedTemplateExpression() && path.get("tag").isMemberExpression()) {
|
||||||
return str;
|
const object = path.get("tag.object");
|
||||||
|
const { node: { name } } = object;
|
||||||
|
const property = path.get("tag.property");
|
||||||
|
|
||||||
|
if (
|
||||||
|
object.isIdentifier() && name === "String" && !path.scope.getBinding(name, true) &&
|
||||||
|
property.isIdentifier && property.node.name === "raw"
|
||||||
|
) {
|
||||||
|
return evaluateQuasis(path, node.quasi.quasis, state, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.isConditionalExpression()) {
|
if (path.isConditionalExpression()) {
|
||||||
@ -349,6 +344,28 @@ function _evaluate(path, state) {
|
|||||||
deopt(path, state);
|
deopt(path, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function evaluateQuasis (path, quasis: Array<Object>, state, raw = false) {
|
||||||
|
let str = "";
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
const exprs = path.get("expressions");
|
||||||
|
|
||||||
|
for (const elem of quasis) {
|
||||||
|
// not confident, evaluated an expression we don't like
|
||||||
|
if (!state.confident) break;
|
||||||
|
|
||||||
|
// add on element
|
||||||
|
str += raw ? elem.value.raw : elem.value.cooked;
|
||||||
|
|
||||||
|
// add on interpolated expression if it's present
|
||||||
|
const expr = exprs[i++];
|
||||||
|
if (expr) str += String(evaluateCached(expr, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.confident) return;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk the input `node` and statically evaluate it.
|
* Walk the input `node` and statically evaluate it.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -119,4 +119,16 @@ describe("evaluation", function () {
|
|||||||
assert.strictEqual(eval_undef.deopt.type, "VariableDeclarator");
|
assert.strictEqual(eval_undef.deopt.type, "VariableDeclarator");
|
||||||
assert.strictEqual(eval_undef.deopt.parentPath.node.kind, "let");
|
assert.strictEqual(eval_undef.deopt.parentPath.node.kind, "let");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should work with String.raw", function () {
|
||||||
|
assert.strictEqual(
|
||||||
|
getPath("String.raw`\\d`").get("body")[0].evaluate().value,
|
||||||
|
"\\d"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
getPath("`${String.raw`\\d`}`").get("body")[0].evaluate().value,
|
||||||
|
"\\d"
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user