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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/oxc_parser/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,12 @@ pub fn cannot_appear_on_a_parameter(
.with_allowed_modifier_help(allowed)
}

#[cold]
pub fn parameter_property_cannot_be_binding_pattern(span: Span) -> OxcDiagnostic {
ts_error("1187", "A parameter property may not be declared using a binding pattern.")
.with_label(span)
}

pub fn cannot_appear_on_an_index_signature(
modifier: &Modifier,
allowed: Option<ModifierFlags>,
Expand Down
19 changes: 19 additions & 0 deletions crates/oxc_parser/src/js/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,25 @@ impl<'a> ParserImpl<'a> {
);
}
let pattern = self.parse_binding_pattern_with_initializer();

if modifiers.accessibility().is_some()
|| modifiers.contains_readonly()
|| modifiers.contains_override()
{
let is_valid_pattern = match &pattern.kind {
BindingPatternKind::BindingIdentifier(_) => true,
BindingPatternKind::AssignmentPattern(assignment) => {
assignment.left.kind.is_binding_identifier()
}
_ => false,
};
if !is_valid_pattern {
self.error(diagnostics::parameter_property_cannot_be_binding_pattern(Span::new(
span,
self.prev_token_end,
)));
}
}
let are_decorators_allowed =
matches!(func_kind, FunctionKind::ClassMethod | FunctionKind::Constructor)
&& self.is_ts;
Expand Down
8 changes: 8 additions & 0 deletions tasks/coverage/misc/fail/oxc-16077.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class A {constructor(override []){}}
class B {constructor(private []){}}
class C {constructor(protected []){}}
class D {constructor(public []){}}
class E {constructor(readonly []){}}
class F {constructor(private {}){}}
class G {constructor(public {a} = {}){}}
class H {constructor(readonly [b] = []){}}
7 changes: 7 additions & 0 deletions tasks/coverage/misc/pass/oxc-16077.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Valid parameter properties with simple identifiers
class ValidA {constructor(private x){}}
class ValidB {constructor(public y){}}
class ValidC {constructor(protected z){}}
class ValidD {constructor(readonly w){}}
class ValidF {constructor(private x = 1){}}
class ValidG {constructor(public y: number = 2){}}
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/codegen_misc.snap
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
codegen_misc Summary:
AST Parsed : 51/51 (100.00%)
Positive Passed: 51/51 (100.00%)
AST Parsed : 52/52 (100.00%)
Positive Passed: 52/52 (100.00%)
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/formatter_misc.snap
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
formatter_misc Summary:
AST Parsed : 51/51 (100.00%)
Positive Passed: 51/51 (100.00%)
AST Parsed : 52/52 (100.00%)
Positive Passed: 52/52 (100.00%)
20 changes: 17 additions & 3 deletions tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ commit: 99dcba5e
parser_babel Summary:
AST Parsed : 2422/2440 (99.26%)
Positive Passed: 2396/2440 (98.20%)
Negative Passed: 1689/1752 (96.40%)
Negative Passed: 1690/1752 (96.46%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/private-in/invalid-private-followed-by-in-2/input.js

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-script-top-level-using-binding/input.js
Expand Down Expand Up @@ -40,8 +40,6 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/ty

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/modifiers-invalid-order/input.ts

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-binding-patterns/input.ts

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/private-fields-modifier-abstract/input.ts

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-var/input.ts
Expand Down Expand Up @@ -13407,6 +13405,22 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
9 │ readonly *[e?.e]?() { }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-binding-patterns/input.ts:2:17]
1 │ class C {
2 │ constructor(public []) {}
· ─────────
3 │ }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-binding-patterns/input.ts:5:17]
4 │ class D {
5 │ constructor(public {}) {}
· ─────────
6 │ }
╰────

× TS(1090): 'readonly' modifier cannot appear on a parameter.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/parameter-properties-not-constructor/input.ts:3:9]
2 │ not_constructor(
Expand Down
68 changes: 65 additions & 3 deletions tasks/coverage/snapshots/parser_misc.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parser_misc Summary:
AST Parsed : 51/51 (100.00%)
Positive Passed: 51/51 (100.00%)
Negative Passed: 118/118 (100.00%)
AST Parsed : 52/52 (100.00%)
Positive Passed: 52/52 (100.00%)
Negative Passed: 119/119 (100.00%)

× Cannot assign to 'arguments' in strict mode
╭─[misc/fail/arguments-eval.ts:1:10]
Expand Down Expand Up @@ -3143,6 +3143,68 @@ Negative Passed: 118/118 (100.00%)
· ╰── `{` expected
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:1:22]
1 │ class A {constructor(override []){}}
· ───────────
2 │ class B {constructor(private []){}}
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:2:22]
1 │ class A {constructor(override []){}}
2 │ class B {constructor(private []){}}
· ──────────
3 │ class C {constructor(protected []){}}
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:3:22]
2 │ class B {constructor(private []){}}
3 │ class C {constructor(protected []){}}
· ────────────
4 │ class D {constructor(public []){}}
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:4:22]
3 │ class C {constructor(protected []){}}
4 │ class D {constructor(public []){}}
· ─────────
5 │ class E {constructor(readonly []){}}
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:5:22]
4 │ class D {constructor(public []){}}
5 │ class E {constructor(readonly []){}}
· ───────────
6 │ class F {constructor(private {}){}}
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:6:22]
5 │ class E {constructor(readonly []){}}
6 │ class F {constructor(private {}){}}
· ──────────
7 │ class G {constructor(public {a} = {}){}}
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:7:22]
6 │ class F {constructor(private {}){}}
7 │ class G {constructor(public {a} = {}){}}
· ───────────────
8 │ class H {constructor(readonly [b] = []){}}
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[misc/fail/oxc-16077.ts:8:22]
7 │ class G {constructor(public {a} = {}){}}
8 │ class H {constructor(readonly [b] = []){}}
· ─────────────────
╰────

