[parser] Disallow static fields named constructor (#10461)

* Disallow static fields named `constructor` in a class

    - Disallowed static fields named `constructor` in a class (previously only non-static were disallowed)
    - Updated the text for the error for one consolidated warning, for both static and non-static fields
    - Added a test
    - Updated an existing test in the `flow` test suite of the parser to reflect the parse error.
  Strangely, the test used to pass and started failing when inlining the `isNonstaticConstructor` method, without any changes.
  In that test, `constructor` was a field, so in theory it should never have passed.
  Would appreciate some feedback on this, as I'm not 100% sure if this is somehow related to Flow

* Update test262 whitelist

* Add comment and fix && operator
This commit is contained in:
Guy Waldman 2019-09-18 02:19:45 +03:00 committed by Nicolò Ribaudo
parent 87dc201411
commit 9c1ad0a9f7
8 changed files with 18 additions and 182 deletions

View File

@ -1498,13 +1498,18 @@ export default class StatementParser extends ExpressionParser {
} }
pushClassProperty(classBody: N.ClassBody, prop: N.ClassProperty) { pushClassProperty(classBody: N.ClassBody, prop: N.ClassProperty) {
// This only affects properties, not methods. if (
if (this.isNonstaticConstructor(prop)) { !prop.computed &&
(prop.key.name === "constructor" || prop.key.value === "constructor")
) {
// Non-computed field, which is either an identifier named "constructor"
// or a string literal named "constructor"
this.raise( this.raise(
prop.key.start, prop.key.start,
"Classes may not have a non-static field named 'constructor'", "Classes may not have a field named 'constructor'",
); );
} }
classBody.body.push(this.parseClassProperty(prop)); classBody.body.push(this.parseClassProperty(prop));
} }

View File

@ -1,4 +1,4 @@
{ {
"throws": "Classes may not have a non-static field named 'constructor' (2:2)", "throws": "Classes may not have a field named 'constructor' (2:2)",
"plugins": ["classProperties"] "plugins": ["classProperties"]
} }

View File

@ -1,4 +1,4 @@
{ {
"throws": "Classes may not have a non-static field named 'constructor' (2:2)", "throws": "Classes may not have a field named 'constructor' (2:2)",
"plugins": ["classProperties"] "plugins": ["classProperties"]
} }

View File

@ -0,0 +1,3 @@
class Foo {
static constructor;
}

View File

@ -0,0 +1,4 @@
{
"throws": "Classes may not have a field named 'constructor' (2:11)",
"plugins": ["classProperties"]
}

View File

@ -1,3 +1,4 @@
{ {
"throws": "Classes may not have a field named 'constructor' (2:2)",
"plugins": ["jsx", "flow", "classProperties"] "plugins": ["jsx", "flow", "classProperties"]
} }

View File

@ -1,169 +0,0 @@
{
"type": "File",
"start": 0,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "Foo"
},
"name": "Foo"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 10,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 3,
"column": 1
}
},
"body": [
{
"type": "ClassProperty",
"start": 14,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 26
}
},
"static": false,
"key": {
"type": "Identifier",
"start": 14,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 13
},
"identifierName": "constructor"
},
"name": "constructor"
},
"computed": false,
"variance": null,
"typeAnnotation": {
"type": "TypeAnnotation",
"start": 25,
"end": 37,
"loc": {
"start": {
"line": 2,
"column": 13
},
"end": {
"line": 2,
"column": 25
}
},
"typeAnnotation": {
"type": "FunctionTypeAnnotation",
"start": 27,
"end": 37,
"loc": {
"start": {
"line": 2,
"column": 15
},
"end": {
"line": 2,
"column": 25
}
},
"params": [],
"rest": null,
"returnType": {
"type": "ThisTypeAnnotation",
"start": 33,
"end": 37,
"loc": {
"start": {
"line": 2,
"column": 21
},
"end": {
"line": 2,
"column": 25
}
}
},
"typeParameters": null
}
},
"value": null
}
]
}
}
],
"directives": []
}
}

View File

@ -12,10 +12,6 @@ language/expressions/async-arrow-function/early-errors-arrow-await-in-formals.js
language/expressions/async-arrow-function/early-errors-arrow-await-in-formals.js(strict mode) language/expressions/async-arrow-function/early-errors-arrow-await-in-formals.js(strict mode)
language/expressions/class/elements/fields-duplicate-privatenames.js(default) language/expressions/class/elements/fields-duplicate-privatenames.js(default)
language/expressions/class/elements/fields-duplicate-privatenames.js(strict mode) language/expressions/class/elements/fields-duplicate-privatenames.js(strict mode)
language/expressions/class/elements/fields-literal-name-static-propname-constructor.js(default)
language/expressions/class/elements/fields-literal-name-static-propname-constructor.js(strict mode)
language/expressions/class/elements/fields-string-name-static-propname-constructor.js(default)
language/expressions/class/elements/fields-string-name-static-propname-constructor.js(strict mode)
language/expressions/class/elements/private-methods/prod-private-method-initialize-order.js(default) language/expressions/class/elements/private-methods/prod-private-method-initialize-order.js(default)
language/expressions/class/elements/private-methods/prod-private-method-initialize-order.js(strict mode) language/expressions/class/elements/private-methods/prod-private-method-initialize-order.js(strict mode)
language/expressions/class/elements/syntax/early-errors/grammar-private-environment-on-class-heritage-chained-usage.js(default) language/expressions/class/elements/syntax/early-errors/grammar-private-environment-on-class-heritage-chained-usage.js(default)
@ -188,10 +184,6 @@ language/module-code/top-level-await/syntax/try-await-expr.js(default)
language/module-code/top-level-await/syntax/try-await-expr.js(strict mode) language/module-code/top-level-await/syntax/try-await-expr.js(strict mode)
language/statements/class/elements/fields-duplicate-privatenames.js(default) language/statements/class/elements/fields-duplicate-privatenames.js(default)
language/statements/class/elements/fields-duplicate-privatenames.js(strict mode) language/statements/class/elements/fields-duplicate-privatenames.js(strict mode)
language/statements/class/elements/fields-literal-name-static-propname-constructor.js(default)
language/statements/class/elements/fields-literal-name-static-propname-constructor.js(strict mode)
language/statements/class/elements/fields-string-name-static-propname-constructor.js(default)
language/statements/class/elements/fields-string-name-static-propname-constructor.js(strict mode)
language/statements/class/elements/private-field-is-visible-in-computed-properties.js(default) language/statements/class/elements/private-field-is-visible-in-computed-properties.js(default)
language/statements/class/elements/private-field-is-visible-in-computed-properties.js(strict mode) language/statements/class/elements/private-field-is-visible-in-computed-properties.js(strict mode)
language/statements/class/elements/private-field-with-initialized-id-is-visible-in-computed-properties.js(default) language/statements/class/elements/private-field-with-initialized-id-is-visible-in-computed-properties.js(default)