diff --git a/crates/oxc_linter/src/rules/early_error/javascript.rs b/crates/oxc_linter/src/rules/early_error/javascript.rs index b9e895227..7a74ba584 100644 --- a/crates/oxc_linter/src/rules/early_error/javascript.rs +++ b/crates/oxc_linter/src/rules/early_error/javascript.rs @@ -34,6 +34,7 @@ impl Rule for EarlyErrorJavaScript { AstKind::LabeledStatement(stmt) => check_labeled_statement(stmt, node, ctx), AstKind::Class(class) => check_class(class, ctx), AstKind::Super(sup) => check_super(sup, node, ctx), + AstKind::Property(prop) => check_property(prop, ctx), _ => {} } } @@ -572,3 +573,20 @@ fn check_super<'a>(sup: &Super, node: &AstNode<'a>, ctx: &LintContext<'a>) { } } } + +fn check_property(prop: &Property, ctx: &LintContext) { + #[derive(Debug, Error, Diagnostic)] + #[error("Invalid assignment in object literal")] + #[diagnostic(help( + "Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern." + ))] + struct CoverInitializedName(#[label] Span); + + // PropertyDefinition : CoverInitializedName + // It is a Syntax Error if any source text is matched by this production. + if prop.shorthand { + if let PropertyValue::Expression(Expression::AssignmentExpression(expr)) = &prop.value { + ctx.diagnostic(CoverInitializedName(expr.span)); + } + } +} diff --git a/tasks/coverage/babel.snap b/tasks/coverage/babel.snap index aadc7caf5..a5e3c767a 100644 --- a/tasks/coverage/babel.snap +++ b/tasks/coverage/babel.snap @@ -1,7 +1,7 @@ Babel Summary: AST Parsed : 2053/2069 (99.23%) Positive Passed: 2053/2069 (99.23%) -Negative Passed: 992/1502 (66.05%) +Negative Passed: 1000/1502 (66.58%) Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-multiple-labels/input.js" @@ -118,10 +118,6 @@ Expect Syntax Error: "es2015/modules/duplicate-named-export-function-declaration Expect Syntax Error: "es2015/modules/duplicate-named-export-variable-declaration/input.js" Expect Syntax Error: "es2015/modules/duplicate-named-export/input.js" Expect Syntax Error: "es2015/object/disallow-duplicate-method-params/input.js" -Expect Syntax Error: "es2015/object/invalid-property-initializer-1/input.js" -Expect Syntax Error: "es2015/object/invalid-property-initializer-in-call/input.js" -Expect Syntax Error: "es2015/object/invalid-property-initializer-in-rhs/input.js" -Expect Syntax Error: "es2015/object/invalid-property-initializer/input.js" Expect Syntax Error: "es2015/shorthand/reserved-word-strict/input.js" Expect Syntax Error: "es2015/statements/label-invalid-func-strict/input.js" Expect Syntax Error: "es2015/uncategorised/.191/input.js" @@ -197,9 +193,6 @@ Expect Syntax Error: "es2016/simple-parameter-list/object-pattern-default/input. Expect Syntax Error: "es2016/simple-parameter-list/object-pattern/input.js" Expect Syntax Error: "es2016/simple-parameter-list/rest/input.js" Expect Syntax Error: "es2017/async-call/parenthesized-argument-object-double-proto/input.js" -Expect Syntax Error: "es2017/async-call/parenthesized-argument-object-with-assignment/input.js" -Expect Syntax Error: "es2017/async-functions/35/input.js" -Expect Syntax Error: "es2017/async-functions/36/input.js" Expect Syntax Error: "es2017/async-functions/9/input.js" Expect Syntax Error: "es2017/async-functions/allow-await-outside-function-throw/input.js" Expect Syntax Error: "es2017/async-functions/async-await-as-arrow-binding-identifier/input.js" @@ -237,7 +230,6 @@ Expect Syntax Error: "esprima/es2015-arrow-function/complex-rest-in-arrow-not-al Expect Syntax Error: "esprima/es2015-arrow-function/invalid-duplicated-params/input.js" Expect Syntax Error: "esprima/es2015-arrow-function/invalid-param-strict-mode/input.js" Expect Syntax Error: "esprima/es2015-class/.migrated_0026/input.js" -Expect Syntax Error: "esprima/es2015-destructuring-assignment/invalid-cover-grammar/input.js" Expect Syntax Error: "esprima/es2015-export-declaration/invalid-export-named-default/input.js" Expect Syntax Error: "esprima/es2015-for-of/invalid-const-init/input.js" Expect Syntax Error: "esprima/es2015-for-of/invalid-let-init/input.js" @@ -2805,6 +2797,38 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" 3 │ set *iterator(iter) { } ╰──── + × Invalid assignment in object literal + ╭─[es2015/object/invalid-property-initializer-1/input.js:2:1] + 2 │ bar: x = 123, + 3 │ foo = 123 + · ───────── + 4 │ }; + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + + × Invalid assignment in object literal + ╭─[es2015/object/invalid-property-initializer-in-call/input.js:1:1] + 1 │ f({x = 0}) + · ───── + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + + × Invalid assignment in object literal + ╭─[es2015/object/invalid-property-initializer-in-rhs/input.js:1:1] + 1 │ obj = {x = 0} + · ───── + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + + × Invalid assignment in object literal + ╭─[es2015/object/invalid-property-initializer/input.js:1:1] + 1 │ const obj = { + 2 │ foo = 123, + · ───────── + 3 │ bar: x = 123 + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + × Flag i is mentioned twice in regular expression literal ╭─[es2015/regex/duplicate-flags/input.js:1:1] 1 │ /./gii; @@ -3738,6 +3762,13 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" ╰──── help: Try insert a semicolon here + × Invalid assignment in object literal + ╭─[es2017/async-call/parenthesized-argument-object-with-assignment/input.js:1:1] + 1 │ async({ foo33 = 1 }); + · ───────── + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + × Expect token ╭─[es2017/async-call/with-optional-operator/input.js:1:1] 1 │ async(x?) @@ -3762,6 +3793,20 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" 3 │ } ╰──── + × Invalid assignment in object literal + ╭─[es2017/async-functions/35/input.js:1:1] + 1 │ const foo = { async = true }; + · ──────────── + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + + × Invalid assignment in object literal + ╭─[es2017/async-functions/36/input.js:1:1] + 1 │ const foo = ({ async = true }); + · ──────────── + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + × Expect token ╭─[es2017/async-functions/4/input.js:1:1] 1 │ ({ async a }); @@ -5907,6 +5952,13 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ╰── Cannot assign to this expression ╰──── + × Invalid assignment in object literal + ╭─[esprima/es2015-destructuring-assignment/invalid-cover-grammar/input.js:1:1] + 1 │ [[[[[[[[[[[[[[[[[[[[{a=b}]]]]]]]]]]]]]]]]]]]] + · ─── + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + × Invalid assignment ╭─[esprima/es2015-destructuring-assignment/invalid-group-assignment/input.js:1:1] 1 │ (a,b)=(c,d); diff --git a/tasks/coverage/test262.snap b/tasks/coverage/test262.snap index 9d0656d96..c14b847ad 100644 --- a/tasks/coverage/test262.snap +++ b/tasks/coverage/test262.snap @@ -1,7 +1,7 @@ Test262 Summary: AST Parsed : 44015/44034 (99.96%) Positive Passed: 44015/44034 (99.96%) -Negative Passed: 2961/3917 (75.59%) +Negative Passed: 2962/3917 (75.62%) Expect Syntax Error: "annexB/language/statements/for-in/const-initializer.js" Expect Syntax Error: "annexB/language/statements/for-in/let-initializer.js" Expect Syntax Error: "annexB/language/statements/for-in/strict-initializer.js" @@ -346,7 +346,6 @@ Expect Syntax Error: "language/expressions/generators/yield-as-generator-express Expect Syntax Error: "language/expressions/import.meta/syntax/goal-script.js" Expect Syntax Error: "language/expressions/object/11.1.5-1gs.js" Expect Syntax Error: "language/expressions/object/__proto__-duplicate.js" -Expect Syntax Error: "language/expressions/object/cover-initialized-name.js" Expect Syntax Error: "language/expressions/object/dstr/async-gen-meth-ary-ptrn-rest-init-ary.js" Expect Syntax Error: "language/expressions/object/dstr/async-gen-meth-ary-ptrn-rest-init-id.js" Expect Syntax Error: "language/expressions/object/dstr/async-gen-meth-ary-ptrn-rest-init-obj.js" @@ -12977,6 +12976,14 @@ Expect to Parse: "language/statements/function/S14_A5_T2.js" 25 │ } ╰──── + × Invalid assignment in object literal + ╭─[language/expressions/object/cover-initialized-name.js:31:1] + 31 │ + 32 │ ({ a = 1 }); + · ───── + ╰──── + help: Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern. + × Rest element must be last element ╭─[language/expressions/object/dstr/async-gen-meth-ary-ptrn-rest-not-final-ary.js:37:1] 37 │ var obj = {