× Unexpected token
╭─[misc/fail/oxc-169.js:2:1]
1 │ 1<(V=82<<t-j0<(V=$<LBI<(V=ut<I<(V=$<LBI<(V=uIV=82<<t-j0<(V=$<LBI<(V=ut<I<(V=$<LBI<(V<II>
Expand Down
94 changes: 81 additions & 13 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ commit: 669c25c0
parser_typescript Summary:
AST Parsed : 9821/9822 (99.99%)
Positive Passed: 9812/9822 (99.90%)
Negative Passed: 1457/2547 (57.20%)
Negative Passed: 1463/2547 (57.44%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment7.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment8.ts
Expand Down Expand Up @@ -218,8 +218,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declFileWith

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declarationEmitComputedPropertyNameEnum3.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declarationEmitDestructuringParameterProperties.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declarationEmitDestructuringWithOptionalBindingParameters.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declarationEmitIndexTypeNotFound.ts
Expand Down Expand Up @@ -1308,16 +1306,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destr

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties1.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties2.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties3.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties4.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/destructuringSpread.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/destructuring/missingAndExcessProperties.ts
Expand Down Expand Up @@ -4914,6 +4902,30 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc
4 │ function h1([a, [b], [[c]], {x = 10, y = [1, 2, 3], z: {a1, b1}}]){ }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/compiler/declarationEmitDestructuringParameterProperties.ts:2:17]
1 │ class C1 {
2 │ constructor(public [x, y, z]: string[]) {
· ──────────────────────────
3 │ }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/compiler/declarationEmitDestructuringParameterProperties.ts:8:17]
7 │ class C2 {
8 │ constructor(public [x, y, z]: TupleType1) {
· ────────────────────────────
9 │ }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/compiler/declarationEmitDestructuringParameterProperties.ts:14:17]
13 │ class C3 {
14 │ constructor(public { x, y, z }: ObjType1) {
· ────────────────────────────
15 │ }
╰────

× TS(2499): An interface can only extend an identifier/qualified-name with optional type arguments.
╭─[typescript/tests/cases/compiler/declarationEmitInterfaceWithNonEntityNameExpressionHeritage.ts:2:25]
1 │ class A { }
Expand Down Expand Up @@ -15746,6 +15758,62 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc
8 │ function a1({public}) { }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties1.ts:2:17]
1 │ class C1 {
2 │ constructor(public [x, y, z]: string[]) {
· ──────────────────────────
3 │ }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties1.ts:9:17]
8 │ class C2 {
9 │ constructor(public [x, y, z]: TupleType1) {
· ────────────────────────────
10 │ }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties1.ts:16:17]
15 │ class C3 {
16 │ constructor(public { x, y, z }: ObjType1) {
· ────────────────────────────
17 │ }
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties2.ts:2:36]
1 │ class C1 {
2 │ constructor(private k: number, private [a, b, c]: [number, string, boolean]) {
· ────────────────────────────────────────────
3 │ if ((b === undefined && c === undefined) || (this.b === undefined && this.c === undefined)) {
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties3.ts:2:31]
1 │ class C1<T, U, V> {
2 │ constructor(private k: T, private [a, b, c]: [T,U,V]) {
· ──────────────────────────
3 │ if ((b === undefined && c === undefined) || (this.b === undefined && this.c === undefined)) {
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties4.ts:2:31]
1 │ class C1<T, U, V> {
2 │ constructor(private k: T, protected [a, b, c]: [T,U,V]) {
· ────────────────────────────
3 │ if ((b === undefined && c === undefined) || (this.b === undefined && this.c === undefined)) {
╰────

× TS(1187): A parameter property may not be declared using a binding pattern.
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts:5:17]
4 │ class C1 {
5 │ constructor(public [{ x1, x2, x3 }, y, z]: TupleType1) {
· ─────────────────────────────────────────
6 │ var foo: any = x1 || x2 || x3 || y || z;
╰────

× Identifier `foo1` has already been declared
╭─[typescript/tests/cases/conformance/es6/destructuring/destructuringSameNames.ts:21:7]
20 │
Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/semantic_misc.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
semantic_misc Summary:
AST Parsed : 51/51 (100.00%)
Positive Passed: 32/51 (62.75%)
AST Parsed : 52/52 (100.00%)
Positive Passed: 33/52 (63.46%)
semantic Error: tasks/coverage/misc/pass/declare-let-private.ts
Bindings mismatch:
after transform: ScopeId(0): ["private"]
Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/transformer_misc.snap
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
transformer_misc Summary:
AST Parsed : 51/51 (100.00%)
Positive Passed: 51/51 (100.00%)
AST Parsed : 52/52 (100.00%)
Positive Passed: 52/52 (100.00%)
Loading