@ibyar/expressions 0.5.6 → 0.6.1
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.
- package/api/abstract.js +5 -0
- package/api/abstract.js.map +1 -1
- package/api/class/class.d.ts +28 -13
- package/api/class/class.js +46 -41
- package/api/class/class.js.map +1 -1
- package/api/computing/return.d.ts +4 -0
- package/api/computing/return.js +5 -0
- package/api/computing/return.js.map +1 -1
- package/api/computing/throw.d.ts +4 -0
- package/api/computing/throw.js +4 -0
- package/api/computing/throw.js.map +1 -1
- package/api/definition/bind.d.ts +6 -0
- package/api/definition/bind.js +6 -0
- package/api/definition/bind.js.map +1 -1
- package/api/definition/function.js +6 -5
- package/api/definition/function.js.map +1 -1
- package/api/definition/member.js.map +1 -1
- package/api/definition/object.js +1 -1
- package/api/definition/object.js.map +1 -1
- package/api/definition/values.d.ts +12 -3
- package/api/definition/values.js +25 -4
- package/api/definition/values.js.map +1 -1
- package/api/deserialize/deserialize.d.ts +5 -0
- package/api/deserialize/deserialize.js +5 -0
- package/api/deserialize/deserialize.js.map +1 -1
- package/api/expression.d.ts +151 -5
- package/api/expression.js.map +1 -1
- package/api/module/export.d.ts +63 -0
- package/api/module/export.js +64 -1
- package/api/module/export.js.map +1 -1
- package/api/module/import.d.ts +53 -0
- package/api/module/import.js +53 -0
- package/api/module/import.js.map +1 -1
- package/api/operators/grouping.d.ts +7 -0
- package/api/operators/grouping.js +7 -0
- package/api/operators/grouping.js.map +1 -1
- package/api/operators/pipeline.d.ts +12 -0
- package/api/operators/pipeline.js +12 -0
- package/api/operators/pipeline.js.map +1 -1
- package/api/operators/unary.js +3 -0
- package/api/operators/unary.js.map +1 -1
- package/api/program.d.ts +2 -2
- package/api/program.js.map +1 -1
- package/api/statement/control/block.d.ts +4 -0
- package/api/statement/control/block.js +4 -0
- package/api/statement/control/block.js.map +1 -1
- package/api/statement/control/empty.d.ts +7 -0
- package/api/statement/control/empty.js +7 -0
- package/api/statement/control/empty.js.map +1 -1
- package/api/statement/control/if.d.ts +5 -0
- package/api/statement/control/if.js +5 -0
- package/api/statement/control/if.js.map +1 -1
- package/api/statement/control/switch.d.ts +6 -0
- package/api/statement/control/switch.js +9 -0
- package/api/statement/control/switch.js.map +1 -1
- package/api/statement/control/terminate.d.ts +8 -0
- package/api/statement/control/terminate.js +8 -0
- package/api/statement/control/terminate.js.map +1 -1
- package/api/statement/iterations/for.d.ts +5 -0
- package/api/statement/iterations/for.js +13 -0
- package/api/statement/iterations/for.js.map +1 -1
- package/api/statement/iterations/while.d.ts +6 -0
- package/api/statement/iterations/while.js +10 -0
- package/api/statement/iterations/while.js.map +1 -1
- package/package.json +5 -3
- package/scope/event.d.ts +3 -3
- package/scope/event.js +2 -2
- package/scope/event.js.map +1 -1
- package/scope/pool.d.ts +7 -0
- package/scope/pool.js +29 -0
- package/scope/pool.js.map +1 -0
- package/scope/proxy.d.ts +6 -9
- package/scope/proxy.js +22 -31
- package/scope/proxy.js.map +1 -1
- package/scope/scope.d.ts +161 -38
- package/scope/scope.js +260 -106
- package/scope/scope.js.map +1 -1
- package/scope/stack.d.ts +95 -19
- package/scope/stack.js +13 -0
- package/scope/stack.js.map +1 -1
- package/v8/enums.js +31 -0
- package/v8/enums.js.map +1 -1
- package/v8/inline.d.ts +36 -0
- package/v8/inline.js +407 -5
- package/v8/inline.js.map +1 -1
- package/v8/nodes.js +2 -1
- package/v8/nodes.js.map +1 -1
- package/v8/parser.d.ts +8 -0
- package/v8/parser.js +304 -1
- package/v8/parser.js.map +1 -1
- package/v8/stream.d.ts +4 -0
- package/v8/stream.js +79 -17
- package/v8/stream.js.map +1 -1
- package/v8/token.d.ts +229 -0
- package/v8/token.js +236 -1
- package/v8/token.js.map +1 -1
- package/visit/visitor.d.ts +3 -0
package/v8/parser.js
CHANGED
|
@@ -11,6 +11,11 @@ import { ImportDeclaration, ImportDefaultSpecifier, ImportExpression, ImportName
|
|
|
11
11
|
import { ImportAttribute } from '../api/module/common.js';
|
|
12
12
|
import { ClassLiteralProperty, ClassLiteralPropertyKind, classPropertyKindFor, createClassInfo, FunctionKind, FunctionSyntaxKind, isAccessor, isStrict, LanguageMode, ParseFunctionFlag, PropertyKind, PropertyKindInfo, PropertyPosition, VariableDeclarationContext } from './enums.js';
|
|
13
13
|
export class JavaScriptParser extends JavaScriptInlineParser {
|
|
14
|
+
/**
|
|
15
|
+
* parser js with
|
|
16
|
+
* @param source
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
14
19
|
static parse(source, { mode } = {}) {
|
|
15
20
|
mode ?? (mode = LanguageMode.Strict);
|
|
16
21
|
const stream = (typeof source === 'string') || Array.isArray(source)
|
|
@@ -18,6 +23,9 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
18
23
|
const parser = new JavaScriptParser(stream);
|
|
19
24
|
return parser.scan();
|
|
20
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* parse inline code like that used in html 2 or 1 way binding
|
|
28
|
+
*/
|
|
21
29
|
static parseScript(source, options) {
|
|
22
30
|
return JavaScriptInlineParser.parse(source, options);
|
|
23
31
|
}
|
|
@@ -49,6 +57,23 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
49
57
|
return new ClassExpression(classLiteral.getBody(), classLiteral.getDecorators(), classLiteral.getId(), classLiteral.getSuperClass());
|
|
50
58
|
}
|
|
51
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.
|
|
52
77
|
const nextToken = this.peek().token;
|
|
53
78
|
const isStrictReserved = Token.isStrictReservedWord(nextToken);
|
|
54
79
|
let name;
|
|
@@ -67,6 +92,7 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
67
92
|
}
|
|
68
93
|
parseClassLiteral(name, nameIsStrictReserved) {
|
|
69
94
|
const isAnonymous = !!!name;
|
|
95
|
+
// All parts of a ClassDeclaration and ClassExpression are strict code.
|
|
70
96
|
if (!isAnonymous) {
|
|
71
97
|
if (nameIsStrictReserved) {
|
|
72
98
|
throw new Error(this.errorMessage(`Unexpected Strict Reserved class name`));
|
|
@@ -85,16 +111,21 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
85
111
|
while (this.peek().isNotType(Token.RBRACE)) {
|
|
86
112
|
if (this.check(Token.SEMICOLON))
|
|
87
113
|
continue;
|
|
114
|
+
// Either we're parsing a `static { }` initialization block or a property.
|
|
88
115
|
if (this.peek().isType(Token.STATIC) && this.peekAhead().isType(Token.LBRACE)) {
|
|
89
116
|
const staticBlock = this.parseClassStaticBlock(classInfo);
|
|
90
117
|
classInfo.staticElements.push(staticBlock);
|
|
91
118
|
classInfo.hasStaticBlocks = true;
|
|
92
119
|
continue;
|
|
93
120
|
}
|
|
121
|
+
// FuncNameInferrerState fni_state(& fni_);
|
|
122
|
+
// If we haven't seen the constructor yet, it potentially is the next
|
|
123
|
+
// property.
|
|
94
124
|
let isConstructor = !classInfo.hasSeenConstructor;
|
|
95
125
|
const propInfo = new PropertyKindInfo();
|
|
96
126
|
propInfo.position = PropertyPosition.ClassLiteral;
|
|
97
127
|
const property = this.parseClassPropertyDefinition(classInfo, propInfo, hasExtends);
|
|
128
|
+
// if (has_error()) return impl() . FailureExpression();
|
|
98
129
|
const propertyKind = classPropertyKindFor(propInfo.kind);
|
|
99
130
|
if (!classInfo.hasStaticComputedNames && propInfo.isStatic && propInfo.isComputedName) {
|
|
100
131
|
classInfo.hasStaticComputedNames = true;
|
|
@@ -126,11 +157,13 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
126
157
|
return new Class(classBody, [], name, classInfo.extends);
|
|
127
158
|
}
|
|
128
159
|
declarePublicClassMethod(name, property, isConstructor, classInfo) {
|
|
160
|
+
// throw new Error('Method not implemented.');
|
|
129
161
|
if (isConstructor) {
|
|
130
162
|
if (classInfo.constructor) {
|
|
131
163
|
throw new SyntaxError(this.errorMessage('A class may only have one constructor.'));
|
|
132
164
|
}
|
|
133
165
|
classInfo.constructor = property;
|
|
166
|
+
// set the class name as the constructor name
|
|
134
167
|
Reflect.set(classInfo.constructor, 'id', name);
|
|
135
168
|
return;
|
|
136
169
|
}
|
|
@@ -143,10 +176,16 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
143
176
|
else {
|
|
144
177
|
classInfo.instanceFields.push(property);
|
|
145
178
|
}
|
|
179
|
+
// if (isComputedName) {
|
|
180
|
+
// classInfo.publicMembers.push(property);
|
|
181
|
+
// }
|
|
146
182
|
}
|
|
147
183
|
declarePrivateClassMember(propertyName, property, kind, isStatic, classInfo) {
|
|
148
184
|
classInfo.privateMembers.push(property);
|
|
149
185
|
}
|
|
186
|
+
// protected createPrivateNameVariable(mode: VariableMode, staticFlag: StaticFlag, propertyName: string) {
|
|
187
|
+
// throw new Error('Method not implemented.');
|
|
188
|
+
// }
|
|
150
189
|
parseClassPropertyDefinition(classInfo, propInfo, hasExtends) {
|
|
151
190
|
if (!classInfo) {
|
|
152
191
|
throw new Error(this.errorMessage('class info is undefined'));
|
|
@@ -182,7 +221,19 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
182
221
|
case PropertyKind.ClassField:
|
|
183
222
|
case PropertyKind.ShorthandOrClassField:
|
|
184
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.
|
|
185
233
|
propInfo.kind = PropertyKind.ClassField;
|
|
234
|
+
// if (!propInfo.isComputedName) {
|
|
235
|
+
// this.checkClassFieldName(propInfo.name, propInfo.isStatic);
|
|
236
|
+
// }
|
|
186
237
|
const initializer = this.parseMemberInitializer(classInfo, propInfo.isStatic);
|
|
187
238
|
this.expectSemicolon();
|
|
188
239
|
const result = this.newClassLiteralProperty(nameExpression, initializer, ClassLiteralPropertyKind.FIELD, propInfo.isStatic, propInfo.isComputedName, propInfo.isPrivate);
|
|
@@ -190,6 +241,13 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
190
241
|
return result;
|
|
191
242
|
}
|
|
192
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 '}'
|
|
193
251
|
if (!propInfo.isComputedName) {
|
|
194
252
|
this.checkClassMethodName(propInfo, classInfo);
|
|
195
253
|
}
|
|
@@ -211,6 +269,9 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
211
269
|
const isGet = propInfo.kind == PropertyKind.AccessorGetter;
|
|
212
270
|
if (!propInfo.isComputedName) {
|
|
213
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.
|
|
214
275
|
nameExpression = new Literal(propInfo.name);
|
|
215
276
|
}
|
|
216
277
|
let kind;
|
|
@@ -232,6 +293,7 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
232
293
|
case PropertyKind.Value:
|
|
233
294
|
case PropertyKind.Shorthand:
|
|
234
295
|
case PropertyKind.Spread:
|
|
296
|
+
// throw new Error(this.errorMessage('Report Unexpected Token'));
|
|
235
297
|
return NullNode;
|
|
236
298
|
}
|
|
237
299
|
throw new Error(this.errorMessage('UNREACHABLE'));
|
|
@@ -263,6 +325,9 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
263
325
|
}
|
|
264
326
|
parseClassStaticBlock(classInfo) {
|
|
265
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.
|
|
266
331
|
this.setStatue(true, FunctionKind.ClassStaticInitializerFunction);
|
|
267
332
|
const block = this.parseBlock();
|
|
268
333
|
this.restoreStatue();
|
|
@@ -314,6 +379,9 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
314
379
|
return initializer;
|
|
315
380
|
}
|
|
316
381
|
setFunctionNameFromPropertyName(property, name, prefix) {
|
|
382
|
+
// TODO: no need for this now
|
|
383
|
+
// check later when needed
|
|
384
|
+
// the ClassExpression* handle this
|
|
317
385
|
}
|
|
318
386
|
parseSuperExpression() {
|
|
319
387
|
this.consume(Token.SUPER);
|
|
@@ -343,6 +411,13 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
343
411
|
return new ClassBody(body);
|
|
344
412
|
}
|
|
345
413
|
parseModuleItemList() {
|
|
414
|
+
// ecma262/#prod-Module
|
|
415
|
+
// Module :
|
|
416
|
+
// ModuleBody?
|
|
417
|
+
//
|
|
418
|
+
// ecma262/#prod-ModuleItemList
|
|
419
|
+
// ModuleBody :
|
|
420
|
+
// ModuleItem*
|
|
346
421
|
const body = [];
|
|
347
422
|
while (this.peek().isNotType(Token.EOS)) {
|
|
348
423
|
const stat = this.parseModuleItem();
|
|
@@ -357,40 +432,110 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
357
432
|
return body;
|
|
358
433
|
}
|
|
359
434
|
parseModuleItem() {
|
|
435
|
+
// ecma262/#prod-ModuleItem
|
|
436
|
+
// ModuleItem :
|
|
437
|
+
// ImportDeclaration
|
|
438
|
+
// ExportDeclaration
|
|
439
|
+
// StatementListItem
|
|
360
440
|
const next = this.peek();
|
|
361
441
|
if (next.isType(Token.EXPORT)) {
|
|
362
442
|
return this.parseExportDeclaration();
|
|
363
443
|
}
|
|
364
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.
|
|
365
447
|
const peekAhead = this.peekAhead();
|
|
366
448
|
if (peekAhead.isNotType(Token.LPAREN) && peekAhead.isNotType(Token.PERIOD)) {
|
|
367
449
|
return this.parseImportDeclaration();
|
|
450
|
+
// return factory() -> EmptyStatement();
|
|
368
451
|
}
|
|
369
452
|
}
|
|
370
453
|
return this.parseStatementListItem();
|
|
371
454
|
}
|
|
372
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
|
|
373
475
|
this.expect(Token.EXPORT);
|
|
374
476
|
let result;
|
|
375
477
|
const names = [];
|
|
478
|
+
// Statement * result = nullptr;
|
|
479
|
+
// ZonePtrList <const AstRawString> names(1, zone());
|
|
480
|
+
// Scanner::Location loc = scanner() -> peek_location();
|
|
376
481
|
switch (this.peek().token) {
|
|
377
482
|
case Token.DEFAULT:
|
|
378
483
|
return this.parseExportDefault();
|
|
379
484
|
case Token.MUL:
|
|
380
485
|
return this.parseExportStar();
|
|
381
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);
|
|
382
503
|
const exportData = this.parseExportClause();
|
|
383
504
|
let moduleSpecifier;
|
|
384
505
|
let importAssertions;
|
|
385
506
|
if (this.checkContextualKeyword('from')) {
|
|
507
|
+
// Scanner::Location specifier_loc = scanner() -> peek_location();
|
|
386
508
|
moduleSpecifier = this.parseModuleSpecifier();
|
|
387
509
|
importAssertions = this.parseImportAssertClause();
|
|
388
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
|
+
// }
|
|
389
520
|
}
|
|
390
521
|
else {
|
|
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
|
+
// }
|
|
391
531
|
this.expectSemicolon();
|
|
532
|
+
// for (const ExportClauseData& data : * export_data) {
|
|
533
|
+
// module() -> AddExport(data.local_name, data.export_name, data.location,
|
|
534
|
+
// zone());
|
|
535
|
+
// }
|
|
392
536
|
}
|
|
393
537
|
return new ExportNamedDeclaration(exportData, undefined, moduleSpecifier, importAssertions);
|
|
538
|
+
// return factory() -> EmptyStatement();
|
|
394
539
|
}
|
|
395
540
|
case Token.FUNCTION: {
|
|
396
541
|
const declaration = this.parseFunctionDeclaration();
|
|
@@ -424,29 +569,63 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
424
569
|
default:
|
|
425
570
|
throw new SyntaxError(this.errorMessage('Unexpected Token'));
|
|
426
571
|
}
|
|
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
|
+
// }
|
|
427
577
|
return result;
|
|
428
578
|
}
|
|
429
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
|
|
430
596
|
this.expect(Token.IMPORT);
|
|
431
597
|
const tok = this.peek();
|
|
598
|
+
// 'import' ModuleSpecifier ';'
|
|
432
599
|
if (tok.isType(Token.STRING)) {
|
|
600
|
+
// Scanner::Location specifier_loc = scanner() -> peek_location();
|
|
433
601
|
const moduleSpecifier = this.parseModuleSpecifier();
|
|
434
602
|
const importAssertions = this.parseImportAssertClause();
|
|
435
603
|
this.expectSemicolon();
|
|
604
|
+
// module() -> AddEmptyImport(module_specifier, import_assertions, specifier_loc,zone());
|
|
436
605
|
return new ImportDeclaration(moduleSpecifier, undefined, importAssertions);
|
|
437
606
|
}
|
|
607
|
+
// Parse ImportedDefaultBinding if present.
|
|
438
608
|
let importDefaultBinding;
|
|
609
|
+
// Scanner::Location import_default_binding_loc;
|
|
439
610
|
if (tok.isNotType(Token.MUL) && tok.isNotType(Token.LBRACE)) {
|
|
440
611
|
importDefaultBinding = this.parseNonRestrictedIdentifier();
|
|
612
|
+
// DeclareUnboundVariable(import_default_binding, VariableMode:: kConst,kNeedsInitialization, pos);
|
|
441
613
|
}
|
|
614
|
+
// Parse NameSpaceImport or NamedImports if present.
|
|
442
615
|
let moduleNamespaceBinding;
|
|
443
616
|
let namedImports;
|
|
617
|
+
// Scanner::Location module_namespace_binding_loc;
|
|
618
|
+
// const ZonePtrList<const NamedImport >* named_imports = nullptr;
|
|
444
619
|
if (importDefaultBinding == undefined || this.check(Token.COMMA)) {
|
|
445
620
|
switch (this.peek().token) {
|
|
446
621
|
case Token.MUL: {
|
|
447
622
|
this.consume(Token.MUL);
|
|
448
623
|
this.expectContextualKeyword('as');
|
|
449
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);
|
|
450
629
|
break;
|
|
451
630
|
}
|
|
452
631
|
case Token.LBRACE:
|
|
@@ -457,9 +636,17 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
457
636
|
}
|
|
458
637
|
}
|
|
459
638
|
this.expectContextualKeyword('from');
|
|
639
|
+
// ExpectContextualKeyword(ast_value_factory() -> from_string());
|
|
640
|
+
// Scanner::Location specifier_loc = scanner() -> peek_location();
|
|
460
641
|
const moduleSpecifier = this.parseModuleSpecifier();
|
|
461
642
|
const importAssertions = this.parseImportAssertClause();
|
|
462
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?
|
|
463
650
|
const specifiers = [];
|
|
464
651
|
if (moduleNamespaceBinding) {
|
|
465
652
|
specifiers.push(new ImportNamespaceSpecifier(moduleNamespaceBinding));
|
|
@@ -489,11 +676,13 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
489
676
|
const specifier = this.parseAssignmentExpressionCoverGrammar();
|
|
490
677
|
if (this.check(Token.COMMA)) {
|
|
491
678
|
if (this.check(Token.RPAREN)) {
|
|
679
|
+
// A trailing comma allowed after the specifier.
|
|
492
680
|
return new ImportExpression(specifier);
|
|
493
681
|
}
|
|
494
682
|
else {
|
|
495
683
|
const importAssertions = this.parseAssignmentExpressionCoverGrammar();
|
|
496
|
-
this.check(Token.COMMA);
|
|
684
|
+
this.check(Token.COMMA); // A trailing comma is allowed after the import
|
|
685
|
+
// assertions.
|
|
497
686
|
this.expect(Token.RPAREN);
|
|
498
687
|
return new ImportExpression(specifier, importAssertions);
|
|
499
688
|
}
|
|
@@ -503,12 +692,39 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
503
692
|
return new ImportExpression(specifier);
|
|
504
693
|
}
|
|
505
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.
|
|
506
708
|
const declarations = this.parseVariableDeclarations(varContext);
|
|
507
709
|
this.expectSemicolon();
|
|
508
710
|
names.push(...declarations.getDeclarations().map(d => d.getId().toString()));
|
|
509
711
|
return declarations;
|
|
510
712
|
}
|
|
511
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.
|
|
512
728
|
if (this.scanner.hasLineTerminatorBeforeNext() || !this.checkContextualKeyword('assert')) {
|
|
513
729
|
return undefined;
|
|
514
730
|
}
|
|
@@ -525,6 +741,7 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
525
741
|
importAssertions.push(new ImportAttribute(attributeKey, attributeValue));
|
|
526
742
|
counts[attributeKey.toString()] = (counts[attributeKey.toString()] ?? 0) + 1;
|
|
527
743
|
if (counts[attributeKey.toString()] > 1) {
|
|
744
|
+
// // It is a syntax error if two AssertEntries have the same key.
|
|
528
745
|
throw new SyntaxError(this.errorMessage('Import Assertion Duplicate Key'));
|
|
529
746
|
}
|
|
530
747
|
if (this.peek().isType(Token.RBRACE))
|
|
@@ -537,9 +754,30 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
537
754
|
return importAssertions;
|
|
538
755
|
}
|
|
539
756
|
parseModuleSpecifier() {
|
|
757
|
+
// ModuleSpecifier :
|
|
758
|
+
// StringLiteral
|
|
540
759
|
return this.expectAndGetValue(Token.STRING);
|
|
541
760
|
}
|
|
542
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());
|
|
543
781
|
this.expect(Token.LBRACE);
|
|
544
782
|
const exportData = [];
|
|
545
783
|
let nameTok = this.peek();
|
|
@@ -564,9 +802,11 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
564
802
|
}
|
|
565
803
|
parseExportSpecifierName() {
|
|
566
804
|
const next = this.next();
|
|
805
|
+
// IdentifierName
|
|
567
806
|
if (next.isType(Token.IDENTIFIER) || Token.isPropertyName(next.token)) {
|
|
568
807
|
return next.getValue();
|
|
569
808
|
}
|
|
809
|
+
// ModuleExportName
|
|
570
810
|
if (next.isType(Token.STRING)) {
|
|
571
811
|
const exportName = next.getValue();
|
|
572
812
|
return exportName;
|
|
@@ -574,11 +814,28 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
574
814
|
throw new SyntaxError(this.errorMessage('Unexpected Token'));
|
|
575
815
|
}
|
|
576
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
|
|
577
830
|
this.expect(Token.LBRACE);
|
|
578
831
|
const result = [];
|
|
832
|
+
// auto result = zone() -> New < ZonePtrList <const NamedImport>> (1, zone());
|
|
579
833
|
while (this.peek().isNotType(Token.RBRACE)) {
|
|
580
834
|
const importName = this.parseExportSpecifierName();
|
|
581
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.
|
|
582
839
|
if (this.checkContextualKeyword('as')) {
|
|
583
840
|
localName = this.parsePropertyOrPrivatePropertyName();
|
|
584
841
|
}
|
|
@@ -589,6 +846,9 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
589
846
|
throw new SyntaxError(this.errorMessage('Strict Eval Arguments'));
|
|
590
847
|
}
|
|
591
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());
|
|
592
852
|
if (this.peek().isType(Token.RBRACE))
|
|
593
853
|
break;
|
|
594
854
|
this.expect(Token.COMMA);
|
|
@@ -597,7 +857,13 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
597
857
|
return result;
|
|
598
858
|
}
|
|
599
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] ';'
|
|
600
864
|
this.expect(Token.DEFAULT);
|
|
865
|
+
// Scanner::Location default_loc = scanner() -> location();
|
|
866
|
+
// ZonePtrList <const AstRawString> localNames(1, zone());
|
|
601
867
|
const localNames = [];
|
|
602
868
|
let result;
|
|
603
869
|
switch (this.peek().token) {
|
|
@@ -615,30 +881,67 @@ export class JavaScriptParser extends JavaScriptInlineParser {
|
|
|
615
881
|
break;
|
|
616
882
|
}
|
|
617
883
|
default: {
|
|
884
|
+
// int pos = position();
|
|
885
|
+
// AcceptINScope scope(this, true);
|
|
618
886
|
this.setAcceptIN(true);
|
|
619
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));
|
|
620
897
|
this.expectSemicolon();
|
|
621
898
|
this.restoreAcceptIN();
|
|
622
899
|
break;
|
|
623
900
|
}
|
|
624
901
|
}
|
|
902
|
+
// if (!result) {
|
|
903
|
+
// DCHECK_EQ(localNames.length(), 1);
|
|
904
|
+
// module() -> AddExport(localNames.first(), ast_value_factory() -> default_string(), default_loc, zone());
|
|
905
|
+
// }
|
|
625
906
|
return new ExportDefaultDeclaration(result);
|
|
626
907
|
}
|
|
627
908
|
parseExportStar() {
|
|
628
909
|
this.consume(Token.MUL);
|
|
629
910
|
if (!this.peekContextualKeyword('as')) {
|
|
911
|
+
// 'export' '*' 'from' ModuleSpecifier ';'
|
|
912
|
+
// Scanner::Location loc = scanner() -> location();
|
|
630
913
|
this.expectContextualKeyword('from');
|
|
914
|
+
// Scanner::Location specifier_loc = scanner() -> peek_location();
|
|
631
915
|
const moduleSpecifier = this.parseModuleSpecifier();
|
|
632
916
|
const importAssertions = this.parseImportAssertClause();
|
|
633
917
|
this.expectSemicolon();
|
|
918
|
+
// module() -> AddStarExport(module_specifier, import_assertions, loc,specifier_loc, zone());
|
|
634
919
|
return new ExportAllDeclaration(moduleSpecifier, undefined, importAssertions);
|
|
635
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.
|
|
636
932
|
this.expectContextualKeyword('as');
|
|
637
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);
|
|
638
938
|
this.expectContextualKeyword('from');
|
|
639
939
|
const moduleSpecifier = this.parseModuleSpecifier();
|
|
640
940
|
const importAssertions = this.parseImportAssertClause();
|
|
641
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());
|
|
642
945
|
return new ExportAllDeclaration(moduleSpecifier, exportName, importAssertions);
|
|
643
946
|
}
|
|
644
947
|
}
|