From 861d87cae622f371ea697b1cb07ed79d32579b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Feb 2023 15:49:08 +0900 Subject: [PATCH] fix(es/resolver): Resolve parameters correctly (#6890) **Related issue:** - Closes https://github.com/swc-project/swc/issues/5622. --- ...ayBindingPatternAndAssignment3.1.normal.js | 2 +- .../functionImplementationErrors.1.normal.js | 2 +- ...InitializersForwardReferencing.1.normal.js | 18 +- ...nitializersForwardReferencing1.1.normal.js | 2 +- ...alizersForwardReferencing1_es6.1.normal.js | 2 +- .../src/resolver/mod.rs | 330 ++++++++++-------- .../tests/ts-resolver/issue-5622/1/input.ts | 8 + .../tests/ts-resolver/issue-5622/1/output.ts | 10 + .../tests/ts-resolver/issue-5622/2/input.ts | 41 +++ .../tests/ts-resolver/issue-5622/2/output.ts | 36 ++ 10 files changed, 295 insertions(+), 156 deletions(-) create mode 100644 crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/input.ts create mode 100644 crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/output.ts create mode 100644 crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/input.ts create mode 100644 crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts diff --git a/crates/swc/tests/tsc-references/destructuringArrayBindingPatternAndAssignment3.1.normal.js b/crates/swc/tests/tsc-references/destructuringArrayBindingPatternAndAssignment3.1.normal.js index caf60c5b414f..19a355c89ca2 100644 --- a/crates/swc/tests/tsc-references/destructuringArrayBindingPatternAndAssignment3.1.normal.js +++ b/crates/swc/tests/tsc-references/destructuringArrayBindingPatternAndAssignment3.1.normal.js @@ -20,7 +20,7 @@ var _ref2 = [ 1 ]); (function(param) { - var _param = _sliced_to_array(param, 4), f = _param[0], tmp = _param[1], g = tmp === void 0 ? f : tmp, tmp1 = _param[2], h = tmp1 === void 0 ? i : tmp1, tmp2 = _param[3], i1 = tmp2 === void 0 ? f : tmp2; + var _param = _sliced_to_array(param, 4), f = _param[0], tmp = _param[1], g = tmp === void 0 ? f : tmp, tmp1 = _param[2], h = tmp1 === void 0 ? i : tmp1, tmp2 = _param[3], i = tmp2 === void 0 ? f : tmp2; })([ 1 ]); diff --git a/crates/swc/tests/tsc-references/functionImplementationErrors.1.normal.js b/crates/swc/tests/tsc-references/functionImplementationErrors.1.normal.js index a7da1043f768..13bbe84aa169 100644 --- a/crates/swc/tests/tsc-references/functionImplementationErrors.1.normal.js +++ b/crates/swc/tests/tsc-references/functionImplementationErrors.1.normal.js @@ -37,7 +37,7 @@ function f6() { } // Function signature with initializer referencing other parameter to the right function f7() { - var n = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : m, m1 = arguments.length > 1 ? arguments[1] : void 0; + var n = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : m, m = arguments.length > 1 ? arguments[1] : void 0; } // FunctionExpression with non -void return type annotation with a throw, no return, and other code // Should be error but isn't diff --git a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js index 6df714f623d6..c50c14c77bfc 100644 --- a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js +++ b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js @@ -6,15 +6,15 @@ function left(a) { b1; } function right() { - var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b, _$b = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : a; + var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b1, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : a; a; - _$b; + b1; } function right2() { - var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b, _$b = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : c, _$c = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : a; + var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b1, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : c1, c1 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : a; a; - _$b; - _$c; + b1; + c1; } function inside() { var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b; @@ -29,13 +29,13 @@ function outside() { } function defaultArgFunction() { var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : function() { - return b; + return b1; }, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 1; } function defaultArgArrow() { var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : function() { return function() { - return b; + return b1; }; }, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 3; } @@ -47,7 +47,7 @@ var C = /*#__PURE__*/ function() { } var _proto = C.prototype; _proto.method = function method() { - var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b, _$b = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 1; + var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b1, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 1; }; return C; }(); @@ -59,6 +59,6 @@ var x = function() { // Should not produce errors - can reference later parameters if they occur within a function expression initializer. function f(a) { var b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : function() { - return c; + return c1; }, c1 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : b1(); } diff --git a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1.1.normal.js b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1.1.normal.js index 67c63ed8540c..223d04bb06da 100644 --- a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1.1.normal.js +++ b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1.1.normal.js @@ -15,7 +15,7 @@ function f2() { return bar(); // returns 1 } function f3() { - var bar = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : foo, foo1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 2; + var bar = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : foo, foo = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 2; return bar; } function f4(foo) { diff --git a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1_es6.1.normal.js b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1_es6.1.normal.js index 6861d001cf85..fdf497c98f79 100644 --- a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1_es6.1.normal.js +++ b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing1_es6.1.normal.js @@ -8,7 +8,7 @@ function f2(bar = (baz = foo)=>baz) { var foo1 = 2; return bar(); // returns 1 } -function f3(bar = foo, foo1 = 2) { +function f3(bar = foo, foo = 2) { return bar; } function f4(foo, bar = foo) { diff --git a/crates/swc_ecma_transforms_base/src/resolver/mod.rs b/crates/swc_ecma_transforms_base/src/resolver/mod.rs index 8117de87064c..3aea2e0af564 100644 --- a/crates/swc_ecma_transforms_base/src/resolver/mod.rs +++ b/crates/swc_ecma_transforms_base/src/resolver/mod.rs @@ -399,9 +399,12 @@ macro_rules! typed_ref { ($name:ident, $T:ty) => { fn $name(&mut self, node: &mut $T) { if self.config.handle_types { + let in_type = self.in_type; let ident_type = self.ident_type; + self.in_type = true; node.visit_mut_children_with(self); self.ident_type = ident_type; + self.in_type = in_type; } } }; @@ -530,106 +533,6 @@ impl<'a> VisitMut for Resolver<'a> { // TODO: How should I handle this? typed!(visit_mut_ts_namespace_export_decl, TsNamespaceExportDecl); - fn visit_mut_ts_expr_with_type_args(&mut self, n: &mut TsExprWithTypeArgs) { - if self.config.handle_types { - let old = self.in_type; - self.in_type = true; - n.visit_mut_children_with(self); - self.in_type = old; - } - } - - fn visit_mut_export_specifier(&mut self, s: &mut ExportSpecifier) { - let old = self.ident_type; - self.ident_type = IdentType::Ref; - s.visit_mut_children_with(self); - self.ident_type = old; - } - - fn visit_mut_import_specifier(&mut self, s: &mut ImportSpecifier) { - let old = self.ident_type; - self.ident_type = IdentType::Binding; - - match s { - ImportSpecifier::Named(ImportNamedSpecifier { imported: None, .. }) - | ImportSpecifier::Namespace(..) - | ImportSpecifier::Default(..) => s.visit_mut_children_with(self), - ImportSpecifier::Named(s) => s.local.visit_mut_with(self), - }; - - self.ident_type = old; - } - - fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) { - let old = self.ident_type; - self.ident_type = IdentType::Ref; - f.key.visit_mut_with(self); - self.ident_type = old; - - f.type_ann.visit_mut_with(self); - - f.body.visit_mut_with(self); - } - - fn visit_mut_labeled_stmt(&mut self, s: &mut LabeledStmt) { - let old = self.ident_type; - self.ident_type = IdentType::Label; - s.label.visit_mut_with(self); - self.ident_type = old; - - s.body.visit_mut_with(self); - } - - fn visit_mut_break_stmt(&mut self, s: &mut BreakStmt) { - let old = self.ident_type; - self.ident_type = IdentType::Label; - s.label.visit_mut_with(self); - self.ident_type = old; - } - - fn visit_mut_continue_stmt(&mut self, s: &mut ContinueStmt) { - let old = self.ident_type; - self.ident_type = IdentType::Label; - s.label.visit_mut_with(self); - self.ident_type = old; - } - - fn visit_mut_key_value_pat_prop(&mut self, n: &mut KeyValuePatProp) { - n.key.visit_mut_with(self); - n.value.visit_mut_with(self); - } - - fn visit_mut_class(&mut self, c: &mut Class) { - let old_strict_mode = self.strict_mode; - self.strict_mode = true; - - let old = self.ident_type; - self.ident_type = IdentType::Ref; - c.decorators.visit_mut_with(self); - - self.ident_type = IdentType::Ref; - c.super_class.visit_mut_with(self); - - self.ident_type = IdentType::Binding; - c.type_params.visit_mut_with(self); - - self.ident_type = IdentType::Ref; - c.super_type_params.visit_mut_with(self); - - self.ident_type = IdentType::Ref; - c.implements.visit_mut_with(self); - self.ident_type = old; - - c.body.visit_mut_with(self); - self.strict_mode = old_strict_mode; - } - - fn visit_mut_prop_name(&mut self, n: &mut PropName) { - if let PropName::Computed(c) = n { - c.visit_mut_with(self); - } - } - fn visit_mut_arrow_expr(&mut self, e: &mut ArrowExpr) { self.with_child(ScopeKind::Fn, |child| { e.type_params.visit_mut_with(child); @@ -659,6 +562,14 @@ impl<'a> VisitMut for Resolver<'a> { }); } + fn visit_mut_assign_pat(&mut self, node: &mut AssignPat) { + // visit the type first so that it doesn't resolve any + // identifiers from the others + node.type_ann.visit_mut_with(self); + node.left.visit_mut_with(self); + node.right.visit_mut_with(self); + } + fn visit_mut_binding_ident(&mut self, i: &mut BindingIdent) { let ident_type = self.ident_type; let in_type = self.in_type; @@ -687,6 +598,13 @@ impl<'a> VisitMut for Resolver<'a> { } } + fn visit_mut_break_stmt(&mut self, s: &mut BreakStmt) { + let old = self.ident_type; + self.ident_type = IdentType::Label; + s.label.visit_mut_with(self); + self.ident_type = old; + } + fn visit_mut_catch_clause(&mut self, c: &mut CatchClause) { // Child folder @@ -699,6 +617,31 @@ impl<'a> VisitMut for Resolver<'a> { }); } + fn visit_mut_class(&mut self, c: &mut Class) { + let old_strict_mode = self.strict_mode; + self.strict_mode = true; + + let old = self.ident_type; + self.ident_type = IdentType::Ref; + c.decorators.visit_mut_with(self); + + self.ident_type = IdentType::Ref; + c.super_class.visit_mut_with(self); + + self.ident_type = IdentType::Binding; + c.type_params.visit_mut_with(self); + + self.ident_type = IdentType::Ref; + c.super_type_params.visit_mut_with(self); + + self.ident_type = IdentType::Ref; + c.implements.visit_mut_with(self); + self.ident_type = old; + + c.body.visit_mut_with(self); + self.strict_mode = old_strict_mode; + } + fn visit_mut_class_decl(&mut self, n: &mut ClassDecl) { self.modify(&mut n.ident, DeclKind::Lexical); @@ -780,6 +723,13 @@ impl<'a> VisitMut for Resolver<'a> { }); } + fn visit_mut_continue_stmt(&mut self, s: &mut ContinueStmt) { + let old = self.ident_type; + self.ident_type = IdentType::Label; + s.label.visit_mut_with(self); + self.ident_type = old; + } + fn visit_mut_decl(&mut self, decl: &mut Decl) { decl.visit_mut_children_with(self) } @@ -828,6 +778,13 @@ impl<'a> VisitMut for Resolver<'a> { } } + fn visit_mut_export_specifier(&mut self, s: &mut ExportSpecifier) { + let old = self.ident_type; + self.ident_type = IdentType::Ref; + s.visit_mut_children_with(self); + self.ident_type = old; + } + fn visit_mut_expr(&mut self, expr: &mut Expr) { let _span = if LOG { Some(span!(Level::ERROR, "visit_mut_expr").entered()) @@ -903,6 +860,18 @@ impl<'a> VisitMut for Resolver<'a> { self.ident_type = IdentType::Ref; f.decorators.visit_mut_with(self); + { + let params = f + .params + .iter() + .filter(|p| !p.pat.is_rest()) + .flat_map(find_pat_ids) + .collect::>(); + + for id in params { + self.current.declared_symbols.insert(id.0, DeclKind::Param); + } + } self.ident_type = IdentType::Binding; f.params.visit_mut_with(self); @@ -925,6 +894,17 @@ impl<'a> VisitMut for Resolver<'a> { } } + fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) { + let old = self.ident_type; + self.ident_type = IdentType::Ref; + f.key.visit_mut_with(self); + self.ident_type = old; + + f.type_ann.visit_mut_with(self); + + f.body.visit_mut_with(self); + } + fn visit_mut_ident(&mut self, i: &mut Ident) { if i.span.ctxt != SyntaxContext::empty() { return; @@ -990,6 +970,23 @@ impl<'a> VisitMut for Resolver<'a> { let old = self.ident_type; self.ident_type = IdentType::Binding; s.local.visit_mut_with(self); + if self.config.handle_types { + self.current.declared_types.insert(s.local.sym.clone()); + } + self.ident_type = old; + } + + fn visit_mut_import_specifier(&mut self, s: &mut ImportSpecifier) { + let old = self.ident_type; + self.ident_type = IdentType::Binding; + + match s { + ImportSpecifier::Named(ImportNamedSpecifier { imported: None, .. }) + | ImportSpecifier::Namespace(..) + | ImportSpecifier::Default(..) => s.visit_mut_children_with(self), + ImportSpecifier::Named(s) => s.local.visit_mut_with(self), + } + self.ident_type = old; } @@ -998,6 +995,20 @@ impl<'a> VisitMut for Resolver<'a> { /// See https://github.com/swc-project/swc/issues/2854 fn visit_mut_jsx_attr_name(&mut self, _: &mut JSXAttrName) {} + fn visit_mut_key_value_pat_prop(&mut self, n: &mut KeyValuePatProp) { + n.key.visit_mut_with(self); + n.value.visit_mut_with(self); + } + + fn visit_mut_labeled_stmt(&mut self, s: &mut LabeledStmt) { + let old = self.ident_type; + self.ident_type = IdentType::Label; + s.label.visit_mut_with(self); + self.ident_type = old; + + s.body.visit_mut_with(self); + } + fn visit_mut_method_prop(&mut self, m: &mut MethodProp) { m.key.visit_mut_with(self); @@ -1005,6 +1016,11 @@ impl<'a> VisitMut for Resolver<'a> { self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child)); } + fn visit_mut_module(&mut self, module: &mut Module) { + self.strict_mode = true; + module.visit_mut_children_with(self) + } + fn visit_mut_module_items(&mut self, stmts: &mut Vec) { if !self.in_ts_module && self.current.kind != ScopeKind::Fn { return stmts.visit_mut_children_with(self); @@ -1050,21 +1066,6 @@ impl<'a> VisitMut for Resolver<'a> { p.visit_mut_children_with(self); } - fn visit_mut_assign_pat(&mut self, node: &mut AssignPat) { - // visit the type first so that it doesn't resolve any - // identifiers from the others - node.type_ann.visit_mut_with(self); - node.left.visit_mut_with(self); - node.right.visit_mut_with(self); - } - - fn visit_mut_rest_pat(&mut self, node: &mut RestPat) { - // visit the type first so that it doesn't resolve any - // identifiers from the arg - node.type_ann.visit_mut_with(self); - node.arg.visit_mut_with(self); - } - fn visit_mut_private_method(&mut self, m: &mut PrivateMethod) { m.key.visit_mut_with(self); @@ -1077,6 +1078,26 @@ impl<'a> VisitMut for Resolver<'a> { fn visit_mut_private_name(&mut self, _: &mut PrivateName) {} + fn visit_mut_prop_name(&mut self, n: &mut PropName) { + if let PropName::Computed(c) = n { + c.visit_mut_with(self); + } + } + + fn visit_mut_rest_pat(&mut self, node: &mut RestPat) { + node.arg.visit_mut_with(self); + node.type_ann.visit_mut_with(self); + } + + fn visit_mut_script(&mut self, script: &mut Script) { + self.strict_mode = script + .body + .first() + .map(|stmt| stmt.is_use_strict()) + .unwrap_or(false); + script.visit_mut_children_with(self) + } + fn visit_mut_setter_prop(&mut self, n: &mut SetterProp) { n.key.visit_mut_with(self); @@ -1119,29 +1140,21 @@ impl<'a> VisitMut for Resolver<'a> { stmts.visit_mut_children_with(self) } - fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) { - s.discriminant.visit_mut_with(self); - - self.with_child(ScopeKind::Block, |child| { - s.cases.visit_mut_with(child); - }); - } - fn visit_mut_switch_case(&mut self, n: &mut SwitchCase) { n.cons.visit_mut_with(self); n.test.visit_mut_with(self); } - fn visit_mut_ts_as_expr(&mut self, n: &mut TsAsExpr) { - if self.config.handle_types { - n.type_ann.visit_mut_with(self); - } + fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) { + s.discriminant.visit_mut_with(self); - n.expr.visit_mut_with(self); + self.with_child(ScopeKind::Block, |child| { + s.cases.visit_mut_with(child); + }); } - fn visit_mut_ts_satisfies_expr(&mut self, n: &mut TsSatisfiesExpr) { + fn visit_mut_ts_as_expr(&mut self, n: &mut TsAsExpr) { if self.config.handle_types { n.type_ann.visit_mut_with(self); } @@ -1209,6 +1222,15 @@ impl<'a> VisitMut for Resolver<'a> { }); } + fn visit_mut_ts_expr_with_type_args(&mut self, n: &mut TsExprWithTypeArgs) { + if self.config.handle_types { + let old = self.in_type; + self.in_type = true; + n.visit_mut_children_with(self); + self.in_type = old; + } + } + fn visit_mut_ts_fn_type(&mut self, ty: &mut TsFnType) { if !self.config.handle_types { return; @@ -1340,6 +1362,14 @@ impl<'a> VisitMut for Resolver<'a> { n.left.visit_mut_with(self) } + fn visit_mut_ts_satisfies_expr(&mut self, n: &mut TsSatisfiesExpr) { + if self.config.handle_types { + n.type_ann.visit_mut_with(self); + } + + n.expr.visit_mut_with(self); + } + fn visit_mut_ts_setter_signature(&mut self, n: &mut TsSetterSignature) { if n.computed { n.key.visit_mut_with(self); @@ -1421,20 +1451,6 @@ impl<'a> VisitMut for Resolver<'a> { decl.init.visit_mut_children_with(self); } - - fn visit_mut_script(&mut self, script: &mut Script) { - self.strict_mode = script - .body - .first() - .map(|stmt| stmt.is_use_strict()) - .unwrap_or(false); - script.visit_mut_children_with(self) - } - - fn visit_mut_module(&mut self, module: &mut Module) { - self.strict_mode = true; - module.visit_mut_children_with(self) - } } /// The folder which handles var / function hoisting. @@ -1566,6 +1582,13 @@ impl VisitMut for Hoister<'_, '_> { return; } self.resolver.modify(&mut node.ident, DeclKind::Lexical); + + if self.resolver.config.handle_types { + self.resolver + .current + .declared_types + .insert(node.ident.sym.clone()); + } } #[inline] @@ -1679,18 +1702,39 @@ impl VisitMut for Hoister<'_, '_> { n.visit_mut_children_with(self); self.resolver.modify(&mut n.local, DeclKind::Lexical); + + if self.resolver.config.handle_types { + self.resolver + .current + .declared_types + .insert(n.local.sym.clone()); + } } fn visit_mut_import_named_specifier(&mut self, n: &mut ImportNamedSpecifier) { n.visit_mut_children_with(self); self.resolver.modify(&mut n.local, DeclKind::Lexical); + + if self.resolver.config.handle_types { + self.resolver + .current + .declared_types + .insert(n.local.sym.clone()); + } } fn visit_mut_import_star_as_specifier(&mut self, n: &mut ImportStarAsSpecifier) { n.visit_mut_children_with(self); self.resolver.modify(&mut n.local, DeclKind::Lexical); + + if self.resolver.config.handle_types { + self.resolver + .current + .declared_types + .insert(n.local.sym.clone()); + } } #[inline] diff --git a/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/input.ts b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/input.ts new file mode 100644 index 000000000000..b67921cda1a3 --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/input.ts @@ -0,0 +1,8 @@ +var x = 1 +function foo(x, y = function () { x = 2 }) { + var x = 3 + y() + expect(x).toBe(3); +} +foo() +expect(x).toBe(1); \ No newline at end of file diff --git a/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/output.ts b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/output.ts new file mode 100644 index 000000000000..fab600564a76 --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/1/output.ts @@ -0,0 +1,10 @@ +var x__1 = 1; +function foo__1(x__2, y__2 = function() { + x__2 = 2; +}) { + var x__2 = 3; + y__2(); + expect(x__2).toBe(3); +} +foo__1(); +expect(x__1).toBe(1); diff --git a/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/input.ts b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/input.ts new file mode 100644 index 000000000000..ecbea74c0fcf --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/input.ts @@ -0,0 +1,41 @@ +function left(a, b = a, c = b) { + a; + b; +} + +function right(a = b, b = a) { + a; + b; +} + +function right2(a = b, b = c, c = a) { + a; + b; + c; +} + +function inside(a = b) { + var b; +} + +function outside() { + var b; + function inside(a = b) { // Still an error because b is declared inside the function + var b; + } +} + +function defaultArgFunction(a = function () { return b; }, b = 1) { } +function defaultArgArrow(a = () => () => b, b = 3) { } + +class C { + constructor(a = b, b = 1) { } + method(a = b, b = 1) { } +} + +// Function expressions +var x = (a = b, b = c, c = d) => { var d; }; + +// Should not produce errors - can reference later parameters if they occur within a function expression initializer. +function f(a, b = function () { return c; }, c = b()) { +} \ No newline at end of file diff --git a/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts new file mode 100644 index 000000000000..326b886cdc50 --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts @@ -0,0 +1,36 @@ +function left__1(a__2, b__2 = a__2, c__2 = b__2) { + a__2; + b__2; +} +function right__1(a__3 = b__3, b__3 = a__3) { + a__3; + b__3; +} +function right2__1(a__4 = b__4, b__4 = c__4, c__4 = a__4) { + a__4; + b__4; + c__4; +} +function inside__1(a__5 = b) { + var b__5; +} +function outside__1() { + var b__7; + function inside__7(a__8 = b__7) { + var b__8; + } +} +function defaultArgFunction__1(a__9 = function() { + return b__9; +}, b__9 = 1) {} +function defaultArgArrow__1(a__10 = ()=>()=>b__10, b__10 = 3) {} +class C__1 { + constructor(a__11 = b, b__11 = 1){} + method(a__12 = b__12, b__12 = 1) {} +} +var x__1 = (a__13 = b, b__13 = c, c__13 = d)=>{ + var d__13; +}; +function f__1(a__14, b__14 = function() { + return c__14; +}, c__14 = b__14()) {}