Fix parsing of nested classes with private fields

The parsing of private fields checks whether or not it is within a
class to determine if it is valid or not. However, the state.inClass
property is incorrect as it marks it as outside a class when the inner
class is closed.

This commit fixes this problem by replacing the state.inClass property
with a class nesting counter.
This commit is contained in:
Karl Cheng 2017-06-23 16:14:41 +10:00
parent 43dba7e7c1
commit b4e06aa279
6 changed files with 3404 additions and 5 deletions

View File

@ -684,7 +684,7 @@ export default class StatementParser extends ExpressionParser {
// class bodies are implicitly strict
const oldStrict = this.state.strict;
this.state.strict = true;
this.state.inClass = true;
this.state.classLevel++;
const state = { hadConstructor: false };
let decorators = [];
@ -731,7 +731,7 @@ export default class StatementParser extends ExpressionParser {
node.body = this.finishNode(classBody, "ClassBody");
this.state.inClass = false;
this.state.classLevel--;
this.state.strict = oldStrict;
}

View File

@ -444,7 +444,7 @@ export default class Tokenizer extends LocationParser {
switch (code) {
case 35: // '#'
if (this.hasPlugin("classPrivateProperties") && this.state.inClass) {
if (this.hasPlugin("classPrivateProperties") && this.state.classLevel > 0) {
++this.state.pos; return this.finishToken(tt.hash);
} else {
this.raise(this.state.pos, `Unexpected character '${codePointToString(code)}'`);

View File

@ -24,11 +24,12 @@ export default class State {
this.inAsync =
this.inPropertyName =
this.inType =
this.inClass =
this.inClassProperty =
this.noAnonFunctionType =
false;
this.classLevel = 0;
this.labels = [];
this.decorators = [];
@ -84,7 +85,9 @@ export default class State {
noAnonFunctionType: boolean;
inPropertyName: boolean;
inClassProperty: boolean;
inClass: boolean;
// Check whether we are in a (nested) class or not.
classLevel: number;
// Labels in scope.
labels: Array<{ kind: ?("loop" | "switch"), statementStart?: number }>;

View File

@ -0,0 +1,40 @@
class Point {
#x = 1;
#y = 2;
constructor(x = 0, y = 0) {
#x = +x;
#y = +y;
this.foo = class {
#x = 1;
#y = 2;
constructor(x = 0, y = 0) {
#x = +x;
#y = +y;
}
get x() { return #x }
set x(value) { #x = +value }
get y() { return #y }
set y(value) { #y = +value }
equals(p) { return #x === p.#x && #y === p.#y }
toString() { return `Point<${ #x },${ #y }>` }
};
}
get x() { return #x }
set x(value) { #x = +value }
get y() { return #y }
set y(value) { #y = +value }
equals(p) { return #x === p.#x && #y === p.#y }
toString() { return `Point<${ #x },${ #y }>` }
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
{
"plugins": ["classProperties", "classPrivateProperties"]
}