From 097f551e1b84e926420d1c2ddc712c49cea6fe80 Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Fri, 30 Aug 2024 14:17:34 +0100 Subject: [PATCH] refactor(ast): optimize `JSXIdentifier::is_reference` --- crates/oxc_ast/src/ast_impl/jsx.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/oxc_ast/src/ast_impl/jsx.rs b/crates/oxc_ast/src/ast_impl/jsx.rs index c9069cd07f4feb..972a98b6b5a307 100644 --- a/crates/oxc_ast/src/ast_impl/jsx.rs +++ b/crates/oxc_ast/src/ast_impl/jsx.rs @@ -24,8 +24,20 @@ impl<'a> JSXIdentifier<'a> { /// /// 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 { - self.name.chars().next().map_or(false, |c| c.is_uppercase() || c == '_' || c == '$') + // 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(), + } } }