@ibyar/expressions 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -0
  3. package/api/abstract.d.ts +3 -3
  4. package/api/abstract.js +7 -2
  5. package/api/abstract.js.map +1 -1
  6. package/api/class/class.d.ts +45 -24
  7. package/api/class/class.js +158 -112
  8. package/api/class/class.js.map +1 -1
  9. package/api/computing/debugger.d.ts +15 -0
  10. package/api/computing/debugger.js +35 -0
  11. package/api/computing/debugger.js.map +1 -0
  12. package/api/computing/rest.d.ts +4 -4
  13. package/api/computing/rest.js.map +1 -1
  14. package/api/computing/return.d.ts +4 -0
  15. package/api/computing/return.js +5 -0
  16. package/api/computing/return.js.map +1 -1
  17. package/api/computing/throw.d.ts +4 -0
  18. package/api/computing/throw.js +4 -0
  19. package/api/computing/throw.js.map +1 -1
  20. package/api/definition/array.d.ts +7 -6
  21. package/api/definition/array.js +20 -14
  22. package/api/definition/array.js.map +1 -1
  23. package/api/definition/bind.d.ts +6 -0
  24. package/api/definition/bind.js +6 -0
  25. package/api/definition/bind.js.map +1 -1
  26. package/api/definition/function.d.ts +35 -46
  27. package/api/definition/function.js +282 -299
  28. package/api/definition/function.js.map +1 -1
  29. package/api/definition/member.js.map +1 -1
  30. package/api/definition/object.d.ts +9 -6
  31. package/api/definition/object.js +35 -5
  32. package/api/definition/object.js.map +1 -1
  33. package/api/definition/statement.js +5 -1
  34. package/api/definition/statement.js.map +1 -1
  35. package/api/definition/values.d.ts +43 -50
  36. package/api/definition/values.js +84 -149
  37. package/api/definition/values.js.map +1 -1
  38. package/api/deserialize/deserialize.d.ts +7 -1
  39. package/api/deserialize/deserialize.js +9 -1
  40. package/api/deserialize/deserialize.js.map +1 -1
  41. package/api/deserialize/type-store.d.ts +2 -2
  42. package/api/deserialize/type-store.js.map +1 -1
  43. package/api/expression.d.ts +156 -12
  44. package/api/expression.js.map +1 -1
  45. package/api/index.d.ts +2 -0
  46. package/api/index.js +2 -0
  47. package/api/index.js.map +1 -1
  48. package/api/module/common.d.ts +29 -0
  49. package/api/module/common.js +71 -0
  50. package/api/module/common.js.map +1 -0
  51. package/api/module/export.d.ts +78 -9
  52. package/api/module/export.js +120 -15
  53. package/api/module/export.js.map +1 -1
  54. package/api/module/import.d.ts +56 -8
  55. package/api/module/import.js +62 -19
  56. package/api/module/import.js.map +1 -1
  57. package/api/operators/grouping.d.ts +7 -0
  58. package/api/operators/grouping.js +7 -0
  59. package/api/operators/grouping.js.map +1 -1
  60. package/api/operators/pipeline.d.ts +12 -0
  61. package/api/operators/pipeline.js +12 -0
  62. package/api/operators/pipeline.js.map +1 -1
  63. package/api/operators/unary.js +3 -0
  64. package/api/operators/unary.js.map +1 -1
  65. package/api/{module/app/program.d.ts → program.d.ts} +5 -5
  66. package/api/{module/app/program.js → program.js} +3 -3
  67. package/api/program.js.map +1 -0
  68. package/api/statement/control/block.d.ts +5 -2
  69. package/api/statement/control/block.js +24 -21
  70. package/api/statement/control/block.js.map +1 -1
  71. package/api/statement/control/empty.d.ts +7 -0
  72. package/api/statement/control/empty.js +7 -0
  73. package/api/statement/control/empty.js.map +1 -1
  74. package/api/statement/control/if.d.ts +5 -0
  75. package/api/statement/control/if.js +5 -0
  76. package/api/statement/control/if.js.map +1 -1
  77. package/api/statement/control/switch.d.ts +6 -0
  78. package/api/statement/control/switch.js +17 -3
  79. package/api/statement/control/switch.js.map +1 -1
  80. package/api/statement/control/terminate.d.ts +44 -11
  81. package/api/statement/control/terminate.js +87 -18
  82. package/api/statement/control/terminate.js.map +1 -1
  83. package/api/statement/declarations/declares.d.ts +7 -7
  84. package/api/statement/declarations/declares.js +1 -1
  85. package/api/statement/declarations/declares.js.map +1 -1
  86. package/api/statement/iterations/for.d.ts +5 -0
  87. package/api/statement/iterations/for.js +35 -16
  88. package/api/statement/iterations/for.js.map +1 -1
  89. package/api/statement/iterations/while.d.ts +6 -0
  90. package/api/statement/iterations/while.js +25 -11
  91. package/api/statement/iterations/while.js.map +1 -1
  92. package/api/utils.d.ts +2 -0
  93. package/api/utils.js +3 -1
  94. package/api/utils.js.map +1 -1
  95. package/package.json +7 -5
  96. package/scope/event.d.ts +3 -3
  97. package/scope/event.js +2 -2
  98. package/scope/event.js.map +1 -1
  99. package/scope/pool.d.ts +7 -0
  100. package/scope/pool.js +29 -0
  101. package/scope/pool.js.map +1 -0
  102. package/scope/proxy.d.ts +6 -11
  103. package/scope/proxy.js +23 -52
  104. package/scope/proxy.js.map +1 -1
  105. package/scope/scope.d.ts +161 -38
  106. package/scope/scope.js +260 -106
  107. package/scope/scope.js.map +1 -1
  108. package/scope/stack.d.ts +97 -21
  109. package/scope/stack.js +13 -0
  110. package/scope/stack.js.map +1 -1
  111. package/v8/enums.d.ts +204 -0
  112. package/v8/enums.js +406 -0
  113. package/v8/enums.js.map +1 -0
  114. package/v8/index.d.ts +2 -1
  115. package/v8/index.js +2 -1
  116. package/v8/index.js.map +1 -1
  117. package/v8/inline.d.ts +213 -0
  118. package/v8/inline.js +2375 -0
  119. package/v8/inline.js.map +1 -0
  120. package/v8/nodes.d.ts +8 -7
  121. package/v8/nodes.js +39 -64
  122. package/v8/nodes.js.map +1 -1
  123. package/v8/parser.d.ts +49 -151
  124. package/v8/parser.js +839 -1608
  125. package/v8/parser.js.map +1 -1
  126. package/v8/stream.d.ts +39 -3
  127. package/v8/stream.js +685 -171
  128. package/v8/stream.js.map +1 -1
  129. package/v8/token.d.ts +244 -9
  130. package/v8/token.js +315 -47
  131. package/v8/token.js.map +1 -1
  132. package/visit/visitor.d.ts +3 -0
  133. package/visit/visitor.js.map +1 -1
  134. package/api/module/app/program.js.map +0 -1
  135. package/v8/app.d.ts +0 -0
  136. package/v8/app.js +0 -2
  137. package/v8/app.js.map +0 -1
package/v8/parser.js CHANGED
@@ -1,1717 +1,948 @@
1
+ import { JavaScriptInlineParser } from './inline.js';
1
2
  import { Token } from './token.js';
2
- import { TokenStream } from './stream.js';
3
- import { OfNode, Identifier, ThisNode, GetIdentifier, SetIdentifier, AsyncIdentifier, NullNode, StringLiteral, AwaitIdentifier, ConstructorIdentifier, NameIdentifier, EvalIdentifier, ArgumentsIdentifier, TaggedTemplateExpression, TemplateLiteral } from '../api/definition/values.js';
4
- import { EmptyStatement } from '../api/statement/control/empty.js';
5
- import { BlockStatement } from '../api/statement/control/block.js';
6
- import { ArrowFunctionExpression, ArrowFunctionType, FunctionKind, Param, FunctionExpression, FunctionDeclaration } from '../api/definition/function.js';
7
- import { IfStatement } from '../api/statement/control/if.js';
8
- import { NewExpression } from '../api/computing/new.js';
9
- import { SpreadElement } from '../api/computing/spread.js';
10
- import { RestElement } from '../api/computing/rest.js';
3
+ import { Class, ClassBody, ClassDeclaration, ClassExpression, MetaProperty, MethodDefinition, PropertyDefinition, StaticBlock, Super } from '../api/class/class.js';
4
+ import { Identifier, Literal, NullNode } from '../api/definition/values.js';
11
5
  import { AssignmentExpression } from '../api/operators/assignment.js';
