feat(parser): support top-level await detection in unambiguous mode
Add support for detecting ES modules via top-level await in unambiguous
parsing mode, conforming with Babel's behavior.
In unambiguous mode, when `await <expr>` is encountered at the top level
and the expression is unambiguous (not an ambiguous token), the file is
detected as an ES module.
Ambiguous tokens after `await` that don't definitively indicate ESM:
- `+`, `-` (unary vs binary operators)
- `(`, `[` (call/member vs grouped expression)
- `/` (regex vs division)
- `%` (modulo operator)
- `;` (semicolon - empty await)
- Template literals
- `of`, `using` (contextual keywords)
- Newlines (ASI boundary)
Also fixes Script mode parsing where `await` at top level should always
be an identifier (not a keyword), preventing `await / 0 / u` from being
incorrectly parsed as `await /0/u` (await + regex).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
perf(lexer): compute identifier hash incrementally during lexing
Add incremental hashing to the lexer so identifier hashes are computed
while scanning bytes, avoiding a second pass over the data.
- Add `identifier_hasher` field to `Lexer` and `LexerCheckpoint`
- Add `hash_identifier: true` variant to `byte_search!` macro
- Update `identifier_name_handler` to hash first byte and use hashing variant
- Handle unicode/escape cold paths with appropriate hashing
- Update `get_ident()` to use `Ident::new_with_hash()` with precomputed hash
- Re-export `IncrementalIdentHasher` from `oxc_span`
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fix(oxc_str): use u64 for hash state to support 32-bit platforms
The IncrementalIdentHasher was using `usize` which is 32-bit on wasm32,
causing overflow errors:
- The constant K doesn't fit in 32 bits
- The `>> 32` shift would overflow on 32-bit
Changed to use explicit `u64` for consistent behavior across platforms.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>