mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Support JsxMemberExpression
This commit is contained in:
@@ -1760,7 +1760,27 @@ function lowerJsxElementName(
|
||||
): Place {
|
||||
const exprNode = exprPath.node;
|
||||
const exprLoc = exprNode.loc ?? GeneratedSource;
|
||||
if (!exprPath.isJSXIdentifier()) {
|
||||
if (exprPath.isJSXIdentifier()) {
|
||||
const tag: string = exprPath.node.name;
|
||||
if (tag.match(/^[A-Z]/)) {
|
||||
return lowerIdentifier(builder, exprPath);
|
||||
} else {
|
||||
const place: Place = buildTemporaryPlace(builder, exprLoc);
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
value: {
|
||||
kind: "Primitive",
|
||||
value: tag,
|
||||
loc: exprLoc,
|
||||
},
|
||||
loc: exprLoc,
|
||||
lvalue: { ...place },
|
||||
});
|
||||
return place;
|
||||
}
|
||||
} else if (exprPath.isJSXMemberExpression()) {
|
||||
return lowerJsxMemberExpression(builder, exprPath);
|
||||
} else {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerJsxElementName) Handle ${exprPath.type} tags`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
@@ -1779,23 +1799,40 @@ function lowerJsxElementName(
|
||||
});
|
||||
return { ...place };
|
||||
}
|
||||
const tag: string = exprPath.node.name;
|
||||
if (tag.match(/^[A-Z]/)) {
|
||||
return lowerIdentifier(builder, exprPath);
|
||||
}
|
||||
|
||||
function lowerJsxMemberExpression(
|
||||
builder: HIRBuilder,
|
||||
exprPath: NodePath<t.JSXMemberExpression>
|
||||
): Place {
|
||||
const loc = exprPath.node.loc ?? GeneratedSource;
|
||||
const object = exprPath.get("object");
|
||||
let objectPlace: Place;
|
||||
if (object.isJSXMemberExpression()) {
|
||||
objectPlace = lowerJsxMemberExpression(builder, object);
|
||||
} else {
|
||||
const place: Place = buildTemporaryPlace(builder, exprLoc);
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
value: {
|
||||
kind: "Primitive",
|
||||
value: tag,
|
||||
loc: exprLoc,
|
||||
},
|
||||
loc: exprLoc,
|
||||
lvalue: { ...place },
|
||||
});
|
||||
return place;
|
||||
invariant(
|
||||
object.isJSXIdentifier(),
|
||||
"TypeScript refinement fail: expected 'JsxIdentifier', got '%s'",
|
||||
object.node.type
|
||||
);
|
||||
objectPlace = lowerIdentifier(builder, object);
|
||||
}
|
||||
const place = buildTemporaryPlace(builder, loc);
|
||||
const property = exprPath.get("property").node.name;
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: { ...place },
|
||||
value: {
|
||||
kind: "PropertyLoad",
|
||||
object: objectPlace,
|
||||
property,
|
||||
optional: false,
|
||||
loc,
|
||||
},
|
||||
loc,
|
||||
});
|
||||
return place;
|
||||
}
|
||||
|
||||
function lowerJsxElement(
|
||||
|
||||
@@ -651,29 +651,26 @@ function codegenInstructionValue(
|
||||
}
|
||||
}
|
||||
let tagValue = codegenPlace(cx, instrValue.tag);
|
||||
let tag: string;
|
||||
let tag: t.JSXIdentifier | t.JSXMemberExpression;
|
||||
if (tagValue.type === "Identifier") {
|
||||
tag = tagValue.name;
|
||||
tag = t.jsxIdentifier(tagValue.name);
|
||||
} else if (tagValue.type === "MemberExpression") {
|
||||
tag = convertMemberExpressionToJsx(tagValue);
|
||||
} else {
|
||||
invariant(
|
||||
tagValue.type === "StringLiteral",
|
||||
"Expected JSX tag to be an identifier or string"
|
||||
"Expected JSX tag to be an identifier or string, got '%s'",
|
||||
tagValue.type
|
||||
);
|
||||
tag = tagValue.value;
|
||||
tag = t.jsxIdentifier(tagValue.value);
|
||||
}
|
||||
const children =
|
||||
instrValue.children !== null
|
||||
? instrValue.children.map((child) => codegenJsxElement(cx, child))
|
||||
: [];
|
||||
value = t.jsxElement(
|
||||
t.jsxOpeningElement(
|
||||
t.jsxIdentifier(tag),
|
||||
attributes,
|
||||
instrValue.children === null
|
||||
),
|
||||
instrValue.children !== null
|
||||
? t.jsxClosingElement(t.jsxIdentifier(tag))
|
||||
: null,
|
||||
t.jsxOpeningElement(tag, attributes, instrValue.children === null),
|
||||
instrValue.children !== null ? t.jsxClosingElement(tag) : null,
|
||||
children,
|
||||
instrValue.children === null
|
||||
);
|
||||
@@ -896,6 +893,26 @@ function codegenJsxElement(
|
||||
}
|
||||
}
|
||||
|
||||
function convertMemberExpressionToJsx(
|
||||
expr: t.MemberExpression
|
||||
): t.JSXMemberExpression {
|
||||
invariant(
|
||||
expr.property.type === "Identifier",
|
||||
"Expected JSX member expression property to be a string"
|
||||
);
|
||||
const property = t.jsxIdentifier(expr.property.name);
|
||||
if (expr.object.type === "Identifier") {
|
||||
return t.jsxMemberExpression(t.jsxIdentifier(expr.object.name), property);
|
||||
} else {
|
||||
invariant(
|
||||
expr.object.type === "MemberExpression",
|
||||
"Expected JSX member expression to be an identifier or nested member expression"
|
||||
);
|
||||
const object = convertMemberExpressionToJsx(expr.object);
|
||||
return t.jsxMemberExpression(object, property);
|
||||
}
|
||||
}
|
||||
|
||||
function codegenLValue(
|
||||
pattern: Pattern | Place | SpreadPattern
|
||||
): t.ArrayPattern | t.ObjectPattern | t.RestElement | t.Identifier {
|
||||
|
||||
@@ -166,15 +166,6 @@ let moduleLocal = false;
|
||||
20 |
|
||||
21 | const j = function bar([quz, qux], ...args) {};
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerJsxElementName) Handle JSXMemberExpression tags
|
||||
17 | <Button haha={1}></Button>;
|
||||
18 | <Button>{/** empty */}</Button>;
|
||||
> 19 | <DesignSystem.Button />;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
20 |
|
||||
21 | const j = function bar([quz, qux], ...args) {};
|
||||
22 |
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lower) Handle RestElement params
|
||||
19 | <DesignSystem.Button />;
|
||||
20 |
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
return (
|
||||
<Sathya.Codes.Forget>
|
||||
<Foo.Bar.Baz />
|
||||
</Sathya.Codes.Forget>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <Foo.Bar.Baz></Foo.Bar.Baz>;
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = <Sathya.Codes.Forget>{t0}</Sathya.Codes.Forget>;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
function Component(props) {
|
||||
return (
|
||||
<Sathya.Codes.Forget>
|
||||
<Foo.Bar.Baz />
|
||||
</Sathya.Codes.Forget>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user