mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[hir syntax] Handle TemplateLiteral syntax
This commit is contained in:
@@ -1420,6 +1420,40 @@ function lowerExpression(
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "TemplateLiteral": {
|
||||
const expr = exprPath as NodePath<t.TemplateLiteral>;
|
||||
const subexprs = expr.get("expressions");
|
||||
const quasis = expr.get("quasis");
|
||||
|
||||
if (subexprs.length !== quasis.length - 1) {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerAssignment) Unexpected quasi and subexpression lengths in TemplateLiteral.`,
|
||||
severity: ErrorSeverity.InvalidInput,
|
||||
nodePath: exprPath,
|
||||
});
|
||||
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
|
||||
}
|
||||
|
||||
if (subexprs.some((e) => !e.isExpression())) {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerAssignment) Handle TSType in TemplateLiteral.`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
nodePath: exprPath,
|
||||
});
|
||||
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
|
||||
}
|
||||
|
||||
const subexprPlaces = subexprs.map((e) =>
|
||||
lowerExpressionToPlace(builder, e as NodePath<t.Expression>)
|
||||
);
|
||||
|
||||
return {
|
||||
kind: "TemplateLiteral",
|
||||
subexprs: subexprPlaces,
|
||||
quasis: expr.get("quasis").map((q) => q.node.value),
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "UnaryExpression": {
|
||||
let expr = exprPath as NodePath<t.UnaryExpression>;
|
||||
return {
|
||||
|
||||
@@ -446,7 +446,11 @@ export type InstructionData =
|
||||
tag: Place;
|
||||
value: { raw: string; cooked?: string };
|
||||
}
|
||||
|
||||
| {
|
||||
kind: "TemplateLiteral";
|
||||
subexprs: Array<Place>;
|
||||
quasis: Array<{ raw: string; cooked?: string }>;
|
||||
}
|
||||
/**
|
||||
* Catch-all for statements such as type imports, nested class declarations, etc
|
||||
* which are not directly represented, but included for completeness and to allow
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
import generate from "@babel/generator";
|
||||
import invariant from "invariant";
|
||||
import DisjointSet from "../Utils/DisjointSet";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import {
|
||||
@@ -370,6 +371,19 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
)} : ${printInstructionValue(instrValue.alternate)}`;
|
||||
break;
|
||||
}
|
||||
case "TemplateLiteral": {
|
||||
value = "`";
|
||||
invariant(
|
||||
instrValue.subexprs.length === instrValue.quasis.length - 1,
|
||||
"Bad assumption about quasi length."
|
||||
);
|
||||
for (let i = 0; i < instrValue.subexprs.length; i++) {
|
||||
value += instrValue.quasis[i].raw;
|
||||
value += `\${${printPlace(instrValue.subexprs[i])}}`;
|
||||
}
|
||||
value += instrValue.quasis.at(-1)!.raw + "`";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
instrValue,
|
||||
|
||||
@@ -127,6 +127,10 @@ export function* eachInstructionValueOperand(
|
||||
yield instrValue.value;
|
||||
break;
|
||||
}
|
||||
case "TemplateLiteral": {
|
||||
yield* instrValue.subexprs;
|
||||
break;
|
||||
}
|
||||
case "UnsupportedNode":
|
||||
case "Primitive":
|
||||
case "JSXText": {
|
||||
@@ -251,6 +255,10 @@ export function mapInstructionOperands(
|
||||
instrValue.value = fn(instrValue.value);
|
||||
break;
|
||||
}
|
||||
case "TemplateLiteral": {
|
||||
instrValue.subexprs = instrValue.subexprs.map(fn);
|
||||
break;
|
||||
}
|
||||
case "UnsupportedNode":
|
||||
case "Primitive":
|
||||
case "JSXText": {
|
||||
|
||||
@@ -599,6 +599,13 @@ function inferBlock(env: Environment, block: BasicBlock) {
|
||||
effectKind = Effect.Mutate;
|
||||
break;
|
||||
}
|
||||
case "TemplateLiteral": {
|
||||
// template literal (with no tag function) always produces
|
||||
// an immutable string
|
||||
valueKind = ValueKind.Immutable;
|
||||
effectKind = Effect.Read;
|
||||
break;
|
||||
}
|
||||
case "JSXText":
|
||||
case "Primitive": {
|
||||
valueKind = ValueKind.Immutable;
|
||||
|
||||
@@ -415,6 +415,7 @@ const createTaggedTemplateExpression = withLoc(t.taggedTemplateExpression);
|
||||
const createLogicalExpression = withLoc(t.logicalExpression);
|
||||
const createSequenceExpression = withLoc(t.sequenceExpression);
|
||||
const createConditionalExpression = withLoc(t.conditionalExpression);
|
||||
const createTemplateLiteral = withLoc(t.templateLiteral);
|
||||
|
||||
type Temporaries = Map<IdentifierId, t.Expression>;
|
||||
|
||||
@@ -751,6 +752,14 @@ function codegenInstructionValue(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "TemplateLiteral": {
|
||||
value = createTemplateLiteral(
|
||||
instrValue.loc,
|
||||
instrValue.quasis.map((q) => t.templateElement(q)),
|
||||
instrValue.subexprs.map((p) => codegenPlace(cx, p))
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
instrValue,
|
||||
|
||||
@@ -174,6 +174,7 @@ function mayAllocate(value: InstructionValue): boolean {
|
||||
case "ComputedLoad":
|
||||
case "JSXText":
|
||||
case "UnaryExpression":
|
||||
case "TemplateLiteral":
|
||||
case "Primitive": {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function componentA(props) {
|
||||
let t = `hello ${props.a}, ${props.b}!`;
|
||||
t += ``;
|
||||
return t;
|
||||
}
|
||||
|
||||
function componentB(props) {
|
||||
let x = useFoo(`hello ${props.a}`);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function componentA(props) {
|
||||
const t = `hello ${props.a}, ${props.b}!`;
|
||||
const t$0 = t + ``;
|
||||
return t$0;
|
||||
}
|
||||
|
||||
function componentB(props) {
|
||||
const $ = React.useMemoCache();
|
||||
const t0 = `hello ${props.a}`;
|
||||
const c_0 = $[0] !== t0;
|
||||
let x;
|
||||
if (c_0) {
|
||||
x = useFoo(t0);
|
||||
$[0] = t0;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function componentA(props) {
|
||||
let t = `hello ${props.a}, ${props.b}!`;
|
||||
t += ``;
|
||||
return t;
|
||||
}
|
||||
|
||||
function componentB(props) {
|
||||
let x = useFoo(`hello ${props.a}`);
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user