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()) {
|
||||
let str = "";
|
||||
|
||||
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));
|
||||
return evaluateQuasis(path, node.quasis, state);
|
||||
}
|
||||
|
||||
if (!state.confident) return;
|
||||
return str;
|
||||
if (path.isTaggedTemplateExpression() && path.get("tag").isMemberExpression()) {
|
||||
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()) {
|
||||
@ -349,6 +344,28 @@ function _evaluate(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.
|
||||
*
|
||||
|
||||
@ -119,4 +119,16 @@ describe("evaluation", function () {
|
||||
assert.strictEqual(eval_undef.deopt.type, "VariableDeclarator");
|
||||
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