Disallow setters to have RestElement (#7498)
This commit is contained in:
parent
eb2a0b0fcd
commit
5d615dd198
@ -1383,17 +1383,24 @@ export default class ExpressionParser extends LValParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get methods aren't allowed to have any parameters
|
// get methods aren't allowed to have any parameters
|
||||||
// set methods must have exactly 1 parameter
|
// set methods must have exactly 1 parameter which is not a rest parameter
|
||||||
checkGetterSetterParamCount(method: N.ObjectMethod | N.ClassMethod): void {
|
checkGetterSetterParams(method: N.ObjectMethod | N.ClassMethod): void {
|
||||||
const paramCount = method.kind === "get" ? 0 : 1;
|
const paramCount = method.kind === "get" ? 0 : 1;
|
||||||
if (method.params.length !== paramCount) {
|
|
||||||
const start = method.start;
|
const start = method.start;
|
||||||
|
if (method.params.length !== paramCount) {
|
||||||
if (method.kind === "get") {
|
if (method.kind === "get") {
|
||||||
this.raise(start, "getter should have no params");
|
this.raise(start, "getter must not have any formal parameters");
|
||||||
} else {
|
} else {
|
||||||
this.raise(start, "setter should have exactly one param");
|
this.raise(start, "setter must have exactly one formal parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method.kind === "set" && method.params[0].type === "RestElement") {
|
||||||
|
this.raise(
|
||||||
|
start,
|
||||||
|
"setter function argument must not be a rest parameter",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parseObjectMethod(
|
parseObjectMethod(
|
||||||
@ -1426,7 +1433,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
/* isConstructor */ false,
|
/* isConstructor */ false,
|
||||||
"ObjectMethod",
|
"ObjectMethod",
|
||||||
);
|
);
|
||||||
this.checkGetterSetterParamCount(prop);
|
this.checkGetterSetterParams(prop);
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1161,7 +1161,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkGetterSetterParamCount(publicMethod);
|
this.checkGetterSetterParams(publicMethod);
|
||||||
} else if (this.isLineTerminator()) {
|
} else if (this.isLineTerminator()) {
|
||||||
// an uninitialized class property (due to ASI, since we don't otherwise recognize the next token)
|
// an uninitialized class property (due to ASI, since we don't otherwise recognize the next token)
|
||||||
if (isPrivate) {
|
if (isPrivate) {
|
||||||
|
|||||||
@ -82,17 +82,24 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkGetterSetterParamCount(prop: N.ObjectMethod | N.ClassMethod): void {
|
checkGetterSetterParams(method: N.ObjectMethod | N.ClassMethod): void {
|
||||||
|
const prop = ((method: any): N.EstreeProperty | N.EstreeMethodDefinition);
|
||||||
const paramCount = prop.kind === "get" ? 0 : 1;
|
const paramCount = prop.kind === "get" ? 0 : 1;
|
||||||
// $FlowFixMe (prop.value present for ObjectMethod, but for ClassMethod should use prop.params?)
|
|
||||||
if (prop.value.params.length !== paramCount) {
|
|
||||||
const start = prop.start;
|
const start = prop.start;
|
||||||
|
if (prop.value.params.length !== paramCount) {
|
||||||
if (prop.kind === "get") {
|
if (prop.kind === "get") {
|
||||||
this.raise(start, "getter should have no params");
|
this.raise(start, "getter must not have any formal parameters");
|
||||||
} else {
|
} else {
|
||||||
this.raise(start, "setter should have exactly one param");
|
this.raise(start, "setter must have exactly one formal parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prop.kind === "set" && prop.value.params[0].type === "RestElement") {
|
||||||
|
this.raise(
|
||||||
|
start,
|
||||||
|
"setter function argument must not be a rest parameter",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkLVal(
|
checkLVal(
|
||||||
|
|||||||
@ -763,7 +763,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
this.startNodeAt(node.start, node.loc.start),
|
this.startNodeAt(node.start, node.loc.start),
|
||||||
);
|
);
|
||||||
if (kind === "get" || kind === "set") {
|
if (kind === "get" || kind === "set") {
|
||||||
this.flowCheckGetterSetterParamCount(node);
|
this.flowCheckGetterSetterParams(node);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (kind !== "init") this.unexpected();
|
if (kind !== "init") this.unexpected();
|
||||||
@ -783,20 +783,29 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is similar to checkGetterSetterParamCount, but as
|
// This is similar to checkGetterSetterParams, but as
|
||||||
// babylon uses non estree properties we cannot reuse it here
|
// babylon uses non estree properties we cannot reuse it here
|
||||||
flowCheckGetterSetterParamCount(
|
flowCheckGetterSetterParams(
|
||||||
property: N.FlowObjectTypeProperty | N.FlowObjectTypeSpreadProperty,
|
property: N.FlowObjectTypeProperty | N.FlowObjectTypeSpreadProperty,
|
||||||
): void {
|
): void {
|
||||||
const paramCount = property.kind === "get" ? 0 : 1;
|
const paramCount = property.kind === "get" ? 0 : 1;
|
||||||
if (property.value.params.length !== paramCount) {
|
|
||||||
const start = property.start;
|
const start = property.start;
|
||||||
|
const length =
|
||||||
|
property.value.params.length + (property.value.rest ? 1 : 0);
|
||||||
|
if (length !== paramCount) {
|
||||||
if (property.kind === "get") {
|
if (property.kind === "get") {
|
||||||
this.raise(start, "getter should have no params");
|
this.raise(start, "getter must not have any formal parameters");
|
||||||
} else {
|
} else {
|
||||||
this.raise(start, "setter should have exactly one param");
|
this.raise(start, "setter must have exactly one formal parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (property.kind === "set" && property.value.rest) {
|
||||||
|
this.raise(
|
||||||
|
start,
|
||||||
|
"setter function argument must not be a rest parameter",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flowObjectTypeSemicolon(): void {
|
flowObjectTypeSemicolon(): void {
|
||||||
|
|||||||
@ -941,6 +941,18 @@ export type EstreeProperty = NodeBase & {
|
|||||||
variance?: ?FlowVariance,
|
variance?: ?FlowVariance,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EstreeMethodDefinition = NodeBase & {
|
||||||
|
type: "MethodDefinition",
|
||||||
|
static: boolean,
|
||||||
|
key: Expression,
|
||||||
|
computed: boolean,
|
||||||
|
value: Expression,
|
||||||
|
decorators: $ReadOnlyArray<Decorator>,
|
||||||
|
kind?: "get" | "set" | "method",
|
||||||
|
|
||||||
|
variance?: ?FlowVariance,
|
||||||
|
};
|
||||||
|
|
||||||
// === === === ===
|
// === === === ===
|
||||||
// TypeScript
|
// TypeScript
|
||||||
// === === === ===
|
// === === === ===
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"throws": "getter should have no params (2:2)"
|
"throws": "getter must not have any formal parameters (2:2)"
|
||||||
}
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"throws": "setter should have exactly one param (1:10)"
|
"throws": "setter must have exactly one formal parameter (1:10)"
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/babylon/test/fixtures/esprima/rest-parameter/invalid-setter-rest/options.json
vendored
Normal file
3
packages/babylon/test/fixtures/esprima/rest-parameter/invalid-setter-rest/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "setter function argument must not be a rest parameter (1:6)"
|
||||||
|
}
|
||||||
@ -1,188 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "File",
|
|
||||||
"start": 0,
|
|
||||||
"end": 22,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 22
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"start": 0,
|
|
||||||
"end": 22,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 22
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sourceType": "script",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ExpressionStatement",
|
|
||||||
"start": 0,
|
|
||||||
"end": 22,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 22
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"expression": {
|
|
||||||
"type": "AssignmentExpression",
|
|
||||||
"start": 0,
|
|
||||||
"end": 22,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 22
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"operator": "=",
|
|
||||||
"left": {
|
|
||||||
"type": "Identifier",
|
|
||||||
"start": 0,
|
|
||||||
"end": 1,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 1
|
|
||||||
},
|
|
||||||
"identifierName": "x"
|
|
||||||
},
|
|
||||||
"name": "x"
|
|
||||||
},
|
|
||||||
"right": {
|
|
||||||
"type": "ObjectExpression",
|
|
||||||
"start": 4,
|
|
||||||
"end": 22,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 4
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 22
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"type": "ObjectMethod",
|
|
||||||
"start": 6,
|
|
||||||
"end": 20,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 6
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 20
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"method": false,
|
|
||||||
"key": {
|
|
||||||
"type": "Identifier",
|
|
||||||
"start": 10,
|
|
||||||
"end": 11,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 10
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 11
|
|
||||||
},
|
|
||||||
"identifierName": "f"
|
|
||||||
},
|
|
||||||
"name": "f"
|
|
||||||
},
|
|
||||||
"computed": false,
|
|
||||||
"kind": "set",
|
|
||||||
"id": null,
|
|
||||||
"generator": false,
|
|
||||||
"async": false,
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "RestElement",
|
|
||||||
"start": 12,
|
|
||||||
"end": 16,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 12
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"argument": {
|
|
||||||
"type": "Identifier",
|
|
||||||
"start": 15,
|
|
||||||
"end": 16,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 15
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 16
|
|
||||||
},
|
|
||||||
"identifierName": "y"
|
|
||||||
},
|
|
||||||
"name": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"body": {
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"start": 18,
|
|
||||||
"end": 20,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 18
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 20
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"body": [],
|
|
||||||
"directives": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directives": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
packages/babylon/test/fixtures/flow/object-types/invalid-getter-param-count-rest/input.js
vendored
Normal file
3
packages/babylon/test/fixtures/flow/object-types/invalid-getter-param-count-rest/input.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
type B = {
|
||||||
|
get a(...foo): number;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "getter must not have any formal parameters (2:2)"
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"throws": "getter should have no params (2:2)"
|
"throws": "getter must not have any formal parameters (2:2)"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"throws": "setter should have exactly one param (2:2)"
|
"throws": "setter must have exactly one formal parameter (2:2)"
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/babylon/test/fixtures/flow/object-types/invalid-setter-param-type/input.js
vendored
Normal file
3
packages/babylon/test/fixtures/flow/object-types/invalid-setter-param-type/input.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
type B = {
|
||||||
|
set a(...w): void;
|
||||||
|
}
|
||||||
3
packages/babylon/test/fixtures/flow/object-types/invalid-setter-param-type/options.json
vendored
Normal file
3
packages/babylon/test/fixtures/flow/object-types/invalid-setter-param-type/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "setter function argument must not be a rest parameter (2:2)"
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user