From 5050f5820a43b8de7a87511070405e189eaafb5f Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 21 Sep 2023 13:16:43 +0800 Subject: [PATCH] fix(es/compat): Handle nullish in fn expr scope (#7980) **Related issue:** - Closes: #7977 --- .../fixture/issues-7xxx/7977/input/.swcrc | 26 ++++++++++++++++ .../fixture/issues-7xxx/7977/input/index.ts | 1 + .../fixture/issues-7xxx/7977/output/index.ts | 4 +++ .../src/es2020/nullish_coalescing.rs | 31 ++++++++++++++++++- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 crates/swc/tests/fixture/issues-7xxx/7977/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-7xxx/7977/input/index.ts create mode 100644 crates/swc/tests/fixture/issues-7xxx/7977/output/index.ts diff --git a/crates/swc/tests/fixture/issues-7xxx/7977/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7977/input/.swcrc new file mode 100644 index 000000000000..a244f09c59f7 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7977/input/.swcrc @@ -0,0 +1,26 @@ +{ + "$schema": "https://json.schemastore.org/swcrc", + "jsc": { + "parser": { + "syntax": "typescript", + "tsx": false, + "dynamicImport": true + }, + "transform": { + "react": { + "runtime": "automatic" + } + }, + "baseUrl": "./", + "target": "es2019", + "keepClassNames": true, + "minify": { + "compress": false + } + }, + "isModule": true, + "module": { + "type": "es6" + }, + "minify": false +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-7xxx/7977/input/index.ts b/crates/swc/tests/fixture/issues-7xxx/7977/input/index.ts new file mode 100644 index 000000000000..4d4635533ac9 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7977/input/index.ts @@ -0,0 +1 @@ +const foo = () => baz() ?? qux; diff --git a/crates/swc/tests/fixture/issues-7xxx/7977/output/index.ts b/crates/swc/tests/fixture/issues-7xxx/7977/output/index.ts new file mode 100644 index 000000000000..e193b6239df6 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7977/output/index.ts @@ -0,0 +1,4 @@ +const foo = ()=>{ + var _baz; + return (_baz = baz()) !== null && _baz !== void 0 ? _baz : qux; +}; diff --git a/crates/swc_ecma_transforms_compat/src/es2020/nullish_coalescing.rs b/crates/swc_ecma_transforms_compat/src/es2020/nullish_coalescing.rs index 533874931ece..df9eb0f38915 100644 --- a/crates/swc_ecma_transforms_compat/src/es2020/nullish_coalescing.rs +++ b/crates/swc_ecma_transforms_compat/src/es2020/nullish_coalescing.rs @@ -1,7 +1,7 @@ use std::mem::take; use serde::Deserialize; -use swc_common::{util::take::Take, Span, DUMMY_SP}; +use swc_common::{util::take::Take, Span, Spanned, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_utils::{alias_if_required, undefined, StmtLike}; use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith}; @@ -192,6 +192,35 @@ impl VisitMut for NullishCoalescing { _ => {} } } + + fn visit_mut_block_stmt_or_expr(&mut self, n: &mut BlockStmtOrExpr) { + let vars = self.vars.take(); + n.visit_mut_children_with(self); + + if !self.vars.is_empty() { + if let BlockStmtOrExpr::Expr(expr) = n { + // expr + // { var decl = init; return expr; } + let span = expr.span(); + let stmts = vec![ + VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Var, + decls: self.vars.take(), + declare: false, + } + .into(), + Stmt::Return(ReturnStmt { + span: DUMMY_SP, + arg: Some(expr.take()), + }), + ]; + *n = BlockStmtOrExpr::BlockStmt(BlockStmt { span, stmts }); + } + } + + self.vars = vars; + } } #[tracing::instrument(level = "info", skip_all)]