diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index 0af2d83edb5be..3ffb6e937256a 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -351,12 +351,6 @@ impl<'a> fmt::Display for IdentifierReference<'a> { } } -impl<'a> From> for IdentifierReference<'a> { - fn from(value: JSXIdentifier<'a>) -> Self { - IdentifierReference { span: value.span, name: value.name, reference_id: Cell::default() } - } -} - impl<'a> Hash for BindingIdentifier<'a> { fn hash(&self, state: &mut H) { self.name.hash(state); diff --git a/crates/oxc_ast/src/ast_impl/jsx.rs b/crates/oxc_ast/src/ast_impl/jsx.rs index 972a98b6b5a30..53f53aa6612ef 100644 --- a/crates/oxc_ast/src/ast_impl/jsx.rs +++ b/crates/oxc_ast/src/ast_impl/jsx.rs @@ -19,28 +19,6 @@ impl<'a> fmt::Display for JSXIdentifier<'a> { } } -impl<'a> JSXIdentifier<'a> { - /// Determines whether the given current identifier is a reference. - /// - /// References begin with a capital letter, `_` or `$`. - /// - // `name.chars().next().unwrap()` cannot panic because name is never an empty string. - #[allow(clippy::missing_panics_doc)] - pub fn is_reference(&self) -> bool { - // The identifier has already been checked to be valid, so when first char is ASCII, it can only - // be `a-z`, `A-Z`, `_` or `$`. But compiler doesn't know that, so we can help it create faster - // code by taking that invariant into account. - // `b < b'a'` matches `A-Z`, `_` and `$`. - // Use a fast path for common case of ASCII characters, to avoid the more expensive - // `char::is_uppercase` in most cases. - let name = self.name.as_str(); - match name.as_bytes()[0] { - b if b.is_ascii() => b < b'a', - _ => name.chars().next().unwrap().is_uppercase(), - } - } -} - impl<'a> fmt::Display for JSXNamespacedName<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}:{}", self.namespace.name, self.property.name) diff --git a/crates/oxc_parser/src/jsx/mod.rs b/crates/oxc_parser/src/jsx/mod.rs index 1240dcba3208a..11b7c0f503dbb 100644 --- a/crates/oxc_parser/src/jsx/mod.rs +++ b/crates/oxc_parser/src/jsx/mod.rs @@ -154,8 +154,23 @@ impl<'a> ParserImpl<'a> { .map(JSXElementName::MemberExpression); } - let element_name = if identifier.is_reference() { - JSXElementName::IdentifierReference(self.ast.alloc(identifier.into())) + // References begin with a capital letter, `_` or `$` e.g. ``, `<_foo>`, `<$foo>`. + // https://babeljs.io/repl#?code_lz=DwMQ9mAED0B8DcAoYAzCMHIPpqnJwAJLhkkA&presets=react + // The identifier has already been checked to be valid, so when first char is ASCII, it can only + // be `a-z`, `A-Z`, `_` or `$`. But compiler doesn't know that, so we can help it create faster + // code by taking that invariant into account. + // `b < b'a'` matches `A-Z`, `_` and `$`. + // Use a fast path for common case of ASCII characters, to avoid the more expensive + // `char::is_uppercase` in most cases. + let name = identifier.name.as_str(); + let is_reference = match name.as_bytes()[0] { + b if b.is_ascii() => b < b'a', + _ => name.chars().next().unwrap().is_uppercase(), + }; + + let element_name = if is_reference { + let identifier = self.ast.identifier_reference(identifier.span, identifier.name); + JSXElementName::IdentifierReference(self.ast.alloc(identifier)) } else { JSXElementName::Identifier(self.ast.alloc(identifier)) }; @@ -171,8 +186,8 @@ impl<'a> ParserImpl<'a> { object: JSXIdentifier<'a>, ) -> Result>> { let mut span = span; - let mut object = - JSXMemberExpressionObject::IdentifierReference(self.ast.alloc(object.into())); + let object = self.ast.identifier_reference(object.span, object.name); + let mut object = JSXMemberExpressionObject::IdentifierReference(self.ast.alloc(object)); let mut property = None; while self.eat(Kind::Dot) && !self.at(Kind::Eof) {