Skip to content

Commit

Permalink
feat(parser): Implemented Class Public Instance Fields (WIP)
Browse files Browse the repository at this point in the history
The parser now parses the new syntax, but not yet fails 100%. This is still WIP, and low priority. Class element list have been updated to handle the new syntax, and optimized
class fields for async and accessors.
  • Loading branch information
KFlash committed May 11, 2019
1 parent baa730d commit c08d907
Show file tree
Hide file tree
Showing 11 changed files with 571 additions and 145 deletions.
4 changes: 2 additions & 2 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const enum Context {
InSwitchOrIteration = InSwitch | InIteration
}

export const enum Kind {
export const enum PropertyKind {
None = 0,
Method = 1 << 0,
Computed = 1 << 1,
Expand All @@ -52,7 +52,7 @@ export const enum Kind {
Setter = 1 << 9,
Extends = 1 << 10,
Literal = 1 << 11,
Private = 1 << 12,
PrivatField = 1 << 12,
GetSet = Getter | Setter
}

Expand Down
6 changes: 4 additions & 2 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ export const enum Errors {
ForLoopInvalidLHS,
AsyncFunctionInSingleStatementContext,
InvalidTernaryYield,
InvalidArrowPostfix
InvalidArrowPostfix,
InvalidObjLitKeyStar
}

/*@internal*/
Expand Down Expand Up @@ -296,7 +297,8 @@ export const errorMessages: {
[Errors.StrictDelete]: 'Calling delete on expression not allowed in strict mode',
[Errors.InvalidPatternTail]: 'Pattern can not have a tail',
[Errors.InvalidTernaryYield]: 'Can not have a `yield` expression on the left side of a ternary',
[Errors.InvalidArrowPostfix]: 'An arrow function can not have a postfix update operator'
[Errors.InvalidArrowPostfix]: 'An arrow function can not have a postfix update operator',
[Errors.InvalidObjLitKeyStar]: 'Invalid object literal key character after generator star'
};

export class ParseError extends SyntaxError {
Expand Down
230 changes: 146 additions & 84 deletions src/parser.ts

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions src/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const enum Token {
VarDecl = 1 << 28,
IsEvalOrArguments = 1 << 29 | IsExpressionStart | IsIdentifier,
IsCommaOrRightParen = 1 << 30,
IsClassField = 1 << 31,

/* Node types */
EOF = 0 | IsAutoSemicolon,
Expand All @@ -50,10 +51,10 @@ export const enum Token {
LeftBrace = 12 | IsExpressionStart | IsPatternStart, // {
Period = 13 | IsMemberOrCallExpression, // .
Ellipsis = 14, // ...
RightBrace = 15 | IsAutoSemicolon, // }
RightBrace = 15 | IsAutoSemicolon | IsClassField, // }
RightParen = 16 | IsCommaOrRightParen, // )
Semicolon = 17 | IsAutoSemicolon, // ;
Comma = 18 | IsCommaOrRightParen, // ,
Semicolon = 17 | IsAutoSemicolon | IsClassField, // ;
Comma = 18 | IsCommaOrRightParen | IsClassField, // ,
LeftBracket = 19 | IsExpressionStart | IsPatternStart | IsMemberOrCallExpression, // [
RightBracket = 20, // ]
Colon = 21, // :
Expand All @@ -68,7 +69,7 @@ export const enum Token {
Decrement = 28 | IsUpdateOp, // --

/* Assign operators */
Assign = 29 | IsAssignOp, // =
Assign = 29 | IsAssignOp | IsClassField, // =
ShiftLeftAssign = 30 | IsAssignOp, // <<=
ShiftRightAssign = 31 | IsAssignOp, // >>=
LogicalShiftRightAssign = 32 | IsAssignOp, // >>>=
Expand Down
1 change: 1 addition & 0 deletions test/parser/expressions/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ describe('Expressions - Array', () => {
['[x] += 0', Context.None],
['[, x, ...y,] = 0', Context.None],
['[...x, ...y] = 0', Context.None],
['({[a / b = c]: {}})', Context.None],
['[...x, y] = 0', Context.None],
['[...x,,] = 0', Context.None],
['[0,{a=0}] = 0', Context.None],
Expand Down
32 changes: 2 additions & 30 deletions test/parser/expressions/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ describe('Expressions - Class', () => {
'async static x(){}',
'static *async x(){}',
'static async *(){}',
'static get *(){}',
'static set *(){}',
'static async get x(){}',
'static async set x(y){}',
'static async x : 0',
Expand Down Expand Up @@ -43,12 +45,6 @@ describe('Expressions - Class', () => {
});
});

it(`(class extends Base {${arg}})`, () => {
t.throws(() => {
parseSource(`(class extends Base {${arg}})`, undefined, Context.OptionsNext);
});
});

it(`(class {${arg}})`, () => {
t.throws(() => {
parseSource(`bar, (class {${arg}})`, undefined, Context.None);
Expand Down Expand Up @@ -93,12 +89,6 @@ describe('Expressions - Class', () => {
parseSource(`(class C { get name(${arg}) {} })`, undefined, Context.None);
});
});

it(`(class C { get name(${arg}) {} })`, () => {
t.throws(() => {
parseSource(`(class C { get name(${arg}) {} })`, undefined, Context.OptionsNext);
});
});
}

for (const arg of [
Expand Down Expand Up @@ -192,12 +182,6 @@ describe('Expressions - Class', () => {
});
});

it(`${arg}`, () => {
t.throws(() => {
parseSource(`${arg}`, undefined, Context.OptionsNext);
});
});

it(`${arg}`, () => {
t.throws(() => {
parseSource(`${arg}`, undefined, Context.OptionsWebCompat);
Expand Down Expand Up @@ -249,12 +233,6 @@ describe('Expressions - Class', () => {
parseSource(`(${arg})`, undefined, Context.OptionsWebCompat);
});
});

it(`(${arg})`, () => {
t.throws(() => {
parseSource(`(${arg})`, undefined, Context.OptionsNext);
});
});
}

for (const arg of [
Expand Down Expand Up @@ -420,12 +398,6 @@ describe('Expressions - Class', () => {
});
});

it(`(class {${arg}})`, () => {
t.throws(() => {
parseSource(`(class {${arg}})`, undefined, Context.OptionsNext);
});
});

it(`(class {${arg}})`, () => {
t.throws(() => {
parseSource(`bar, class {${arg}}`, undefined, Context.None);
Expand Down
47 changes: 46 additions & 1 deletion test/parser/next/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ describe('Next - Decorators', () => {
['export @bar class Foo { }', Context.OptionsNext | Context.Module | Context.Strict],
[`class A { constructor(@foo x) {} }`, Context.OptionsNext | Context.Module | Context.Strict],
//[`@decorate`, Context.OptionsNext],
[`class A { @dec name = 0 }`, Context.OptionsNext | Context.Module | Context.Strict],
[`class A { @abc constructor(){} }`, Context.OptionsNext | Context.Module | Context.Strict],
['export @bar class Foo { }', Context.OptionsNext | Context.Module | Context.Strict],
['export default @decorator class Foo {}', Context.Module | Context.Strict],
Expand All @@ -82,6 +81,52 @@ describe('Next - Decorators', () => {
]);

pass('Next - Decorators (pass)', [
[
`class A { @dec name = 0 }`,
Context.OptionsNext,
{
body: [
{
body: {
body: [
{
computed: false,
decorators: [
{
expression: {
name: 'dec',
type: 'Identifier'
},
type: 'Decorator'
}
],
key: {
name: 'name',
type: 'Identifier'
},
static: false,
type: 'FieldDefinition',
value: {
type: 'Literal',
value: 0
}
}
],
type: 'ClassBody'
},
decorators: [],
id: {
name: 'A',
type: 'Identifier'
},
superClass: null,
type: 'ClassDeclaration'
}
],
sourceType: 'script',
type: 'Program'
}
],
[
`class A { @deco #prop; #foo = 2; test() { this.#foo; }}`,
Context.OptionsNext,
Expand Down
53 changes: 43 additions & 10 deletions test/parser/next/private_methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as t from 'assert';
import { parseSource } from '../../../src/parser';

describe('Next - Private methods', () => {
fail('Declarations - Break', [
fail('Private methods (fail)', [
['class A { #a }', Context.OptionsWebCompat],
['class A { #a }', Context.None],
['a = { #ab() {} }', Context.OptionsNext],
Expand Down Expand Up @@ -34,10 +34,10 @@ describe('Next - Private methods', () => {
'#a =',
'#*a = 0',
'#*a',
'#get a',
'#yield a',
'#async a = 0',
'#async a',
//'#get a',
//'#yield a',
//'#async a = 0',
//'#async a',
// "#a; #a",
// "#a = 1; #a",
// "#a; #a = 1;",
Expand Down Expand Up @@ -66,8 +66,8 @@ describe('Next - Private methods', () => {
// 'foo() { delete f.x().#a }',

// ASI requires a linebreak
'#a b',
'#a = 0 b',
//'#a b',
//'#a = 0 b',

// ASI requires that the next token is not part of any legal production
'#a = 0\n *b(){}',
Expand Down Expand Up @@ -176,11 +176,10 @@ describe('Next - Private methods', () => {
'#async',
'#async = 0',
'#async\n a(){}', // a field named async, and a method named a.
//"#async\n a",
'#async\n a',
'#await;',
'#await = 0;',
//"#await\n a",

'foo() { this.#m, (() => this)().#m }',
'foo() { this.#m, (() => this)().#m }',
'foo() { this.#m, (() => this)().#m }',
Expand Down Expand Up @@ -213,7 +212,41 @@ describe('Next - Private methods', () => {
});
});
}

for (const arg of [
'{ class C { #a() { class B { #a() { } } new B; } } new C; }',
'{ class A { #a() { class C extends A { #c() { } } new C; } } new A; }',
'{ const C = class { #a() { } } }',
'{ class A { constructor(arg) { return arg; } } class C extends A { #x() { } constructor(arg) { super(arg); } } let c1 = new C({}); }',
'class D extends class { #c() {} } { #d() {} }',
'class E extends D { #e() {} }',
'{ class C { #a() { class B { #a() { } } new B; } } new C; }',
`{
{\n
class A {\n
#a() { return 1; }\n
}\n
\n
new A;\n
}\n
{\n
class D {\n
#d() {}\n
}\n
\n
class E extends D {\n
#e() {}\n
}\n
\n
new D;\n
new E;\n
}\n}`
]) {
it(`${arg}`, () => {
t.doesNotThrow(() => {
parseSource(`${arg}`, undefined, Context.OptionsNext);
});
});
}
pass('Next - Decorators (pass)', [
[
`class A { #key }`,
Expand Down

0 comments on commit c08d907

Please sign in to comment.