From 536ede838be90581cdc37380b518c47884b6c2b6 Mon Sep 17 00:00:00 2001 From: Boshen Date: Mon, 3 Mar 2025 22:26:06 +0800 Subject: [PATCH] fix(parser): parse `@__NO_SIDE_EFFECTS` between `export default` and `async function` --- crates/oxc_codegen/src/gen.rs | 1 + .../oxc_codegen/tests/integration/pure_comments.rs | 2 ++ .../tests/integration/snapshots/pure_comments.snap | 6 ++++++ crates/oxc_parser/src/js/module.rs | 12 +++++++++--- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 128450e39f151..0c57bea42b096 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -221,6 +221,7 @@ impl Gen for Statement<'_> { Self::FunctionDeclaration(decl) => { p.print_statement_comments(decl.span.start); if decl.pure && p.options.print_annotation_comments() { + p.print_indent(); p.print_str(NO_SIDE_EFFECTS_NEW_LINE_COMMENT); } p.print_indent(); diff --git a/crates/oxc_codegen/tests/integration/pure_comments.rs b/crates/oxc_codegen/tests/integration/pure_comments.rs index 9a28a7277873f..89b81e846e626 100644 --- a/crates/oxc_codegen/tests/integration/pure_comments.rs +++ b/crates/oxc_codegen/tests/integration/pure_comments.rs @@ -61,6 +61,8 @@ async function* d() {} /* @__NO_SIDE_EFFECTS__ */ export function* b() {} /* @__NO_SIDE_EFFECTS__ */ export async function c() {} /* @__NO_SIDE_EFFECTS__ */ export async function* d() {} +export default /* @__NO_SIDE_EFFECTS__ */ async function() {} +export default /* @__NO_SIDE_EFFECTS__ */ function() {} ", // Only "c0" and "c2" should have "no side effects" (Rollup only respects "const" and only for the first one) r" diff --git a/crates/oxc_codegen/tests/integration/snapshots/pure_comments.snap b/crates/oxc_codegen/tests/integration/snapshots/pure_comments.snap index 210b0dbf4bad3..8c9b21057fb73 100644 --- a/crates/oxc_codegen/tests/integration/snapshots/pure_comments.snap +++ b/crates/oxc_codegen/tests/integration/snapshots/pure_comments.snap @@ -128,6 +128,8 @@ export async function* d() {} /* @__NO_SIDE_EFFECTS__ */ export function* b() {} /* @__NO_SIDE_EFFECTS__ */ export async function c() {} /* @__NO_SIDE_EFFECTS__ */ export async function* d() {} +export default /* @__NO_SIDE_EFFECTS__ */ async function() {} +export default /* @__NO_SIDE_EFFECTS__ */ function() {} ---------- /* @__NO_SIDE_EFFECTS__ */ @@ -138,6 +140,10 @@ export function* b() {} export async function c() {} /* @__NO_SIDE_EFFECTS__ */ export async function* d() {} +/* @__NO_SIDE_EFFECTS__ */ +export default async function() {} +/* @__NO_SIDE_EFFECTS__ */ +export default function() {} ########## 7 diff --git a/crates/oxc_parser/src/js/module.rs b/crates/oxc_parser/src/js/module.rs index 40936005154d1..b9ee36cf4b0f1 100644 --- a/crates/oxc_parser/src/js/module.rs +++ b/crates/oxc_parser/src/js/module.rs @@ -383,6 +383,8 @@ impl<'a> ParserImpl<'a> { ) -> Result>> { let exported = self.parse_keyword_identifier(Kind::Default); let decl_span = self.start_span(); + let has_no_side_effects_comment = + self.lexer.trivia_builder.previous_token_has_no_side_effects_comment(); // For tc39/proposal-decorators // For more information, please refer to self.eat_decorators()?; @@ -406,9 +408,13 @@ impl<'a> ParserImpl<'a> { } })? } - _ if self.at_function_with_async() => self - .parse_function_impl(FunctionKind::DefaultExport) - .map(ExportDefaultDeclarationKind::FunctionDeclaration)?, + _ if self.at_function_with_async() => { + let mut func = self.parse_function_impl(FunctionKind::DefaultExport)?; + if has_no_side_effects_comment { + func.pure = true; + } + ExportDefaultDeclarationKind::FunctionDeclaration(func) + } _ => { let decl = self .parse_assignment_expression_or_higher()