mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
fix(parser): recognize contextual binding names in type lookaheads (#26532)
Recognize `await` and `yield` as binding names when looking ahead for TypeScript function types and index signatures. This allows valid syntax such as `(await: number) => void` and `interface I { [await: string]: unknown }`, while leaving contextual legality to actual parsing.
This commit is contained in:
@@ -410,10 +410,10 @@ impl<'a, C: Config> ParserImpl<'a, C> {
|
||||
}
|
||||
if self.cur_kind().is_modifier_kind() {
|
||||
self.bump_any();
|
||||
if self.cur_kind().is_identifier() {
|
||||
if self.cur_kind().is_binding_identifier() {
|
||||
return true;
|
||||
}
|
||||
} else if !self.cur_kind().is_identifier() {
|
||||
} else if !self.cur_kind().is_binding_identifier() {
|
||||
return false;
|
||||
} else {
|
||||
self.bump_any();
|
||||
|
||||
@@ -128,7 +128,7 @@ impl<'a, C: Config> ParserImpl<'a, C> {
|
||||
self.parse_modifiers(false, false);
|
||||
}
|
||||
let kind = self.cur_kind();
|
||||
if kind.is_identifier() || kind == Kind::This {
|
||||
if kind.is_binding_identifier() || kind == Kind::This {
|
||||
self.bump_any();
|
||||
return true;
|
||||
}
|
||||
@@ -1603,6 +1603,7 @@ impl<'a, C: Config> ParserImpl<'a, C> {
|
||||
|
||||
fn parse_ts_index_signature_name(&mut self) -> TSIndexSignatureName<'a> {
|
||||
let start = self.cur_start();
|
||||
self.check_identifier(self.cur_kind(), self.ctx);
|
||||
let name = self.parse_identifier_name().name;
|
||||
if self.at(Kind::Question) {
|
||||
self.error(diagnostics::index_signature_question_mark(self.cur_token().span()));
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
let fn: (break: number) => void;
|
||||
@@ -0,0 +1,9 @@
|
||||
function* generatorInterface() {
|
||||
interface I { [yield: string]: unknown }
|
||||
}
|
||||
function* generatorClass() {
|
||||
class C { [yield: string]: unknown }
|
||||
}
|
||||
async function asyncClass() {
|
||||
class C { [await: string]: unknown }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
interface I { [public await: string]: unknown }
|
||||
@@ -0,0 +1 @@
|
||||
interface I { [break: string]: unknown }
|
||||
@@ -0,0 +1,24 @@
|
||||
// First parameters take the function-type lookahead; later and generic parameters do not.
|
||||
let firstAwait: (await: number) => void;
|
||||
let laterAwait: (value: number, await: number) => void;
|
||||
let genericAwait: <T>(await: T) => void;
|
||||
let firstYield: (yield: number) => void;
|
||||
let laterYield: (value: number, yield: number) => void;
|
||||
let genericYield: <T>(yield: T) => void;
|
||||
let optionalAwait: (await?: number) => void;
|
||||
let optionalYield: (yield?: number) => void;
|
||||
let untypedAwait: (await) => void;
|
||||
let untypedYield: (yield) => void;
|
||||
|
||||
// Parenthesized types and computed properties must retain their interpretation.
|
||||
type await = number;
|
||||
type yield = number;
|
||||
type AwaitType = (await);
|
||||
type YieldType = (yield);
|
||||
const key = "key";
|
||||
interface Computed { [key]: unknown }
|
||||
|
||||
interface AwaitIndex { [await: string]: unknown }
|
||||
interface YieldIndex { [yield: string]: unknown }
|
||||
type AwaitIndexType = { [await: string]: unknown };
|
||||
type YieldIndexType = { [yield: string]: unknown };
|
||||
@@ -1,3 +1,3 @@
|
||||
codegen_misc Summary:
|
||||
AST Parsed : 104/104 (100.00%)
|
||||
Positive Passed: 104/104 (100.00%)
|
||||
AST Parsed : 105/105 (100.00%)
|
||||
Positive Passed: 105/105 (100.00%)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
formatter_misc Summary:
|
||||
AST Parsed : 104/104 (100.00%)
|
||||
Positive Passed: 104/104 (100.00%)
|
||||
AST Parsed : 105/105 (100.00%)
|
||||
Positive Passed: 105/105 (100.00%)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
lexer_misc Summary:
|
||||
AST Parsed : 314/314 (100.00%)
|
||||
Positive Passed: 314/314 (100.00%)
|
||||
AST Parsed : 319/319 (100.00%)
|
||||
Positive Passed: 319/319 (100.00%)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
parser_misc Summary:
|
||||
AST Parsed : 104/104 (100.00%)
|
||||
Positive Passed: 104/104 (100.00%)
|
||||
Negative Passed: 210/210 (100.00%)
|
||||
AST Parsed : 105/105 (100.00%)
|
||||
Positive Passed: 105/105 (100.00%)
|
||||
Negative Passed: 214/214 (100.00%)
|
||||
|
||||
× Cannot assign to 'arguments' in strict mode
|
||||
╭─[misc/fail/arguments-eval-ambient.ts:2:13]
|
||||
@@ -383,6 +383,49 @@ Negative Passed: 210/210 (100.00%)
|
||||
3 │ constructor() {}
|
||||
╰────
|
||||
|
||||
× Expected `)` but found `:`
|
||||
╭─[misc/fail/contextual-binding-lookahead-function-reserved.ts:1:15]
|
||||
1 │ let fn: (break: number) => void;
|
||||
· ┬
|
||||
· ╰── `)` expected
|
||||
╰────
|
||||
|
||||
× Cannot use `yield` as an identifier in a generator context
|
||||
╭─[misc/fail/contextual-binding-lookahead-index-context.ts:2:18]
|
||||
1 │ function* generatorInterface() {
|
||||
2 │ interface I { [yield: string]: unknown }
|
||||
· ─────
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× Cannot use `yield` as an identifier in a generator context
|
||||
╭─[misc/fail/contextual-binding-lookahead-index-context.ts:5:14]
|
||||
4 │ function* generatorClass() {
|
||||
5 │ class C { [yield: string]: unknown }
|
||||
· ─────
|
||||
6 │ }
|
||||
╰────
|
||||
|
||||
× Cannot use `await` as an identifier in an async context
|
||||
╭─[misc/fail/contextual-binding-lookahead-index-context.ts:8:14]
|
||||
7 │ async function asyncClass() {
|
||||
8 │ class C { [await: string]: unknown }
|
||||
· ─────
|
||||
9 │ }
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[misc/fail/contextual-binding-lookahead-index-modifier.ts:1:23]
|
||||
1 │ interface I { [public await: string]: unknown }
|
||||
· ─────
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[misc/fail/contextual-binding-lookahead-index-reserved.ts:1:16]
|
||||
1 │ interface I { [break: string]: unknown }
|
||||
· ─────
|
||||
╰────
|
||||
|
||||
× A `continue` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement.
|
||||
╭─[misc/fail/continue-label-chain-non-iteration.js:1:1]
|
||||
1 │ a: b: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
semantic_misc Summary:
|
||||
AST Parsed : 104/104 (100.00%)
|
||||
Positive Passed: 100/104 (96.15%)
|
||||
AST Parsed : 105/105 (100.00%)
|
||||
Positive Passed: 101/105 (96.19%)
|
||||
semantic Error: tasks/coverage/misc/pass/declare-let-private.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["private"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
transformer_misc Summary:
|
||||
AST Parsed : 104/104 (100.00%)
|
||||
Positive Passed: 104/104 (100.00%)
|
||||
AST Parsed : 105/105 (100.00%)
|
||||
Positive Passed: 105/105 (100.00%)
|
||||
|
||||
Reference in New Issue
Block a user