Skip to content

Commit e3189aa

Browse files
committed
raise syntax error on declaration of private method, and add syntax tests for private fields
1 parent 183dd68 commit e3189aa

6 files changed

Lines changed: 43 additions & 18 deletions

File tree

javascript/extractor/src/com/semmle/jcorn/Parser.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,6 +3238,9 @@ protected MemberDefinition<?> parseClassPropertyBody(
32383238
if (pi.kind.equals("set") && node.getValue().hasRest())
32393239
this.raiseRecoverable(params.get(params.size() - 1), "Setter cannot use rest params");
32403240
}
3241+
if (pi.key instanceof Identifier && ((Identifier)pi.key).getName().startsWith("#")) {
3242+
raiseRecoverable(pi.key, "Only fields, not methods, can be declared private.");
3243+
}
32413244
return node;
32423245
}
32433246

javascript/ql/test/library-tests/Classes/privateFields.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ class Foo {
1919
#privSecond; // is a PropNode, not a PropRef. Doesn't matter.
2020

2121
["#publicField"] = 6;
22+
23+
calls() {
24+
this.#privDecl();
25+
new this.#privDecl();
26+
}
2227
}

javascript/ql/test/library-tests/Classes/tests.expected

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ test_ClassDefinitions
2323
| fields.js:1:1:4:1 | class C ... = 42\\n} |
2424
| points.js:1:1:18:1 | class P ... ;\\n }\\n} |
2525
| points.js:20:1:33:1 | class C ... ;\\n }\\n} |
26-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} |
26+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} |
2727
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} |
2828
| tst.js:1:9:4:1 | class { ... */ }\\n} |
2929
| tst.js:6:1:8:1 | class B ... t); }\\n} |
@@ -43,7 +43,7 @@ test_ClassDefinition_getName
4343
| fields.js:1:1:4:1 | class C ... = 42\\n} | C |
4444
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | Point |
4545
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | ColouredPoint |
46-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | Foo |
46+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | Foo |
4747
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | MyClass |
4848
| tst.js:1:9:4:1 | class { ... */ }\\n} | A |
4949
| tst.js:6:1:8:1 | class B ... t); }\\n} | B |
@@ -60,10 +60,11 @@ test_MethodDefinitions
6060
| points.js:21:3:24:3 | constru ... c;\\n } | points.js:21:3:21:13 | constructor | points.js:21:14:24:3 | (x, y, ... c;\\n } | points.js:20:1:33:1 | class C ... ;\\n }\\n} |
6161
| points.js:26:3:28:3 | toStrin ... ur;\\n } | points.js:26:3:26:10 | toString | points.js:26:11:28:3 | () {\\n ... ur;\\n } | points.js:20:1:33:1 | class C ... ;\\n }\\n} |
6262
| points.js:30:3:32:3 | static ... t";\\n } | points.js:30:10:30:18 | className | points.js:30:19:32:3 | () {\\n ... t";\\n } | points.js:20:1:33:1 | class C ... ;\\n }\\n} |
63-
| privateFields.js:1:11:1:10 | constructor() {} | privateFields.js:1:11:1:10 | constructor | privateFields.js:1:11:1:10 | () {} | privateFields.js:1:1:22:1 | class F ... = 6;\\n} |
64-
| privateFields.js:4:2:8:2 | reads() ... #if;\\n\\t} | privateFields.js:4:2:4:6 | reads | privateFields.js:4:7:8:2 | () {\\n\\t\\t ... #if;\\n\\t} | privateFields.js:1:1:22:1 | class F ... = 6;\\n} |
65-
| privateFields.js:10:2:12:2 | equals( ... ecl;\\n\\t} | privateFields.js:10:2:10:7 | equals | privateFields.js:10:8:12:2 | (o) {\\n\\t ... ecl;\\n\\t} | privateFields.js:1:1:22:1 | class F ... = 6;\\n} |
66-
| privateFields.js:14:2:17:2 | writes( ... = 5;\\n\\t} | privateFields.js:14:2:14:7 | writes | privateFields.js:14:8:17:2 | () {\\n\\t\\t ... = 5;\\n\\t} | privateFields.js:1:1:22:1 | class F ... = 6;\\n} |
63+
| privateFields.js:1:11:1:10 | constructor() {} | privateFields.js:1:11:1:10 | constructor | privateFields.js:1:11:1:10 | () {} | privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} |
64+
| privateFields.js:4:2:8:2 | reads() ... #if;\\n\\t} | privateFields.js:4:2:4:6 | reads | privateFields.js:4:7:8:2 | () {\\n\\t\\t ... #if;\\n\\t} | privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} |
65+
| privateFields.js:10:2:12:2 | equals( ... ecl;\\n\\t} | privateFields.js:10:2:10:7 | equals | privateFields.js:10:8:12:2 | (o) {\\n\\t ... ecl;\\n\\t} | privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} |
66+
| privateFields.js:14:2:17:2 | writes( ... = 5;\\n\\t} | privateFields.js:14:2:14:7 | writes | privateFields.js:14:8:17:2 | () {\\n\\t\\t ... = 5;\\n\\t} | privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} |
67+
| privateFields.js:23:2:26:2 | calls() ... l();\\n\\t} | privateFields.js:23:2:23:6 | calls | privateFields.js:23:7:26:2 | () {\\n\\t\\t ... l();\\n\\t} | privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} |
6768
| staticConstructor.js:1:15:1:14 | constructor() {} | staticConstructor.js:1:15:1:14 | constructor | staticConstructor.js:1:15:1:14 | () {} | staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} |
6869
| staticConstructor.js:2:3:2:59 | static ... tor"; } | staticConstructor.js:2:10:2:20 | constructor | staticConstructor.js:2:21:2:59 | () { re ... tor"; } | staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} |
6970
| tst.js:2:3:2:50 | "constr ... r. */ } | tst.js:2:3:2:15 | "constructor" | tst.js:2:16:2:50 | () { /* ... r. */ } | tst.js:1:9:4:1 | class { ... */ }\\n} |
@@ -87,14 +88,15 @@ test_getAMember
8788
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | points.js:21:3:24:3 | constru ... c;\\n } |
8889
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | points.js:26:3:28:3 | toStrin ... ur;\\n } |
8990
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | points.js:30:3:32:3 | static ... t";\\n } |
90-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:1:11:1:10 | constructor() {} |
91-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:2:2:2:15 | #privDecl = 3; |
92-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:3:2:3:12 | #if = "if"; |
93-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:4:2:8:2 | reads() ... #if;\\n\\t} |
94-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:10:2:12:2 | equals( ... ecl;\\n\\t} |
95-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:14:2:17:2 | writes( ... = 5;\\n\\t} |
96-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:19:2:19:13 | #privSecond; |
97-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:21:2:21:22 | ["#publ ... "] = 6; |
91+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:1:11:1:10 | constructor() {} |
92+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:2:2:2:15 | #privDecl = 3; |
93+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:3:2:3:12 | #if = "if"; |
94+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:4:2:8:2 | reads() ... #if;\\n\\t} |
95+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:10:2:12:2 | equals( ... ecl;\\n\\t} |
96+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:14:2:17:2 | writes( ... = 5;\\n\\t} |
97+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:19:2:19:13 | #privSecond; |
98+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:21:2:21:22 | ["#publ ... "] = 6; |
99+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:23:2:26:2 | calls() ... l();\\n\\t} |
98100
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | staticConstructor.js:1:15:1:14 | constructor() {} |
99101
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | staticConstructor.js:2:3:2:59 | static ... tor"; } |
100102
| tst.js:1:9:4:1 | class { ... */ }\\n} | tst.js:2:3:2:50 | "constr ... r. */ } |
@@ -119,6 +121,7 @@ test_MethodNames
119121
| privateFields.js:4:2:8:2 | reads() ... #if;\\n\\t} | reads |
120122
| privateFields.js:10:2:12:2 | equals( ... ecl;\\n\\t} | equals |
121123
| privateFields.js:14:2:17:2 | writes( ... = 5;\\n\\t} | writes |
124+
| privateFields.js:23:2:26:2 | calls() ... l();\\n\\t} | calls |
122125
| staticConstructor.js:1:15:1:14 | constructor() {} | constructor |
123126
| staticConstructor.js:2:3:2:59 | static ... tor"; } | constructor |
124127
| tst.js:2:3:2:50 | "constr ... r. */ } | constructor |
@@ -153,7 +156,7 @@ test_ClassNodeConstructor
153156
| fields.js:1:1:4:1 | class C ... = 42\\n} | fields.js:1:9:1:8 | () {} |
154157
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | points.js:2:14:5:3 | (x, y) ... y;\\n } |
155158
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | points.js:21:14:24:3 | (x, y, ... c;\\n } |
156-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | privateFields.js:1:11:1:10 | () {} |
159+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | privateFields.js:1:11:1:10 | () {} |
157160
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | staticConstructor.js:1:15:1:14 | () {} |
158161
| tst.js:1:9:4:1 | class { ... */ }\\n} | tst.js:2:16:2:50 | () { /* ... r. */ } |
159162
| tst.js:6:1:8:1 | class B ... t); }\\n} | tst.js:7:14:7:38 | () { su ... get); } |
@@ -163,9 +166,10 @@ test_ClassNodeInstanceMethod
163166
| dataflow.js:4:2:13:2 | class F ... \\n\\t\\t}\\n\\t} | getPriv | dataflow.js:6:10:8:3 | () {\\n\\t\\t ... iv;\\n\\t\\t} |
164167
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | toString | points.js:11:11:13:3 | () {\\n ... )";\\n } |
165168
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | toString | points.js:26:11:28:3 | () {\\n ... ur;\\n } |
166-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | equals | privateFields.js:10:8:12:2 | (o) {\\n\\t ... ecl;\\n\\t} |
167-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | reads | privateFields.js:4:7:8:2 | () {\\n\\t\\t ... #if;\\n\\t} |
168-
| privateFields.js:1:1:22:1 | class F ... = 6;\\n} | writes | privateFields.js:14:8:17:2 | () {\\n\\t\\t ... = 5;\\n\\t} |
169+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | calls | privateFields.js:23:7:26:2 | () {\\n\\t\\t ... l();\\n\\t} |
170+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | equals | privateFields.js:10:8:12:2 | (o) {\\n\\t ... ecl;\\n\\t} |
171+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | reads | privateFields.js:4:7:8:2 | () {\\n\\t\\t ... #if;\\n\\t} |
172+
| privateFields.js:1:1:27:1 | class F ... );\\n\\t}\\n} | writes | privateFields.js:14:8:17:2 | () {\\n\\t\\t ... = 5;\\n\\t} |
169173
| tst.js:1:9:4:1 | class { ... */ }\\n} | constructor | tst.js:3:18:3:56 | () { /* ... r. */ } |
170174
| tst.js:11:1:14:1 | class C ... () {}\\n} | m | tst.js:12:4:12:8 | () {} |
171175
getAccessModifier
@@ -212,6 +216,9 @@ getAccessModifier
212216
| privateFields.js:15:3:15:16 | this.#privDecl | privateFields.js:15:8:15:16 | #privDecl | Private |
213217
| privateFields.js:16:3:16:17 | this["#public"] | privateFields.js:16:8:16:16 | "#public" | Public |
214218
| privateFields.js:21:2:21:22 | ["#publ ... "] = 6; | privateFields.js:21:3:21:16 | "#publicField" | Public |
219+
| privateFields.js:23:2:26:2 | calls() ... l();\\n\\t} | privateFields.js:23:2:23:6 | calls | Public |
220+
| privateFields.js:24:3:24:16 | this.#privDecl | privateFields.js:24:8:24:16 | #privDecl | Private |
221+
| privateFields.js:25:7:25:20 | this.#privDecl | privateFields.js:25:12:25:20 | #privDecl | Private |
215222
| staticConstructor.js:1:15:1:14 | constructor() {} | staticConstructor.js:1:15:1:14 | constructor | Public |
216223
| staticConstructor.js:2:3:2:59 | static ... tor"; } | staticConstructor.js:2:10:2:20 | constructor | Public |
217224
| staticConstructor.js:4:1:4:11 | console.log | staticConstructor.js:4:9:4:11 | log | Public |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
| arrows.js:1:5:1:5 | Error: Argument name clash | Error: Argument name clash |
2+
| destructingPrivate.js:3:6:3:6 | Error: Unexpected token | Error: Unexpected token |
3+
| privateMethod.js:2:3:2:3 | Error: Only fields, not methods, can be declared private. | Error: Only fields, not methods, can be declared private. |
24
| tst.js:2:12:2:12 | Error: Unterminated string constant | Error: Unterminated string constant |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class C {
2+
bar() {
3+
{#privDecl} = this;
4+
}
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class C {
2+
#privateMethod() {}
3+
}

0 commit comments

Comments
 (0)