mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
fix(transformer): correct spans for JSX transform (#3549)
Correct spans in output of React JSX transform, so it should produce correct source maps. Have copied which AST nodes have spans and which don't from Babel.
This commit is contained in:
parent
e4d74ac3ee
commit
7982b93fb5
1 changed files with 28 additions and 25 deletions
|
|
@ -429,7 +429,7 @@ enum JSXElementOrFragment<'a, 'b> {
|
||||||
impl<'a, 'b> JSXElementOrFragment<'a, 'b> {
|
impl<'a, 'b> JSXElementOrFragment<'a, 'b> {
|
||||||
fn span(&self) -> Span {
|
fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Self::Element(e) => e.span(),
|
Self::Element(e) => e.span,
|
||||||
Self::Fragment(e) => e.span,
|
Self::Fragment(e) => e.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -693,7 +693,7 @@ impl<'a> ReactJsx<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let callee = self.get_create_element(has_key_after_props_spread, need_jsxs, ctx);
|
let callee = self.get_create_element(has_key_after_props_spread, need_jsxs, ctx);
|
||||||
self.ast().call_expression(SPAN, callee, arguments, false, None)
|
self.ast().call_expression(e.span(), callee, arguments, false, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_element_name(
|
fn transform_element_name(
|
||||||
|
|
@ -704,9 +704,9 @@ impl<'a> ReactJsx<'a> {
|
||||||
match name {
|
match name {
|
||||||
JSXElementName::Identifier(ident) => {
|
JSXElementName::Identifier(ident) => {
|
||||||
if ident.name == "this" {
|
if ident.name == "this" {
|
||||||
self.ast().this_expression(SPAN)
|
self.ast().this_expression(ident.span)
|
||||||
} else if ident.name.chars().next().is_some_and(|c| c.is_ascii_lowercase()) {
|
} else if ident.name.chars().next().is_some_and(|c| c.is_ascii_lowercase()) {
|
||||||
let string = StringLiteral::new(SPAN, ident.name.clone());
|
let string = StringLiteral::new(ident.span, ident.name.clone());
|
||||||
self.ast().literal_string_expression(string)
|
self.ast().literal_string_expression(string)
|
||||||
} else {
|
} else {
|
||||||
let ident = get_read_identifier_reference(ident.span, ident.name.clone(), ctx);
|
let ident = get_read_identifier_reference(ident.span, ident.name.clone(), ctx);
|
||||||
|
|
@ -716,12 +716,12 @@ impl<'a> ReactJsx<'a> {
|
||||||
JSXElementName::MemberExpression(member_expr) => {
|
JSXElementName::MemberExpression(member_expr) => {
|
||||||
self.transform_jsx_member_expression(member_expr, ctx)
|
self.transform_jsx_member_expression(member_expr, ctx)
|
||||||
}
|
}
|
||||||
JSXElementName::NamespacedName(name) => {
|
JSXElementName::NamespacedName(namespaced) => {
|
||||||
if self.options.throw_if_namespace {
|
if self.options.throw_if_namespace {
|
||||||
self.ctx.error(diagnostics::namespace_does_not_support(name.span));
|
self.ctx.error(diagnostics::namespace_does_not_support(namespaced.span));
|
||||||
}
|
}
|
||||||
let name = self.ast().new_atom(&name.to_string());
|
let name = self.ast().new_atom(&namespaced.to_string());
|
||||||
let string_literal = StringLiteral::new(SPAN, name);
|
let string_literal = StringLiteral::new(namespaced.span, name);
|
||||||
self.ast().literal_string_expression(string_literal)
|
self.ast().literal_string_expression(string_literal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -786,7 +786,7 @@ impl<'a> ReactJsx<'a> {
|
||||||
let object = match &expr.object {
|
let object = match &expr.object {
|
||||||
JSXMemberExpressionObject::Identifier(ident) => {
|
JSXMemberExpressionObject::Identifier(ident) => {
|
||||||
if ident.name == "this" {
|
if ident.name == "this" {
|
||||||
self.ast().this_expression(SPAN)
|
self.ast().this_expression(ident.span)
|
||||||
} else {
|
} else {
|
||||||
let ident = get_read_identifier_reference(ident.span, ident.name.clone(), ctx);
|
let ident = get_read_identifier_reference(ident.span, ident.name.clone(), ctx);
|
||||||
self.ast().identifier_reference_expression(ident)
|
self.ast().identifier_reference_expression(ident)
|
||||||
|
|
@ -796,8 +796,8 @@ impl<'a> ReactJsx<'a> {
|
||||||
self.transform_jsx_member_expression(expr, ctx)
|
self.transform_jsx_member_expression(expr, ctx)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let property = IdentifierName::new(SPAN, expr.property.name.clone());
|
let property = IdentifierName::new(expr.property.span, expr.property.name.clone());
|
||||||
self.ast().static_member_expression(SPAN, object, property, false)
|
self.ast().static_member_expression(expr.span, object, property, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_jsx_attribute_item(
|
fn transform_jsx_attribute_item(
|
||||||
|
|
@ -811,8 +811,9 @@ impl<'a> ReactJsx<'a> {
|
||||||
let kind = PropertyKind::Init;
|
let kind = PropertyKind::Init;
|
||||||
let key = self.get_attribute_name(&attr.name);
|
let key = self.get_attribute_name(&attr.name);
|
||||||
let value = self.transform_jsx_attribute_value(attr.value.as_ref(), ctx);
|
let value = self.transform_jsx_attribute_value(attr.value.as_ref(), ctx);
|
||||||
let object_property =
|
let object_property = self
|
||||||
self.ast().object_property(SPAN, kind, key, value, None, false, false, false);
|
.ast()
|
||||||
|
.object_property(attr.span, kind, key, value, None, false, false, false);
|
||||||
let object_property = ObjectPropertyKind::ObjectProperty(object_property);
|
let object_property = ObjectPropertyKind::ObjectProperty(object_property);
|
||||||
properties.push(object_property);
|
properties.push(object_property);
|
||||||
}
|
}
|
||||||
|
|
@ -822,7 +823,7 @@ impl<'a> ReactJsx<'a> {
|
||||||
}
|
}
|
||||||
expr => {
|
expr => {
|
||||||
let argument = self.ast().copy(expr);
|
let argument = self.ast().copy(expr);
|
||||||
let spread_property = self.ast().spread_element(SPAN, argument);
|
let spread_property = self.ast().spread_element(attr.span, argument);
|
||||||
let object_property = ObjectPropertyKind::SpreadProperty(spread_property);
|
let object_property = ObjectPropertyKind::SpreadProperty(spread_property);
|
||||||
properties.push(object_property);
|
properties.push(object_property);
|
||||||
}
|
}
|
||||||
|
|
@ -849,8 +850,8 @@ impl<'a> ReactJsx<'a> {
|
||||||
}
|
}
|
||||||
Some(JSXAttributeValue::ExpressionContainer(c)) => match &c.expression {
|
Some(JSXAttributeValue::ExpressionContainer(c)) => match &c.expression {
|
||||||
e @ match_expression!(JSXExpression) => self.ast().copy(e.to_expression()),
|
e @ match_expression!(JSXExpression) => self.ast().copy(e.to_expression()),
|
||||||
JSXExpression::EmptyExpression(_e) => {
|
JSXExpression::EmptyExpression(e) => {
|
||||||
self.ast().literal_boolean_expression(BooleanLiteral::new(SPAN, true))
|
self.ast().literal_boolean_expression(BooleanLiteral::new(e.span, true))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => self.ast().literal_boolean_expression(BooleanLiteral::new(SPAN, true)),
|
None => self.ast().literal_boolean_expression(BooleanLiteral::new(SPAN, true)),
|
||||||
|
|
@ -863,7 +864,7 @@ impl<'a> ReactJsx<'a> {
|
||||||
ctx: &mut TraverseCtx<'a>,
|
ctx: &mut TraverseCtx<'a>,
|
||||||
) -> Option<Expression<'a>> {
|
) -> Option<Expression<'a>> {
|
||||||
match child {
|
match child {
|
||||||
JSXChild::Text(text) => self.transform_jsx_text(text.value.as_str()),
|
JSXChild::Text(text) => self.transform_jsx_text(text),
|
||||||
JSXChild::ExpressionContainer(e) => match &e.expression {
|
JSXChild::ExpressionContainer(e) => match &e.expression {
|
||||||
e @ match_expression!(JSXExpression) => Some(self.ast().copy(e.to_expression())),
|
e @ match_expression!(JSXExpression) => Some(self.ast().copy(e.to_expression())),
|
||||||
JSXExpression::EmptyExpression(_) => None,
|
JSXExpression::EmptyExpression(_) => None,
|
||||||
|
|
@ -886,23 +887,25 @@ impl<'a> ReactJsx<'a> {
|
||||||
JSXAttributeName::Identifier(ident) => {
|
JSXAttributeName::Identifier(ident) => {
|
||||||
let name = ident.name.clone();
|
let name = ident.name.clone();
|
||||||
if ident.name.contains('-') {
|
if ident.name.contains('-') {
|
||||||
let expr = self.ast().literal_string_expression(StringLiteral::new(SPAN, name));
|
let expr =
|
||||||
|
self.ast().literal_string_expression(StringLiteral::new(ident.span, name));
|
||||||
self.ast().property_key_expression(expr)
|
self.ast().property_key_expression(expr)
|
||||||
} else {
|
} else {
|
||||||
self.ast().property_key_identifier(IdentifierName::new(SPAN, name))
|
self.ast().property_key_identifier(IdentifierName::new(ident.span, name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSXAttributeName::NamespacedName(name) => {
|
JSXAttributeName::NamespacedName(namespaced) => {
|
||||||
let name = self.ast().new_atom(&name.to_string());
|
let name = self.ast().new_atom(&namespaced.to_string());
|
||||||
let expr = self.ast().literal_string_expression(StringLiteral::new(SPAN, name));
|
let expr =
|
||||||
|
self.ast().literal_string_expression(StringLiteral::new(namespaced.span, name));
|
||||||
self.ast().property_key_expression(expr)
|
self.ast().property_key_expression(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_jsx_text(&self, text: &str) -> Option<Expression<'a>> {
|
fn transform_jsx_text(&self, text: &JSXText<'a>) -> Option<Expression<'a>> {
|
||||||
Self::fixup_whitespace_and_decode_entities(text).map(|s| {
|
Self::fixup_whitespace_and_decode_entities(text.value.as_str()).map(|s| {
|
||||||
let s = StringLiteral::new(SPAN, self.ast().new_atom(&s));
|
let s = StringLiteral::new(text.span, self.ast().new_atom(&s));
|
||||||
self.ast().literal_string_expression(s)
|
self.ast().literal_string_expression(s)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue