Skip to content

Commit ea260b2

Browse files
gkzmeta-codesync[bot]
authored andcommitted
[flow][records] Parse errors for some invalid property names
Summary: Parse errors for some invalid property names. Restrictions on `prototype` and `constructor` match the restrictions on classes. We also don't allow private elements, so error on that. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D85915068 fbshipit-source-id: a86f91188e7086fb292b4459752406c55b222df4
1 parent 6f34baf commit ea260b2

8 files changed

Lines changed: 264 additions & 1 deletion

src/parser/object_parser.ml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,10 +1206,23 @@ module Object
12061206
let (generator, leading_generator) = Declaration.generator env in
12071207
let leading_key = Peek.comments env in
12081208
let leading = List.concat [leading_static; leading_async; leading_generator; leading_key] in
1209+
if Peek.token env = T_POUND then (
1210+
let error_loc = Peek.loc env in
1211+
Eat.token env;
1212+
error_at env (error_loc, Parse_error.RecordPrivateElementUnsupported)
1213+
);
12091214
let key = identifier_name env in
1210-
let (key_loc, _) = key in
1215+
let (key_loc, { Identifier.name = key_name; _ }) = key in
1216+
let check_invalid_name env ~method_ =
1217+
if String.equal key_name "constructor" || (String.equal key_name "prototype" && static)
1218+
then
1219+
error_at
1220+
env
1221+
(key_loc, Parse_error.RecordInvalidPropertyName { name = key_name; static; method_ })
1222+
in
12111223
(match Peek.token env with
12121224
| T_COLON when static ->
1225+
check_invalid_name env ~method_:false;
12131226
let prop =
12141227
with_loc
12151228
~start_loc:key_loc
@@ -1228,6 +1241,7 @@ module Object
12281241
in
12291242
elements env (Body.StaticProperty prop :: acc)
12301243
| T_COLON when not (async || generator) ->
1244+
check_invalid_name env ~method_:false;
12311245
let prop =
12321246
with_loc
12331247
~start_loc:key_loc
@@ -1250,6 +1264,7 @@ module Object
12501264
in
12511265
elements env (Body.Property prop :: acc)
12521266
| _ ->
1267+
check_invalid_name env ~method_:true;
12531268
let meth =
12541269
with_loc
12551270
~start_loc:key_loc

src/parser/parse_error.ml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ type t =
127127
| PrivateDelete
128128
| PrivateNotInClass
129129
| PropertyAfterRestElement
130+
| RecordInvalidPropertyName of {
131+
name: string;
132+
static: bool;
133+
method_: bool;
134+
}
135+
| RecordPrivateElementUnsupported
130136
| Redeclaration of string * string
131137
| SetterArity
132138
| SetterMayNotHaveThisParam
@@ -438,6 +444,21 @@ module PP = struct
438444
| PrivateDelete -> "Private fields may not be deleted."
439445
| PrivateNotInClass -> "Private fields can only be referenced from within a class."
440446
| PropertyAfterRestElement -> "Rest property must be final property of an object pattern"
447+
| RecordInvalidPropertyName { name; static; method_ } ->
448+
let static_modifier =
449+
if static then
450+
"static "
451+
else
452+
""
453+
in
454+
let category =
455+
if method_ then
456+
"methods"
457+
else
458+
"properties"
459+
in
460+
Printf.sprintf "Records may not have %s%s named `%s`." static_modifier category name
461+
| RecordPrivateElementUnsupported -> "Records to not support private elements. Remove the `#`."
441462
| Redeclaration (what, name) -> Printf.sprintf "%s '%s' has already been declared" what name
442463
| SetterArity -> "Setter should have exactly one parameter"
443464
| SetterMayNotHaveThisParam -> "A setter cannot have a `this` parameter."
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
record R {
2+
static prototype: {} = {},
3+
4+
constructor() {}
5+
6+
static constructor() {}
7+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"records": true
3+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
{
2+
"errors":[
3+
{
4+
"loc":{"source":null,"start":{"line":2,"column":9},"end":{"line":2,"column":18}},
5+
"message":"Records may not have static properties named `prototype`."
6+
},
7+
{
8+
"loc":{"source":null,"start":{"line":4,"column":2},"end":{"line":4,"column":13}},
9+
"message":"Records may not have methods named `constructor`."
10+
},
11+
{
12+
"loc":{"source":null,"start":{"line":6,"column":9},"end":{"line":6,"column":20}},
13+
"message":"Records may not have static methods named `constructor`."
14+
}
15+
],
16+
"type":"Program",
17+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":7,"column":1}},
18+
"range":[0,88],
19+
"body":[
20+
{
21+
"type":"RecordDeclaration",
22+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":7,"column":1}},
23+
"range":[0,88],
24+
"id":{
25+
"type":"Identifier",
26+
"loc":{"source":null,"start":{"line":1,"column":7},"end":{"line":1,"column":8}},
27+
"range":[7,8],
28+
"name":"R",
29+
"typeAnnotation":null,
30+
"optional":false
31+
},
32+
"typeParameters":null,
33+
"implements":[],
34+
"body":{
35+
"type":"RecordBody",
36+
"loc":{"source":null,"start":{"line":1,"column":9},"end":{"line":7,"column":1}},
37+
"range":[9,88],
38+
"body":[
39+
{
40+
"type":"RecordStaticProperty",
41+
"loc":{"source":null,"start":{"line":2,"column":9},"end":{"line":2,"column":28}},
42+
"range":[20,39],
43+
"key":{
44+
"type":"Identifier",
45+
"loc":{"source":null,"start":{"line":2,"column":9},"end":{"line":2,"column":18}},
46+
"range":[20,29],
47+
"name":"prototype",
48+
"typeAnnotation":null,
49+
"optional":false
50+
},
51+
"typeAnnotation":{
52+
"type":"TypeAnnotation",
53+
"loc":{"source":null,"start":{"line":2,"column":18},"end":{"line":2,"column":22}},
54+
"range":[29,33],
55+
"typeAnnotation":{
56+
"type":"ObjectTypeAnnotation",
57+
"loc":{"source":null,"start":{"line":2,"column":20},"end":{"line":2,"column":22}},
58+
"range":[31,33],
59+
"inexact":false,
60+
"exact":false,
61+
"properties":[],
62+
"indexers":[],
63+
"callProperties":[],
64+
"internalSlots":[]
65+
}
66+
},
67+
"value":{
68+
"type":"ObjectExpression",
69+
"loc":{"source":null,"start":{"line":2,"column":25},"end":{"line":2,"column":27}},
70+
"range":[36,38],
71+
"properties":[]
72+
}
73+
},
74+
{
75+
"type":"MethodDefinition",
76+
"loc":{"source":null,"start":{"line":4,"column":2},"end":{"line":4,"column":18}},
77+
"range":[43,59],
78+
"key":{
79+
"type":"Identifier",
80+
"loc":{"source":null,"start":{"line":4,"column":2},"end":{"line":4,"column":13}},
81+
"range":[43,54],
82+
"name":"constructor",
83+
"typeAnnotation":null,
84+
"optional":false
85+
},
86+
"value":{
87+
"type":"FunctionExpression",
88+
"loc":{"source":null,"start":{"line":4,"column":13},"end":{"line":4,"column":18}},
89+
"range":[54,59],
90+
"id":null,
91+
"params":[],
92+
"body":{
93+
"type":"BlockStatement",
94+
"loc":{"source":null,"start":{"line":4,"column":16},"end":{"line":4,"column":18}},
95+
"range":[57,59],
96+
"body":[]
97+
},
98+
"async":false,
99+
"generator":false,
100+
"predicate":null,
101+
"expression":false,
102+
"returnType":null,
103+
"typeParameters":null
104+
},
105+
"kind":"method",
106+
"static":false,
107+
"computed":false,
108+
"decorators":[]
109+
},
110+
{
111+
"type":"MethodDefinition",
112+
"loc":{"source":null,"start":{"line":6,"column":9},"end":{"line":6,"column":25}},
113+
"range":[70,86],
114+
"key":{
115+
"type":"Identifier",
116+
"loc":{"source":null,"start":{"line":6,"column":9},"end":{"line":6,"column":20}},
117+
"range":[70,81],
118+
"name":"constructor",
119+
"typeAnnotation":null,
120+
"optional":false
121+
},
122+
"value":{
123+
"type":"FunctionExpression",
124+
"loc":{"source":null,"start":{"line":6,"column":20},"end":{"line":6,"column":25}},
125+
"range":[81,86],
126+
"id":null,
127+
"params":[],
128+
"body":{
129+
"type":"BlockStatement",
130+
"loc":{"source":null,"start":{"line":6,"column":23},"end":{"line":6,"column":25}},
131+
"range":[84,86],
132+
"body":[]
133+
},
134+
"async":false,
135+
"generator":false,
136+
"predicate":null,
137+
"expression":false,
138+
"returnType":null,
139+
"typeParameters":null
140+
},
141+
"kind":"method",
142+
"static":true,
143+
"computed":false,
144+
"decorators":[]
145+
}
146+
]
147+
}
148+
}
149+
],
150+
"comments":[]
151+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
record R {
2+
#foo: number,
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"records": true
3+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"errors":[
3+
{
4+
"loc":{"source":null,"start":{"line":2,"column":2},"end":{"line":2,"column":3}},
5+
"message":"Records to not support private elements. Remove the `#`."
6+
}
7+
],
8+
"type":"Program",
9+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
10+
"range":[0,28],
11+
"body":[
12+
{
13+
"type":"RecordDeclaration",
14+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
15+
"range":[0,28],
16+
"id":{
17+
"type":"Identifier",
18+
"loc":{"source":null,"start":{"line":1,"column":7},"end":{"line":1,"column":8}},
19+
"range":[7,8],
20+
"name":"R",
21+
"typeAnnotation":null,
22+
"optional":false
23+
},
24+
"typeParameters":null,
25+
"implements":[],
26+
"body":{
27+
"type":"RecordBody",
28+
"loc":{"source":null,"start":{"line":1,"column":9},"end":{"line":3,"column":1}},
29+
"range":[9,28],
30+
"body":[
31+
{
32+
"type":"RecordProperty",
33+
"loc":{"source":null,"start":{"line":2,"column":3},"end":{"line":2,"column":15}},
34+
"range":[14,26],
35+
"key":{
36+
"type":"Identifier",
37+
"loc":{"source":null,"start":{"line":2,"column":3},"end":{"line":2,"column":6}},
38+
"range":[14,17],
39+
"name":"foo",
40+
"typeAnnotation":null,
41+
"optional":false
42+
},
43+
"typeAnnotation":{
44+
"type":"TypeAnnotation",
45+
"loc":{"source":null,"start":{"line":2,"column":6},"end":{"line":2,"column":14}},
46+
"range":[17,25],
47+
"typeAnnotation":{
48+
"type":"NumberTypeAnnotation",
49+
"loc":{"source":null,"start":{"line":2,"column":8},"end":{"line":2,"column":14}},
50+
"range":[19,25]
51+
}
52+
},
53+
"defaultValue":null
54+
}
55+
]
56+
}
57+
}
58+
],
59+
"comments":[]
60+
}

0 commit comments

Comments
 (0)