From d037fd7b23da1d6ed75c3422294c5f37789cbfd3 Mon Sep 17 00:00:00 2001 From: Ayush7614 Date: Fri, 31 Jul 2026 15:33:26 +0530 Subject: [PATCH 1/4] fix(es/parser): enforce UniqueFormalParameters Reject duplicate formal parameter bindings for methods, setters, constructors, arrows, strict-mode functions, non-simple parameter lists, and functions whose body contains a use strict directive, matching ECMA-262 early errors while still allowing simple duplicate parameters in sloppy-mode functions. --- .changeset/unique-formal-parameters.md | 6 + crates/swc_ecma_parser/src/error.rs | 8 + .../src/parser/class_and_fn.rs | 12 +- crates/swc_ecma_parser/src/parser/expr.rs | 2 + crates/swc_ecma_parser/src/parser/object.rs | 2 +- crates/swc_ecma_parser/src/parser/pat.rs | 115 ++++++- .../unique-formal-params/arrow/input.js | 4 + .../arrow/input.js.swc-stderr | 26 ++ .../async-method/input.js | 1 + .../async-method/input.js.swc-stderr | 5 + .../class-constructor/input.js | 6 + .../class-constructor/input.js.swc-stderr | 14 + .../class-method/input.js | 6 + .../class-method/input.js.swc-stderr | 28 ++ .../generator-method/input.js | 1 + .../generator-method/input.js.swc-stderr | 5 + .../non-simple-fn/input.js | 4 + .../non-simple-fn/input.js.swc-stderr | 26 ++ .../object-method/input.js | 4 + .../object-method/input.js.swc-stderr | 26 ++ .../private-method/input.js | 3 + .../private-method/input.js.swc-stderr | 7 + .../setter-destructure/input.js | 4 + .../setter-destructure/input.js.swc-stderr | 13 + .../unique-formal-params/strict-fn/input.js | 4 + .../strict-fn/input.js.swc-stderr | 20 ++ .../use-strict-body/input.js | 9 + .../use-strict-body/input.js.swc-stderr | 20 ++ .../sloppy-simple-ok/input.cjs | 9 + .../sloppy-simple-ok/input.cjs.json | 283 ++++++++++++++++++ 30 files changed, 667 insertions(+), 6 deletions(-) create mode 100644 .changeset/unique-formal-parameters.md create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js create mode 100644 crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs create mode 100644 crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs.json diff --git a/.changeset/unique-formal-parameters.md b/.changeset/unique-formal-parameters.md new file mode 100644 index 000000000000..fdee3046300e --- /dev/null +++ b/.changeset/unique-formal-parameters.md @@ -0,0 +1,6 @@ +--- +swc_core: patch +swc_ecma_parser: patch +--- + +fix(es/parser): enforce UniqueFormalParameters for methods, arrows, and non-simple forms diff --git a/crates/swc_ecma_parser/src/error.rs b/crates/swc_ecma_parser/src/error.rs index 327936244382..9234a3930904 100644 --- a/crates/swc_ecma_parser/src/error.rs +++ b/crates/swc_ecma_parser/src/error.rs @@ -214,6 +214,10 @@ pub enum SyntaxError { DuplicatedRegExpFlags(char), UnknownRegExpFlags, + /// Duplicate binding in UniqueFormalParameters / non-simple + /// FormalParameters. + DuplicateFormalParameter(Atom), + TS1003, TS1005, TS1009, @@ -592,6 +596,10 @@ impl SyntaxError { } SyntaxError::UnknownRegExpFlags => "Unknown regular expression flags.".into(), + SyntaxError::DuplicateFormalParameter(name) => { + format!("Duplicate parameter name not allowed in this context: {name}").into() + } + SyntaxError::TS1003 => "Expected an identifier".into(), SyntaxError::TS1005 => "Expected a semicolon".into(), SyntaxError::TS1009 => "Trailing comma is not allowed".into(), diff --git a/crates/swc_ecma_parser/src/parser/class_and_fn.rs b/crates/swc_ecma_parser/src/parser/class_and_fn.rs index bb4915dc7b44..d061d5e1c5b7 100644 --- a/crates/swc_ecma_parser/src/parser/class_and_fn.rs +++ b/crates/swc_ecma_parser/src/parser/class_and_fn.rs @@ -348,6 +348,14 @@ impl Parser { params.is_simple_parameter_list(), )?; + // `function f(a, a) { "use strict"; }` is an early error even though + // the parameter list is simple and the outer context may be sloppy. + if let Some(body) = &body { + if params.is_simple_parameter_list() && has_use_strict(body).is_some() { + p.ensure_unique_formal_params(params.iter().map(|param| ¶m.pat)); + } + } + if p.syntax().flow() && body.is_none() && !p.ctx().contains(Context::InDeclare) { p.emit_err(p.input().cur_span(), SyntaxError::TS1005); } @@ -1293,7 +1301,7 @@ impl Parser { })); } else { return self.make_method( - Self::parse_formal_params, + Self::parse_unique_formal_params, MakeMethodArgs { start, is_optional, @@ -1448,7 +1456,7 @@ impl Parser { ), Token::Set => self.make_method( |p| { - let params = p.parse_formal_params()?; + let params = p.parse_unique_formal_params()?; if p.syntax().flow() && params.iter().any(|p| !is_not_this(p)) { p.emit_err(key_span, SyntaxError::TS1003); diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs index a7bdb5cb006d..7048593f343d 100644 --- a/crates/swc_ecma_parser/src/parser/expr.rs +++ b/crates/swc_ecma_parser/src/parser/expr.rs @@ -2716,6 +2716,8 @@ impl Parser { }; let validate_arrow_params = |p: &mut Self, params: &[Pat], is_async: bool| { + p.ensure_unique_formal_params(params.iter()); + for param in params { if is_async { match param { diff --git a/crates/swc_ecma_parser/src/parser/object.rs b/crates/swc_ecma_parser/src/parser/object.rs index d58aa4528eb7..d18423227b44 100644 --- a/crates/swc_ecma_parser/src/parser/object.rs +++ b/crates/swc_ecma_parser/src/parser/object.rs @@ -422,7 +422,7 @@ impl Parser { Vec::new(), start, |p| { - let params = p.parse_formal_params()?; + let params = p.parse_unique_formal_params()?; if params.iter().filter(|p| is_not_this(p)).count() != 1 { p.emit_err(key_span, SyntaxError::SetterParam); diff --git a/crates/swc_ecma_parser/src/parser/pat.rs b/crates/swc_ecma_parser/src/parser/pat.rs index 503faa7871af..65e7121953d2 100644 --- a/crates/swc_ecma_parser/src/parser/pat.rs +++ b/crates/swc_ecma_parser/src/parser/pat.rs @@ -1,9 +1,11 @@ //! 13.3.3 Destructuring Binding Patterns +use rustc_hash::FxHashSet; +use swc_atoms::Atom; use swc_common::Spanned; use super::*; -use crate::parser::{expr::AssignTargetOrSpread, Parser}; +use crate::parser::{expr::AssignTargetOrSpread, util::IsSimpleParameterList, Parser}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum PatType { @@ -77,6 +79,63 @@ impl Parser { } } + /// Enforce UniqueFormalParameters: BoundNames must not contain duplicates. + /// + /// Used for methods, setters, arrows, constructors, strict-mode functions, + /// and any FormalParameters list that is not a simple parameter list. + pub(crate) fn ensure_unique_formal_params<'a, Iter>(&mut self, pats: Iter) + where + Iter: IntoIterator, + { + let mut names = FxHashSet::default(); + for pat in pats { + self.collect_unique_formal_bindings(pat, &mut names); + } + } + + fn collect_unique_formal_bindings(&mut self, pat: &Pat, names: &mut FxHashSet) { + match pat { + Pat::Ident(i) => { + if !names.insert(i.id.sym.clone()) { + self.emit_err( + i.id.span, + SyntaxError::DuplicateFormalParameter(i.id.sym.clone()), + ); + } + } + Pat::Array(arr) => { + for elem in arr.elems.iter().flatten() { + self.collect_unique_formal_bindings(elem, names); + } + } + Pat::Rest(r) => self.collect_unique_formal_bindings(&r.arg, names), + Pat::Object(obj) => { + for prop in &obj.props { + match prop { + ObjectPatProp::KeyValue(KeyValuePatProp { value, .. }) + | ObjectPatProp::Rest(RestPat { arg: value, .. }) => { + self.collect_unique_formal_bindings(value, names); + } + ObjectPatProp::Assign(AssignPatProp { key, .. }) => { + if !names.insert(key.sym.clone()) { + self.emit_err( + key.span, + SyntaxError::DuplicateFormalParameter(key.sym.clone()), + ); + } + } + #[cfg(swc_ast_unknown)] + _ => unreachable!(), + } + } + } + Pat::Assign(a) => self.collect_unique_formal_bindings(&a.left, names), + Pat::Invalid(_) | Pat::Expr(_) => {} + #[cfg(swc_ast_unknown)] + _ => unreachable!(), + } + } + fn assign_pat_type_ann(&mut self, pat: &mut Pat, span: Span, type_ann: Box) { let type_ann = Some(Box::new(TsTypeAnn { span, type_ann })); @@ -767,6 +826,36 @@ impl Parser { } } + // Class constructors always use UniqueFormalParameters (class bodies are + // strict mode code). + { + let mut names = FxHashSet::default(); + for p in ¶ms { + match p { + ParamOrTsParamProp::Param(param) => { + self.collect_unique_formal_bindings(¶m.pat, &mut names); + } + ParamOrTsParamProp::TsParamProp(prop) => match &prop.param { + TsParamPropParam::Ident(i) => { + if !names.insert(i.id.sym.clone()) { + self.emit_err( + i.id.span, + SyntaxError::DuplicateFormalParameter(i.id.sym.clone()), + ); + } + } + TsParamPropParam::Assign(a) => { + self.collect_unique_formal_bindings(&a.left, &mut names); + } + #[cfg(swc_ast_unknown)] + _ => {} + }, + #[cfg(swc_ast_unknown)] + _ => {} + } + } + } + Ok(params) } @@ -867,12 +956,32 @@ impl Parser { } } + // UniqueFormalParameters / FormalParameters early errors: + // duplicate BoundNames are always illegal in strict mode, and also + // illegal whenever the parameter list is not simple. + if self.ctx().contains(Context::Strict) || !params.is_simple_parameter_list() { + self.ensure_unique_formal_params(params.iter().map(|p| &p.pat)); + } + + if self.ctx().contains(Context::Strict) { + for param in params.iter() { + self.pat_is_valid_argument_in_strict(¶m.pat) + } + } + Ok(params) } pub(crate) fn parse_unique_formal_params(&mut self) -> PResult> { - // FIXME: This is wrong - self.parse_formal_params() + let params = self.parse_formal_params()?; + // Methods / object methods always require UniqueFormalParameters, + // including simple duplicate bindings that sloppy-mode functions allow. + // `parse_formal_params` already checks when !simple or Strict; cover the + // remaining simple+non-strict case used by class/object methods. + if params.is_simple_parameter_list() && !self.ctx().contains(Context::Strict) { + self.ensure_unique_formal_params(params.iter().map(|p| &p.pat)); + } + Ok(params) } pub(super) fn parse_paren_items_as_params( diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js new file mode 100644 index 000000000000..da38adf25dd1 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js @@ -0,0 +1,4 @@ +(a, a) => a; +async (a, a) => a; +({a}, a) => a; +(a, a = 1) => a; diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js.swc-stderr new file mode 100644 index 000000000000..0f00444c87a0 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/arrow/input.js.swc-stderr @@ -0,0 +1,26 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/arrow/input.js:1:1] + 1 | (a, a) => a; + : ^ + 2 | async (a, a) => a; + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/arrow/input.js:2:1] + 1 | (a, a) => a; + 2 | async (a, a) => a; + : ^ + 3 | ({a}, a) => a; + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/arrow/input.js:3:1] + 2 | async (a, a) => a; + 3 | ({a}, a) => a; + : ^ + 4 | (a, a = 1) => a; + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/arrow/input.js:4:1] + 3 | ({a}, a) => a; + 4 | (a, a = 1) => a; + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js new file mode 100644 index 000000000000..cab591a7adc5 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js @@ -0,0 +1 @@ +({ async m(a, a) { return a; } }); diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js.swc-stderr new file mode 100644 index 000000000000..d2f86327da1f --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/async-method/input.js.swc-stderr @@ -0,0 +1,5 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/async-method/input.js:1:1] + 1 | ({ async m(a, a) { return a; } }); + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js new file mode 100644 index 000000000000..2287a506af32 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js @@ -0,0 +1,6 @@ +class C { + constructor(a, a) {} +} +class D { + constructor([a], a) {} +} diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js.swc-stderr new file mode 100644 index 000000000000..621938f33fd1 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-constructor/input.js.swc-stderr @@ -0,0 +1,14 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/class-constructor/input.js:2:1] + 1 | class C { + 2 | constructor(a, a) {} + : ^ + 3 | } + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/class-constructor/input.js:5:1] + 4 | class D { + 5 | constructor([a], a) {} + : ^ + 6 | } + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js new file mode 100644 index 000000000000..8434887da77a --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js @@ -0,0 +1,6 @@ +class C { + m(a, a) { return a; } + static m2(a, a) { return a; } + async m3(a, a) { return a; } + *m4(a, a) { return a; } +} diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js.swc-stderr new file mode 100644 index 000000000000..81341081831c --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/class-method/input.js.swc-stderr @@ -0,0 +1,28 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/class-method/input.js:2:1] + 1 | class C { + 2 | m(a, a) { return a; } + : ^ + 3 | static m2(a, a) { return a; } + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/class-method/input.js:3:1] + 2 | m(a, a) { return a; } + 3 | static m2(a, a) { return a; } + : ^ + 4 | async m3(a, a) { return a; } + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/class-method/input.js:4:1] + 3 | static m2(a, a) { return a; } + 4 | async m3(a, a) { return a; } + : ^ + 5 | *m4(a, a) { return a; } + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/class-method/input.js:5:1] + 4 | async m3(a, a) { return a; } + 5 | *m4(a, a) { return a; } + : ^ + 6 | } + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js new file mode 100644 index 000000000000..ef6fcc595ed1 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js @@ -0,0 +1 @@ +({ *m(a, a) { return a; } }); diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js.swc-stderr new file mode 100644 index 000000000000..d7b9d5a80e94 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/generator-method/input.js.swc-stderr @@ -0,0 +1,5 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/generator-method/input.js:1:1] + 1 | ({ *m(a, a) { return a; } }); + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js new file mode 100644 index 000000000000..75f6e9ebf34a --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js @@ -0,0 +1,4 @@ +function f([a], a) {} +function g({a}, a) {} +function h(a, a = 1) {} +function i(a = 1, a) {} diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js.swc-stderr new file mode 100644 index 000000000000..be1216a1a40c --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/non-simple-fn/input.js.swc-stderr @@ -0,0 +1,26 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/non-simple-fn/input.js:1:1] + 1 | function f([a], a) {} + : ^ + 2 | function g({a}, a) {} + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/non-simple-fn/input.js:2:1] + 1 | function f([a], a) {} + 2 | function g({a}, a) {} + : ^ + 3 | function h(a, a = 1) {} + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/non-simple-fn/input.js:3:1] + 2 | function g({a}, a) {} + 3 | function h(a, a = 1) {} + : ^ + 4 | function i(a = 1, a) {} + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/non-simple-fn/input.js:4:1] + 3 | function h(a, a = 1) {} + 4 | function i(a = 1, a) {} + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js new file mode 100644 index 000000000000..df6d462290f7 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js @@ -0,0 +1,4 @@ +({ m(a, a) { return a; } }); +({ m([a], a) { return a; } }); +({ m({a}, a) { return a; } }); +({ m(a, a = 1) { return a; } }); diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js.swc-stderr new file mode 100644 index 000000000000..b2d2042403c2 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/object-method/input.js.swc-stderr @@ -0,0 +1,26 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/object-method/input.js:1:1] + 1 | ({ m(a, a) { return a; } }); + : ^ + 2 | ({ m([a], a) { return a; } }); + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/object-method/input.js:2:1] + 1 | ({ m(a, a) { return a; } }); + 2 | ({ m([a], a) { return a; } }); + : ^ + 3 | ({ m({a}, a) { return a; } }); + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/object-method/input.js:3:1] + 2 | ({ m([a], a) { return a; } }); + 3 | ({ m({a}, a) { return a; } }); + : ^ + 4 | ({ m(a, a = 1) { return a; } }); + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/object-method/input.js:4:1] + 3 | ({ m({a}, a) { return a; } }); + 4 | ({ m(a, a = 1) { return a; } }); + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js new file mode 100644 index 000000000000..7bdf8768e9a1 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js @@ -0,0 +1,3 @@ +class C { + #m(a, a) { return a; } +} diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js.swc-stderr new file mode 100644 index 000000000000..f474e580b4f2 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/private-method/input.js.swc-stderr @@ -0,0 +1,7 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/private-method/input.js:2:1] + 1 | class C { + 2 | #m(a, a) { return a; } + : ^ + 3 | } + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js new file mode 100644 index 000000000000..87a79e716ff8 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js @@ -0,0 +1,4 @@ +({ set x({a, a}) {} }); +class C { + set x({a, a}) {} +} diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js.swc-stderr new file mode 100644 index 000000000000..6357a016cf97 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/setter-destructure/input.js.swc-stderr @@ -0,0 +1,13 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/setter-destructure/input.js:1:1] + 1 | ({ set x({a, a}) {} }); + : ^ + 2 | class C { + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/setter-destructure/input.js:3:1] + 2 | class C { + 3 | set x({a, a}) {} + : ^ + 4 | } + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js new file mode 100644 index 000000000000..641233302145 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js @@ -0,0 +1,4 @@ +"use strict"; +function f(a, a) {} +async function g(a, a) {} +function* h(a, a) {} diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js.swc-stderr new file mode 100644 index 000000000000..f69024fffbdb --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/strict-fn/input.js.swc-stderr @@ -0,0 +1,20 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/strict-fn/input.js:2:1] + 1 | "use strict"; + 2 | function f(a, a) {} + : ^ + 3 | async function g(a, a) {} + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/strict-fn/input.js:3:1] + 2 | function f(a, a) {} + 3 | async function g(a, a) {} + : ^ + 4 | function* h(a, a) {} + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/strict-fn/input.js:4:1] + 3 | async function g(a, a) {} + 4 | function* h(a, a) {} + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js b/crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js new file mode 100644 index 000000000000..3f66f5b7c56c --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js @@ -0,0 +1,9 @@ +function f(a, a) { + "use strict"; +} +async function g(a, a) { + "use strict"; +} +function* h(a, a) { + "use strict"; +} diff --git a/crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js.swc-stderr b/crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js.swc-stderr new file mode 100644 index 000000000000..cb8485c128c4 --- /dev/null +++ b/crates/swc_ecma_parser/tests/errors/unique-formal-params/use-strict-body/input.js.swc-stderr @@ -0,0 +1,20 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/use-strict-body/input.js:1:1] + 1 | function f(a, a) { + : ^ + 2 | "use strict"; + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/use-strict-body/input.js:4:1] + 3 | } + 4 | async function g(a, a) { + : ^ + 5 | "use strict"; + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/errors/unique-formal-params/use-strict-body/input.js:7:1] + 6 | } + 7 | function* h(a, a) { + : ^ + 8 | "use strict"; + `---- diff --git a/crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs b/crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs new file mode 100644 index 000000000000..3d66b957abf7 --- /dev/null +++ b/crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs @@ -0,0 +1,9 @@ +function f(a, a) { + return a; +} +function* g(a, a) { + return a; +} +async function h(a, a) { + return a; +} diff --git a/crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs.json b/crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs.json new file mode 100644 index 000000000000..efa9840ae215 --- /dev/null +++ b/crates/swc_ecma_parser/tests/js/unique-formal-params/sloppy-simple-ok/input.cjs.json @@ -0,0 +1,283 @@ +{ + "type": "Script", + "span": { + "start": 1, + "end": 106 + }, + "body": [ + { + "type": "FunctionDeclaration", + "identifier": { + "type": "Identifier", + "span": { + "start": 10, + "end": 11 + }, + "ctxt": 0, + "value": "f", + "optional": false + }, + "declare": false, + "params": [ + { + "type": "Parameter", + "span": { + "start": 12, + "end": 13 + }, + "decorators": [], + "pat": { + "type": "Identifier", + "span": { + "start": 12, + "end": 13 + }, + "ctxt": 0, + "value": "a", + "optional": false, + "typeAnnotation": null + } + }, + { + "type": "Parameter", + "span": { + "start": 15, + "end": 16 + }, + "decorators": [], + "pat": { + "type": "Identifier", + "span": { + "start": 15, + "end": 16 + }, + "ctxt": 0, + "value": "a", + "optional": false, + "typeAnnotation": null + } + } + ], + "decorators": [], + "span": { + "start": 1, + "end": 33 + }, + "ctxt": 0, + "body": { + "type": "BlockStatement", + "span": { + "start": 18, + "end": 33 + }, + "ctxt": 0, + "stmts": [ + { + "type": "ReturnStatement", + "span": { + "start": 22, + "end": 31 + }, + "argument": { + "type": "Identifier", + "span": { + "start": 29, + "end": 30 + }, + "ctxt": 0, + "value": "a", + "optional": false + } + } + ] + }, + "generator": false, + "async": false, + "typeParameters": null, + "returnType": null + }, + { + "type": "FunctionDeclaration", + "identifier": { + "type": "Identifier", + "span": { + "start": 44, + "end": 45 + }, + "ctxt": 0, + "value": "g", + "optional": false + }, + "declare": false, + "params": [ + { + "type": "Parameter", + "span": { + "start": 46, + "end": 47 + }, + "decorators": [], + "pat": { + "type": "Identifier", + "span": { + "start": 46, + "end": 47 + }, + "ctxt": 0, + "value": "a", + "optional": false, + "typeAnnotation": null + } + }, + { + "type": "Parameter", + "span": { + "start": 49, + "end": 50 + }, + "decorators": [], + "pat": { + "type": "Identifier", + "span": { + "start": 49, + "end": 50 + }, + "ctxt": 0, + "value": "a", + "optional": false, + "typeAnnotation": null + } + } + ], + "decorators": [], + "span": { + "start": 34, + "end": 67 + }, + "ctxt": 0, + "body": { + "type": "BlockStatement", + "span": { + "start": 52, + "end": 67 + }, + "ctxt": 0, + "stmts": [ + { + "type": "ReturnStatement", + "span": { + "start": 56, + "end": 65 + }, + "argument": { + "type": "Identifier", + "span": { + "start": 63, + "end": 64 + }, + "ctxt": 0, + "value": "a", + "optional": false + } + } + ] + }, + "generator": true, + "async": false, + "typeParameters": null, + "returnType": null + }, + { + "type": "FunctionDeclaration", + "identifier": { + "type": "Identifier", + "span": { + "start": 83, + "end": 84 + }, + "ctxt": 0, + "value": "h", + "optional": false + }, + "declare": false, + "params": [ + { + "type": "Parameter", + "span": { + "start": 85, + "end": 86 + }, + "decorators": [], + "pat": { + "type": "Identifier", + "span": { + "start": 85, + "end": 86 + }, + "ctxt": 0, + "value": "a", + "optional": false, + "typeAnnotation": null + } + }, + { + "type": "Parameter", + "span": { + "start": 88, + "end": 89 + }, + "decorators": [], + "pat": { + "type": "Identifier", + "span": { + "start": 88, + "end": 89 + }, + "ctxt": 0, + "value": "a", + "optional": false, + "typeAnnotation": null + } + } + ], + "decorators": [], + "span": { + "start": 68, + "end": 106 + }, + "ctxt": 0, + "body": { + "type": "BlockStatement", + "span": { + "start": 91, + "end": 106 + }, + "ctxt": 0, + "stmts": [ + { + "type": "ReturnStatement", + "span": { + "start": 95, + "end": 104 + }, + "argument": { + "type": "Identifier", + "span": { + "start": 102, + "end": 103 + }, + "ctxt": 0, + "value": "a", + "optional": false + } + } + ] + }, + "generator": false, + "async": true, + "typeParameters": null, + "returnType": null + } + ], + "interpreter": null +} From be8a1cde5d3ee7560240540a7877cc0e617adff6 Mon Sep 17 00:00:00 2001 From: Ayush7614 Date: Fri, 31 Jul 2026 16:17:00 +0530 Subject: [PATCH 2/4] test: update fixtures for UniqueFormalParameters errors Align no-dupe-args and test262 error snapshots with parser-emitted duplicate formal parameter diagnostics. --- .../lints/no-dupe-args/2/output.swc-stderr | 53 +- .../lints/no-dupe-args/3/output.swc-stderr | 18 +- .../lints/no-dupe-args/4/output.swc-stderr | 18 +- .../no-dupe-args/hash-mode/output.swc-stderr | 480 +++++------------- .../fail/5fae862d7fe6531c.js.swc-stderr | 5 + 5 files changed, 151 insertions(+), 423 deletions(-) diff --git a/crates/swc/tests/errors/lints/no-dupe-args/2/output.swc-stderr b/crates/swc/tests/errors/lints/no-dupe-args/2/output.swc-stderr index 19f9cd9d6bec..e820645c5c03 100644 --- a/crates/swc/tests/errors/lints/no-dupe-args/2/output.swc-stderr +++ b/crates/swc/tests/errors/lints/no-dupe-args/2/output.swc-stderr @@ -1,93 +1,68 @@ - x the name `b` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: b ,-[1:1] 1 | const foo = (a, b, b) => {}; - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 2 | (a, b, b) => {}; 3 | ((a, b, b) => {})(); `---- - x the name `b` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: b ,-[2:1] 1 | const foo = (a, b, b) => {}; 2 | (a, b, b) => {}; - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 3 | ((a, b, b) => {})(); 4 | 5 | class Bar { `---- - x the name `b` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: b ,-[3:1] 1 | const foo = (a, b, b) => {}; 2 | (a, b, b) => {}; 3 | ((a, b, b) => {})(); - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 4 | 5 | class Bar { 6 | constructor(a, b, b) {} `---- - x the name `b` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: b ,-[6:1] 3 | ((a, b, b) => {})(); 4 | 5 | class Bar { 6 | constructor(a, b, b) {} - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 7 | 8 | foo = (a, b, b) => {}; `---- - x the name `b` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: b ,-[8:1] 5 | class Bar { 6 | constructor(a, b, b) {} 7 | 8 | foo = (a, b, b) => {}; - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 9 | 10 | bar(a, b, b) {} 11 | } `---- - x the name `b` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: b ,-[10:1] 7 | 8 | foo = (a, b, b) => {}; 9 | 10 | bar(a, b, b) {} - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 11 | } 12 | 13 | const baz = { `---- - x the name `b` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: b ,-[14:1] 11 | } 12 | 13 | const baz = { 14 | foo(a, b, b) {}, - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 15 | bar: function (a, b, b) {}, 16 | }; `---- - x the name `b` is bound more than once in this parameter list - ,-[15:1] - 12 | - 13 | const baz = { - 14 | foo(a, b, b) {}, - 15 | bar: function (a, b, b) {}, - : | | - : | `-- used as parameter more than once - : `-- previous definition here - 16 | }; - `---- diff --git a/crates/swc/tests/errors/lints/no-dupe-args/3/output.swc-stderr b/crates/swc/tests/errors/lints/no-dupe-args/3/output.swc-stderr index 976e7d5df65e..35da82ddd2f6 100644 --- a/crates/swc/tests/errors/lints/no-dupe-args/3/output.swc-stderr +++ b/crates/swc/tests/errors/lints/no-dupe-args/3/output.swc-stderr @@ -1,27 +1,21 @@ - x the name `a` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: a ,-[1:1] 1 | function foo(a, b, [a]) {} - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 2 | function bar(a, b, ...a) {} 3 | function baz({ a }, b, { c: [a] }) {} `---- - x the name `a` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: a ,-[2:1] 1 | function foo(a, b, [a]) {} 2 | function bar(a, b, ...a) {} - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 3 | function baz({ a }, b, { c: [a] }) {} `---- - x the name `a` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: a ,-[3:1] 1 | function foo(a, b, [a]) {} 2 | function bar(a, b, ...a) {} 3 | function baz({ a }, b, { c: [a] }) {} - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ `---- diff --git a/crates/swc/tests/errors/lints/no-dupe-args/4/output.swc-stderr b/crates/swc/tests/errors/lints/no-dupe-args/4/output.swc-stderr index 80670cb2623d..70a0fb1fa353 100644 --- a/crates/swc/tests/errors/lints/no-dupe-args/4/output.swc-stderr +++ b/crates/swc/tests/errors/lints/no-dupe-args/4/output.swc-stderr @@ -1,32 +1,26 @@ - x the name `a` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: a ,-[1:1] 1 | function foo(a, b, [a]) { - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 2 | function bar(c, d, ...d) { 3 | function baz({ e }, f, { f: [e] }) {} 4 | } `---- - x the name `d` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: d ,-[2:1] 1 | function foo(a, b, [a]) { 2 | function bar(c, d, ...d) { - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 3 | function baz({ e }, f, { f: [e] }) {} 4 | } 5 | } `---- - x the name `e` is bound more than once in this parameter list + x Duplicate parameter name not allowed in this context: e ,-[3:1] 1 | function foo(a, b, [a]) { 2 | function bar(c, d, ...d) { 3 | function baz({ e }, f, { f: [e] }) {} - : | | - : | `-- used as parameter more than once - : `-- previous definition here + : ^ 4 | } 5 | } `---- diff --git a/crates/swc/tests/errors/lints/no-dupe-args/hash-mode/output.swc-stderr b/crates/swc/tests/errors/lints/no-dupe-args/hash-mode/output.swc-stderr index bdc28ca2314e..a2c3bdb131ae 100644 --- a/crates/swc/tests/errors/lints/no-dupe-args/hash-mode/output.swc-stderr +++ b/crates/swc/tests/errors/lints/no-dupe-args/hash-mode/output.swc-stderr @@ -1,640 +1,400 @@ - x the name `a0` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a0 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a1` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a1 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a2` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a2 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a3` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a3 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a4` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a4 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a5` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a5 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a6` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a6 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a7` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a7 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a8` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a8 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a9` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: a9 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b0` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b0 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b1` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b1 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b2` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b2 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b3` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b3 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b4` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b4 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b5` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b5 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b6` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b6 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b7` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b7 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b8` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b8 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `b9` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here + x Duplicate parameter name not allowed in this context: b9 + ,-[6:1] 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- used as parameter more than once + : ^^ 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { `---- - x the name `a0` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a0 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a1` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a1 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a2` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a2 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a3` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a3 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a4` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a4 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a5` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a5 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a6` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a6 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a7` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a7 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a8` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a8 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `a9` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: a9 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b0` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b0 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b1` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b1 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b2` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b2 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b3` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b3 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b4` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b4 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b5` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b5 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b6` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b6 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b7` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b7 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b8` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b8 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- - x the name `b9` is bound more than once in this parameter list - ,-[2:1] - 1 | function foo( - 2 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], - : ^| - : `-- previous definition here - 3 | [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9], [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], - 4 | [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9], [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9], + x Duplicate parameter name not allowed in this context: b9 + ,-[8:1] 5 | [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9], [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9], 6 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9], 7 | [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9], [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9], 8 | [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9], [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9],) { - : ^| - : `-- used as parameter more than once + : ^^ 9 | 10 | } `---- diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/5fae862d7fe6531c.js.swc-stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/5fae862d7fe6531c.js.swc-stderr index 94f10374e907..0f147dabf73e 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/5fae862d7fe6531c.js.swc-stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/5fae862d7fe6531c.js.swc-stderr @@ -3,3 +3,8 @@ 1 | ({a = 0}, {a = 0}, 0) => 0 : ^ `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/test262-parser/fail/5fae862d7fe6531c.js:1:1] + 1 | ({a = 0}, {a = 0}, 0) => 0 + : ^ + `---- From b6d45d674a4f0fc328aba6c60c55921b7d549f1f Mon Sep 17 00:00:00 2001 From: Ayush7614 Date: Fri, 31 Jul 2026 17:34:58 +0530 Subject: [PATCH 3/4] fix(es/parser): cover remaining UniqueFormalParameters paths Apply uniqueness checks after speculative TS arrow parses leave IgnoreError, buffer simple-list duplicates for auto-detected modules, and cover conditional typed / generic async arrow parsers. --- crates/swc_ecma_parser/src/parser/expr.rs | 89 +++++++++------ crates/swc_ecma_parser/src/parser/pat.rs | 103 ++++++++++++------ crates/swc_ecma_parser/src/parser/tests.rs | 12 ++ .../swc_ecma_parser/src/parser/typescript.rs | 4 + .../async-generic-arrow/input.ts | 1 + .../async-generic-arrow/input.ts.swc-stderr | 5 + .../cond-typed-arrow/input.ts | 1 + .../cond-typed-arrow/input.ts.swc-stderr | 5 + .../generic-arrow/input.ts | 1 + .../generic-arrow/input.ts.swc-stderr | 5 + .../unique-formal-params/simple-fn/input.ts | 1 + .../simple-fn/input.ts.swc-stderr | 5 + 12 files changed, 168 insertions(+), 64 deletions(-) create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts.swc-stderr create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts.swc-stderr diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs index 7048593f343d..fe928163dd44 100644 --- a/crates/swc_ecma_parser/src/parser/expr.rs +++ b/crates/swc_ecma_parser/src/parser/expr.rs @@ -159,6 +159,11 @@ impl Parser { }) }); if let Some(res) = res { + // try_parse_ts sets IgnoreError while parsing the arrow body; + // re-validate UniqueFormalParameters after the parse commits. + if let Expr::Arrow(ref arrow) = *res { + self.validate_arrow_params(&arrow.params, arrow.is_async); + } if syntax.disallow_ambiguous_jsx_like() { self.emit_err(start, SyntaxError::ReservedArrowTypeParam); } @@ -1306,8 +1311,12 @@ impl Parser { }) }); - if let Some(expr) = result { - return Ok(expr); + if let Some((expr, done)) = result { + // Nested try_parse_ts sets IgnoreError; re-validate after commit. + if let Expr::Arrow(ref arrow) = *expr { + self.validate_arrow_params(&arrow.params, arrow.is_async); + } + return Ok((expr, done)); } } } @@ -2577,6 +2586,7 @@ impl Parser { } } { let params: Vec = self.parse_paren_items_as_params(items.clone(), None)?; + self.validate_arrow_params(¶ms, is_async); let body: Box = self.parse_fn_block_or_expr_body( false, @@ -2614,6 +2624,40 @@ impl Parser { Ok((items, trailing_comma)) } + /// Validate arrow-function parameters (UniqueFormalParameters and + /// async/generator early errors). Safe to call after a speculative + /// `try_parse_ts` commits, since that path sets `IgnoreError` during + /// the speculative parse. + pub(crate) fn validate_arrow_params(&mut self, params: &[Pat], is_async: bool) { + self.ensure_unique_formal_params(params.iter()); + + for param in params { + if is_async { + match param { + Pat::Ident(BindingIdent { id, .. }) if id.sym == *"await" => { + self.emit_err(id.span, SyntaxError::ExpectedIdent); + } + Pat::Assign(AssignPat { right, .. }) + if matches!(right.as_ref(), Expr::Await(..)) => + { + self.emit_err(right.span(), SyntaxError::AwaitParamInAsync); + } + _ => {} + } + } + + if self.ctx().contains(Context::InGenerator) + && matches!( + param, + Pat::Assign(AssignPat { right, .. }) + if matches!(right.as_ref(), Expr::Yield(..)) + ) + { + self.emit_err(param.span(), SyntaxError::YieldParamInGen); + } + } + } + #[cfg_attr( all(debug_assertions, feature = "tracing-spans"), tracing::instrument(level = "debug", skip_all) @@ -2688,6 +2732,12 @@ impl Parser { .into(), )) }) { + // try_parse_ts sets IgnoreError; re-check UniqueFormalParameters + // after the speculative parse commits. + let expr: Box = expr; + if let Expr::Arrow(ref arrow) = *expr { + self.validate_arrow_params(&arrow.params, arrow.is_async); + } return Ok(expr); } } @@ -2715,36 +2765,6 @@ impl Parser { None }; - let validate_arrow_params = |p: &mut Self, params: &[Pat], is_async: bool| { - p.ensure_unique_formal_params(params.iter()); - - for param in params { - if is_async { - match param { - Pat::Ident(BindingIdent { id, .. }) if id.sym == *"await" => { - p.emit_err(id.span, SyntaxError::ExpectedIdent); - } - Pat::Assign(AssignPat { right, .. }) - if matches!(right.as_ref(), Expr::Await(..)) => - { - p.emit_err(right.span(), SyntaxError::AwaitParamInAsync); - } - _ => {} - } - } - - if p.ctx().contains(Context::InGenerator) - && matches!( - param, - Pat::Assign(AssignPat { right, .. }) - if matches!(right.as_ref(), Expr::Yield(..)) - ) - { - p.emit_err(param.span(), SyntaxError::YieldParamInGen); - } - } - }; - // we parse arrow function at here, to handle it efficiently. if has_pattern || return_type.is_some() || self.input().is(Token::Arrow) { if self.input().had_line_break_before_cur() { @@ -2761,7 +2781,7 @@ impl Parser { expect!(self, Token::Arrow); let params: Vec = self.parse_paren_items_as_params(paren_items, trailing_comma)?; - validate_arrow_params(self, ¶ms, async_span.is_some()); + self.validate_arrow_params(¶ms, async_span.is_some()); let body: Box = self.parse_fn_block_or_expr_body( async_span.is_some(), @@ -3133,6 +3153,9 @@ impl Parser { p.assert_and_bump(Token::Async); p.try_parse_ts_generic_async_arrow_fn(start) }) { + // Outer try_parse_ts sets IgnoreError; UniqueFormalParameters must be + // checked after the speculative parse commits. + self.validate_arrow_params(&res.params, res.is_async); return Some(Ok(res.into())); } } diff --git a/crates/swc_ecma_parser/src/parser/pat.rs b/crates/swc_ecma_parser/src/parser/pat.rs index 65e7121953d2..8581a214156d 100644 --- a/crates/swc_ecma_parser/src/parser/pat.rs +++ b/crates/swc_ecma_parser/src/parser/pat.rs @@ -81,46 +81,76 @@ impl Parser { /// Enforce UniqueFormalParameters: BoundNames must not contain duplicates. /// - /// Used for methods, setters, arrows, constructors, strict-mode functions, - /// and any FormalParameters list that is not a simple parameter list. + /// Used for methods, setters, arrows, constructors, and any + /// FormalParameters list that is not a simple parameter list. Reports + /// immediately. pub(crate) fn ensure_unique_formal_params<'a, Iter>(&mut self, pats: Iter) + where + Iter: IntoIterator, + { + self.ensure_unique_formal_params_inner(pats, false); + } + + /// Like [`Self::ensure_unique_formal_params`], but buffers the diagnostic + /// for auto-detected modules (and reports immediately in strict / + /// module code). + /// + /// Simple FormalParameters are only illegal in strict/module code. While + /// `parse_program` is still treating the file as a script, record the error + /// via [`Self::emit_strict_mode_err`] so a later `import`/`export` promotes + /// it. + pub(crate) fn ensure_unique_formal_params_strict<'a, Iter>(&mut self, pats: Iter) + where + Iter: IntoIterator, + { + self.ensure_unique_formal_params_inner(pats, true); + } + + fn ensure_unique_formal_params_inner<'a, Iter>(&mut self, pats: Iter, strict_or_module: bool) where Iter: IntoIterator, { let mut names = FxHashSet::default(); for pat in pats { - self.collect_unique_formal_bindings(pat, &mut names); + self.collect_unique_formal_bindings(pat, &mut names, strict_or_module); } } - fn collect_unique_formal_bindings(&mut self, pat: &Pat, names: &mut FxHashSet) { + fn collect_unique_formal_bindings( + &mut self, + pat: &Pat, + names: &mut FxHashSet, + strict_or_module: bool, + ) { match pat { Pat::Ident(i) => { if !names.insert(i.id.sym.clone()) { - self.emit_err( + self.emit_duplicate_formal_parameter( i.id.span, - SyntaxError::DuplicateFormalParameter(i.id.sym.clone()), + i.id.sym.clone(), + strict_or_module, ); } } Pat::Array(arr) => { for elem in arr.elems.iter().flatten() { - self.collect_unique_formal_bindings(elem, names); + self.collect_unique_formal_bindings(elem, names, strict_or_module); } } - Pat::Rest(r) => self.collect_unique_formal_bindings(&r.arg, names), + Pat::Rest(r) => self.collect_unique_formal_bindings(&r.arg, names, strict_or_module), Pat::Object(obj) => { for prop in &obj.props { match prop { ObjectPatProp::KeyValue(KeyValuePatProp { value, .. }) | ObjectPatProp::Rest(RestPat { arg: value, .. }) => { - self.collect_unique_formal_bindings(value, names); + self.collect_unique_formal_bindings(value, names, strict_or_module); } ObjectPatProp::Assign(AssignPatProp { key, .. }) => { if !names.insert(key.sym.clone()) { - self.emit_err( + self.emit_duplicate_formal_parameter( key.span, - SyntaxError::DuplicateFormalParameter(key.sym.clone()), + key.sym.clone(), + strict_or_module, ); } } @@ -129,13 +159,22 @@ impl Parser { } } } - Pat::Assign(a) => self.collect_unique_formal_bindings(&a.left, names), + Pat::Assign(a) => self.collect_unique_formal_bindings(&a.left, names, strict_or_module), Pat::Invalid(_) | Pat::Expr(_) => {} #[cfg(swc_ast_unknown)] _ => unreachable!(), } } + fn emit_duplicate_formal_parameter(&mut self, span: Span, name: Atom, strict_or_module: bool) { + let err = SyntaxError::DuplicateFormalParameter(name); + if strict_or_module { + self.emit_strict_mode_err(span, err); + } else { + self.emit_err(span, err); + } + } + fn assign_pat_type_ann(&mut self, pat: &mut Pat, span: Span, type_ann: Box) { let type_ann = Some(Box::new(TsTypeAnn { span, type_ann })); @@ -833,19 +872,20 @@ impl Parser { for p in ¶ms { match p { ParamOrTsParamProp::Param(param) => { - self.collect_unique_formal_bindings(¶m.pat, &mut names); + self.collect_unique_formal_bindings(¶m.pat, &mut names, false); } ParamOrTsParamProp::TsParamProp(prop) => match &prop.param { TsParamPropParam::Ident(i) => { if !names.insert(i.id.sym.clone()) { - self.emit_err( + self.emit_duplicate_formal_parameter( i.id.span, - SyntaxError::DuplicateFormalParameter(i.id.sym.clone()), + i.id.sym.clone(), + false, ); } } TsParamPropParam::Assign(a) => { - self.collect_unique_formal_bindings(&a.left, &mut names); + self.collect_unique_formal_bindings(&a.left, &mut names, false); } #[cfg(swc_ast_unknown)] _ => {} @@ -860,6 +900,16 @@ impl Parser { } pub(crate) fn parse_formal_params(&mut self) -> PResult> { + self.parse_formal_params_with(false) + } + + pub(crate) fn parse_unique_formal_params(&mut self) -> PResult> { + // Methods / object methods always require UniqueFormalParameters, + // including simple duplicate bindings that sloppy-mode functions allow. + self.parse_formal_params_with(true) + } + + fn parse_formal_params_with(&mut self, always_unique: bool) -> PResult> { let mut params = Vec::new(); let mut rest_span = Span::default(); @@ -957,10 +1007,13 @@ impl Parser { } // UniqueFormalParameters / FormalParameters early errors: - // duplicate BoundNames are always illegal in strict mode, and also - // illegal whenever the parameter list is not simple. - if self.ctx().contains(Context::Strict) || !params.is_simple_parameter_list() { + // non-simple lists always forbid duplicates; simple lists only forbid + // them in strict/module code (buffered for auto-detected modules), + // unless always_unique (methods / setters). + if always_unique || !params.is_simple_parameter_list() { self.ensure_unique_formal_params(params.iter().map(|p| &p.pat)); + } else { + self.ensure_unique_formal_params_strict(params.iter().map(|p| &p.pat)); } if self.ctx().contains(Context::Strict) { @@ -972,18 +1025,6 @@ impl Parser { Ok(params) } - pub(crate) fn parse_unique_formal_params(&mut self) -> PResult> { - let params = self.parse_formal_params()?; - // Methods / object methods always require UniqueFormalParameters, - // including simple duplicate bindings that sloppy-mode functions allow. - // `parse_formal_params` already checks when !simple or Strict; cover the - // remaining simple+non-strict case used by class/object methods. - if params.is_simple_parameter_list() && !self.ctx().contains(Context::Strict) { - self.ensure_unique_formal_params(params.iter().map(|p| &p.pat)); - } - Ok(params) - } - pub(super) fn parse_paren_items_as_params( &mut self, mut exprs: Vec, diff --git a/crates/swc_ecma_parser/src/parser/tests.rs b/crates/swc_ecma_parser/src/parser/tests.rs index c984d9c41a05..08013ae374ad 100644 --- a/crates/swc_ecma_parser/src/parser/tests.rs +++ b/crates/swc_ecma_parser/src/parser/tests.rs @@ -65,6 +65,18 @@ fn parse_program_module_02() { ); } +#[test] +fn parse_program_duplicate_params_promoted_to_module() { + // Simple duplicate params are buffered until an export turns the file into a + // module. + assert_module_error( + " + function f(a, a) {} + export {}; + ", + ); +} + #[test] fn parse_program_module_error_01() { assert_module_error( diff --git a/crates/swc_ecma_parser/src/parser/typescript.rs b/crates/swc_ecma_parser/src/parser/typescript.rs index 4b1d4de9627d..6539cb19198b 100644 --- a/crates/swc_ecma_parser/src/parser/typescript.rs +++ b/crates/swc_ecma_parser/src/parser/typescript.rs @@ -5260,6 +5260,10 @@ impl Parser { None => return Ok(None), }; + // try_parse_ts sets IgnoreError; emit UniqueFormalParameters diagnostics + // only after the speculative parse commits. + self.validate_arrow_params(¶ms, true); + self.do_inside_of_context(Context::InAsync, |p| { p.do_outside_of_context(Context::InGenerator, |p| { let is_generator = false; diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts new file mode 100644 index 000000000000..029a9912a13b --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts @@ -0,0 +1 @@ +const f = async (a, a) => a; diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts.swc-stderr b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts.swc-stderr new file mode 100644 index 000000000000..9f2b6831e0de --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts.swc-stderr @@ -0,0 +1,5 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/typescript-errors/unique-formal-params/async-generic-arrow/input.ts:1:1] + 1 | const f = async (a, a) => a; + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts new file mode 100644 index 000000000000..f72c3abd5e3c --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts @@ -0,0 +1 @@ +const x = true ? (a, a): number => a : 0; diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts.swc-stderr b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts.swc-stderr new file mode 100644 index 000000000000..9ee2e95ab5df --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts.swc-stderr @@ -0,0 +1,5 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/typescript-errors/unique-formal-params/cond-typed-arrow/input.ts:1:1] + 1 | const x = true ? (a, a): number => a : 0; + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts new file mode 100644 index 000000000000..13c3bb22ceed --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts @@ -0,0 +1 @@ +const f = (a, a) => a; diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts.swc-stderr b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts.swc-stderr new file mode 100644 index 000000000000..dbce664be98b --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts.swc-stderr @@ -0,0 +1,5 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/typescript-errors/unique-formal-params/generic-arrow/input.ts:1:1] + 1 | const f = (a, a) => a; + : ^ + `---- diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts new file mode 100644 index 000000000000..1ed555a8987d --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts @@ -0,0 +1 @@ +function f(a, a) {} diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts.swc-stderr b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts.swc-stderr new file mode 100644 index 000000000000..be7b7cb40343 --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/simple-fn/input.ts.swc-stderr @@ -0,0 +1,5 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/typescript-errors/unique-formal-params/simple-fn/input.ts:1:1] + 1 | function f(a, a) {} + : ^ + `---- From f62a9349411d88fe7f975be5337b76e30d4338c1 Mon Sep 17 00:00:00 2001 From: Ayush7614 Date: Fri, 31 Jul 2026 20:44:53 +0530 Subject: [PATCH 4/4] fix(es/parser): honor no_early_errors and recheck TSX arrows emit_strict_mode_err must respect TsSyntax::no_early_errors like emit_err. Outer TSX try_parse_ts also sets IgnoreError, so re-run validate_arrow_params after that speculative parse commits. --- crates/swc_ecma_parser/src/parser/expr.rs | 6 ++++++ crates/swc_ecma_parser/src/parser/mod.rs | 2 +- crates/swc_ecma_parser/src/parser/tests.rs | 18 ++++++++++++++++++ .../tsx/generic-arrow/input.tsx | 2 ++ .../tsx/generic-arrow/input.tsx.swc-stderr | 12 ++++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx create mode 100644 crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx.swc-stderr diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs index fe928163dd44..bf2f78d45352 100644 --- a/crates/swc_ecma_parser/src/parser/expr.rs +++ b/crates/swc_ecma_parser/src/parser/expr.rs @@ -81,6 +81,12 @@ impl Parser { // syntax. let res = self.try_parse_ts(|p| p.parse_assignment_expr_base().map(Some)); if let Some(res) = res { + // Outer try_parse_ts sets IgnoreError, so UniqueFormalParameters + // checks inside parse_assignment_expr_base were discarded. Re-check + // after the speculative TSX generic-arrow parse commits. + if let Expr::Arrow(ref arrow) = *res { + self.validate_arrow_params(&arrow.params, arrow.is_async); + } return Ok(res); } } diff --git a/crates/swc_ecma_parser/src/parser/mod.rs b/crates/swc_ecma_parser/src/parser/mod.rs index c078886c8f0a..4b5f7e94e9a9 100644 --- a/crates/swc_ecma_parser/src/parser/mod.rs +++ b/crates/swc_ecma_parser/src/parser/mod.rs @@ -481,7 +481,7 @@ impl Parser { #[cold] pub fn emit_strict_mode_err(&mut self, span: Span, error: SyntaxError) { - if self.ctx().contains(Context::IgnoreError) { + if self.ctx().contains(Context::IgnoreError) || !self.syntax().early_errors() { return; } let error = crate::error::Error::new(span, error); diff --git a/crates/swc_ecma_parser/src/parser/tests.rs b/crates/swc_ecma_parser/src/parser/tests.rs index 08013ae374ad..c607863cb653 100644 --- a/crates/swc_ecma_parser/src/parser/tests.rs +++ b/crates/swc_ecma_parser/src/parser/tests.rs @@ -77,6 +77,24 @@ fn parse_program_duplicate_params_promoted_to_module() { ); } +#[test] +fn no_early_errors_skips_duplicate_formal() { + // TsSyntax::no_early_errors must suppress DuplicateFormalParameter even for + // simple params in module/strict code (emit_strict_mode_err path). + test_parser( + "function f(a, a) {}", + Syntax::Typescript(TsSyntax { + no_early_errors: true, + ..Default::default() + }), + |p| { + let _ = p.parse_typescript_module()?; + assert_eq!(p.take_errors(), Vec::new()); + Ok(()) + }, + ); +} + #[test] fn parse_program_module_error_01() { assert_module_error( diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx new file mode 100644 index 000000000000..43d66d15f472 --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx @@ -0,0 +1,2 @@ +const f = (a, a) => a; +const g = (a, a) => a; diff --git a/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx.swc-stderr b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx.swc-stderr new file mode 100644 index 000000000000..2b74418b7800 --- /dev/null +++ b/crates/swc_ecma_parser/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx.swc-stderr @@ -0,0 +1,12 @@ + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx:1:1] + 1 | const f = (a, a) => a; + : ^ + 2 | const g = (a, a) => a; + `---- + x Duplicate parameter name not allowed in this context: a + ,-[$DIR/tests/typescript-errors/unique-formal-params/tsx/generic-arrow/input.tsx:2:1] + 1 | const f = (a, a) => a; + 2 | const g = (a, a) => a; + : ^ + `----