Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions crates/oxc_parser/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,32 @@ impl<'a> ParserImpl<'a> {
answer
}

#[expect(clippy::inline_always)]
#[inline(always)] // inline because this is always on a hot path
pub(crate) fn context_add<F, T>(&mut self, add_flags: Context, cb: F) -> T
where
F: FnOnce(&mut Self) -> T,
{
let ctx = self.ctx;
self.ctx = ctx.union(add_flags);
let result = cb(self);
self.ctx = ctx;
result
}

#[expect(clippy::inline_always)]
#[inline(always)] // inline because this is always on a hot path
pub(crate) fn context_remove<F, T>(&mut self, remove_flags: Context, cb: F) -> T
where
F: FnOnce(&mut Self) -> T,
{
let ctx = self.ctx;
self.ctx = ctx.difference(remove_flags);
let result = cb(self);
self.ctx = ctx;
result
}

#[expect(clippy::inline_always)]
#[inline(always)] // inline because this is always on a hot path
pub(crate) fn context<F, T>(&mut self, add_flags: Context, remove_flags: Context, cb: F) -> T
Expand Down
7 changes: 3 additions & 4 deletions crates/oxc_parser/src/js/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ impl<'a> ParserImpl<'a> {
pub(super) fn parse_binding_pattern_with_initializer(&mut self) -> BindingPattern<'a> {
let span = self.start_span();
let pattern = self.parse_binding_pattern(true);
self.context(Context::In, Context::empty(), |p| p.parse_initializer(span, pattern))
self.context_add(Context::In, |p| p.parse_initializer(span, pattern))
}

