Skip to content

Commit

Permalink
perf(transformer): React display name transform reduce Atom allocatio…
Browse files Browse the repository at this point in the history
…ns (#3616)

Re-use existing `Atom`s in React Display Name transform rather than writing duplicate strings into the arena.

Also add comments for where our implementation diverges from Babel's (in my opinion, ours is an improvement).
  • Loading branch information
overlookmotel committed Jun 11, 2024
1 parent 8d237c4 commit 3a59294
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 21 deletions.
28 changes: 17 additions & 11 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,17 +810,9 @@ impl<'a> MemberExpression<'a> {

pub fn static_property_name(&self) -> Option<&str> {
match self {
MemberExpression::ComputedMemberExpression(expr) => match &expr.expression {
Expression::StringLiteral(lit) => Some(&lit.value),
Expression::TemplateLiteral(lit) => {
if lit.expressions.is_empty() && lit.quasis.len() == 1 {
Some(&lit.quasis[0].value.raw)
} else {
None
}
}
_ => None,
},
MemberExpression::ComputedMemberExpression(expr) => {
expr.static_property_name().map(|name| name.as_str())
}
MemberExpression::StaticMemberExpression(expr) => Some(expr.property.name.as_str()),
MemberExpression::PrivateFieldExpression(_) => None,
}
Expand Down Expand Up @@ -883,6 +875,20 @@ pub struct ComputedMemberExpression<'a> {
pub optional: bool, // for optional chaining
}

impl<'a> ComputedMemberExpression<'a> {
pub fn static_property_name(&self) -> Option<Atom<'a>> {
match &self.expression {
Expression::StringLiteral(lit) => Some(lit.value.clone()),
Expression::TemplateLiteral(lit)
if lit.expressions.is_empty() && lit.quasis.len() == 1 =>
{
Some(lit.quasis[0].value.raw.clone())
}
_ => None,
}
}
}

/// `MemberExpression[?Yield, ?Await] . IdentifierName`
#[visited_node]
#[derive(Debug, Hash)]
Expand Down
24 changes: 14 additions & 10 deletions crates/oxc_transformer/src/react/display_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,22 @@ impl<'a> ReactDisplayName<'a> {
let name = ctx.find_ancestor(|ancestor| {
match ancestor {
// `foo = React.createClass({})`
Ancestor::AssignmentExpressionRight(assign_expr) => match &assign_expr.left() {
Ancestor::AssignmentExpressionRight(assign_expr) => match assign_expr.left() {
AssignmentTarget::AssignmentTargetIdentifier(ident) => {
FinderRet::Found(ident.name.clone())
}
target => {
if let Some(target) = target.as_member_expression() {
if let Some(name) = target.static_property_name() {
FinderRet::Found(ctx.ast.new_atom(name))
} else {
FinderRet::Stop
}
} else {
FinderRet::Stop
AssignmentTarget::StaticMemberExpression(expr) => {
FinderRet::Found(expr.property.name.clone())
}
// Babel does not handle computed member expressions e.g. `foo["bar"]`,
// so we diverge from Babel here, but that's probably an improvement
AssignmentTarget::ComputedMemberExpression(expr) => {
match expr.static_property_name() {
Some(name) => FinderRet::Found(name),
None => FinderRet::Stop,
}
}
_ => FinderRet::Stop,
},
// `let foo = React.createClass({})`
Ancestor::VariableDeclaratorInit(declarator) => match &declarator.id().kind {
Expand All @@ -62,6 +63,9 @@ impl<'a> ReactDisplayName<'a> {
},
// `{foo: React.createClass({})}`
Ancestor::ObjectPropertyValue(prop) => {
// Babel only handles static identifiers e.g. `{foo: React.createClass({})}`,
// whereas we also handle e.g. `{"foo-bar": React.createClass({})}`,
// so we diverge from Babel here, but that's probably an improvement
if let Some(name) = prop.key().static_name() {
FinderRet::Found(ctx.ast.new_atom(&name))
} else {
Expand Down

0 comments on commit 3a59294

Please sign in to comment.