Skip to content

Commit 00e4477

Browse files
committed
fix(parser): update ident reference check in jsx (#13819)
https://github.com/microsoft/typescript/blob/1c4083f4edc71cb1744a62013732e3c95d05a035/src/compiler/utilities.ts#L6189-L6192 This directly copies TS's implementation - non-ascii characters are always references (vs intrinsic elements) closes #13817
1 parent bdc33f1 commit 00e4477

File tree

1 file changed

+12
-10
lines changed
  • crates/oxc_parser/src/jsx

1 file changed

+12
-10
lines changed

crates/oxc_parser/src/jsx/mod.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,21 @@ impl<'a> ParserImpl<'a> {
149149
return JSXElementName::dummy(self.ast.allocator);
150150
}
151151

152-
// References begin with a capital letter, `_` or `$` e.g. `<Foo>`, `<_foo>`, `<$foo>`.
152+
// Determine if this JSX element name is a reference (component) or an intrinsic element.
153+
// References (components) are:
154+
// - ASCII names that start with uppercase letter, `_` or `$`: `<Foo>`, `<_foo>`, `<$foo>`
155+
// - All non-ASCII names (e.g., Unicode identifiers like `<테스트>`)
156+
// - Names without hyphens (hyphenated names like `<my-element>` are custom elements)
153157
// https://babeljs.io/repl#?code_lz=DwMQ9mAED0B8DcAoYAzCMHIPpqnJwAJLhkkA&presets=react
154-
// The identifier has already been checked to be valid, so when first char is ASCII, it can only
155-
// be `a-z`, `A-Z`, `_` or `$`. But compiler doesn't know that, so we can help it create faster
156-
// code by taking that invariant into account.
157-
// `b < b'a'` matches `A-Z`, `_` and `$`.
158-
// Use a fast path for common case of ASCII characters, to avoid the more expensive
159-
// `char::is_uppercase` in most cases.
158+
//
159+
// The identifier has already been validated by the parser, so for ASCII characters
160+
// we know it can only be `a-z`, `A-Z`, `_` or `$`.
161+
// Use a fast path for ASCII to avoid expensive Unicode operations in the common case.
160162
let name = identifier.name.as_str();
161163
let is_reference = match name.as_bytes()[0] {
162-
b if b.is_ascii() => b < b'a',
163-
_ => name.chars().next().unwrap().is_uppercase(),
164-
};
164+
b if b.is_ascii() => !b.is_ascii_lowercase(), // Matches A-Z, _, $
165+
_ => true, // Non-ASCII characters are always treated as references
166+
} && !name.contains('-'); // Exclude hyphenated custom elements
165167

166168
if is_reference {
167169
let identifier = self.ast.alloc_identifier_reference(identifier.span, identifier.name);

0 commit comments

Comments
 (0)