mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
parent
7cc90134d3
commit
e2d2ce3369
9 changed files with 50 additions and 107 deletions
|
|
@ -29,6 +29,9 @@ bitflags! {
|
|||
/// i.e. the [Return] in Statement[Yield, Await, Return]
|
||||
const Return = 1<< 3;
|
||||
|
||||
/// If node was parsed as part of a decorator
|
||||
const Decorator = 1 << 4;
|
||||
|
||||
/// Typescript should parse extends clause as conditional type instead of type constrains.
|
||||
/// Used in infer clause
|
||||
///
|
||||
|
|
@ -37,13 +40,13 @@ bitflags! {
|
|||
///
|
||||
/// type X<U, T> = T extends (infer U extends number ? U : T) ? U : T;
|
||||
/// The "(infer U extends number ? U : T)" is conditional type.
|
||||
const DisallowConditionalTypes = 1 << 4;
|
||||
const DisallowConditionalTypes = 1 << 5;
|
||||
|
||||
/// A declaration file, or inside something with the `declare` modifier.
|
||||
/// Declarations that don't define an implementation is "ambient":
|
||||
/// * ambient variable declaration => `declare var $: any`
|
||||
/// * ambient class declaration => `declare class C { foo(); } , etc..`
|
||||
const Ambient = 1 << 5;
|
||||
const Ambient = 1 << 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,6 +77,11 @@ impl Context {
|
|||
self.contains(Self::Return)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn has_decorator(self) -> bool {
|
||||
self.contains(Self::Decorator)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn has_disallow_conditional_types(self) -> bool {
|
||||
self.contains(Self::DisallowConditionalTypes)
|
||||
|
|
@ -128,6 +136,11 @@ impl Context {
|
|||
self.and(Self::Return, include)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn and_decorator(self, include: bool) -> Self {
|
||||
self.and(Self::Decorator, include)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn and_ambient(self, include: bool) -> Self {
|
||||
self.and(Self::Ambient, include)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ impl<'a> ParserImpl<'a> {
|
|||
pub(crate) fn parse_expression(&mut self) -> Result<Expression<'a>> {
|
||||
let span = self.start_span();
|
||||
|
||||
let has_decorator = self.ctx.has_decorator();
|
||||
if has_decorator {
|
||||
self.ctx = self.ctx.and_decorator(false);
|
||||
}
|
||||
|
||||
let lhs = self.parse_assignment_expression_base()?;
|
||||
if !self.at(Kind::Comma) {
|
||||
return Ok(lhs);
|
||||
|
|
@ -41,6 +46,10 @@ impl<'a> ParserImpl<'a> {
|
|||
|
||||
let expr = self.parse_sequence_expression(span, lhs)?;
|
||||
|
||||
if has_decorator {
|
||||
self.ctx = self.ctx.and_decorator(true);
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
|
|
@ -191,9 +200,10 @@ impl<'a> ParserImpl<'a> {
|
|||
|
||||
fn parse_parenthesized_expression(&mut self, span: Span) -> Result<Expression<'a>> {
|
||||
let has_in = self.ctx.has_in();
|
||||
self.ctx = self.ctx.and_in(true);
|
||||
let has_decorator = self.ctx.has_decorator();
|
||||
self.ctx = self.ctx.and_in(true).and_decorator(false);
|
||||
let list = SequenceExpressionList::parse(self)?;
|
||||
self.ctx = self.ctx.and_in(has_in);
|
||||
self.ctx = self.ctx.and_in(has_in).and_decorator(has_decorator);
|
||||
|
||||
let mut expressions = list.elements;
|
||||
let paren_span = self.end_span(span);
|
||||
|
|
@ -518,20 +528,6 @@ impl<'a> ParserImpl<'a> {
|
|||
.and_then(|lhs| self.parse_member_expression_rhs(span, lhs, in_optional_chain))
|
||||
}
|
||||
|
||||
/// `DecoratorMemberExpression`[Yield, Await]:
|
||||
/// [ `IdentifierReference`[?Yield, ?Await] ]
|
||||
/// [ `DecoratorMemberExpression`[?Yield, ?Await] . `IdentifierName` ]
|
||||
/// [ `DecoratorMemberExpression`[?Yield, ?Await] . `PrivateIdentifier` ]
|
||||
fn parse_decorator_member_expression(&mut self) -> Result<Expression<'a>> {
|
||||
let lhs_span = self.start_span();
|
||||
let lhs = self.parse_identifier_reference()?;
|
||||
let mut lhs = self.ast.identifier_reference_expression(lhs);
|
||||
while self.at(Kind::Dot) {
|
||||
lhs = self.parse_static_member_expression(lhs_span, lhs, false)?;
|
||||
}
|
||||
Ok(lhs)
|
||||
}
|
||||
|
||||
/// Section 13.3 Super Call
|
||||
fn parse_super(&mut self) -> Expression<'a> {
|
||||
let span = self.start_span();
|
||||
|
|
@ -561,12 +557,17 @@ impl<'a> ParserImpl<'a> {
|
|||
let mut lhs = lhs;
|
||||
loop {
|
||||
lhs = match self.cur_kind() {
|
||||
Kind::LBrack => self.parse_computed_member_expression(lhs_span, lhs, false)?,
|
||||
// computed member expression is not allowed in decorator
|
||||
// class C { @dec ["1"]() { } }
|
||||
// ^
|
||||
Kind::LBrack if !self.ctx.has_decorator() => {
|
||||
self.parse_computed_member_expression(lhs_span, lhs, false)?
|
||||
}
|
||||
Kind::Dot => self.parse_static_member_expression(lhs_span, lhs, false)?,
|
||||
Kind::QuestionDot => {
|
||||
*in_optional_chain = true;
|
||||
match self.peek_kind() {
|
||||
Kind::LBrack => {
|
||||
Kind::LBrack if !self.ctx.has_decorator() => {
|
||||
self.bump_any(); // bump `?.`
|
||||
self.parse_computed_member_expression(lhs_span, lhs, true)?
|
||||
}
|
||||
|
|
@ -734,49 +735,6 @@ impl<'a> ParserImpl<'a> {
|
|||
Ok(lhs)
|
||||
}
|
||||
|
||||
/// `DecoratorCallExpression`[Yield, Await] :
|
||||
/// `DecoratorMemberExpression`[?Yield, ?Await] `Arguments`[?Yield, ?Await]
|
||||
/// This is different from `CallExpression` in that it only has one level. `@a()()` is not valid Decorator.
|
||||
fn parse_decorator_call_expression(
|
||||
&mut self,
|
||||
lhs_span: Span,
|
||||
lhs: Expression<'a>, /* `DecoratorMemberExpression` */
|
||||
) -> Result<Expression<'a>> {
|
||||
let mut type_arguments = None;
|
||||
if matches!(self.cur_kind(), Kind::LAngle | Kind::ShiftLeft) && self.ts_enabled() {
|
||||
let result = self.try_parse(|p| {
|
||||
let arguments = p.parse_ts_type_arguments()?;
|
||||
if p.at(Kind::RAngle) {
|
||||
// a<b>>c is not (a<b>)>c, but a<(b>>c)
|
||||
return Err(p.unexpected());
|
||||
}
|
||||
|
||||
// a<b>c is (a<b)>c
|
||||
if !p.at(Kind::LParen)
|
||||
&& !p.at(Kind::NoSubstitutionTemplate)
|
||||
&& !p.at(Kind::TemplateHead)
|
||||
&& p.cur_kind().is_at_expression()
|
||||
&& !p.cur_token().is_on_new_line
|
||||
{
|
||||
return Err(p.unexpected());
|
||||
}
|
||||
|
||||
type_arguments = arguments;
|
||||
|
||||
Ok(())
|
||||
});
|
||||
if result.is_err() {
|
||||
return Ok(lhs);
|
||||
}
|
||||
}
|
||||
|
||||
if self.at(Kind::LParen) {
|
||||
self.parse_call_arguments(lhs_span, lhs, false, type_arguments.take())
|
||||
} else {
|
||||
Ok(lhs)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_call_arguments(
|
||||
&mut self,
|
||||
lhs_span: Span,
|
||||
|
|
@ -1093,12 +1051,7 @@ impl<'a> ParserImpl<'a> {
|
|||
pub(crate) fn parse_decorator(&mut self) -> Result<Decorator<'a>> {
|
||||
let span = self.start_span();
|
||||
self.bump_any(); // bump @
|
||||
let expr = if self.cur_kind() == Kind::LParen {
|
||||
self.parse_paren_expression()?
|
||||
} else {
|
||||
let lhs = self.parse_decorator_member_expression()?;
|
||||
self.parse_decorator_call_expression(span, lhs)?
|
||||
};
|
||||
let expr = self.with_context(Context::Decorator, Self::parse_lhs_expression)?;
|
||||
Ok(self.ast.decorator(self.end_span(span), expr))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
codegen_misc Summary:
|
||||
AST Parsed : 11/11 (100.00%)
|
||||
Positive Passed: 11/11 (100.00%)
|
||||
AST Parsed : 12/12 (100.00%)
|
||||
Positive Passed: 12/12 (100.00%)
|
||||
|
|
|
|||
2
tasks/coverage/misc/pass/oxc-2562.ts
Normal file
2
tasks/coverage/misc/pass/oxc-2562.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
@http.controller('hooks').middleware(HooksMiddleware)
|
||||
export class HooksController {}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
parser_misc Summary:
|
||||
AST Parsed : 11/11 (100.00%)
|
||||
Positive Passed: 11/11 (100.00%)
|
||||
AST Parsed : 12/12 (100.00%)
|
||||
Positive Passed: 12/12 (100.00%)
|
||||
Negative Passed: 8/8 (100.00%)
|
||||
|
||||
× Unexpected token
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
parser_test262 Summary:
|
||||
AST Parsed : 45265/45265 (100.00%)
|
||||
Positive Passed: 45265/45265 (100.00%)
|
||||
AST Parsed : 45289/45289 (100.00%)
|
||||
Positive Passed: 45289/45289 (100.00%)
|
||||
Negative Passed: 3925/3929 (99.90%)
|
||||
Expect Syntax Error: "language/import/import-assertions/json-invalid.js"
|
||||
Expect Syntax Error: "language/import/import-assertions/json-named-bindings.js"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
parser_typescript Summary:
|
||||
AST Parsed : 5239/5243 (99.92%)
|
||||
Positive Passed: 5232/5243 (99.79%)
|
||||
Negative Passed: 1063/4879 (21.79%)
|
||||
AST Parsed : 5240/5243 (99.94%)
|
||||
Positive Passed: 5233/5243 (99.81%)
|
||||
Negative Passed: 1061/4879 (21.75%)
|
||||
Expect Syntax Error: "compiler/ClassDeclaration10.ts"
|
||||
Expect Syntax Error: "compiler/ClassDeclaration11.ts"
|
||||
Expect Syntax Error: "compiler/ClassDeclaration13.ts"
|
||||
|
|
@ -2196,6 +2196,8 @@ Expect Syntax Error: "conformance/decorators/class/constructor/decoratorOnClassC
|
|||
Expect Syntax Error: "conformance/decorators/class/decoratorChecksFunctionBodies.ts"
|
||||
Expect Syntax Error: "conformance/decorators/class/decoratorOnClass8.ts"
|
||||
Expect Syntax Error: "conformance/decorators/class/method/decoratorOnClassMethod10.ts"
|
||||
Expect Syntax Error: "conformance/decorators/class/method/decoratorOnClassMethod11.ts"
|
||||
Expect Syntax Error: "conformance/decorators/class/method/decoratorOnClassMethod12.ts"
|
||||
Expect Syntax Error: "conformance/decorators/class/method/decoratorOnClassMethod6.ts"
|
||||
Expect Syntax Error: "conformance/decorators/class/method/decoratorOnClassMethod8.ts"
|
||||
Expect Syntax Error: "conformance/decorators/class/method/decoratorOnClassMethodOverload1.ts"
|
||||
|
|
@ -3918,15 +3920,6 @@ Expect to Parse: "conformance/es6/moduleExportsSystem/topLevelVarHoistingCommonJ
|
|||
· ────
|
||||
69 │ var y = _;
|
||||
╰────
|
||||
Expect to Parse: "conformance/esDecorators/esDecorators-preservesThis.ts"
|
||||
|
||||
× Unexpected token
|
||||
╭─[conformance/esDecorators/esDecorators-preservesThis.ts:27:14]
|
||||
26 │ class C {
|
||||
27 │ @super.decorate
|
||||
· ─────
|
||||
28 │ method1() { }
|
||||
╰────
|
||||
Expect to Parse: "conformance/externalModules/topLevelAwait.2.ts"
|
||||
|
||||
× Cannot use `await` as an identifier in an async context
|
||||
|
|
@ -12037,22 +12030,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
|
|||
7 │ }
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[conformance/decorators/class/method/decoratorOnClassMethod11.ts:7:10]
|
||||
6 │
|
||||
7 │ @this.decorator
|
||||
· ────
|
||||
8 │ method() { }
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[conformance/decorators/class/method/decoratorOnClassMethod12.ts:8:10]
|
||||
7 │ class C extends S {
|
||||
8 │ @super.decorator
|
||||
· ─────
|
||||
9 │ method() { }
|
||||
╰────
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[conformance/decorators/class/method/decoratorOnClassMethod17.ts:7:17]
|
||||
6 │ class Foo {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
prettier_misc Summary:
|
||||
AST Parsed : 11/11 (100.00%)
|
||||
Positive Passed: 6/11 (54.55%)
|
||||
AST Parsed : 12/12 (100.00%)
|
||||
Positive Passed: 7/12 (58.33%)
|
||||
Expect to Parse: "pass/oxc-1740.tsx"
|
||||
Expect to Parse: "pass/oxc-2087.ts"
|
||||
Expect to Parse: "pass/oxc-2394.ts"
|
||||
|
|
|
|||
|
|
@ -170,8 +170,6 @@ impl Case for Test262Case {
|
|||
// Regex parser is required. See https://github.com/oxc-project/oxc/issues/385#issuecomment-1755566240
|
||||
"regexp-v-flag",
|
||||
"regexp-unicode-property-escapes",
|
||||
// Stage 3 `https://github.com/tc39/proposal-decorators`
|
||||
"decorators",
|
||||
]
|
||||
.iter()
|
||||
.any(|feature| self.meta.features.iter().any(|f| **f == **feature))
|
||||
|
|
|
|||
Loading…
Reference in a new issue