12
- import { GroupingExpression } from '../api/operators/grouping.js';
13
- import { MemberExpression } from '../api/definition/member.js';
14
- import { BindExpression } from '../api/definition/bind.js';
15
- import { ObjectExpression, Property, ObjectPattern } from '../api/definition/object.js';
16
- import { ArrayExpression, ArrayPattern } from '../api/definition/array.js';
17
- import { CallExpression } from '../api/computing/call.js';
18
- import { DoWhileNode, WhileNode } from '../api/statement/iterations/while.js';
19
- import { CatchClauseNode, ThrowStatement, TryCatchNode } from '../api/computing/throw.js';
20
- import { SwitchCase, DefaultExpression, SwitchStatement } from '../api/statement/control/switch.js';
21
- import { BreakStatement, ContinueStatement } from '../api/statement/control/terminate.js';
22
- import { ReturnStatement } from '../api/computing/return.js';
23
- import { YieldExpression } from '../api/computing/yield.js';
24
- import { VariableDeclarator, VariableDeclarationNode } from '../api/statement/declarations/declares.js';
25
- import { ForNode, ForOfNode, ForInNode, ForAwaitOfNode } from '../api/statement/iterations/for.js';
26
- import { ConditionalExpression } from '../api/operators/ternary.js';
27
- import { PipelineExpression } from '../api/operators/pipeline.js';
28
- import { LogicalExpression } from '../api/operators/logical.js';
29
- import { SequenceExpression } from '../api/operators/comma.js';
30
- import { ChainExpression } from '../api/operators/chaining.js';
31
- import { ExpressionStatement } from '../api/definition/statement.js';
32
- import { buildPostfixExpression, buildUnaryExpression, expressionFromLiteral, shortcutNumericLiteralBinaryExpression } from './nodes.js';
33
- import { BinaryExpression } from '../api/operators/binary.js';
34
- export var ParsingArrowHeadFlag;
35
- (function (ParsingArrowHeadFlag) {
36
- ParsingArrowHeadFlag[ParsingArrowHeadFlag["CertainlyNotArrowHead"] = 0] = "CertainlyNotArrowHead";
37
- ParsingArrowHeadFlag[ParsingArrowHeadFlag["MaybeArrowHead"] = 1] = "MaybeArrowHead";
38
- ParsingArrowHeadFlag[ParsingArrowHeadFlag["AsyncArrowFunction"] = 2] = "AsyncArrowFunction";
39
- })(ParsingArrowHeadFlag || (ParsingArrowHeadFlag = {}));
40
- export var PropertyKind;
41
- (function (PropertyKind) {
42
- PropertyKind[PropertyKind["Value"] = 0] = "Value";
43
- PropertyKind[PropertyKind["Shorthand"] = 1] = "Shorthand";
44
- PropertyKind[PropertyKind["ShorthandOrClassField"] = 2] = "ShorthandOrClassField";
45
- PropertyKind[PropertyKind["Assign"] = 3] = "Assign";
46
- PropertyKind[PropertyKind["Method"] = 4] = "Method";
47
- PropertyKind[PropertyKind["ClassField"] = 5] = "ClassField";
48
- PropertyKind[PropertyKind["AccessorGetter"] = 6] = "AccessorGetter";
49
- PropertyKind[PropertyKind["AccessorSetter"] = 7] = "AccessorSetter";
50
- PropertyKind[PropertyKind["Spread"] = 8] = "Spread";
51
- PropertyKind[PropertyKind["NotSet"] = 9] = "NotSet";
52
- })(PropertyKind || (PropertyKind = {}));
53
- export function parsePropertyKindFromToken(token, info) {
54
- switch (token) {
55
- case Token.COLON:
56
- info.kind = PropertyKind.Value;
57
- return true;
58
- case Token.COMMA:
59
- info.kind = PropertyKind.Shorthand;
60
- return true;
61
- case Token.R_CURLY:
62
- info.kind = PropertyKind.ShorthandOrClassField;
63
- return true;
64
- case Token.ASSIGN:
65
- info.kind = PropertyKind.Assign;
66
- return true;
67
- case Token.L_PARENTHESES:
68
- info.kind = PropertyKind.Method;
69
- return true;
70
- case Token.MUL:
71
- case Token.SEMICOLON:
72
- info.kind = PropertyKind.ClassField;
73
- return true;
74
- default:
75
- break;
76
- }
77
- return false;
78
- }
79
- export var PreParserIdentifierType;
80
- (function (PreParserIdentifierType) {
81
- PreParserIdentifierType["NullIdentifier"] = "NullIdentifier";
82
- PreParserIdentifierType["UnknownIdentifier"] = "UnknownIdentifier";
83
- PreParserIdentifierType["EvalIdentifier"] = "EvalIdentifier";
84
- PreParserIdentifierType["ArgumentsIdentifier"] = "ArgumentsIdentifier";
85
- PreParserIdentifierType["ConstructorIdentifier"] = "ConstructorIdentifier";
86
- PreParserIdentifierType["AwaitIdentifier"] = "AwaitIdentifier";
87
- PreParserIdentifierType["AsyncIdentifier"] = "AsyncIdentifier";
88
- PreParserIdentifierType["NameIdentifier"] = "NameIdentifier";
89
- PreParserIdentifierType["PrivateNameIdentifier"] = "PrivateNameIdentifier";
90
- })(PreParserIdentifierType || (PreParserIdentifierType = {}));
91
- export class AbstractParser {
92
- constructor(scanner) {
93
- this.scanner = scanner;
94
- }
95
- position() {
96
- return this.scanner.getPos();
97
- }
98
- current() {
99
- return this.scanner.currentToken();
100
- }
101
- next() {
102
- return this.scanner.next();
103
- }
104
- peek() {
105
- return this.scanner.peek();
106
- }
107
- peekAhead() {
108
- return this.scanner.peekAhead();
109
- }
110
- peekAheadPosition() {
111
- return this.scanner.peekAheadPosition();
112
- }
113
- peekPosition() {
114
- return this.scanner.peekPosition();
115
- }
116
- consume(token) {
117
- if (this.scanner.next().isNotType(token)) {
118
- throw new Error(this.errorMessage(`Parsing ${JSON.stringify(token)}`));
119
- }
120
- }
121
- check(token) {
122
- const next = this.scanner.peek();
123
- if (next.isType(token)) {
124
- this.scanner.next();
125
- return true;
126
- }
127
- return false;
128
- }
129
- checkValue(value) {
130
- const next = this.scanner.peek();
131
- if (next.value == value) {
132
- this.scanner.next();
133
- return true;
134
- }
135
- return false;
136
- }
137
- expect(token) {
138
- const current = this.scanner.next();
139
- if (current.isNotType(token)) {
140
- throw new Error(this.errorMessage(`Unexpected Token: ${JSON.stringify(token)}, current is ${JSON.stringify(current)}`));
141
- }
142
- }
143
- checkInOrOf() {
144
- if (this.check(Token.IN)) {
145
- return 'IN';
146
- }
147
- else if (this.checkValue(OfNode)) {
148
- return 'OF';
149
- }
150
- return false;
151
- }
152
- peekInOrOf() {
153
- var next = this.peek();
154
- if (next.isType(Token.IN)) {
155
- return 'IN';
156
- }
157
- else if (next.value === OfNode) {
158
- return 'OF';
159
- }
160
- return false;
161
- }
162
- isEvalOrArguments(name) {
163
- if (name.toString() === 'eval') {
164
- return true;
165
- }
166
- else if (name.toString() === 'arguments') {
167
- return true;
168
- }
169
- return false;
170
- }
171
- isNextLetKeyword() {
172
- if (this.peek().isNotType(Token.LET)) {
173
- return false;
174
- }
175
- const nextNextToken = this.peekAhead().token;
176
- switch (nextNextToken) {
177
- case Token.L_CURLY:
178
- case Token.L_BRACKETS:
179
- case Token.IDENTIFIER:
180
- case Token.STATIC:
181
- case Token.LET:
182
- case Token.YIELD:
183
- case Token.AWAIT:
184
- case Token.GET:
185
- case Token.SET:
186
- case Token.ASYNC:
187
- return true;
188
- default:
189
- return false;
190
- }
191
- }
192
- isIdentifier(expression) {
193
- return expression instanceof Identifier;
6
+ import { VariableDeclarationNode, VariableDeclarator } from '../api/statement/declarations/declares.js';
7
+ import { TokenStream } from './stream.js';
8
+ import { Program } from '../api/program.js';
9
+ import { ExportAllDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier } from '../api/module/export.js';
10
+ import { ImportDeclaration, ImportDefaultSpecifier, ImportExpression, ImportNamespaceSpecifier, ImportSpecifier } from '../api/module/import.js';
11
+ import { ImportAttribute } from '../api/module/common.js';
12
+ import { ClassLiteralProperty, ClassLiteralPropertyKind, classPropertyKindFor, createClassInfo, FunctionKind, FunctionSyntaxKind, isAccessor, isStrict, LanguageMode, ParseFunctionFlag, PropertyKind, PropertyKindInfo, PropertyPosition, VariableDeclarationContext } from './enums.js';
13
+ export class JavaScriptParser extends JavaScriptInlineParser {
14
+ /**
15
+ * parser js with
16
+ * @param source
17
+ * @returns
18
+ */
19
+ static parse(source, { mode } = {}) {
20
+ mode ?? (mode = LanguageMode.Strict);
21
+ const stream = (typeof source === 'string') || Array.isArray(source)
22
+ ? TokenStream.getTokenStream(source, mode) : source;
23
+ const parser = new JavaScriptParser(stream);
24
+ return parser.scan();
194
25
  }
195
- isParenthesized(expression) {
196
- return expression instanceof GroupingExpression || expression instanceof SequenceExpression;
26
+ /**
27
+ * parse inline code like that used in html 2 or 1 way binding
28
+ */
29
+ static parseScript(source, options) {
30
+ return JavaScriptInlineParser.parse(source, options);
197
31
  }
198
- isAssignableIdentifier(expression) {
199
- if (!(expression instanceof Identifier)) {
200
- return false;
201
- }
202
- if (this.isEvalOrArguments(expression)) {
203
- return false;
32
+ scan() {
33
+ const isModule = isStrict(this.languageMode);
34
+ if (isModule) {
35
+ this.setFunctionKind(FunctionKind.Module);
204
36
  }
205
- return true;
206
- }
207
- isPattern(expression) {
208
- return expression instanceof ObjectPattern || expression instanceof ArrayPattern;
209
- }
210
- isProperty(expression) {
211
- return expression instanceof MemberExpression;
212
- }
213
- isCallNew(expression) {
214
- return expression instanceof NewExpression;
37
+ const body = isModule ? this.parseModuleItemList() : this.parseStatementList(Token.EOS);
38
+ return new Program(isModule ? 'module' : 'script', body);
215
39
  }
216
- isCall(expression) {
217
- return expression instanceof CallExpression;
218
- }
219
- isEmptyStatement(expression) {
220
- return expression instanceof EmptyStatement;
221
- }
222
- isThisProperty(expression) {
223
- if (this.isProperty(expression)) {
224
- if (expression.getObject() === ThisNode || expression.getObject().toString() === 'this') {
225
- return true;
226
- }
40
+ parseNewTargetExpression() {
41
+ this.consume(Token.PERIOD);
42
+ const target = this.parsePropertyOrPrivatePropertyName();
43
+ if (target.toString() !== 'target') {
44
+ throw new Error(this.errorMessage(`Expression (new.${target.toString()}) not supported.`));
227
45
  }
228
- return false;
229
- }
230
- isValidReferenceExpression(expression) {
231
- return this.isAssignableIdentifier(expression) || this.isProperty(expression);
46
+ return MetaProperty.NewTarget;
232
47
  }
233
- expectSemicolon() {
234
- const tok = this.peek();
235
- if (tok.isType(Token.SEMICOLON)) {
236
- this.next();
237
- return;
238
- }
239
- if (this.scanner.hasLineTerminatorBeforeNext() || Token.isAutoSemicolon(tok.token)) {
240
- return;
241
- }
242
- if (this.scanner.currentToken().isType(Token.AWAIT)) {
243
- throw new Error(this.errorMessage(`Await Not In Async Context/Function`));
48
+ parseClassExpression() {
49
+ this.consume(Token.CLASS);
50
+ let name;
51
+ let isStrictReserved = false;
52
+ if (this.peekAnyIdentifier()) {
53
+ name = this.parseAndClassifyIdentifier(this.next());
54
+ isStrictReserved = Token.isStrictReservedWord(this.current().token);
244
55
  }
56
+ const classLiteral = this.parseClassLiteral(name, isStrictReserved);
57
+ return new ClassExpression(classLiteral.getBody(), classLiteral.getDecorators(), classLiteral.getId(), classLiteral.getSuperClass());
245
58
  }
246
- peekAnyIdentifier() {
247
- return Token.isAnyIdentifier(this.peek().token);
248
- }
249
- errorMessage(message) {
250
- return this.scanner.createError(message);
251
- }
252
- }
253
- export class JavaScriptParser extends AbstractParser {
254
- static parse(source) {
255
- const stream = (typeof source === 'string' || Array.isArray(source))
256
- ? TokenStream.getTokenStream(source)
257
- : source;
258
- const parser = new JavaScriptParser(stream);
259
- return parser.scan();
260
- }
261
- scan() {
262
- const list = this.parseStatementList(Token.EOS);
263
- if (list.length === 1) {
264
- return list[0];
59
+ parseClassDeclaration(names, defaultExport) {
60
+ // ClassDeclaration ::
61
+ // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
62
+ // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
63
+ //
64
+ // The anonymous form is allowed iff [default_export] is true.
65
+ //
66
+ // 'class' is expected to be consumed by the caller.
67
+ //
68
+ // A ClassDeclaration
69
+ //
70
+ // class C { ... }
71
+ //
72
+ // has the same semantics as:
73
+ //
74
+ // let C = class C { ... };
75
+ //
76
+ // so rewrite it as such.
77
+ const nextToken = this.peek().token;
78
+ const isStrictReserved = Token.isStrictReservedWord(nextToken);
79
+ let name;
80
+ let variableName;
81
+ if (defaultExport && (nextToken == Token.EXTENDS || nextToken == Token.LBRACE)) {
82
+ name = new Literal('default');
83
+ variableName = '.default';
265
84
  }
266
- return new ExpressionStatement(list);
267
- }
268
- parseStatement() {
269
- switch (this.peek().token) {
270
- case Token.L_CURLY:
271
- return this.parseBlock();
272
- case Token.SEMICOLON:
273
- this.consume(Token.SEMICOLON);
274
- return EmptyStatement.INSTANCE;
275
- case Token.IF:
276
- return this.parseIfStatement();
277
- case Token.DO:
278
- return this.parseDoWhileStatement();
279
- case Token.WHILE:
280
- return this.parseWhileStatement();
281
- case Token.FOR:
282
- return this.parseForStatement();
283
- case Token.CONTINUE:
284
- return this.parseContinueStatement();
285
- case Token.BREAK:
286
- return this.parseBreakStatement();
287
- case Token.RETURN:
288
- return this.parseReturnStatement();
289
- case Token.THROW:
290
- return this.parseThrowStatement();
291
- case Token.TRY:
292
- return this.parseTryStatement();
293
- case Token.SWITCH:
294
- return this.parseSwitchStatement();
295
- case Token.VAR:
296
- case Token.LET:
297
- case Token.CONST:
298
- return this.parseVariableDeclarations();
299
- case Token.ASYNC:
300
- if (this.peekAhead().isType(Token.FUNCTION)) {
301
- this.consume(Token.ASYNC);
302
- this.consume(Token.FUNCTION);
303
- if (this.peek().isType(Token.MUL)) {
304
- return this.parseFunctionExpression(FunctionKind.ASYNC_GENERATOR);
305
- }
306
- return this.parseFunctionExpression(FunctionKind.ASYNC);
307
- }
308
- default:
309
- return this.parseExpressionOrLabelledStatement();
85
+ else {
86
+ const identifier = this.parseIdentifier();
87
+ variableName = identifier.getName();
88
+ name = identifier;
310
89
  }
90
+ const classLiteral = this.parseClassLiteral(name, isStrictReserved);
91
+ return new ClassDeclaration(classLiteral.getBody(), classLiteral.getDecorators(), classLiteral.getId(), classLiteral.getSuperClass());
311
92
  }
312
- parseTryStatement() {
313
- this.consume(Token.TRY);
314
- const tryBlock = this.parseBlock();
315
- if (tryBlock instanceof BlockStatement) {
316
- tryBlock.isStatement = true;
317
- }
318
- let peek = this.peek();
319
- if (peek.isNotType(Token.CATCH) && peek.isNotType(Token.FINALLY)) {
320
- throw new Error(this.errorMessage(`Uncaught SyntaxError: Missing catch or finally after try`));
321
- }
322
- let catchBlock;
323
- if (this.check(Token.CATCH)) {
324
- let catchVar;
325
- const hasBinding = this.check(Token.L_PARENTHESES);
326
- if (hasBinding) {
327
- catchVar = this.parseIdentifier();
328
- this.expect(Token.R_PARENTHESES);
93
+ parseClassLiteral(name, nameIsStrictReserved) {
94
+ const isAnonymous = !!!name;
95
+ // All parts of a ClassDeclaration and ClassExpression are strict code.
96
+ if (!isAnonymous) {
97
+ if (nameIsStrictReserved) {
98
+ throw new Error(this.errorMessage(`Unexpected Strict Reserved class name`));
329
99
  }
330
- const block = this.parseBlock();
331
- if (block instanceof BlockStatement) {
332
- block.isStatement = true;
100
+ if (this.isEvalOrArguments(name)) {
101
+ throw new Error(this.errorMessage(`Strict Eval Arguments not allowed for class name`));
333
102
  }
334
- catchBlock = new CatchClauseNode(block, catchVar);
335
103
  }
336
- let finallyBlock;
337
- if (this.check(Token.FINALLY)) {
338
- finallyBlock = this.parseBlock();
339
- if (finallyBlock instanceof BlockStatement) {
340
- finallyBlock.isStatement = true;
341
- }
104
+ const classInfo = createClassInfo();
105
+ classInfo.isAnonymous = isAnonymous;
106
+ if (this.check(Token.EXTENDS)) {
107
+ classInfo.extends = this.parseLeftHandSideExpression();
342
108
  }
343
- return new TryCatchNode(tryBlock, catchBlock, finallyBlock);
344
- }
345
- parseBlock() {
346
- this.expect(Token.L_CURLY);
347
- const statements = [];
348
- const block = new BlockStatement(statements, false);
349
- while (this.peek().isNotType(Token.R_CURLY)) {
350
- const stat = this.parseStatementListItem();
351
- if (!stat) {
352
- return block;
109
+ this.expect(Token.LBRACE);
110
+ const hasExtends = !!classInfo.extends;
111
+ while (this.peek().isNotType(Token.RBRACE)) {
112
+ if (this.check(Token.SEMICOLON))
113
+ continue;
114
+ // Either we're parsing a `static { }` initialization block or a property.
115
+ if (this.peek().isType(Token.STATIC) && this.peekAhead().isType(Token.LBRACE)) {
116
+ const staticBlock = this.parseClassStaticBlock(classInfo);
117
+ classInfo.staticElements.push(staticBlock);
118
+ classInfo.hasStaticBlocks = true;
119
+ continue;
353
120
  }
354
- else if (stat instanceof EmptyStatement) {
121
+ // FuncNameInferrerState fni_state(& fni_);
122
+ // If we haven't seen the constructor yet, it potentially is the next
123
+ // property.
124
+ let isConstructor = !classInfo.hasSeenConstructor;
125
+ const propInfo = new PropertyKindInfo();
126
+ propInfo.position = PropertyPosition.ClassLiteral;
127
+ const property = this.parseClassPropertyDefinition(classInfo, propInfo, hasExtends);
128
+ // if (has_error()) return impl() . FailureExpression();
129
+ const propertyKind = classPropertyKindFor(propInfo.kind);
130
+ if (!classInfo.hasStaticComputedNames && propInfo.isStatic && propInfo.isComputedName) {
131
+ classInfo.hasStaticComputedNames = true;
132
+ }
133
+ isConstructor && (isConstructor = classInfo.hasSeenConstructor);
134
+ const isField = propertyKind == ClassLiteralPropertyKind.FIELD;
135
+ if (propInfo.isPrivate) {
136
+ if (isConstructor) {
137
+ throw new Error(this.errorMessage('private constructor is not allowed'));
138
+ }
139
+ classInfo.requiresBrand || (classInfo.requiresBrand = !isField && !propInfo.isStatic);
140
+ const isMethod = propertyKind == ClassLiteralPropertyKind.METHOD;
141
+ classInfo.hasPrivateMethods || (classInfo.hasPrivateMethods = isMethod);
142
+ classInfo.hasStaticPrivateMethods || (classInfo.hasStaticPrivateMethods = isMethod && propInfo.isStatic);
143
+ this.declarePrivateClassMember(propInfo.name, property, propertyKind, propInfo.isStatic, classInfo);
355
144
  continue;
356
145
  }
357
- statements.push(stat);
358
- }
359
- this.expect(Token.R_CURLY);
360
- return block;
361
- }
362
- parseStatementListItem() {
363
- switch (this.peek().token) {
364
- case Token.FUNCTION:
365
- this.consume(Token.FUNCTION);
366
- if (this.peek().isType(Token.MUL)) {
367
- this.consume(Token.MUL);
368
- return this.parseFunctionExpression(FunctionKind.GENERATOR);
369
- }
370
- return this.parseFunctionExpression(FunctionKind.NORMAL);
371
- case Token.CLASS:
372
- this.consume(Token.CLASS);
373
- return this.parseClassDeclaration(undefined, false);
374
- case Token.VAR:
375
- case Token.LET:
376
- case Token.CONST:
377
- return this.parseVariableDeclarations();
378
- case Token.ASYNC:
379
- if (this.peekAhead().isType(Token.FUNCTION)) {
380
- this.consume(Token.ASYNC);
381
- this.consume(Token.FUNCTION);
382
- if (this.peek().isType(Token.MUL)) {
383
- this.consume(Token.MUL);
384
- return this.parseFunctionExpression(FunctionKind.ASYNC_GENERATOR);
385
- }
386
- return this.parseFunctionExpression(FunctionKind.ASYNC);
146
+ if (isField) {
147
+ if (propInfo.isComputedName) {
148
+ classInfo.computedFieldCount++;
387
149
  }
388
- break;
389
- default:
390
- break;
391
- }
392
- return this.parseStatement();
393
- }
394
- parseFunctionExpression(type) {
395
- let funcName;
396
- const peek = this.peek();
397
- if (peek.isNotType(Token.L_PARENTHESES)) {
398
- if (peek.isType(Token.L_BRACKETS)) {
399
- this.consume(Token.L_BRACKETS);
400
- funcName = this.parseMemberExpression();
401
- this.expect(Token.R_BRACKETS);
402
- }
403
- else {
404
- funcName = this.parseIdentifier();
150
+ this.declarePublicClassField(property, propInfo.isStatic, propInfo.isComputedName, classInfo);
151
+ continue;
405
152
  }
153
+ this.declarePublicClassMethod(name, property, isConstructor, classInfo);
406
154
  }
407
- return this.parseFunctionLiteral(type, funcName);
155
+ this.expect(Token.RBRACE);
156
+ const classBody = this.rewriteClassLiteral(classInfo, name);
157
+ return new Class(classBody, [], name, classInfo.extends);
408
158
  }
409
- parseIfStatement() {
410
- this.consume(Token.IF);
411
- this.consume(Token.L_PARENTHESES);
412
- const condition = this.parseExpression();
413
- this.consume(Token.R_PARENTHESES);
414
- const thenStatement = this.parseStatement();
415
- if (thenStatement instanceof BlockStatement) {
416
- thenStatement.isStatement = true;
417
- }
418
- let elseStatement;
419
- if (this.peek().isType(Token.ELSE)) {
420
- this.consume(Token.ELSE);
421
- elseStatement = this.parseStatement();
422
- }
423
- return new IfStatement(condition, thenStatement, elseStatement);
424
- }
425
- parseDoWhileStatement() {
426
- this.consume(Token.DO);
427
- const body = this.parseStatement();
428
- if (body instanceof BlockStatement) {
429
- body.isStatement = true;
430
- }
431
- this.expect(Token.WHILE);
432
- this.expect(Token.L_PARENTHESES);
433
- const condition = this.parseExpression();
434
- this.expect(Token.R_PARENTHESES);
435
- this.check(Token.SEMICOLON);
436
- return new DoWhileNode(condition, body);
437
- }
438
- parseWhileStatement() {
439
- this.consume(Token.WHILE);
440
- this.expect(Token.L_PARENTHESES);
441
- const condition = this.parseExpression();
442
- this.expect(Token.R_PARENTHESES);
443
- const body = this.parseStatement();
444
- if (body instanceof BlockStatement) {
445
- body.isStatement = true;
446
- }
447
- return new WhileNode(condition, body);
448
- }
449
- parseThrowStatement() {
450
- this.consume(Token.THROW);
451
- if (this.scanner.hasLineTerminatorBeforeNext()) {
452
- throw new Error(this.scanner.createError(`New line After Throw`));
453
- }
454
- const exception = this.parseExpression();
455
- this.expectSemicolon();
456
- return new ThrowStatement(exception);
457
- }
458
- parseSwitchStatement() {
459
- this.consume(Token.SWITCH);
460
- this.expect(Token.L_PARENTHESES);
461
- const tag = this.parseExpression();
462
- this.expect(Token.R_PARENTHESES);
463
- const cases = [];
464
- const switchStatement = new SwitchStatement(tag, cases);
465
- let defaultSeen = false;
466
- this.expect(Token.L_CURLY);
467
- while (this.peek().isNotType(Token.R_CURLY)) {
468
- const statements = [];
469
- let label;
470
- if (this.check(Token.CASE)) {
471
- label = this.parseExpression();
472
- }
473
- else {
474
- this.expect(Token.DEFAULT);
475
- if (defaultSeen) {
476
- throw new Error(this.errorMessage(`Multiple Defaults In Switch`));
477
- }
478
- defaultSeen = true;
479
- }
480
- this.expect(Token.COLON);
481
- while (this.peek().isNotType(Token.CASE)
482
- && this.peek().isNotType(Token.DEFAULT)
483
- && this.peek().isNotType(Token.R_CURLY)) {
484
- const statement = this.parseStatementListItem();
485
- if (!statement || this.isEmptyStatement(statement)) {
486
- continue;
487
- }
488
- statements.push(statement);
159
+ declarePublicClassMethod(name, property, isConstructor, classInfo) {
160
+ // throw new Error('Method not implemented.');
161
+ if (isConstructor) {
162
+ if (classInfo.constructor) {
163
+ throw new SyntaxError(this.errorMessage('A class may only have one constructor.'));
489
164
  }
490
- const block = new BlockStatement(statements, true);
491
- const clause = defaultSeen ? new DefaultExpression(block) : new SwitchCase(label, block);
492
- cases.push(clause);
165
+ classInfo.constructor = property;
166
+ // set the class name as the constructor name
167
+ Reflect.set(classInfo.constructor, 'id', name);
168
+ return;
493
169
  }
494
- this.expect(Token.R_CURLY);
495
- return switchStatement;
170
+ classInfo.publicMembers.push(property);
496
171
  }
497
- parseForStatement() {
498
- this.consume(Token.FOR);
499
- const isAwait = this.check(Token.AWAIT);
500
- this.expect(Token.L_PARENTHESES);
501
- const peek = this.peek();
502
- const startsWithLet = peek.isType(Token.LET) || peek.isType(Token.VAR);
503
- let initializer;
504
- if (peek.isType(Token.CONST) || (startsWithLet && this.isNextLetKeyword())) {
505
- initializer = this.parseVariableDeclarations();
506
- }
507
- else if (peek.isType(Token.SEMICOLON)) {
508
- initializer = EmptyStatement.INSTANCE;
172
+ declarePublicClassField(property, isStatic, isComputedName, classInfo) {
173
+ if (isStatic) {
174
+ classInfo.staticElements.push(property);
509
175
  }
510
176
  else {
511
- initializer = this.parseExpressionCoverGrammar();
512
- }
513
- if (initializer instanceof BinaryExpression) {
514
- const objectNode = initializer.getRight();
515
- initializer = initializer.getLeft();
516
- this.expect(Token.R_PARENTHESES);
517
- const statement = this.parseStatement();
518
- return new ForInNode(initializer, objectNode, statement);
519
- }
520
- const forMode = this.checkInOrOf();
521
- if (forMode) {
522
- const object = forMode === 'IN' ? this.parseAssignmentExpression() : this.parseExpression();
523
- this.expect(Token.R_PARENTHESES);
524
- const statement = this.parseStatement();
525
- if (statement instanceof BlockStatement) {
526
- statement.isStatement = true;
527
- }
528
- if (isAwait && forMode === 'OF') {
529
- return new ForAwaitOfNode(initializer, object, statement);
530
- }
531
- else if (forMode === 'OF') {
532
- return new ForOfNode(initializer, object, statement);
533
- }
534
- else if (forMode === 'IN') {
535
- return new ForInNode(initializer, object, statement);
177
+ classInfo.instanceFields.push(property);
178
+ }
179
+ // if (isComputedName) {
180
+ // classInfo.publicMembers.push(property);
181
+ // }
182
+ }
183
+ declarePrivateClassMember(propertyName, property, kind, isStatic, classInfo) {
184
+ classInfo.privateMembers.push(property);
185
+ }
186
+ // protected createPrivateNameVariable(mode: VariableMode, staticFlag: StaticFlag, propertyName: string) {
187
+ // throw new Error('Method not implemented.');
188
+ // }
189
+ parseClassPropertyDefinition(classInfo, propInfo, hasExtends) {
190
+ if (!classInfo) {
191
+ throw new Error(this.errorMessage('class info is undefined'));
192
+ }
193
+ if (propInfo.position !== PropertyPosition.ClassLiteral) {
194
+ throw new Error(this.errorMessage('expected property position ClassLiteral'));
195
+ }
196
+ const nameToken = this.peek();
197
+ let nameExpression;
198
+ if (nameToken.isType(Token.STATIC)) {
199
+ this.consume(Token.STATIC);
200
+ if (this.peek().isType(Token.LPAREN)) {
201
+ propInfo.kind = PropertyKind.Method;
202
+ nameExpression = this.parseIdentifier();
203
+ propInfo.name = nameExpression.getName();
204
+ }
205
+ else if (this.peek().isType(Token.ASSIGN)
206
+ || this.peek().isType(Token.SEMICOLON)
207
+ || this.peek().isType(Token.RBRACK)) {
208
+ nameExpression = this.parseIdentifier();
209
+ propInfo.name = nameExpression.getName();
536
210
  }
537
211
  else {
538
- throw new Error(this.errorMessage(`parsing for loop: ${this.position()}`));
212
+ propInfo.isStatic = true;
213
+ nameExpression = this.parseProperty(propInfo);
539
214
  }
540
215
  }
541
- this.expect(Token.SEMICOLON);
542
- let condition;
543
- if (!this.check(Token.SEMICOLON)) {
544
- condition = this.parseExpression();
545
- this.expect(Token.SEMICOLON);
546
- }
547
- let finalExpression;
548
- if (!this.check(Token.R_PARENTHESES)) {
549
- finalExpression = this.parseExpression();
550
- this.expect(Token.R_PARENTHESES);
551
- }
552
- const body = this.parseStatement();
553
- if (body instanceof BlockStatement) {
554
- body.isStatement = true;
555
- }
556
- return new ForNode(body, initializer, condition, finalExpression);
557
- }
558
- parseVariableDeclarations() {
559
- let mode;
560
- const token = this.peek().token;
561
- switch (token) {
562
- case Token.CONST:
563
- this.consume(token);
564
- mode = 'const';
565
- break;
566
- case Token.VAR:
567
- this.consume(token);
568
- mode = 'var';
569
- break;
570
- case Token.LET:
571
- default:
572
- this.consume(token);
573
- mode = 'let';
574
- break;
216
+ else {
217
+ nameExpression = this.parseProperty(propInfo);
575
218
  }
576
- const variables = [];
577
- do {
578
- let name;
579
- let value;
580
- if (Token.isAnyIdentifier(this.peek().token)) {
581
- name = this.parseAndClassifyIdentifier(this.next());
582
- if (this.isEvalOrArguments(name)) {
583
- throw new Error(this.errorMessage(`Strict Eval Arguments`));
584
- }
585
- }
586
- else {
587
- name = this.parseBindingPattern(true);
219
+ switch (propInfo.kind) {
220
+ case PropertyKind.Assign:
221
+ case PropertyKind.ClassField:
222
+ case PropertyKind.ShorthandOrClassField:
223
+ case PropertyKind.NotSet: {
224
+ // This case is a name followed by a
225
+ // name or other property. Here we have
226
+ // to assume that's an uninitialized
227
+ // field followed by a line break
228
+ // followed by a property, with ASI
229
+ // adding the semicolon. If not, there
230
+ // will be a syntax error after parsing
231
+ // the first name as an uninitialized
232
+ // field.
233
+ propInfo.kind = PropertyKind.ClassField;
234
+ // if (!propInfo.isComputedName) {
235
+ // this.checkClassFieldName(propInfo.name, propInfo.isStatic);
236
+ // }
237
+ const initializer = this.parseMemberInitializer(classInfo, propInfo.isStatic);
238
+ this.expectSemicolon();
239
+ const result = this.newClassLiteralProperty(nameExpression, initializer, ClassLiteralPropertyKind.FIELD, propInfo.isStatic, propInfo.isComputedName, propInfo.isPrivate);
240
+ this.setFunctionNameFromPropertyName(result, propInfo.name);
241
+ return result;
588
242
  }
589
- if (this.check(Token.ASSIGN)) {
590
- value = this.parseAssignmentExpression();
243
+ case PropertyKind.Method: {
244
+ // MethodDefinition
245
+ // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
246
+ // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
247
+ // async PropertyName '(' StrictFormalParameters ')'
248
+ // '{' FunctionBody '}'
249
+ // async '*' PropertyName '(' StrictFormalParameters ')'
250
+ // '{' FunctionBody '}'
251
+ if (!propInfo.isComputedName) {
252
+ this.checkClassMethodName(propInfo, classInfo);
253
+ }
254
+ let kind = this.methodKindFor(propInfo.isStatic, propInfo.funcFlag);
255
+ if (!propInfo.isStatic && propInfo.name.toString() === 'constructor') {
256
+ classInfo.hasSeenConstructor = true;
257
+ kind = hasExtends ? FunctionKind.DerivedConstructor : FunctionKind.BaseConstructor;
258
+ }
259
+ const value = this.parseFunctionLiteral(kind, FunctionSyntaxKind.AccessorOrMethod, nameExpression);
260
+ const result = this.newClassLiteralProperty(nameExpression, value, ClassLiteralProperty.Kind.METHOD, propInfo.isStatic, propInfo.isComputedName, propInfo.isPrivate);
261
+ this.setFunctionNameFromPropertyName(result, propInfo.name);
262
+ return result;
591
263
  }
592
- else if (!this.peekInOrOf()) {
593
- if (mode === 'const' && (name === undefined || value === undefined)) {
594
- throw new Error(this.errorMessage(`Declaration Missing Initializer : ${this.position()}`));
264
+ case PropertyKind.AccessorGetter:
265
+ case PropertyKind.AccessorSetter: {
266
+ if (propInfo.funcFlag !== ParseFunctionFlag.IsNormal) {
267
+ throw new Error(this.errorMessage('accessor is not normal function'));
595
268
  }
269
+ const isGet = propInfo.kind == PropertyKind.AccessorGetter;
270
+ if (!propInfo.isComputedName) {
271
+ this.checkClassMethodName(propInfo, classInfo);
272
+ // Make sure the name expression is a string since we need a Name for
273
+ // Runtime_DefineAccessorPropertyUnchecked and since we can determine
274
+ // this statically we can skip the extra runtime check.
275
+ nameExpression = new Literal(propInfo.name);
276
+ }
277
+ let kind;
278
+ if (propInfo.isStatic) {
279
+ kind = isGet ? FunctionKind.StaticGetterFunction
280
+ : FunctionKind.StaticSetterFunction;
281
+ }
282
+ else {
283
+ kind = isGet ? FunctionKind.GetterFunction
284
+ : FunctionKind.SetterFunction;
285
+ }
286
+ const value = this.parseFunctionLiteral(kind, FunctionSyntaxKind.AccessorOrMethod, nameExpression);
287
+ const propertyKind = isGet ? ClassLiteralProperty.Kind.GETTER : ClassLiteralProperty.Kind.SETTER;
288
+ const result = this.newClassLiteralProperty(nameExpression, value, propertyKind, propInfo.isStatic, propInfo.isComputedName, propInfo.isPrivate);
289
+ const prefix = isGet ? 'get ' : 'set ';
290
+ this.setFunctionNameFromPropertyName(result, propInfo.name, prefix);
291
+ return result;
596
292
  }
597
- variables.push(new VariableDeclarator(name, value));
598
- } while (this.check(Token.COMMA));
599
- return new VariableDeclarationNode(variables, mode);
600
- }
601
- parseBindingPattern(isPattern) {
602
- const token = this.peek().token;
603
- if (Token.isAnyIdentifier(token)) {
604
- const name = this.parseAndClassifyIdentifier(this.next());
605
- if (this.isEvalOrArguments(name)) {
606
- throw new Error(this.errorMessage(`Strict Eval Arguments`));
607
- }
608
- return name;
609
- }
610
- if (token == Token.L_BRACKETS) {
611
- return this.parseArrayLiteral(isPattern);
612
- }
613
- else if (token == Token.L_CURLY) {
614
- return this.parseObjectLiteral(isPattern);
615
- }
616
- else {
617
- throw new Error(this.errorMessage(`Unexpected Token: ${this.next().getValue()}`));
293
+ case PropertyKind.Value:
294
+ case PropertyKind.Shorthand:
295
+ case PropertyKind.Spread:
296
+ // throw new Error(this.errorMessage('Report Unexpected Token'));
297
+ return NullNode;
618
298
  }
299
+ throw new Error(this.errorMessage('UNREACHABLE'));
619
300
  }
620
- parseAndClassifyIdentifier(next) {
621
- if (next.isType(Token.IDENTIFIER)) {
622
- return next.getValue();
301
+ checkClassMethodName(propInfo, classInfo) {
302
+ if (!(propInfo.kind == PropertyKind.Method || isAccessor(propInfo.kind))) {
303
+ throw new Error(this.errorMessage('not kind of method or setter or getter'));
623
304
  }
624
- else if (next.isType(Token.SET)) {
625
- const value = this.parseFunctionDeclaration();
626
- return new Property(next.getValue(), value, 'set');
305
+ if (propInfo.isPrivate && propInfo.name.toString() === 'constructor') {
306
+ throw new Error(this.errorMessage('constructor is private'));
627
307
  }
628
- else if (next.isType(Token.GET)) {
629
- const value = this.parseFunctionDeclaration();
630
- return new Property(next.getValue(), value, 'get');
308
+ else if (propInfo.isStatic && propInfo.name.toString() === 'prototype') {
309
+ throw new Error(this.errorMessage('static prototype'));
631
310
  }
632
- else if (next.isType(Token.AWAIT)) {
633
- throw new Error(this.errorMessage(`un supported expression (await)`));
634
- }
635
- return next.getValue();
636
- }
637
- parseContinueStatement() {
638
- this.consume(Token.CONTINUE);
639
- this.expectSemicolon();
640
- return ContinueStatement.CONTINUE_INSTANCE;
641
- }
642
- parseBreakStatement() {
643
- this.consume(Token.BREAK);
644
- this.expectSemicolon();
645
- return BreakStatement.BREAK_INSTANCE;
646
- }
647
- parseReturnStatement() {
648
- this.consume(Token.RETURN);
649
- const tokenExp = this.peek();
650
- let returnValue;
651
- if (this.scanner.hasLineTerminatorBeforeNext() || Token.isAutoSemicolon(tokenExp.token)) {
652
- }
653
- else {
654
- returnValue = this.parseExpression();
655
- }
656
- this.expectSemicolon();
657
- return new ReturnStatement(returnValue);
658
- }
659
- parseExpressionOrLabelledStatement() {
660
- switch (this.peek().token) {
661
- case Token.FUNCTION:
662
- case Token.L_CURLY:
663
- throw new Error(this.errorMessage(`Unreachable state`));
664
- case Token.CLASS:
665
- throw new Error(this.errorMessage(`Unexpected Token ${this.next().getValue().toString()}`));
666
- case Token.LET: {
667
- const nextNext = this.peekAhead();
668
- if (nextNext.isNotType(Token.L_BRACKETS) &&
669
- ((nextNext.isNotType(Token.L_CURLY) && nextNext.isNotType(Token.IDENTIFIER)))) {
670
- break;
311
+ else if (propInfo.name.toString() === 'constructor') {
312
+ if (propInfo.funcFlag !== ParseFunctionFlag.IsNormal || isAccessor(propInfo.kind)) {
313
+ if (propInfo.funcFlag === ParseFunctionFlag.IsGenerator) {
314
+ throw new Error(this.errorMessage('constructor is generator'));
315
+ }
316
+ else if (propInfo.funcFlag === ParseFunctionFlag.IsAsync) {
317
+ throw new Error(this.errorMessage('constructor is async'));
318
+ }
319
+ if (classInfo.hasSeenConstructor) {
320
+ throw new Error(this.errorMessage('duplicate constructor'));
671
321
  }
672
- throw new Error(this.errorMessage(`Unexpected Lexical Declaration ${this.position()}`));
673
- }
674
- default:
675
- break;
676
- }
677
- const startsWithIdentifier = Token.isAnyIdentifier(this.peek().token);
678
- const expression = this.parseExpressionCoverGrammar();
679
- if (this.peek().isType(Token.COLON) && startsWithIdentifier && this.isIdentifier(expression)) {
680
- this.consume(Token.COLON);
681
- if (this.peek().isType(Token.FUNCTION)) {
682
- return this.parseFunctionDeclaration();
683
322
  }
684
- return this.parseStatement();
323
+ classInfo.hasSeenConstructor = true;
685
324
  }
686
- this.expectSemicolon();
687
- return expression;
688
325
  }
689
- parseExpression() {
690
- return this.parseExpressionCoverGrammar();
326
+ parseClassStaticBlock(classInfo) {
327
+ this.consume(Token.STATIC);
328
+ // Each static block has its own var and lexical scope, so make a new var
329
+ // block scope instead of using the synthetic members initializer function
330
+ // scope.
331
+ this.setStatue(true, FunctionKind.ClassStaticInitializerFunction);
332
+ const block = this.parseBlock();
333
+ this.restoreStatue();
334
+ classInfo.hasStaticElements = true;
335
+ return new StaticBlock(block.getBody());
691
336
  }
692
- parseFunctionDeclaration() {
693
- this.consume(Token.FUNCTION);
694
- if (this.check(Token.MUL)) {
695
- throw new Error(this.errorMessage(`Error Generator In Single Statement Context`));
696
- }
697
- return this.parseHoistableDeclaration(FunctionKind.NORMAL);
337
+ declareClass(variableName, value, names) {
338
+ names?.push(variableName);
339
+ const proxy = this.declareVariable(variableName, 'let');
340
+ return new AssignmentExpression('=', proxy, value);
698
341
  }
699
- parseFunctionDeclarationAndGenerator() {
700
- this.consume(Token.FUNCTION);
701
- if (this.check(Token.MUL)) {
702
- return this.parseHoistableDeclaration(FunctionKind.GENERATOR);
703
- }
704
- return this.parseHoistableDeclaration(FunctionKind.NORMAL);
342
+ declareVariable(name, mode) {
343
+ return new VariableDeclarationNode([new VariableDeclarator(new Identifier(name))], mode);
705
344
  }
706
- parseHoistableDeclaration(flag) {
707
- if (FunctionKind.ASYNC === flag && this.check(Token.MUL)) {
708
- flag = FunctionKind.ASYNC_GENERATOR;
709
- }
710
- let name;
711
- if (this.peek().isNotType(Token.L_PARENTHESES)) {
712
- name = this.parseIdentifier();
713
- }
714
- return this.parseFunctionLiteral(flag, name);
715
- }
716
- parseIdentifier() {
717
- const next = this.next();
718
- if (!Token.isValidIdentifier(next.token)) {
719
- throw new Error(this.errorMessage(`Unexpected Token: ${next.getValue()}`));
720
- }
721
- if (next.isType(Token.IDENTIFIER)) {
722
- return next.getValue();
723
- }
724
- return this.getIdentifier();
725
- }
726
- getIdentifier() {
727
- const current = this.current();
728
- const string = current.getValue().toString();
729
- switch (current.token) {
730
- case Token.AWAIT:
731
- return AwaitIdentifier;
732
- case Token.ASYNC:
733
- return AsyncIdentifier;
734
- case Token.PRIVATE_NAME:
735
- return new Identifier(`#${string}`);
345
+ newClassLiteralProperty(nameExpression, initializer, kind, isStatic, isComputedName, isPrivate) {
346
+ switch (kind) {
347
+ case ClassLiteralPropertyKind.METHOD:
348
+ if (nameExpression.toString() === 'constructor') {
349
+ return new MethodDefinition('constructor', nameExpression, initializer, [], isComputedName, isStatic);
350
+ }
351
+ return new MethodDefinition('method', nameExpression, initializer, [], isComputedName, isStatic);
352
+ case ClassLiteralPropertyKind.GETTER:
353
+ return new MethodDefinition('get', nameExpression, initializer, [], isComputedName, isStatic);
354
+ case ClassLiteralPropertyKind.SETTER:
355
+ return new MethodDefinition('set', nameExpression, initializer, [], isComputedName, isStatic);
356
+ case ClassLiteralPropertyKind.FIELD:
357
+ return new PropertyDefinition(nameExpression, [], isComputedName, isStatic, initializer);
736
358
  default:
737
359
  break;
738
360
  }
739
- if (string == 'constructor') {
740
- return ConstructorIdentifier;
741
- }
742
- if (string == 'name') {
743
- return NameIdentifier;
744
- }
745
- if (string == 'eval') {
746
- return EvalIdentifier;
747
- }
748
- else if (string == 'arguments') {
749
- return ArgumentsIdentifier;
750
- }
751
- throw new Error(this.errorMessage(`can't identify token ${string}`));
361
+ throw new Error(this.errorMessage('UNREACHABLE'));
752
362
  }
753
- parseFunctionLiteral(flag, name) {
754
- const functionInfo = {};
755
- this.expect(Token.L_PARENTHESES);
756
- const formals = this.parseFormalParameterList(functionInfo);
757
- this.expect(Token.R_PARENTHESES);
758
- const body = this.parseFunctionBody();
759
- if (name) {
760
- return new FunctionDeclaration(formals, body, flag, name, functionInfo.rest);
363
+ parseMemberInitializer(classInfo, isStatic) {
364
+ const kind = isStatic
365
+ ? FunctionKind.ClassStaticInitializerFunction
366
+ : FunctionKind.ClassMembersInitializerFunction;
367
+ let initializer = undefined;
368
+ if (this.check(Token.ASSIGN)) {
369
+ this.setStatue(true, kind);
370
+ initializer = this.parseAssignmentExpression();
371
+ this.restoreStatue();
761
372
  }
762
- return new FunctionExpression(formals, body, flag, name, functionInfo.rest);
763
- }
764
- parseArrowFunctionBody() {
765
- const isExpression = this.peek().isNotType(Token.L_CURLY);
766
- if (isExpression) {
767
- const expression = this.parseAssignmentExpression();
768
- return expression;
373
+ if (isStatic) {
374
+ classInfo.hasStaticElements = true;
769
375
  }
770
376
  else {
771
- return this.parseFunctionBody();
377
+ classInfo.hasInstanceMembers = true;
772
378
  }
379
+ return initializer;
773
380
  }
774
- parseFunctionBody() {
775
- this.expect(Token.L_CURLY);
776
- const list = this.parseStatementList(Token.R_CURLY);
777
- this.expect(Token.R_CURLY);
778
- return list;
381
+ setFunctionNameFromPropertyName(property, name, prefix) {
382
+ // TODO: no need for this now
383
+ // check later when needed
384
+ // the ClassExpression* handle this
779
385
  }
780
- parseStatementList(endToken) {
781
- const list = [];
782
- while (this.peek().isNotType(endToken)) {
783
- const stat = this.parseStatementListItem();
386
+ parseSuperExpression() {
387
+ this.consume(Token.SUPER);
388
+ if (Token.isProperty(this.peek().token)) {
389
+ if (this.peek().isType(Token.PERIOD) && this.peekAhead().isType(Token.PRIVATE_NAME)) {
390
+ this.consume(Token.PERIOD);
391
+ this.consume(Token.PRIVATE_NAME);
392
+ throw new Error(this.errorMessage('Unexpected Private Field'));
393
+ }
394
+ if (this.peek().isType(Token.QUESTION_PERIOD)) {
395
+ this.consume(Token.QUESTION_PERIOD);
396
+ throw new Error(this.errorMessage('Optional Chaining No Super'));
397
+ }
398
+ return Super.INSTANCE;
399
+ }
400
+ throw new Error(this.errorMessage('Unexpected Super'));
401
+ }
402
+ rewriteClassLiteral(classInfo, name) {
403
+ const body = [];
404
+ if (classInfo.hasSeenConstructor) {
405
+ body.push(classInfo.constructor);
406
+ }
407
+ body.push(...classInfo.staticElements);
408
+ body.push(...classInfo.instanceFields);
409
+ body.push(...classInfo.publicMembers);
410
+ body.push(...classInfo.privateMembers);
411
+ return new ClassBody(body);
412
+ }
413
+ parseModuleItemList() {
414
+ // ecma262/#prod-Module
415
+ // Module :
416
+ // ModuleBody?
417
+ //
418
+ // ecma262/#prod-ModuleItemList
419
+ // ModuleBody :
420
+ // ModuleItem*
421
+ const body = [];
422
+ while (this.peek().isNotType(Token.EOS)) {
423
+ const stat = this.parseModuleItem();
784
424
  if (!stat) {
785
425
  break;
786
426
  }
787
427
  if (this.isEmptyStatement(stat)) {
788
428
  continue;
789
429
  }
790
- list.push(stat);
791
- }
792
- return list;
793
- }
794
- parseFormalParameterList(functionInfo) {
795
- const parameters = [];
796
- if (this.peek().isNotType(Token.R_PARENTHESES)) {
797
- while (true) {
798
- const param = this.parseFormalParameter(functionInfo);
799
- parameters.push(param);
800
- if (functionInfo.rest) {
801
- if (this.peek().isType(Token.COMMA)) {
802
- throw new Error(this.errorMessage(`Param After Rest`));
803
- }
804
- break;
805
- }
806
- if (!this.check(Token.COMMA))
807
- break;
808
- if (this.peek().isType(Token.R_PARENTHESES)) {
809
- break;
810
- }
811
- }
812
- }
813
- return parameters;
814
- }
815
- parseFormalParameter(functionInfo) {
816
- functionInfo.rest = this.check(Token.ELLIPSIS);
817
- let pattern = this.parseBindingPattern(true);
818
- let initializer;
819
- if (this.check(Token.ASSIGN)) {
820
- if (functionInfo.rest) {
821
- throw new Error(this.errorMessage(`Rest Default Initializer`));
822
- }
823
- const value = this.parseAssignmentExpression();
824
- initializer = new Param(pattern, value);
825
- }
826
- else {
827
- initializer = new Param(pattern);
828
- }
829
- return initializer;
830
- }
831
- parseExpressionCoverGrammar(info) {
832
- let variableIndex = 0;
833
- const list = [];
834
- let expression;
835
- while (true) {
836
- if (this.peek().isType(Token.ELLIPSIS)) {
837
- if (info) {
838
- info.rest = true;
839
- }
840
- return this.parseArrowParametersWithRest(list, variableIndex);
841
- }
842
- expression = this.parseAssignmentExpressionCoverGrammar();
843
- list.push(expression);
844
- if (!this.check(Token.COMMA))
845
- break;
846
- if (this.peek().isType(Token.R_PARENTHESES) && this.peekAhead().isType(Token.ARROW)) {
847
- break;
848
- }
849
- }
850
- if (list.length == 1)
851
- return expression;
852
- return this.expressionListToExpression(list);
853
- }
854
- parseArrowParametersWithRest(list, variableIndex) {
855
- this.consume(Token.ELLIPSIS);
856
- const pattern = this.parseBindingPattern(true);
857
- if (this.peek().isType(Token.ASSIGN)) {
858
- throw new Error(this.errorMessage(`Error A rest parameter cannot have an initializer`));
859
- }
860
- if (this.peek().isType(Token.COMMA)) {
861
- throw new Error(this.errorMessage(`Error A rest parameter or binding pattern may not have a trailing comma`));
862
- }
863
- if (this.peek().isNotType(Token.R_PARENTHESES) || this.peekAhead().isNotType(Token.ARROW)) {
864
- throw new Error(this.errorMessage(`Error Unexpected Token At ${this.position()}`));
865
- }
866
- list.push(pattern);
867
- return this.expressionListToExpression(list);
868
- }
869
- expressionListToExpression(list) {
870
- if (list.length === 1) {
871
- return list[0];
872
- }
873
- return new SequenceExpression(list);
874
- }
875
- parseMemberExpression() {
876
- const result = this.parsePrimaryExpression();
877
- return this.parseMemberExpressionContinuation(result);
878
- }
879
- toParamNode(expression) {
880
- if (expression instanceof AssignmentExpression) {
881
- return new Param(expression.getLeft(), expression.getRight());
882
- }
883
- if (expression instanceof GroupingExpression) {
884
- return new Param(expression.getNode());
885
- }
886
- return new Param(expression);
887
- }
888
- parsePrimaryExpression() {
889
- let token = this.peek();
890
- if (Token.isAnyIdentifier(token.token)) {
891
- this.consume(token.token);
892
- let kind = ArrowFunctionType.NORMAL;
893
- if (token.isType(Token.ASYNC) && !this.scanner.hasLineTerminatorBeforeNext()) {
894
- if (this.peek().isType(Token.FUNCTION)) {
895
- return this.parseFunctionDeclarationAndGenerator();
896
- }
897
- ;
898
- if (Token.isAnyIdentifier(this.peek().token) && this.peekAhead().isType(Token.ARROW)) {
899
- token = this.next();
900
- kind = ArrowFunctionType.ASYNC;
901
- }
902
- }
903
- if (this.peek().isType(Token.ARROW)) {
904
- const name = this.parseAndClassifyIdentifier(token);
905
- const params = [];
906
- if (name instanceof SequenceExpression) {
907
- params.push(...name.getExpressions().map(this.toParamNode));
908
- }
909
- else {
910
- params.push(this.toParamNode(name));
911
- }
912
- return this.parseArrowFunctionLiteral(params, kind);
913
- }
914
- return this.parseAndClassifyIdentifier(token);
915
- }
916
- if (Token.isLiteral(token.token)) {
917
- return expressionFromLiteral(this.next());
918
- }
919
- switch (token.token) {
920
- case Token.NEW:
921
- return this.parseMemberWithPresentNewPrefixesExpression();
922
- case Token.THIS:
923
- this.consume(Token.THIS);
924
- return ThisNode;
925
- case Token.DIV:
926
- case Token.DIV_ASSIGN:
927
- return this.parseRegExpLiteral();
928
- case Token.FUNCTION:
929
- this.consume(Token.FUNCTION);
930
- if (this.peek().isType(Token.MUL)) {
931
- this.consume(Token.MUL);
932
- return this.parseFunctionExpression(FunctionKind.GENERATOR);
933
- }
934
- return this.parseFunctionExpression(FunctionKind.NORMAL);
935
- case Token.SUPER: {
936
- return this.parseSuperExpression();
937
- }
938
- case Token.IMPORT:
939
- return this.parseImportExpressions();
940
- case Token.L_BRACKETS:
941
- return this.parseArrayLiteral(false);
942
- case Token.L_CURLY:
943
- return this.parseObjectLiteral(false);
944
- case Token.L_PARENTHESES: {
945
- this.consume(Token.L_PARENTHESES);
946
- if (this.check(Token.R_PARENTHESES)) {
947
- if (!this.peek().isType(Token.ARROW)) {
948
- throw new Error(this.errorMessage(`Unexpected Token: ${Token.R_PARENTHESES.getName()}`));
949
- }
950
- return this.parseArrowFunctionLiteral([], ArrowFunctionType.NORMAL);
951
- }
952
- const peekToken = this.peek();
953
- let expression;
954
- const info = {};
955
- if (peekToken.isType(Token.FUNCTION)) {
956
- this.consume(Token.FUNCTION);
957
- expression = this.parseFunctionLiteral(FunctionKind.NORMAL);
958
- }
959
- else if (peekToken.isType(Token.ASYNC) && this.peekAhead().isType(Token.FUNCTION)) {
960
- this.consume(Token.ASYNC);
961
- this.consume(Token.FUNCTION);
962
- expression = this.parseFunctionLiteral(FunctionKind.ASYNC);
430
+ body.push(stat);
431
+ }
432
+ return body;
433
+ }
434
+ parseModuleItem() {
435
+ // ecma262/#prod-ModuleItem
436
+ // ModuleItem :
437
+ // ImportDeclaration
438
+ // ExportDeclaration
439
+ // StatementListItem
440
+ const next = this.peek();
441
+ if (next.isType(Token.EXPORT)) {
442
+ return this.parseExportDeclaration();
443
+ }
444
+ if (next.isType(Token.IMPORT)) {
445
+ // We must be careful not to parse a dynamic import expression as an import
446
+ // declaration. Same for import.meta expressions.
447
+ const peekAhead = this.peekAhead();
448
+ if (peekAhead.isNotType(Token.LPAREN) && peekAhead.isNotType(Token.PERIOD)) {
449
+ return this.parseImportDeclaration();
450
+ // return factory() -> EmptyStatement();
451
+ }
452
+ }
453
+ return this.parseStatementListItem();
454
+ }
455
+ parseExportDeclaration() {
456
+ // ExportDeclaration:
457
+ // 'export' '*' 'from' ModuleSpecifier ';'
458
+ // 'export' '*' 'from' ModuleSpecifier [no LineTerminator here]
459
+ // AssertClause ';'
460
+ // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';'
461
+ // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier
462
+ // [no LineTerminator here] AssertClause ';'
463
+ // 'export' '*' 'as' ModuleExportName 'from' ModuleSpecifier ';'
464
+ // 'export' '*' 'as' ModuleExportName 'from' ModuleSpecifier ';'
465
+ // [no LineTerminator here] AssertClause ';'
466
+ // 'export' ExportClause ('from' ModuleSpecifier)? ';'
467
+ // 'export' ExportClause ('from' ModuleSpecifier [no LineTerminator here]
468
+ // AssertClause)? ';'
469
+ // 'export' VariableStatement
470
+ // 'export' Declaration
471
+ // 'export' 'default' ... (handled in ParseExportDefault)
472
+ //
473
+ // ModuleExportName :
474
+ // StringLiteral
475
+ this.expect(Token.EXPORT);
476
+ let result;
477
+ const names = [];
478
+ // Statement * result = nullptr;
479
+ // ZonePtrList <const AstRawString> names(1, zone());
480
+ // Scanner::Location loc = scanner() -> peek_location();
481
+ switch (this.peek().token) {
482
+ case Token.DEFAULT:
483
+ return this.parseExportDefault();
484
+ case Token.MUL:
485
+ return this.parseExportStar();
486
+ case Token.LBRACE: {
487
+ // There are two cases here:
488
+ //
489
+ // 'export' ExportClause ';'
490
+ // and
491
+ // 'export' ExportClause FromClause ';'
492
+ //
493
+ // In the first case, the exported identifiers in ExportClause must
494
+ // not be reserved words, while in the latter they may be. We
495
+ // pass in a location that gets filled with the first reserved word
496
+ // encountered, and then throw a SyntaxError if we are in the
497
+ // non-FromClause case.
498
+ // Scanner::Location reserved_loc = Scanner:: Location:: invalid();
499
+ // Scanner::Location string_literal_local_name_loc =
500
+ // Scanner:: Location:: invalid();
501
+ // ZoneChunkList < ExportClauseData >* export_data =
502
+ // ParseExportClause(& reserved_loc, & string_literal_local_name_loc);
503
+ const exportData = this.parseExportClause();
504
+ let moduleSpecifier;
505
+ let importAssertions;
506
+ if (this.checkContextualKeyword('from')) {
507
+ // Scanner::Location specifier_loc = scanner() -> peek_location();
508
+ moduleSpecifier = this.parseModuleSpecifier();
509
+ importAssertions = this.parseImportAssertClause();
510
+ this.expectSemicolon();
511
+ // if (exportData.isEmpty()) {
512
+ // // module() -> AddEmptyImport(module_specifier, import_assertions, specifier_loc, zone());
513
+ // } else {
514
+ // // for (const ExportClauseData& data : * export_data) {
515
+ // // module() -> AddExport(data.local_name, data.export_name,
516
+ // // module_specifier, import_assertions,
517
+ // // data.location, specifier_loc, zone());
518
+ // // }
519
+ // }
963
520
  }
964
521
  else {
965
- expression = this.parseExpressionCoverGrammar(info);
966
- }
967
- this.expect(Token.R_PARENTHESES);
968
- if (this.peek().isType(Token.ARROW)) {
969
- if (expression instanceof SequenceExpression) {
970
- expression = this.parseArrowFunctionLiteral(expression.getExpressions(), ArrowFunctionType.NORMAL, info.rest);
971
- }
972
- else {
973
- expression = this.parseArrowFunctionLiteral([expression], ArrowFunctionType.NORMAL, info.rest);
974
- }
975
- }
976
- return expression;
522
+ // if (reserved_loc.IsValid()) {
523
+ // // No FromClause, so reserved words are invalid in ExportClause.
524
+ // ReportMessageAt(reserved_loc, MessageTemplate:: kUnexpectedReserved);
525
+ // return nullptr;
526
+ // } else if (string_literal_local_name_loc.IsValid()) {
527
+ // ReportMessageAt(string_literal_local_name_loc,
528
+ // MessageTemplate:: kModuleExportNameWithoutFromClause);
529
+ // return nullptr;
530
+ // }
531
+ this.expectSemicolon();
532
+ // for (const ExportClauseData& data : * export_data) {
533
+ // module() -> AddExport(data.local_name, data.export_name, data.location,
534
+ // zone());
535
+ // }
536
+ }
537
+ return new ExportNamedDeclaration(exportData, undefined, moduleSpecifier, importAssertions);
538
+ // return factory() -> EmptyStatement();
539
+ }
540
+ case Token.FUNCTION: {
541
+ const declaration = this.parseFunctionDeclaration();
542
+ const identifier = declaration.getId();
543
+ result = new ExportNamedDeclaration([new ExportSpecifier(identifier, identifier)], declaration);
544
+ break;
977
545
  }
978
546
  case Token.CLASS: {
979
547
  this.consume(Token.CLASS);
980
- let name;
981
- let isStrictReserved = false;
982
- if (this.peekAnyIdentifier()) {
983
- name = this.parseAndClassifyIdentifier(this.next());
984
- isStrictReserved = Token.isStrictReservedWord(this.current().token);
985
- }
986
- return this.parseClassLiteral(name, isStrictReserved);
987
- }
988
- case Token.TEMPLATE_LITERALS:
989
- return this.parseTemplateLiteral();
990
- default:
548
+ const declaration = this.parseClassDeclaration(names, false);
549
+ const identifier = declaration.getId();
550
+ result = new ExportNamedDeclaration([new ExportSpecifier(identifier, identifier)], declaration);
991
551
  break;
992
- }
993
- throw new Error(this.errorMessage(`Unexpected Token: ${JSON.stringify(this.next())}`));
994
- }
995
- parseTemplateLiteral(tag) {
996
- const template = this.next().getValue();
997
- const exprs = template.expressions.map(expr => JavaScriptParser.parse(expr));
998
- if (tag) {
999
- return new TaggedTemplateExpression(tag, template.strings, exprs);
1000
- }
1001
- else {
1002
- return new TemplateLiteral(template.strings, exprs);
1003
- }
1004
- }
1005
- parseMemberWithPresentNewPrefixesExpression() {
1006
- this.consume(Token.NEW);
1007
- let classRef;
1008
- if (this.peek().isType(Token.IMPORT) && this.peekAhead().isType(Token.L_PARENTHESES)) {
1009
- throw new Error(this.errorMessage(`parsing new import (`));
1010
- }
1011
- else if (this.peek().isType(Token.SUPER)) {
1012
- throw new Error(this.errorMessage(`parsing new super() is never allowed`));
1013
- }
1014
- else if (this.peek().isType(Token.PERIOD)) {
1015
- classRef = this.parseNewTargetExpression();
1016
- return this.parseMemberExpressionContinuation(classRef);
1017
- }
1018
- else {
1019
- classRef = this.parseMemberExpression();
1020
- }
1021
- if (this.peek().isType(Token.L_PARENTHESES)) {
1022
- const args = this.parseArguments();
1023
- classRef = new NewExpression(classRef, args);
1024
- return this.parseMemberExpressionContinuation(classRef);
1025
- }
1026
- if (this.peek().isType(Token.QUESTION_PERIOD)) {
1027
- throw new Error(this.errorMessage(`parsing new xxx?.yyy at position`));
1028
- }
1029
- return new NewExpression(classRef);
1030
- }
1031
- parseArguments(maybeArrow) {
1032
- this.consume(Token.L_PARENTHESES);
1033
- const args = [];
1034
- while (this.peek().isNotType(Token.R_PARENTHESES)) {
1035
- const isSpread = this.check(Token.ELLIPSIS);
1036
- let argument = this.parseAssignmentExpressionCoverGrammar();
1037
- if (ParsingArrowHeadFlag.MaybeArrowHead === maybeArrow) {
1038
- if (isSpread) {
1039
- if (argument instanceof AssignmentExpression) {
1040
- throw new Error(this.errorMessage(` Rest parameter may not have a default initializer'`));
1041
- }
1042
- if (this.peek().isType(Token.COMMA)) {
1043
- throw new Error(this.errorMessage(`parsing '...spread,arg =>'`));
1044
- }
1045
- }
1046
- }
1047
- if (isSpread) {
1048
- argument = new SpreadElement(argument);
1049
552
  }
1050
- args.push(argument);
1051
- if (!this.check(Token.COMMA))
1052
- break;
1053
- }
1054
- if (!this.check(Token.R_PARENTHESES)) {
1055
- throw new Error(this.errorMessage(`parsing arguments call, expecting ')'`));
1056
- }
1057
- return args;
1058
- }
1059
- parseAssignmentExpressionCoverGrammar() {
1060
- if (this.peek().isType(Token.YIELD)) {
1061
- return this.parseYieldExpression();
1062
- }
1063
- let expression = this.parseConditionalExpression();
1064
- const op = this.peek().token;
1065
- if (!Token.isArrowOrAssignmentOp(op))
1066
- return expression;
1067
- if (op === Token.ARROW) {
1068
- if (!this.isIdentifier(expression) && !this.isParenthesized(expression)) {
1069
- throw new Error(this.errorMessage(`Malformed Arrow Fun Param List`));
1070
- }
1071
- if (expression instanceof SequenceExpression) {
1072
- const params = expression.getExpressions().map(expr => new Param(expr));
1073
- return this.parseArrowFunctionLiteral(params, ArrowFunctionType.NORMAL);
1074
- }
1075
- if (expression instanceof GroupingExpression) {
1076
- return this.parseArrowFunctionLiteral([new Param(expression.getNode())], ArrowFunctionType.NORMAL);
1077
- }
1078
- return this.parseArrowFunctionLiteral([new Param(expression)], ArrowFunctionType.NORMAL);
1079
- }
1080
- if (this.isAssignableIdentifier(expression)) {
1081
- if (this.isParenthesized(expression)) {
1082
- throw new Error(this.errorMessage(`Invalid Destructuring Target`));
1083
- }
1084
- }
1085
- else if (this.isProperty(expression)) {
1086
- }
1087
- else if (this.isPattern(expression) && Token.isAssignment(op)) {
1088
- if (this.isParenthesized(expression)) {
1089
- }
1090
- }
1091
- else {
1092
- if (!this.isValidReferenceExpression(expression)) {
1093
- throw new Error(this.errorMessage(`Invalid Reference Expression`));
1094
- }
1095
- if (Token.isLogicalAssignmentOp(op)) {
1096
- throw new Error(this.errorMessage(`Invalid Lhs In Assignment`));
1097
- }
1098
- }
1099
- this.consume(op);
1100
- const right = this.parseAssignmentExpression();
1101
- if (!Token.isAssignment(op)) {
1102
- throw new Error(this.errorMessage(`Invalid Destructuring Target`));
1103
- }
1104
- return new AssignmentExpression(op.getName(), expression, right);
1105
- }
1106
- parseAssignmentExpression() {
1107
- return this.parseAssignmentExpressionCoverGrammar();
1108
- }
1109
- parseArrowFunctionLiteral(parameters, flag, rest) {
1110
- this.consume(Token.ARROW);
1111
- const body = this.parseArrowFunctionBody();
1112
- return new ArrowFunctionExpression(parameters, body, flag, rest);
1113
- }
1114
- parseRegExpLiteral() {
1115
- if (!this.scanner.scanRegExpPattern()) {
1116
- throw new Error('Unterminated RegExp');
1117
- }
1118
- return this.scanner.currentToken().getValue();
1119
- }
1120
- parseArrayLiteral(isPattern) {
1121
- this.consume(Token.L_BRACKETS);
1122
- const values = [];
1123
- let firstSpreadIndex = -1;
1124
- while (!this.check(Token.R_BRACKETS)) {
1125
- let elem;
1126
- if (this.peek().isType(Token.COMMA)) {
1127
- this.consume(Token.COMMA);
1128
- continue;
1129
- }
1130
- else if (this.check(Token.ELLIPSIS)) {
1131
- const argument = this.parsePossibleDestructuringSubPattern();
1132
- elem = isPattern
1133
- ? new RestElement(argument)
1134
- : new SpreadElement(argument);
1135
- if (firstSpreadIndex < 0) {
1136
- firstSpreadIndex = values.length;
1137
- }
1138
- if (this.peek().isType(Token.COMMA)) {
1139
- throw new Error(this.errorMessage(`Element After Rest @${this.position()}`));
1140
- }
1141
- }
1142
- else {
1143
- elem = this.parsePossibleDestructuringSubPattern();
1144
- }
1145
- values.push(elem);
1146
- }
1147
- if (isPattern) {
1148
- return new ArrayPattern(values);
1149
- }
1150
- return new ArrayExpression(values);
1151
- }
1152
- parsePossibleDestructuringSubPattern() {
1153
- return this.parseAssignmentExpressionCoverGrammar();
1154
- }
1155
- parseObjectLiteral(isPattern) {
1156
- this.consume(Token.L_CURLY);
1157
- const properties = [];
1158
- while (!this.check(Token.R_CURLY)) {
1159
- const property = this.parseObjectPropertyDefinition(isPattern);
1160
- properties.push(property);
1161
- if (this.peek().isNotType(Token.R_CURLY)) {
1162
- this.expect(Token.COMMA);
1163
- }
1164
- }
1165
- if (isPattern) {
1166
- return new ObjectPattern(properties);
1167
- }
1168
- return new ObjectExpression(properties);
1169
- }
1170
- parseObjectPropertyDefinition(isPattern) {
1171
- const propInfo = { kind: PropertyKind.NotSet };
1172
- const nameExpression = this.parseProperty(propInfo);
1173
- switch (propInfo.kind) {
1174
- case PropertyKind.Spread:
1175
- let value = nameExpression;
1176
- if (isPattern) {
1177
- value = new RestElement(value.getArgument());
1178
- }
1179
- return new Property(value.getArgument(), value, 'init');
1180
- case PropertyKind.Value: {
1181
- this.consume(Token.COLON);
1182
- const value = this.parsePossibleDestructuringSubPattern();
1183
- return new Property(nameExpression, value, 'init');
1184
- }
1185
- case PropertyKind.Assign:
1186
- case PropertyKind.ShorthandOrClassField:
1187
- case PropertyKind.Shorthand: {
1188
- const lhs = new Identifier(propInfo.name);
1189
- if (!this.isAssignableIdentifier(lhs)) {
1190
- throw new Error(this.errorMessage('Strict Eval Arguments'));
1191
- }
1192
- let value;
1193
- if (this.peek().isType(Token.ASSIGN)) {
1194
- this.consume(Token.ASSIGN);
1195
- const rhs = this.parseAssignmentExpression();
1196
- value = new AssignmentExpression(Token.ASSIGN.getName(), lhs, rhs);
1197
- }
1198
- else {
1199
- value = lhs;
1200
- }
1201
- return new Property(nameExpression, value, 'init');
1202
- }
1203
- case PropertyKind.Method: {
1204
- const value = this.parseFunctionLiteral(propInfo.funcFlag);
1205
- return new Property(nameExpression, value, 'init');
1206
- }
1207
- case PropertyKind.AccessorGetter:
1208
- case PropertyKind.AccessorSetter: {
1209
- const isGet = propInfo.kind == PropertyKind.AccessorGetter;
1210
- const value = this.parseFunctionLiteral(propInfo.funcFlag);
1211
- return new Property(nameExpression, value, isGet ? 'get' : 'set');
1212
- }
1213
- case PropertyKind.ClassField:
1214
- case PropertyKind.NotSet:
1215
- return NullNode;
1216
- }
1217
- }
1218
- parseProperty(propInfo) {
1219
- let nextToken = this.peek();
1220
- if (this.check(Token.ASYNC)) {
1221
- nextToken = this.peek();
1222
- if (nextToken.isNotType(Token.MUL)
1223
- && parsePropertyKindFromToken(nextToken.token, propInfo)
1224
- || this.scanner.hasLineTerminatorBeforeNext()) {
1225
- return AsyncIdentifier;
1226
- }
1227
- propInfo.kind = PropertyKind.Method;
1228
- propInfo.funcFlag = FunctionKind.ASYNC;
1229
- }
1230
- if (this.check(Token.MUL)) {
1231
- propInfo.kind = PropertyKind.Method;
1232
- propInfo.funcFlag = FunctionKind.ASYNC_GENERATOR;
1233
- }
1234
- nextToken = this.peek();
1235
- if (propInfo.kind == PropertyKind.NotSet && nextToken.isType(Token.GET) || nextToken.isType(Token.SET)) {
1236
- const token = this.next();
1237
- if (parsePropertyKindFromToken(this.peek().token, propInfo)) {
1238
- return nextToken.isType(Token.GET) ? GetIdentifier : SetIdentifier;
1239
- }
1240
- if (token.isType(Token.GET)) {
1241
- propInfo.kind = PropertyKind.AccessorGetter;
1242
- }
1243
- else if (token.isType(Token.SET)) {
1244
- propInfo.kind = PropertyKind.AccessorSetter;
1245
- }
1246
- }
1247
- let propertyName;
1248
- switch (nextToken.token) {
1249
- case Token.PRIVATE_NAME:
1250
- this.consume(Token.PRIVATE_NAME);
1251
- if (propInfo.kind == PropertyKind.NotSet) {
1252
- parsePropertyKindFromToken(this.peek().token, propInfo);
1253
- }
1254
- propertyName = this.getIdentifier();
1255
- break;
1256
- case Token.STRING:
1257
- case Token.NUMBER:
1258
- case Token.BIGINT:
1259
- this.consume(nextToken.token);
1260
- propertyName = nextToken.getValue();
1261
- propInfo.name = propertyName.getValue();
553
+ case Token.VAR:
554
+ case Token.LET:
555
+ case Token.CONST:
556
+ const declaration = this.parseVariableStatement(VariableDeclarationContext.StatementListItem, names);
557
+ const specifiers = declaration.getDeclarations()
558
+ .map(node => new ExportSpecifier(node.getId(), node.getId()));
559
+ result = new ExportNamedDeclaration(specifiers, declaration);
1262
560
  break;
1263
- case Token.L_BRACKETS:
1264
- this.consume(Token.L_BRACKETS);
1265
- propertyName = this.parseAssignmentExpression();
1266
- this.expect(Token.R_BRACKETS);
1267
- if (propInfo.kind === PropertyKind.NotSet) {
1268
- parsePropertyKindFromToken(this.peek().token, propInfo);
1269
- }
1270
- propInfo.name = propertyName.toString();
1271
- return propertyName;
1272
- case Token.ELLIPSIS:
1273
- if (propInfo.kind == PropertyKind.NotSet) {
1274
- this.consume(Token.ELLIPSIS);
1275
- propertyName = this.parsePossibleDestructuringSubPattern();
1276
- propInfo.kind = PropertyKind.Spread;
1277
- if (!this.isValidReferenceExpression(propertyName)) {
1278
- throw new Error(this.errorMessage('Invalid Rest Binding/Assignment Pattern'));
1279
- }
1280
- if (this.peek().isNotType(Token.R_CURLY)) {
1281
- throw new Error(this.errorMessage('Element After Rest'));
1282
- }
1283
- propInfo.name = propertyName.toString();
1284
- return propertyName;
561
+ case Token.ASYNC:
562
+ this.consume(Token.ASYNC);
563
+ if (this.peek().isType(Token.FUNCTION) && !this.scanner.hasLineTerminatorBeforeNext()) {
564
+ const declaration = this.parseAsyncFunctionDeclaration(names, false);
565
+ const identifier = declaration.getId();
566
+ result = new ExportNamedDeclaration([new ExportSpecifier(identifier, identifier)], declaration);
567
+ break;
1285
568
  }
1286
569
  default:
1287
- propertyName = new StringLiteral(this.parsePropertyName().toString());
1288
- propInfo.name = propertyName.toString();
1289
- break;
1290
- }
1291
- if (propInfo.kind === PropertyKind.NotSet) {
1292
- parsePropertyKindFromToken(this.peek().token, propInfo);
570
+ throw new SyntaxError(this.errorMessage('Unexpected Token'));
1293
571
  }
1294
- return propertyName;
1295
- }
1296
- parseMemberExpressionContinuation(expression) {
1297
- if (!Token.isMember(this.peek().token))
1298
- return expression;
1299
- return this.doParseMemberExpressionContinuation(expression);
572
+ // loc.end_pos = scanner() -> location().end_pos;
573
+ // SourceTextModuleDescriptor * descriptor = module();
574
+ // for (const AstRawString* name : names) {
575
+ // descriptor -> AddExport(name, name, loc, zone());
576
+ // }
577
+ return result;
1300
578
  }
1301
- doParseMemberExpressionContinuation(expression) {
1302
- if (!Token.isMember(this.peek().token)) {
1303
- throw new Error(this.errorMessage(`Parsing member expression`));
1304
- }
1305
- do {
579
+ parseImportDeclaration() {
580
+ // ImportDeclaration :
581
+ // 'import' ImportClause 'from' ModuleSpecifier ';'
582
+ // 'import' ModuleSpecifier ';'
583
+ // 'import' ImportClause 'from' ModuleSpecifier [no LineTerminator here]
584
+ // AssertClause ';'
585
+ // 'import' ModuleSpecifier [no LineTerminator here] AssertClause';'
586
+ //
587
+ // ImportClause :
588
+ // ImportedDefaultBinding
589
+ // NameSpaceImport
590
+ // NamedImports
591
+ // ImportedDefaultBinding ',' NameSpaceImport
592
+ // ImportedDefaultBinding ',' NamedImports
593
+ //
594
+ // NameSpaceImport :
595
+ // '*' 'as' ImportedBinding
596
+ this.expect(Token.IMPORT);
597
+ const tok = this.peek();
598
+ // 'import' ModuleSpecifier ';'
599
+ if (tok.isType(Token.STRING)) {
600
+ // Scanner::Location specifier_loc = scanner() -> peek_location();
601
+ const moduleSpecifier = this.parseModuleSpecifier();
602
+ const importAssertions = this.parseImportAssertClause();
603
+ this.expectSemicolon();
604
+ // module() -> AddEmptyImport(module_specifier, import_assertions, specifier_loc,zone());
605
+ return new ImportDeclaration(moduleSpecifier, undefined, importAssertions);
606
+ }
607
+ // Parse ImportedDefaultBinding if present.
608
+ let importDefaultBinding;
609
+ // Scanner::Location import_default_binding_loc;
610
+ if (tok.isNotType(Token.MUL) && tok.isNotType(Token.LBRACE)) {
611
+ importDefaultBinding = this.parseNonRestrictedIdentifier();
612
+ // DeclareUnboundVariable(import_default_binding, VariableMode:: kConst,kNeedsInitialization, pos);
613
+ }
614
+ // Parse NameSpaceImport or NamedImports if present.
615
+ let moduleNamespaceBinding;
616
+ let namedImports;
617
+ // Scanner::Location module_namespace_binding_loc;
618
+ // const ZonePtrList<const NamedImport >* named_imports = nullptr;
619
+ if (importDefaultBinding == undefined || this.check(Token.COMMA)) {
1306
620
  switch (this.peek().token) {
1307
- case Token.L_BRACKETS: {
1308
- this.consume(Token.L_BRACKETS);
1309
- const index = this.parseExpressionCoverGrammar();
1310
- expression = new MemberExpression(expression, index, true);
1311
- this.expect(Token.R_BRACKETS);
1312
- break;
1313
- }
1314
- case Token.PERIOD: {
1315
- this.consume(Token.PERIOD);
1316
- const key = this.parsePropertyName();
1317
- expression = new MemberExpression(expression, key, false);
621
+ case Token.MUL: {
622
+ this.consume(Token.MUL);
623
+ this.expectContextualKeyword('as');
624
+ moduleNamespaceBinding = this.parseNonRestrictedIdentifier();
625
+ // ExpectContextualKeyword(ast_value_factory() -> as_string());
626
+ // module_namespace_binding = ParseNonRestrictedIdentifier();
627
+ // module_namespace_binding_loc = scanner() -> location();
628
+ // DeclareUnboundVariable(module_namespace_binding, VariableMode:: kConst, kCreatedInitialized, pos);
1318
629
  break;
1319
630
  }
1320
- case Token.TEMPLATE_LITERALS: {
1321
- expression = this.parseTemplateLiteral(expression);
631
+ case Token.LBRACE:
632
+ namedImports = this.parseNamedImports();
1322
633
  break;
1323
- }
1324
634
  default:
1325
- break;
635
+ throw new SyntaxError(this.errorMessage('Unexpected Token'));
1326
636
  }
1327
- } while (Token.isMember(this.peek().token));
1328
- return expression;
1329
- }
1330
- parsePropertyName() {
1331
- const next = this.next();
1332
- if (next.getValue() instanceof Identifier) {
1333
- return next.getValue();
1334
- }
1335
- if (Token.isPropertyName(next.token)) {
1336
- return new Identifier(next.token.getName());
1337
- }
1338
- throw new Error(this.errorMessage(`Parsing property expression: Unexpected Token`));
1339
- }
1340
- parsePipelineExpression(expression) {
1341
- let token;
1342
- while (Token.isPipelineOperator(token = this.peek().token)) {
1343
- this.consume(token);
1344
- expression = this.parsePipelineBody(expression);
1345
- }
1346
- return expression;
1347
- }
1348
- parsePipelineBody(lhs) {
1349
- let body;
1350
- let token = this.peek();
1351
- switch (token.token) {
1352
- case Token.FUNCTION:
1353
- this.consume(Token.FUNCTION);
1354
- if (this.peek().isType(Token.MUL)) {
1355
- this.consume(Token.MUL);
1356
- body = this.parseFunctionExpression(FunctionKind.GENERATOR);
1357
- break;
1358
- }
1359
- body = this.parseFunctionExpression(FunctionKind.NORMAL);
1360
- break;
1361
- case Token.ASYNC:
1362
- if (this.peekAhead().isType(Token.FUNCTION)) {
1363
- this.consume(Token.ASYNC);
1364
- this.consume(Token.FUNCTION);
1365
- if (this.peek().isType(Token.MUL)) {
1366
- this.consume(Token.MUL);
1367
- body = this.parseFunctionExpression(FunctionKind.ASYNC_GENERATOR);
1368
- break;
1369
- }
1370
- body = this.parseFunctionExpression(FunctionKind.ASYNC);
1371
- break;
1372
- }
1373
- break;
1374
- default:
1375
- break;
1376
- }
1377
- if (body) {
1378
- return new PipelineExpression(lhs, body);
1379
- }
1380
- if (token.isType(Token.L_PARENTHESES)) {
1381
- body = this.parsePrimaryExpression();
1382
- return new PipelineExpression(lhs, body);
1383
637
  }
1384
- const func = this.parseMemberExpression();
1385
- let args = [];
1386
- switch (this.peek().token) {
1387
- case Token.COLON:
1388
- do {
1389
- this.consume(Token.COLON);
1390
- const isSpread = this.check(Token.ELLIPSIS);
1391
- if (this.peek().isType(Token.CONDITIONAL)) {
1392
- this.consume(Token.CONDITIONAL);
1393
- if (isSpread) {
1394
- args.push('...?');
1395
- }
1396
- else {
1397
- args.push('?');
1398
- }
1399
- }
1400
- else {
1401
- const arg = this.parseAssignmentExpressionCoverGrammar();
1402
- if (isSpread) {
1403
- args.push(new SpreadElement(arg));
1404
- }
1405
- else {
1406
- args.push(arg);
1407
- }
1408
- }
1409
- } while (this.peek().isType(Token.COLON));
1410
- break;
1411
- case Token.L_PARENTHESES:
1412
- this.consume(Token.L_PARENTHESES);
1413
- let indexed = false;
1414
- while (this.peek().isNotType(Token.R_PARENTHESES)) {
1415
- const isSpread = this.check(Token.ELLIPSIS);
1416
- if (this.peek().isType(Token.CONDITIONAL)) {
1417
- this.consume(Token.CONDITIONAL);
1418
- indexed = true;
1419
- if (isSpread) {
1420
- args.push('...?');
1421
- }
1422
- else {
1423
- args.push('?');
1424
- }
1425
- }
1426
- else {
1427
- const arg = this.parseAssignmentExpressionCoverGrammar();
1428
- if (isSpread) {
1429
- args.push(new SpreadElement(arg));
1430
- }
1431
- else {
1432
- args.push(arg);
1433
- }
1434
- }
1435
- this.check(Token.COMMA);
1436
- }
1437
- this.expect(Token.R_PARENTHESES);
1438
- if (!indexed) {
1439
- body = new CallExpression(func, args);
1440
- return new PipelineExpression(lhs, body);
1441
- }
1442
- break;
1443
- default:
1444
- break;
638
+ this.expectContextualKeyword('from');
639
+ // ExpectContextualKeyword(ast_value_factory() -> from_string());
640
+ // Scanner::Location specifier_loc = scanner() -> peek_location();
641
+ const moduleSpecifier = this.parseModuleSpecifier();
642
+ const importAssertions = this.parseImportAssertClause();
643
+ this.expectSemicolon();
644
+ // Now that we have all the information, we can make the appropriate
645
+ // declarations.
646
+ // TODO(neis): Would prefer to call DeclareVariable for each case below rather
647
+ // than above and in ParseNamedImports, but then a possible error message
648
+ // would point to the wrong location. Maybe have a DeclareAt version of
649
+ // Declare that takes a location?
650
+ const specifiers = [];
651
+ if (moduleNamespaceBinding) {
652
+ specifiers.push(new ImportNamespaceSpecifier(moduleNamespaceBinding));
1445
653
  }
1446
- return new PipelineExpression(lhs, func, args);
1447
- }
1448
- parseConditionalExpression() {
1449
- let expression = this.parseLogicalExpression();
1450
- expression = this.parsePipelineExpression(expression);
1451
- return this.peek().isType(Token.CONDITIONAL) ? this.parseConditionalContinuation(expression) : expression;
1452
- }
1453
- parseLogicalExpression() {
1454
- let expression = this.parseBinaryExpression(6);
1455
- const peek = this.peek();
1456
- if (peek.isType(Token.AND) || peek.isType(Token.OR)) {
1457
- const precedence = peek.token.getPrecedence();
1458
- expression = this.parseBinaryContinuation(expression, 4, precedence);
654
+ if (importDefaultBinding) {
655
+ specifiers.push(new ImportDefaultSpecifier(importDefaultBinding));
1459
656
  }
1460
- else if (peek.isType(Token.NULLISH)) {
1461
- expression = this.parseNullishExpression(expression);
657
+ if (namedImports?.length) {
658
+ specifiers.push(...namedImports);
1462
659
  }
1463
- return expression;
1464
- }
1465
- parseBinaryContinuation(x, prec, prec1) {
1466
- do {
1467
- while (this.peek().token.getPrecedence() === prec1) {
1468
- let y;
1469
- let op = this.next();
1470
- const is_right_associative = op.isType(Token.EXP);
1471
- const next_prec = is_right_associative ? prec1 : prec1 + 1;
1472
- y = this.parseBinaryExpression(next_prec);
1473
- if (Token.isCompare(op.token)) {
1474
- let cmp = op.token;
1475
- switch (op.token) {
1476
- case Token.NE:
1477
- cmp = Token.EQ;
1478
- break;
1479
- case Token.NE_STRICT:
1480
- cmp = Token.EQ_STRICT;
1481
- break;
1482
- default: break;
1483
- }
1484
- x = shortcutNumericLiteralBinaryExpression(x, y, cmp);
1485
- if (op.isNotType(cmp)) {
1486
- x = buildUnaryExpression(x, Token.NOT);
1487
- }
1488
- }
1489
- else {
1490
- x = shortcutNumericLiteralBinaryExpression(x, y, op.token);
1491
- }
1492
- }
1493
- --prec1;
1494
- } while (prec1 >= prec);
1495
- return x;
660
+ return new ImportDeclaration(moduleSpecifier, specifiers.length ? specifiers : undefined, importAssertions);
1496
661
  }
1497
- parseBinaryExpression(precedence) {
1498
- const x = this.parseUnaryExpression();
1499
- const precedence1 = this.peek().token.getPrecedence();
1500
- if (precedence1 >= precedence) {
1501
- return this.parseBinaryContinuation(x, precedence, precedence1);
662
+ parseImportExpressions() {
663
+ this.consume(Token.IMPORT);
664
+ if (this.check(Token.PERIOD)) {
665
+ this.expectContextualKeyword('meta');
666
+ return MetaProperty.ImportMeta;
1502
667
  }
1503
- return x;
1504
- }
1505
- parseUnaryExpression() {
1506
- const op = this.peek();
1507
- if (Token.isUnaryOrCount(op.token)) {
1508
- return this.parseUnaryOrPrefixExpression();
668
+ if (this.peek().isNotType(Token.LPAREN)) {
669
+ throw new SyntaxError(this.errorMessage('Unexpected Token'));
1509
670
  }
1510
- if (op.isType(Token.AWAIT)) {
1511
- return this.parseAwaitExpression();
671
+ this.consume(Token.LPAREN);
672
+ if (this.peek().isType(Token.RPAREN)) {
673
+ throw new SyntaxError(this.errorMessage('Import Missing Specifier'));
1512
674
  }
1513
- return this.parsePostfixExpression();
1514
- }
1515
- parseUnaryOrPrefixExpression() {
1516
- const op = this.next();
1517
- const expression = this.parseUnaryExpression();
1518
- if (Token.isUnary(op.token)) {
1519
- if (op.isType(Token.DELETE)) {
1520
- if (this.isIdentifier(expression)) {
1521
- throw new Error(this.errorMessage(`"delete identifier" is a syntax error in strict mode`));
1522
- }
1523
- if (expression instanceof MemberExpression && expression.getProperty().toString().startsWith('#')) {
1524
- throw new Error(this.errorMessage(`"Delete Private Field" is a syntax error`));
1525
- }
675
+ this.setAcceptIN(true);
676
+ const specifier = this.parseAssignmentExpressionCoverGrammar();
677
+ if (this.check(Token.COMMA)) {
678
+ if (this.check(Token.RPAREN)) {
679
+ // A trailing comma allowed after the specifier.
680
+ return new ImportExpression(specifier);
1526
681
  }
1527
- if (this.peek().isType(Token.EXP)) {
1528
- throw new Error(this.errorMessage(`Unexpected Token Unary Exponentiation`));
682
+ else {
683
+ const importAssertions = this.parseAssignmentExpressionCoverGrammar();
684
+ this.check(Token.COMMA); // A trailing comma is allowed after the import
685
+ // assertions.
686
+ this.expect(Token.RPAREN);
687
+ return new ImportExpression(specifier, importAssertions);
688
+ }
689
+ }
690
+ this.expect(Token.RPAREN);
691
+ this.restoreAcceptIN();
692
+ return new ImportExpression(specifier);
693
+ }
694
+ parseVariableStatement(varContext, names) {
695
+ // VariableStatement ::
696
+ // VariableDeclarations ';'
697
+ // The scope of a var declared variable anywhere inside a function
698
+ // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
699
+ // transform a source-level var declaration into a (Function) Scope
700
+ // declaration, and rewrite the source-level initialization into an assignment
701
+ // statement. We use a block to collect multiple assignments.
702
+ //
703
+ // We mark the block as initializer block because we don't want the
704
+ // rewriter to add a '.result' assignment to such a block (to get compliant
705
+ // behavior for code such as print(eval('var x = 7')), and for cosmetic
706
+ // reasons when pretty-printing. Also, unless an assignment (initialization)
707
+ // is inside an initializer block, it is ignored.
708
+ const declarations = this.parseVariableDeclarations(varContext);
709
+ this.expectSemicolon();
710
+ names.push(...declarations.getDeclarations().map(d => d.getId().toString()));
711
+ return declarations;
712
+ }
713
+ parseImportAssertClause() {
714
+ // AssertClause :
715
+ // assert '{' '}'
716
+ // assert '{' AssertEntries '}'
717
+ // AssertEntries :
718
+ // IdentifierName: AssertionKey
719
+ // IdentifierName: AssertionKey , AssertEntries
720
+ // AssertionKey :
721
+ // IdentifierName
722
+ // StringLiteral
723
+ // auto import_assertions = zone() -> New<ImportAssertions>(zone());
724
+ // if (!FLAG_harmony_import_assertions) {
725
+ // return import_assertions;
726
+ // }
727
+ // Assert clause is optional, and cannot be preceded by a LineTerminator.
728
+ if (this.scanner.hasLineTerminatorBeforeNext() || !this.checkContextualKeyword('assert')) {
729
+ return undefined;
730
+ }
731
+ this.expect(Token.LBRACE);
732
+ const counts = {};
733
+ const importAssertions = [];
734
+ while (this.peek().isNotType(Token.RBRACE)) {
735
+ let attributeKey = this.checkAndGetValue(Token.STRING);
736
+ if (!attributeKey) {
737
+ attributeKey = this.parsePropertyOrPrivatePropertyName();
1529
738
  }
1530
- }
1531
- if (Token.isCount(op.token) || Token.isUnary(op.token)) {
1532
- return buildUnaryExpression(expression, op.token);
1533
- }
1534
- throw new Error(this.errorMessage(`while rewrite unary operation`));
1535
- }
1536
- parsePostfixExpression() {
1537
- const expression = this.parseLeftHandSideExpression();
1538
- if (!Token.isCount(this.peek().token) || this.scanner.hasLineTerminatorBeforeNext()) {
1539
- return expression;
1540
- }
1541
- return this.parsePostfixContinuation(expression);
1542
- }
1543
- parsePostfixContinuation(expression) {
1544
- if (!this.isValidReferenceExpression(expression)) {
1545
- throw new Error(this.errorMessage(`Invalid LHS In Postfix Op.`));
1546
- }
1547
- const op = this.next();
1548
- return buildPostfixExpression(expression, op.token);
1549
- }
1550
- parseLeftHandSideExpression() {
1551
- const result = this.parseMemberExpression();
1552
- if (!Token.isPropertyOrCall(this.peek().token))
1553
- return result;
1554
- return this.parseLeftHandSideContinuation(result);
1555
- }
1556
- parseLeftHandSideContinuation(result) {
1557
- if (this.peek().isType(Token.L_PARENTHESES)
1558
- && this.isIdentifier(result)
1559
- && this.scanner.currentToken().isType(Token.ASYNC)
1560
- && !this.scanner.hasLineTerminatorBeforeNext()) {
1561
- const args = this.parseArguments(ParsingArrowHeadFlag.AsyncArrowFunction);
1562
- if (this.peek().isType(Token.ARROW)) {
1563
- if (!args.length)
1564
- return new EmptyStatement;
1565
- return this.expressionListToExpression(args);
739
+ this.expect(Token.COLON);
740
+ const attributeValue = this.expectAndGetValue(Token.STRING);
741
+ importAssertions.push(new ImportAttribute(attributeKey, attributeValue));
742
+ counts[attributeKey.toString()] = (counts[attributeKey.toString()] ?? 0) + 1;
743
+ if (counts[attributeKey.toString()] > 1) {
744
+ // // It is a syntax error if two AssertEntries have the same key.
745
+ throw new SyntaxError(this.errorMessage('Import Assertion Duplicate Key'));
746
+ }
747
+ if (this.peek().isType(Token.RBRACE))
748
+ break;
749
+ if (!this.check(Token.COMMA)) {
750
+ throw new SyntaxError('Unexpected Token');
751
+ }
752
+ }
753
+ this.expect(Token.RBRACE);
754
+ return importAssertions;
755
+ }
756
+ parseModuleSpecifier() {
757
+ // ModuleSpecifier :
758
+ // StringLiteral
759
+ return this.expectAndGetValue(Token.STRING);
760
+ }
761
+ parseExportClause() {
762
+ // ExportClause :
763
+ // '{' '}'
764
+ // '{' ExportsList '}'
765
+ // '{' ExportsList ',' '}'
766
+ //
767
+ // ExportsList :
768
+ // ExportSpecifier
769
+ // ExportsList ',' ExportSpecifier
770
+ //
771
+ // ExportSpecifier :
772
+ // IdentifierName
773
+ // IdentifierName 'as' IdentifierName
774
+ // IdentifierName 'as' ModuleExportName
775
+ // ModuleExportName
776
+ // ModuleExportName 'as' ModuleExportName
777
+ //
778
+ // ModuleExportName :
779
+ // StringLiteral
780
+ // ZoneChunkList < ExportClauseData >* export_data = zone() -> New<ZoneChunkList<ExportClauseData>>(zone());
781
+ this.expect(Token.LBRACE);
782
+ const exportData = [];
783
+ let nameTok = this.peek();
784
+ while (nameTok.isNotType(Token.RBRACE)) {
785
+ const localName = this.parseExportSpecifierName();
786
+ let exportName;
787
+ if (this.checkContextualKeyword('as')) {
788
+ exportName = this.parseExportSpecifierName();
1566
789
  }
1567
- result = new CallExpression(result, args);
1568
- if (!Token.isPropertyOrCall(this.peek().token))
1569
- return result;
1570
- }
1571
- let optionalChaining = false;
1572
- let isOptional = false;
1573
- do {
1574
- switch (this.peek().token) {
1575
- case Token.QUESTION_PERIOD: {
1576
- if (isOptional) {
1577
- throw new Error(this.errorMessage(`Failure Expression`));
1578
- }
1579
- this.consume(Token.QUESTION_PERIOD);
1580
- isOptional = true;
1581
- optionalChaining = true;
1582
- if (Token.isPropertyOrCall(this.peek().token))
1583
- continue;
1584
- const key = this.parsePropertyName();
1585
- result = new MemberExpression(result, key, false, isOptional);
1586
- break;
1587
- }
1588
- case Token.L_BRACKETS: {
1589
- this.consume(Token.L_BRACKETS);
1590
- const index = this.parseExpressionCoverGrammar();
1591
- result = new MemberExpression(result, index, true, isOptional);
1592
- this.expect(Token.R_BRACKETS);
1593
- break;
1594
- }
1595
- case Token.PERIOD: {
1596
- if (isOptional) {
1597
- throw new Error(this.errorMessage(`Unexpected Token:${this.position()}`));
1598
- }
1599
- this.consume(Token.PERIOD);
1600
- const key = this.parsePropertyName();
1601
- result = new MemberExpression(result, key, false, isOptional);
1602
- break;
1603
- }
1604
- case Token.L_PARENTHESES: {
1605
- const args = this.parseArguments();
1606
- if (result.toString() === 'eval') {
1607
- throw new Error(this.errorMessage(`'eval(...)' is not supported.`));
1608
- }
1609
- result = new CallExpression(result, args, isOptional);
1610
- break;
1611
- }
1612
- case Token.BIND: {
1613
- if (isOptional) {
1614
- throw new Error(this.errorMessage(`Unexpected Token:${this.position()}`));
1615
- }
1616
- this.consume(Token.BIND);
1617
- const key = this.parsePropertyName();
1618
- result = new BindExpression(result, key, false, isOptional);
1619
- break;
1620
- }
1621
- case Token.QUESTION_BIND: {
1622
- if (isOptional) {
1623
- throw new Error(this.errorMessage(`Failure Expression`));
1624
- }
1625
- this.consume(Token.QUESTION_BIND);
1626
- isOptional = true;
1627
- optionalChaining = true;
1628
- const key = this.parsePropertyName();
1629
- result = new BindExpression(result, key, true, isOptional);
1630
- break;
1631
- }
1632
- default:
1633
- if (optionalChaining) {
1634
- throw new Error(this.errorMessage(`Optional Chaining No Template support`));
1635
- }
1636
- result = this.parseTemplateLiteral(result);
1637
- break;
790
+ else {
791
+ exportName = localName;
1638
792
  }
1639
- if (isOptional) {
1640
- isOptional = false;
793
+ exportData.push(new ExportSpecifier(exportName, localName));
794
+ if (this.peek().isType(Token.RBRACE))
795
+ break;
796
+ if (!this.check(Token.COMMA)) {
797
+ throw new SyntaxError('Unexpected Token');
1641
798
  }
1642
- } while (Token.isPropertyOrCall(this.peek().token));
1643
- if (optionalChaining) {
1644
- result = new ChainExpression(result);
1645
799
  }
1646
- return result;
800
+ this.expect(Token.RBRACE);
801
+ return exportData;
1647
802
  }
1648
- parseAwaitExpression() {
1649
- this.consume(Token.AWAIT);
1650
- const value = this.parseUnaryExpression();
1651
- if (this.peek().isType(Token.EXP)) {
1652
- throw new Error(this.scanner.createError(`Unexpected Token Unary Exponentiation`));
803
+ parseExportSpecifierName() {
804
+ const next = this.next();
805
+ // IdentifierName
806
+ if (next.isType(Token.IDENTIFIER) || Token.isPropertyName(next.token)) {
807
+ return next.getValue();
1653
808
  }
1654
- return buildUnaryExpression(value, Token.AWAIT);
1655
- }
1656
- parseNullishExpression(expression) {
1657
- const list = [];
1658
- list.push(expression);
1659
- while (this.peek().isType(Token.NULLISH)) {
1660
- this.consume(Token.NULLISH);
1661
- expression = this.parseBinaryExpression(6);
1662
- list.push(expression);
809
+ // ModuleExportName
810
+ if (next.isType(Token.STRING)) {
811
+ const exportName = next.getValue();
812
+ return exportName;
813
+ }
814
+ throw new SyntaxError(this.errorMessage('Unexpected Token'));
815
+ }
816
+ parseNamedImports() {
817
+ // NamedImports :
818
+ // '{' '}'
819
+ // '{' ImportsList '}'
820
+ // '{' ImportsList ',' '}'
821
+ //
822
+ // ImportsList :
823
+ // ImportSpecifier
824
+ // ImportsList ',' ImportSpecifier
825
+ //
826
+ // ImportSpecifier :
827
+ // BindingIdentifier
828
+ // IdentifierName 'as' BindingIdentifier
829
+ // ModuleExportName 'as' BindingIdentifier
830
+ this.expect(Token.LBRACE);
831
+ const result = [];
832
+ // auto result = zone() -> New < ZonePtrList <const NamedImport>> (1, zone());
833
+ while (this.peek().isNotType(Token.RBRACE)) {
834
+ const importName = this.parseExportSpecifierName();
835
+ let localName = importName;
836
+ // In the presence of 'as', the left-side of the 'as' can
837
+ // be any IdentifierName. But without 'as', it must be a valid
838
+ // BindingIdentifier.
839
+ if (this.checkContextualKeyword('as')) {
840
+ localName = this.parsePropertyOrPrivatePropertyName();
841
+ }
842
+ if (!Token.isValidIdentifier(this.current().token, LanguageMode.Strict, false, isStrict(this.languageMode))) {
843
+ throw new SyntaxError(this.errorMessage('Unexpected Reserved Keyword'));
844
+ }
845
+ else if (this.isEvalOrArguments(localName)) {
846
+ throw new SyntaxError(this.errorMessage('Strict Eval Arguments'));
847
+ }
848
+ result.push(new ImportSpecifier(localName, importName));
849
+ // DeclareUnboundVariable(localName, VariableMode:: kConst, kNeedsInitialization, position());
850
+ // NamedImport * import = zone() -> New<NamedImport>(import_name, local_name, location);
851
+ // result-> Add(import, zone());
852
+ if (this.peek().isType(Token.RBRACE))
853
+ break;
854
+ this.expect(Token.COMMA);
1663
855
  }
1664
- expression = list.pop();
1665
- expression = list.reverse()
1666
- .reduce((previous, current) => new LogicalExpression(Token.NULLISH.getName(), current, previous), expression);
1667
- return expression;
1668
- }
1669
- parseConditionalContinuation(expression) {
1670
- this.consume(Token.CONDITIONAL);
1671
- const left = this.parseAssignmentExpression();
1672
- this.expect(Token.COLON);
1673
- const right = this.parseAssignmentExpression();
1674
- return new ConditionalExpression(expression, left, right);
856
+ this.expect(Token.RBRACE);
857
+ return result;
1675
858
  }
1676
- parseYieldExpression() {
1677
- this.consume(Token.YIELD);
1678
- let delegating = false;
1679
- let expression;
1680
- if (this.check(Token.MUL)) {
1681
- delegating = true;
1682
- }
859
+ parseExportDefault() {
860
+ // Supports the following productions, starting after the 'default' token:
861
+ // 'export' 'default' HoistableDeclaration
862
+ // 'export' 'default' ClassDeclaration
863
+ // 'export' 'default' AssignmentExpression[In] ';'
864
+ this.expect(Token.DEFAULT);
865
+ // Scanner::Location default_loc = scanner() -> location();
866
+ // ZonePtrList <const AstRawString> localNames(1, zone());
867
+ const localNames = [];
868
+ let result;
1683
869
  switch (this.peek().token) {
1684
- case Token.EOS:
1685
- case Token.SEMICOLON:
1686
- case Token.R_CURLY:
1687
- case Token.R_BRACKETS:
1688
- case Token.R_PARENTHESES:
1689
- case Token.COLON:
1690
- case Token.COMMA:
1691
- case Token.IN:
1692
- if (!delegating)
870
+ case Token.FUNCTION:
871
+ result = this.parseHoistableDeclaration(localNames, true);
872
+ break;
873
+ case Token.CLASS:
874
+ this.consume(Token.CLASS);
875
+ result = this.parseClassDeclaration(localNames, true);
876
+ break;
877
+ case Token.ASYNC:
878
+ if (this.peekAhead().isType(Token.FUNCTION) && !this.scanner.hasLineTerminatorBeforeNext()) {
879
+ this.consume(Token.ASYNC);
880
+ result = this.parseHoistableDeclaration(localNames, true);
1693
881
  break;
1694
- throw new Error(this.errorMessage(`Delegating yields require an RHS`));
1695
- default:
1696
- expression = this.parseAssignmentExpressionCoverGrammar();
882
+ }
883
+ default: {
884
+ // int pos = position();
885
+ // AcceptINScope scope(this, true);
886
+ this.setAcceptIN(true);
887
+ result = this.parseAssignmentExpression();
888
+ // SetFunctionName(value, ast_value_factory() -> default_string());
889
+ // const AstRawString* local_name = ast_value_factory() -> dot_default_string();
890
+ // localNames.Add(local_name, zone());
891
+ // It's fine to declare this as VariableMode::kConst because the user has
892
+ // no way of writing to it.
893
+ // VariableProxy * proxy = DeclareBoundVariable(local_name, VariableMode:: kConst, pos);
894
+ // proxy ->var() -> set_initializer_position(position());
895
+ // Assignment * assignment = factory() -> NewAssignment(Token.INIT, proxy, value, kNoSourcePosition);
896
+ // result = IgnoreCompletion( factory() -> NewExpressionStatement(assignment, kNoSourcePosition));
897
+ this.expectSemicolon();
898
+ this.restoreAcceptIN();
1697
899
  break;
900
+ }
1698
901
  }
1699
- return new YieldExpression(delegating, expression);
1700
- }
1701
- parseNewTargetExpression() {
1702
- throw new Error(this.errorMessage('Expression (new.target) not supported.'));
1703
- }
1704
- parseClassDeclaration(names, defaultExport) {
1705
- throw new Error(this.errorMessage(`Expression (class) not supported.`));
1706
- }
1707
- parseClassLiteral(name, isStrictReserved) {
1708
- throw new Error(this.errorMessage(`Expression (class) not supported.`));
1709
- }
1710
- parseSuperExpression() {
1711
- throw new Error(this.errorMessage('Expression (supper) not supported.'));
1712
- }
1713
- parseImportExpressions() {
1714
- throw new Error(this.errorMessage('Expression (import) not supported.'));
902
+ // if (!result) {
903
+ // DCHECK_EQ(localNames.length(), 1);
904
+ // module() -> AddExport(localNames.first(), ast_value_factory() -> default_string(), default_loc, zone());
905
+ // }
906
+ return new ExportDefaultDeclaration(result);
907
+ }
908
+ parseExportStar() {
909
+ this.consume(Token.MUL);
910
+ if (!this.peekContextualKeyword('as')) {
911
+ // 'export' '*' 'from' ModuleSpecifier ';'
912
+ // Scanner::Location loc = scanner() -> location();
913
+ this.expectContextualKeyword('from');
914
+ // Scanner::Location specifier_loc = scanner() -> peek_location();
915
+ const moduleSpecifier = this.parseModuleSpecifier();
916
+ const importAssertions = this.parseImportAssertClause();
917
+ this.expectSemicolon();
918
+ // module() -> AddStarExport(module_specifier, import_assertions, loc,specifier_loc, zone());
919
+ return new ExportAllDeclaration(moduleSpecifier, undefined, importAssertions);
920
+ }
921
+ // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';'
922
+ //
923
+ // Desugaring:
924
+ // export * as x from "...";
925
+ // ~>
926
+ // import * as .x from "..."; export {.x as x};
927
+ //
928
+ // Note that the desugared internal namespace export name (.x above) will
929
+ // never conflict with a string literal export name, as literal string export
930
+ // names in local name positions (i.e. left of 'as' or in a clause without
931
+ // 'as') are disallowed without a following 'from' clause.
932
+ this.expectContextualKeyword('as');
933
+ const exportName = this.parseExportSpecifierName();
934
+ // Scanner::Location export_name_loc = scanner() -> location();
935
+ // const localName = this.nextInternalNamespaceExportName();
936
+ // Scanner::Location local_name_loc = Scanner:: Location:: invalid();
937
+ // DeclareUnboundVariable(local_name, VariableMode:: kConst, kCreatedInitialized,pos);
938
+ this.expectContextualKeyword('from');
939
+ const moduleSpecifier = this.parseModuleSpecifier();
940
+ const importAssertions = this.parseImportAssertClause();
941
+ this.expectSemicolon();
942
+ // const specifiers = [new ExportSpecifier(exportName as Identifier, exportName as Identifier)];
943
+ // module() -> AddStarImport(local_name, module_specifier, import_assertions,local_name_loc, specifier_loc, zone());
944
+ // module() -> AddExport(local_name, export_name, export_name_loc, zone());
945
+ return new ExportAllDeclaration(moduleSpecifier, exportName, importAssertions);
1715
946
  }
1716
947
  }
1717
948
  //# sourceMappingURL=parser.js.map