pub(super) fn parse_binding_pattern(&mut self, allow_question: bool) -> BindingPattern<'a> {
Expand Down Expand Up @@ -114,8 +114,7 @@ impl<'a> ParserImpl<'a> {
// Rest element does not allow `= initializer`
// function foo([...x = []]) { }
// ^^^^ A rest element cannot have an initializer
let argument = self
.context(Context::In, Context::empty(), |p| p.parse_initializer(init_span, pattern));
let argument = self.context_add(Context::In, |p| p.parse_initializer(init_span, pattern));
if let BindingPatternKind::AssignmentPattern(pat) = &argument.kind {
self.error(diagnostics::a_rest_element_cannot_have_an_initializer(pat.span));
}
Expand All @@ -142,7 +141,7 @@ impl<'a> ParserImpl<'a> {
let identifier =
self.ast.binding_pattern_kind_binding_identifier(ident.span, ident.name);
let left = self.ast.binding_pattern(identifier, NONE, false);
self.context(Context::In, Context::empty(), |p| p.parse_initializer(span, left))
self.context_add(Context::In, |p| p.parse_initializer(span, left))
} else {
return self.unexpected();
}
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_parser/src/js/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ impl<'a> ParserImpl<'a> {
if kind.is_identifier_or_keyword() || kind == Kind::Star || kind == Kind::LBrack {
let is_ambient = modifiers.contains(ModifierKind::Declare);
return if is_ambient {
self.context(Context::Ambient, Context::empty(), |p| {
self.context_add(Context::Ambient, |p| {
p.parse_property_or_method_declaration(span, r#type, &modifiers, decorators)
})
} else {
Expand Down
24 changes: 9 additions & 15 deletions crates/oxc_parser/src/js/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_array_expression(&mut self) -> Expression<'a> {
let span = self.start_span();
self.expect(Kind::LBrack);
let (elements, comma_span) = self.context(Context::In, Context::empty(), |p| {
let (elements, comma_span) = self.context_add(Context::In, |p| {
p.parse_delimited_list(Kind::RBrack, Kind::Comma, Self::parse_array_expression_element)
});
if let Some(comma_span) = comma_span {
Expand Down Expand Up @@ -480,7 +480,7 @@ impl<'a> ParserImpl<'a> {

quasis.push(self.parse_template_element(tagged));
// TemplateHead Expression[+In, ?Yield, ?Await]
let expr = self.context(Context::In, Context::empty(), Self::parse_expr);
let expr = self.context_add(Context::In, Self::parse_expr);
expressions.push(expr);
self.re_lex_template_substitution_tail();
while self.fatal_error.is_none() {
Expand All @@ -492,8 +492,7 @@ impl<'a> ParserImpl<'a> {
Kind::TemplateMiddle => {
quasis.push(self.parse_template_element(tagged));
// TemplateMiddle Expression[+In, ?Yield, ?Await]
let expr =
self.context(Context::In, Context::empty(), Self::parse_expr);
let expr = self.context_add(Context::In, Self::parse_expr);
expressions.push(expr);
self.re_lex_template_substitution_tail();
}
Expand Down Expand Up @@ -840,7 +839,7 @@ impl<'a> ParserImpl<'a> {
optional: bool,
) -> Expression<'a> {
self.bump_any(); // advance `[`
let property = self.context(Context::In, Context::empty(), Self::parse_expr);
let property = self.context_add(Context::In, Self::parse_expr);
self.expect(Kind::RBrack);
self.ast.member_expression_computed(self.end_span(lhs_span), lhs, property, optional).into()
}
Expand Down Expand Up @@ -889,7 +888,7 @@ impl<'a> ParserImpl<'a> {
let arguments = if self.eat(Kind::LParen) {
// ArgumentList[Yield, Await] :
// AssignmentExpression[+In, ?Yield, ?Await]
let (call_arguments, _) = self.context(Context::In, Context::empty(), |p| {
let (call_arguments, _) = self.context_add(Context::In, |p| {
p.parse_delimited_list(Kind::RParen, Kind::Comma, Self::parse_call_argument)
});
self.expect(Kind::RParen);
Expand Down Expand Up @@ -1213,7 +1212,7 @@ impl<'a> ParserImpl<'a> {
if !self.eat(Kind::Question) {
return lhs;
}
let consequent = self.context(Context::In, Context::empty(), |p| {
let consequent = self.context_add(Context::In, |p| {
p.parse_assignment_expression_or_higher_impl(
/* allow_return_type_in_arrow_function */ false,
)
Expand Down Expand Up @@ -1399,9 +1398,8 @@ impl<'a> ParserImpl<'a> {
self.error(diagnostics::await_expression(self.cur_token().span()));
}
self.bump_any();
let argument = self.context(Context::Await, Context::empty(), |p| {
p.parse_simple_unary_expression(lhs_span)
});
let argument =
self.context_add(Context::Await, |p| p.parse_simple_unary_expression(lhs_span));
self.ast.expression_await(self.end_span(span), argument)
}

Expand Down Expand Up @@ -1435,11 +1433,7 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_decorator(&mut self) -> Decorator<'a> {
let span = self.start_span();
self.bump_any(); // bump @
let expr = self.context(
Context::Decorator,
Context::empty(),
Self::parse_lhs_expression_or_higher,
);
let expr = self.context_add(Context::Decorator, Self::parse_lhs_expression_or_higher);
self.ast.decorator(self.end_span(span), expr)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_parser/src/js/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl<'a> ParserImpl<'a> {
let span = self.start_span();
self.expect(Kind::LCurly);

let (directives, statements) = self.context(Context::Return, Context::empty(), |p| {
let (directives, statements) = self.context_add(Context::Return, |p| {
p.parse_directives_and_statements(/* is_top_level */ false)
});

Expand Down
8 changes: 4 additions & 4 deletions crates/oxc_parser/src/js/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;

use super::FunctionKind;
use crate::{
Context, ParserImpl, StatementContext, diagnostics,
ParserImpl, StatementContext, diagnostics,
lexer::Kind,
modifiers::{Modifier, ModifierFlags, ModifierKind, Modifiers},
};
Expand Down Expand Up @@ -281,7 +281,7 @@ impl<'a> ParserImpl<'a> {
import_kind: ImportOrExportKind,
) -> Vec<'a, ImportDeclarationSpecifier<'a>> {
self.expect(Kind::LCurly);
let (list, _) = self.context(Context::empty(), self.ctx, |p| {
let (list, _) = self.context_remove(self.ctx, |p| {
p.parse_delimited_list(Kind::RCurly, Kind::Comma, |parser| {
parser.parse_import_specifier(import_kind)
})
Expand All @@ -302,7 +302,7 @@ impl<'a> ParserImpl<'a> {

let span = self.start_span();
self.expect(Kind::LCurly);
let (with_entries, _) = self.context(Context::empty(), self.ctx, |p| {
let (with_entries, _) = self.context_remove(self.ctx, |p| {
p.parse_delimited_list(Kind::RCurly, Kind::Comma, Self::parse_import_attribute)
});
self.expect(Kind::RCurly);
Expand Down Expand Up @@ -478,7 +478,7 @@ impl<'a> ParserImpl<'a> {
) -> Box<'a, ExportNamedDeclaration<'a>> {
let export_kind = self.parse_import_or_export_kind();
self.expect(Kind::LCurly);
let (mut specifiers, _) = self.context(Context::empty(), self.ctx, |p| {
let (mut specifiers, _) = self.context_remove(self.ctx, |p| {
p.parse_delimited_list(Kind::RCurly, Kind::Comma, |parser| {
parser.parse_export_specifier(export_kind)
})
Expand Down
8 changes: 2 additions & 6 deletions crates/oxc_parser/src/js/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_object_expression(&mut self) -> Box<'a, ObjectExpression<'a>> {
let span = self.start_span();
self.expect(Kind::LCurly);
let (object_expression_properties, _) = self.context(Context::In, Context::empty(), |p| {
let (object_expression_properties, _) = self.context_add(Context::In, |p| {
p.parse_delimited_list(
Kind::RCurly,
Kind::Comma,
Expand Down Expand Up @@ -180,11 +180,7 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_computed_property_name(&mut self) -> Expression<'a> {
self.bump_any(); // advance `[`

let expression = self.context(
Context::In,
Context::empty(),
Self::parse_assignment_expression_or_higher,
);
let expression = self.context_add(Context::In, Self::parse_assignment_expression_or_higher);

self.expect(Kind::RBrack);
expression
Expand Down
10 changes: 5 additions & 5 deletions crates/oxc_parser/src/js/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ impl<'a> ParserImpl<'a> {
let is_async = self.at(Kind::Async) && !self.cur_token().escaped();
let expr_span = self.start_span();

let init_expression = self.context(Context::empty(), Context::In, ParserImpl::parse_expr);
let init_expression = self.context_remove(Context::In, ParserImpl::parse_expr);

match self.cur_kind() {
Kind::In => {
Expand Down Expand Up @@ -418,7 +418,7 @@ impl<'a> ParserImpl<'a> {
decl_kind: VariableDeclarationKind,
r#await: bool,
) -> Statement<'a> {
let init_declaration = self.context(Context::empty(), Context::In, |p| {
let init_declaration = self.context_remove(Context::In, |p| {
p.parse_variable_declaration(
start_span,
decl_kind,
Expand Down Expand Up @@ -495,13 +495,13 @@ impl<'a> ParserImpl<'a> {
let test = if matches!(self.cur_kind(), Kind::Semicolon | Kind::RParen) {
None
} else {
Some(self.context(Context::In, Context::empty(), ParserImpl::parse_expr))
Some(self.context_add(Context::In, ParserImpl::parse_expr))
};
self.expect(Kind::Semicolon);
let update = if self.at(Kind::RParen) {
None
} else {
Some(self.context(Context::In, Context::empty(), ParserImpl::parse_expr))
Some(self.context_add(Context::In, ParserImpl::parse_expr))
};
self.expect(Kind::RParen);
if r#await {
Expand Down Expand Up @@ -575,7 +575,7 @@ impl<'a> ParserImpl<'a> {
let argument = if self.eat(Kind::Semicolon) || self.can_insert_semicolon() {
None
} else {
let expr = self.context(Context::In, Context::empty(), ParserImpl::parse_expr);
let expr = self.context_add(Context::In, ParserImpl::parse_expr);
self.asi();
Some(expr)
};
Expand Down
37 changes: 10 additions & 27 deletions crates/oxc_parser/src/ts/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,14 @@ impl<'a> ParserImpl<'a> {
&& !self.cur_token().is_on_new_line()
&& self.eat(Kind::Extends)
{
let extends_type = self.context(
Context::DisallowConditionalTypes,
Context::empty(),
Self::parse_ts_type,
);
let extends_type =
self.context_add(Context::DisallowConditionalTypes, Self::parse_ts_type);
self.expect(Kind::Question);
let true_type = self.context(
Context::empty(),
Context::DisallowConditionalTypes,
Self::parse_ts_type,
);
let true_type =
self.context_remove(Context::DisallowConditionalTypes, Self::parse_ts_type);
self.expect(Kind::Colon);
let false_type = self.context(
Context::empty(),
Context::DisallowConditionalTypes,
Self::parse_ts_type,
);
let false_type =
self.context_remove(Context::DisallowConditionalTypes, Self::parse_ts_type);
return self.ast.ts_type_conditional_type(
self.end_span(span),
ty,
Expand Down Expand Up @@ -258,8 +249,7 @@ impl<'a> ParserImpl<'a> {
Kind::Unique => self.parse_type_operator(TSTypeOperatorOperator::Unique),
Kind::Readonly => self.parse_type_operator(TSTypeOperatorOperator::Readonly),
Kind::Infer => self.parse_infer_type(),
_ => self.context(
Context::empty(),
_ => self.context_remove(
Context::DisallowConditionalTypes,
Self::parse_postfix_type_or_higher,
),
Expand Down Expand Up @@ -1042,11 +1032,8 @@ impl<'a> ParserImpl<'a> {

fn try_parse_constraint_of_infer_type(&mut self) -> Option<TSType<'a>> {
if self.eat(Kind::Extends) {
let constraint = self.context(
Context::DisallowConditionalTypes,
Context::empty(),
Self::parse_ts_type,
);
let constraint =
self.context_add(Context::DisallowConditionalTypes, Self::parse_ts_type);
if self.ctx.has_disallow_conditional_types() || !self.at(Kind::Question) {
return Some(constraint);
}
Expand All @@ -1067,11 +1054,7 @@ impl<'a> ParserImpl<'a> {

fn parse_return_type(&mut self) -> TSType<'a> {
self.bump_any();
self.context(
Context::empty(),
Context::DisallowConditionalTypes,
Self::parse_type_or_type_predicate,
)
self.context_remove(Context::DisallowConditionalTypes, Self::parse_type_or_type_predicate)
}

fn parse_type_or_type_predicate(&mut self) -> TSType<'a> {
Expand Down
Loading