14
Identifier,
15
IdentifierId,
16
InstructionKind,
17
+ JsxAttribute,
18
Pattern,
19
Place,
20
ReactiveBlock,
567
const createSequenceExpression = withLoc(t.sequenceExpression);
568
const createConditionalExpression = withLoc(t.conditionalExpression);
569
const createTemplateLiteral = withLoc(t.templateLiteral);
570
+const createJsxNamespacedName = withLoc(t.jsxNamespacedName);
571
+const createJsxElement = withLoc(t.jsxElement);
572
+const createJsxAttribute = withLoc(t.jsxAttribute);
573
+const createJsxIdentifier = withLoc(t.jsxIdentifier);
574
+const createJsxExpressionContainer = withLoc(t.jsxExpressionContainer);
575
+const createJsxText = withLoc(t.jsxText);
576
+const createJsxClosingElement = withLoc(t.jsxClosingElement);
577
+const createStringLiteral = withLoc(t.stringLiteral);
578
579
type Temporaries = Map<IdentifierId, t.Expression>;
580
651
break;
652
}
653
case "Primitive": {
645
- value = codegenValue(cx, instrValue.value);
654
+ value = codegenValue(cx, instrValue.loc, instrValue.value);
655
break;
656
}
657
case "CallExpression": {
721
break;
722
}
723
case "JSXText": {
715
- value = t.stringLiteral(instrValue.value);
724
+ value = createStringLiteral(instrValue.loc, instrValue.value);
725
break;
726
}
727
case "JsxExpression": {
728
const attributes: Array<t.JSXAttribute | t.JSXSpreadAttribute> = [];
729
for (const attribute of instrValue.props) {
721
- switch (attribute.kind) {
722
- case "JsxAttribute": {
723
- let propName: t.JSXIdentifier | t.JSXNamespacedName;
724
- if (attribute.name.indexOf(":") === -1) {
725
- propName = t.jsxIdentifier(attribute.name);
726
- } else {
727
- const [namespace, name] = attribute.name.split(":", 2);
728
- propName = t.jsxNamespacedName(
729
- t.jsxIdentifier(namespace),
730
- t.jsxIdentifier(name)
731
- );
732
- }
733
- attributes.push(
734
- t.jsxAttribute(
735
- propName,
736
- t.jsxExpressionContainer(codegenPlace(cx, attribute.place))
737
- )
738
- );
739
- break;
740
- }
741
- case "JsxSpreadAttribute": {
742
- attributes.push(
743
- t.jsxSpreadAttribute(codegenPlace(cx, attribute.argument))
744
- );
745
- break;
746
- }
747
- default: {
748
- assertExhaustive(
749
- attribute,
750
- `Unexpected attribute kind '${(attribute as any).kind}'`
751
- );
752
- }
753
- }
730
+ attributes.push(codegenJsxAttribute(cx, attribute));
731
}
732
let tagValue = codegenPlace(cx, instrValue.tag);
733
let tag: t.JSXIdentifier | t.JSXNamespacedName | t.JSXMemberExpression;
734
if (tagValue.type === "Identifier") {
758
- if (tagValue.name.indexOf(":") >= 0) {
759
- const [namespace, name] = tagValue.name.split(":", 2);
760
- tag = t.jsxNamespacedName(
761
- t.jsxIdentifier(namespace),
762
- t.jsxIdentifier(name)
763
- );
764
- } else {
765
- tag = t.jsxIdentifier(tagValue.name);
766
- }
735
+ tag = createJsxIdentifier(instrValue.tag.loc, tagValue.name);
736
} else if (tagValue.type === "MemberExpression") {
737
tag = convertMemberExpressionToJsx(tagValue);
738
} else {
741
"Expected JSX tag to be an identifier or string, got '%s'",
742
tagValue.type
743
);
775
- tag = t.jsxIdentifier(tagValue.value);
744
+ if (tagValue.value.indexOf(":") >= 0) {
745
+ const [namespace, name] = tagValue.value.split(":", 2);
746
+ tag = createJsxNamespacedName(
747
+ instrValue.tag.loc,
748
+ createJsxIdentifier(instrValue.tag.loc, namespace),
749
+ createJsxIdentifier(instrValue.tag.loc, name)
750
+ );
751
+ } else {
752
+ tag = createJsxIdentifier(instrValue.loc, tagValue.value);
753
+ }
754
}
755
const children =
756
instrValue.children !== null
757
? instrValue.children.map((child) => codegenJsxElement(cx, child))
758
: [];
781
- value = t.jsxElement(
759
+ value = createJsxElement(
760
+ instrValue.loc,
761
t.jsxOpeningElement(tag, attributes, instrValue.children === null),
783
- instrValue.children !== null ? t.jsxClosingElement(tag) : null,
762
+ instrValue.children !== null
763
+ ? createJsxClosingElement(instrValue.tag.loc, tag)
764
+ : null,
765
children,
766
instrValue.children === null
767
);
988
return value;
989
}
990
991
+function codegenJsxAttribute(
992
+ cx: Context,
993
+ attribute: JsxAttribute
994
+): t.JSXAttribute | t.JSXSpreadAttribute {
995
+ switch (attribute.kind) {
996
+ case "JsxAttribute": {
997
+ let propName: t.JSXIdentifier | t.JSXNamespacedName;
998
+ if (attribute.name.indexOf(":") === -1) {
999
+ propName = createJsxIdentifier(attribute.place.loc, attribute.name);
1000
+ } else {
1001
+ const [namespace, name] = attribute.name.split(":", 2);
1002
+ propName = createJsxNamespacedName(
1003
+ attribute.place.loc,
1004
+ createJsxIdentifier(attribute.place.loc, namespace),
1005
+ createJsxIdentifier(attribute.place.loc, name)
1006
+ );
1007
+ }
1008
+ const innerValue = codegenPlace(cx, attribute.place);
1009
+ let value;
1010
+ switch (innerValue.type) {
1011
+ case "StringLiteral":
1012
+ case "JSXElement":
1013
+ case "JSXFragment": {
1014
+ value = innerValue;
1015
+ break;
1016
+ }
1017
+ default: {
1018
+ value = createJsxExpressionContainer(attribute.place.loc, innerValue);
1019
+ break;
1020
+ }
1021
+ }
1022
+ return createJsxAttribute(attribute.place.loc, propName, value);
1023
+ }
1024
+ case "JsxSpreadAttribute": {
1025
+ return t.jsxSpreadAttribute(codegenPlace(cx, attribute.argument));
1026
+ }
1027
+ default: {
1028
+ assertExhaustive(
1029
+ attribute,
1030
+ `Unexpected attribute kind '${(attribute as any).kind}'`
1031
+ );
1032
+ }
1033
+ }
1034
+}
1035
+
1036
function codegenJsxElement(
1037
cx: Context,
1038
place: Place
1045
const value = codegenPlace(cx, place);
1046
switch (value.type) {
1047
case "StringLiteral": {
1022
- return t.jsxText(value.value);
1048
+ return createJsxText(place.loc, value.value);
1049
}
1050
case "JSXElement":
1051
case "JSXFragment": {
1052
return value;
1053
}
1054
default: {
1029
- return t.jsxExpressionContainer(value);
1055
+ return createJsxExpressionContainer(place.loc, value);
1056
}
1057
}
1058
}
1119
1120
function codegenValue(
1121
cx: Context,
1122
+ loc: SourceLocation,
1123
value: boolean | number | string | null | undefined
1124
): t.Expression {
1125
if (typeof value === "number") {
1127
} else if (typeof value === "boolean") {
1128
return t.booleanLiteral(value);
1129
} else if (typeof value === "string") {
1103
- return t.stringLiteral(value);
1130
+ return createStringLiteral(loc, value);
1131
} else if (value === null) {
1132
return t.nullLiteral();
1133
} else if (value === undefined) {
1153
if (tmp != null) {
1154
return tmp;
1155
}
1129
- return convertIdentifier(place.identifier);
1156
+ const identifier = convertIdentifier(place.identifier);
1157
+ identifier.loc = place.loc as any;
1158
+ return identifier;
1159
}
1160
1161
function convertIdentifier(identifier: Identifier): t.Identifier {