1 // This file was autogenerated by binjs_generate_spidermonkey,
2 // please DO NOT EDIT BY HAND.
3 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 * vim: set ts=8 sts=2 et sw=2 tw=80:
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8
9 // To generate this file, see the documentation in
10 // js/src/frontend/binast/README.md.
11
12 #include "frontend/BinASTParser.h"
13
14 #include "mozilla/ArrayUtils.h"
15 #include "mozilla/Casting.h"
16 #include "mozilla/Maybe.h"
17 #include "mozilla/PodOperations.h"
18 #include "mozilla/Vector.h"
19
20 #include <type_traits>
21 #include <utility>
22
23 #include "frontend/BinAST-macros.h"
24 #include "frontend/BinASTTokenReaderContext.h"
25 #include "frontend/BinASTTokenReaderMultipart.h"
26 #include "frontend/FullParseHandler.h"
27 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
28 #include "frontend/ParseNode.h"
29 #include "frontend/Parser.h"
30 #include "frontend/SharedContext.h"
31 #ifndef ENABLE_NEW_REGEXP
32 # include "irregexp/RegExpParser.h"
33 #endif
34 #include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
35 #ifdef ENABLE_NEW_REGEXP
36 # include "new-regexp/RegExpAPI.h"
37 #endif
38 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
39 #include "vm/RegExpObject.h"
40
41 #include "frontend/ParseContext-inl.h"
42
43 using JS::RegExpFlag;
44 using JS::RegExpFlags;
45
46 namespace js::frontend {
47
48 // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
49 // a string literal (and ONLY a string literal).
50 template <typename Tok, size_t N>
operator ==(const typename Tok::Chars & left,const char (& right)[N])51 bool operator==(const typename Tok::Chars& left, const char (&right)[N]) {
52 return Tok::equals(left, right);
53 }
54
55 // ----- Sums of interfaces (autogenerated, by lexicographical order)
56 // Sums of sums are flattened.
57 /*
58 AssertedMaybePositionalParameterName ::= AssertedParameterName
59 AssertedPositionalParameterName
60 AssertedRestParameterName
61 */
62 template <typename Tok>
parseAssertedMaybePositionalParameterName(AssertedScopeKind scopeKind,MutableHandle<GCVector<JSAtom * >> positionalParams,const ListContext & context)63 JS::Result<Ok> BinASTParser<Tok>::parseAssertedMaybePositionalParameterName(
64 AssertedScopeKind scopeKind,
65 MutableHandle<GCVector<JSAtom*>> positionalParams,
66 const ListContext& context) {
67 BinASTKind kind = BinASTKind::_Uninitialized;
68 AutoTaggedTuple guard(*tokenizer_);
69 const auto start = tokenizer_->offset();
70
71 guard.init();
72 MOZ_TRY(tokenizer_->enterSum(kind, context));
73
74 BINJS_MOZ_TRY_DECL(result,
75 parseSumAssertedMaybePositionalParameterName(
76 start, kind, scopeKind, positionalParams, context));
77
78 MOZ_TRY(guard.done());
79 return result;
80 }
81
82 template <typename Tok>
parseSumAssertedMaybePositionalParameterName(const size_t start,const BinASTKind kind,AssertedScopeKind scopeKind,MutableHandle<GCVector<JSAtom * >> positionalParams,const ListContext & context)83 JS::Result<Ok> BinASTParser<Tok>::parseSumAssertedMaybePositionalParameterName(
84 const size_t start, const BinASTKind kind, AssertedScopeKind scopeKind,
85 MutableHandle<GCVector<JSAtom*>> positionalParams,
86 const ListContext& context) {
87 Ok result;
88 switch (kind) {
89 case BinASTKind::AssertedParameterName:
90 return raiseError(
91 "FIXME: Not implemented yet in this preview release "
92 "(AssertedParameterName)");
93 case BinASTKind::AssertedPositionalParameterName:
94 MOZ_TRY_VAR(result, parseInterfaceAssertedPositionalParameterName(
95 start, scopeKind, positionalParams, context));
96 break;
97 case BinASTKind::AssertedRestParameterName:
98 return raiseError(
99 "FIXME: Not implemented yet in this preview release "
100 "(AssertedRestParameterName)");
101 default:
102 if (isInvalidKindPossible()) {
103 return raiseInvalidKind("AssertedMaybePositionalParameterName", kind);
104 } else {
105 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
106 "invalid BinASTKind should not appear");
107 }
108 }
109 return result;
110 }
111
112 /*
113 AssignmentTarget ::= ArrayAssignmentTarget
114 AssignmentTargetIdentifier
115 ComputedMemberAssignmentTarget
116 ObjectAssignmentTarget
117 StaticMemberAssignmentTarget
118 */
119 template <typename Tok>
parseAssignmentTarget(const FieldContext & context)120 JS::Result<ParseNode*> BinASTParser<Tok>::parseAssignmentTarget(
121 const FieldContext& context) {
122 BinASTKind kind = BinASTKind::_Uninitialized;
123 AutoTaggedTuple guard(*tokenizer_);
124 const auto start = tokenizer_->offset();
125
126 guard.init();
127 MOZ_TRY(tokenizer_->enterSum(kind, context));
128
129 BINJS_MOZ_TRY_DECL(result, parseSumAssignmentTarget(start, kind, context));
130
131 MOZ_TRY(guard.done());
132 return result;
133 }
134
135 template <typename Tok>
parseSumAssignmentTarget(const size_t start,const BinASTKind kind,const FieldContext & context)136 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumAssignmentTarget(
137 const size_t start, const BinASTKind kind, const FieldContext& context) {
138 ParseNode* result;
139 switch (kind) {
140 case BinASTKind::ArrayAssignmentTarget:
141 MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, context));
142 break;
143 case BinASTKind::AssignmentTargetIdentifier:
144 MOZ_TRY_VAR(result,
145 parseInterfaceAssignmentTargetIdentifier(start, context));
146 break;
147 case BinASTKind::ComputedMemberAssignmentTarget:
148 MOZ_TRY_VAR(result,
149 parseInterfaceComputedMemberAssignmentTarget(start, context));
150 break;
151 case BinASTKind::ObjectAssignmentTarget:
152 MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, context));
153 break;
154 case BinASTKind::StaticMemberAssignmentTarget:
155 MOZ_TRY_VAR(result,
156 parseInterfaceStaticMemberAssignmentTarget(start, context));
157 break;
158 default:
159 if (isInvalidKindPossible()) {
160 return raiseInvalidKind("AssignmentTarget", kind);
161 } else {
162 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
163 "invalid BinASTKind should not appear");
164 }
165 }
166 return result;
167 }
168
169 /*
170 AssignmentTargetOrForInOfBinding ::= ArrayAssignmentTarget
171 AssignmentTargetIdentifier
172 ComputedMemberAssignmentTarget
173 ForInOfBinding
174 ObjectAssignmentTarget
175 StaticMemberAssignmentTarget
176 */
177 template <typename Tok>
parseAssignmentTargetOrForInOfBinding(const FieldContext & context)178 JS::Result<ParseNode*> BinASTParser<Tok>::parseAssignmentTargetOrForInOfBinding(
179 const FieldContext& context) {
180 BinASTKind kind = BinASTKind::_Uninitialized;
181 AutoTaggedTuple guard(*tokenizer_);
182 const auto start = tokenizer_->offset();
183
184 guard.init();
185 MOZ_TRY(tokenizer_->enterSum(kind, context));
186
187 BINJS_MOZ_TRY_DECL(
188 result, parseSumAssignmentTargetOrForInOfBinding(start, kind, context));
189
190 MOZ_TRY(guard.done());
191 return result;
192 }
193
194 template <typename Tok>
195 JS::Result<ParseNode*>
parseSumAssignmentTargetOrForInOfBinding(const size_t start,const BinASTKind kind,const FieldContext & context)196 BinASTParser<Tok>::parseSumAssignmentTargetOrForInOfBinding(
197 const size_t start, const BinASTKind kind, const FieldContext& context) {
198 ParseNode* result;
199 switch (kind) {
200 case BinASTKind::ArrayAssignmentTarget:
201 MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, context));
202 break;
203 case BinASTKind::AssignmentTargetIdentifier:
204 MOZ_TRY_VAR(result,
205 parseInterfaceAssignmentTargetIdentifier(start, context));
206 break;
207 case BinASTKind::ComputedMemberAssignmentTarget:
208 MOZ_TRY_VAR(result,
209 parseInterfaceComputedMemberAssignmentTarget(start, context));
210 break;
211 case BinASTKind::ForInOfBinding:
212 MOZ_TRY_VAR(result, parseInterfaceForInOfBinding(start, context));
213 break;
214 case BinASTKind::ObjectAssignmentTarget:
215 MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, context));
216 break;
217 case BinASTKind::StaticMemberAssignmentTarget:
218 MOZ_TRY_VAR(result,
219 parseInterfaceStaticMemberAssignmentTarget(start, context));
220 break;
221 default:
222 if (isInvalidKindPossible()) {
223 return raiseInvalidKind("AssignmentTargetOrForInOfBinding", kind);
224 } else {
225 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
226 "invalid BinASTKind should not appear");
227 }
228 }
229 return result;
230 }
231
232 /*
233 Binding ::= ArrayBinding
234 BindingIdentifier
235 ObjectBinding
236 */
237 template <typename Tok>
parseBinding(const FieldContext & context)238 JS::Result<ParseNode*> BinASTParser<Tok>::parseBinding(
239 const FieldContext& context) {
240 BinASTKind kind = BinASTKind::_Uninitialized;
241 AutoTaggedTuple guard(*tokenizer_);
242 const auto start = tokenizer_->offset();
243
244 guard.init();
245 MOZ_TRY(tokenizer_->enterSum(kind, context));
246
247 BINJS_MOZ_TRY_DECL(result, parseSumBinding(start, kind, context));
248
249 MOZ_TRY(guard.done());
250 return result;
251 }
252
253 template <typename Tok>
parseSumBinding(const size_t start,const BinASTKind kind,const FieldContext & context)254 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumBinding(
255 const size_t start, const BinASTKind kind, const FieldContext& context) {
256 ParseNode* result;
257 switch (kind) {
258 case BinASTKind::ArrayBinding:
259 MOZ_TRY_VAR(result, parseInterfaceArrayBinding(
260 start, FieldOrListContext(context)));
261 break;
262 case BinASTKind::BindingIdentifier:
263 MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(
264 start, FieldOrListContext(context)));
265 break;
266 case BinASTKind::ObjectBinding:
267 MOZ_TRY_VAR(result, parseInterfaceObjectBinding(
268 start, FieldOrListContext(context)));
269 break;
270 default:
271 if (isInvalidKindPossible()) {
272 return raiseInvalidKind("Binding", kind);
273 } else {
274 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
275 "invalid BinASTKind should not appear");
276 }
277 }
278 return result;
279 }
280
281 /*
282 Expression ::= ArrayExpression
283 AssignmentExpression
284 AwaitExpression
285 BinaryExpression
286 CallExpression
287 ClassExpression
288 CompoundAssignmentExpression
289 ComputedMemberExpression
290 ConditionalExpression
291 EagerArrowExpressionWithExpression
292 EagerArrowExpressionWithFunctionBody
293 EagerFunctionExpression
294 IdentifierExpression
295 LazyArrowExpressionWithExpression
296 LazyArrowExpressionWithFunctionBody
297 LazyFunctionExpression
298 LiteralBooleanExpression
299 LiteralInfinityExpression
300 LiteralNullExpression
301 LiteralNumericExpression
302 LiteralRegExpExpression
303 LiteralStringExpression
304 NewExpression
305 NewTargetExpression
306 ObjectExpression
307 StaticMemberExpression
308 TemplateExpression
309 ThisExpression
310 UnaryExpression
311 UpdateExpression
312 YieldExpression
313 YieldStarExpression
314 */
315 template <typename Tok>
parseExpression(const FieldContext & context)316 JS::Result<ParseNode*> BinASTParser<Tok>::parseExpression(
317 const FieldContext& context) {
318 BinASTKind kind = BinASTKind::_Uninitialized;
319 AutoTaggedTuple guard(*tokenizer_);
320 const auto start = tokenizer_->offset();
321
322 guard.init();
323 MOZ_TRY(tokenizer_->enterSum(kind, context));
324
325 BINJS_MOZ_TRY_DECL(result, parseSumExpression(start, kind, context));
326
327 MOZ_TRY(guard.done());
328 return result;
329 }
330
331 template <typename Tok>
parseSumExpression(const size_t start,const BinASTKind kind,const FieldContext & context)332 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumExpression(
333 const size_t start, const BinASTKind kind, const FieldContext& context) {
334 ParseNode* result;
335 switch (kind) {
336 case BinASTKind::ArrayExpression:
337 MOZ_TRY_VAR(result, parseInterfaceArrayExpression(
338 start, FieldOrListContext(context)));
339 break;
340 case BinASTKind::AssignmentExpression:
341 MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
342 start, FieldOrListContext(context)));
343 break;
344 case BinASTKind::AwaitExpression:
345 MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(
346 start, FieldOrListContext(context)));
347 break;
348 case BinASTKind::BinaryExpression:
349 MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(
350 start, FieldOrListContext(context)));
351 break;
352 case BinASTKind::CallExpression:
353 MOZ_TRY_VAR(result, parseInterfaceCallExpression(
354 start, FieldOrListContext(context)));
355 break;
356 case BinASTKind::ClassExpression:
357 MOZ_TRY_VAR(result, parseInterfaceClassExpression(
358 start, FieldOrListContext(context)));
359 break;
360 case BinASTKind::CompoundAssignmentExpression:
361 MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
362 start, FieldOrListContext(context)));
363 break;
364 case BinASTKind::ComputedMemberExpression:
365 MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
366 start, FieldOrListContext(context)));
367 break;
368 case BinASTKind::ConditionalExpression:
369 MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
370 start, FieldOrListContext(context)));
371 break;
372 case BinASTKind::EagerArrowExpressionWithExpression:
373 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
374 start, FieldOrListContext(context)));
375 break;
376 case BinASTKind::EagerArrowExpressionWithFunctionBody:
377 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
378 start, FieldOrListContext(context)));
379 break;
380 case BinASTKind::EagerFunctionExpression:
381 MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
382 start, FieldOrListContext(context)));
383 break;
384 case BinASTKind::IdentifierExpression:
385 MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
386 start, FieldOrListContext(context)));
387 break;
388 case BinASTKind::LazyArrowExpressionWithExpression:
389 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
390 start, FieldOrListContext(context)));
391 break;
392 case BinASTKind::LazyArrowExpressionWithFunctionBody:
393 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
394 start, FieldOrListContext(context)));
395 break;
396 case BinASTKind::LazyFunctionExpression:
397 MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
398 start, FieldOrListContext(context)));
399 break;
400 case BinASTKind::LiteralBooleanExpression:
401 MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
402 start, FieldOrListContext(context)));
403 break;
404 case BinASTKind::LiteralInfinityExpression:
405 MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
406 start, FieldOrListContext(context)));
407 break;
408 case BinASTKind::LiteralNullExpression:
409 MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
410 start, FieldOrListContext(context)));
411 break;
412 case BinASTKind::LiteralNumericExpression:
413 MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
414 start, FieldOrListContext(context)));
415 break;
416 case BinASTKind::LiteralRegExpExpression:
417 MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
418 start, FieldOrListContext(context)));
419 break;
420 case BinASTKind::LiteralStringExpression:
421 MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
422 start, FieldOrListContext(context)));
423 break;
424 case BinASTKind::NewExpression:
425 MOZ_TRY_VAR(result, parseInterfaceNewExpression(
426 start, FieldOrListContext(context)));
427 break;
428 case BinASTKind::NewTargetExpression:
429 MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(
430 start, FieldOrListContext(context)));
431 break;
432 case BinASTKind::ObjectExpression:
433 MOZ_TRY_VAR(result, parseInterfaceObjectExpression(
434 start, FieldOrListContext(context)));
435 break;
436 case BinASTKind::StaticMemberExpression:
437 MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
438 start, FieldOrListContext(context)));
439 break;
440 case BinASTKind::TemplateExpression:
441 MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(
442 start, FieldOrListContext(context)));
443 break;
444 case BinASTKind::ThisExpression:
445 MOZ_TRY_VAR(result, parseInterfaceThisExpression(
446 start, FieldOrListContext(context)));
447 break;
448 case BinASTKind::UnaryExpression:
449 MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(
450 start, FieldOrListContext(context)));
451 break;
452 case BinASTKind::UpdateExpression:
453 MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(
454 start, FieldOrListContext(context)));
455 break;
456 case BinASTKind::YieldExpression:
457 MOZ_TRY_VAR(result, parseInterfaceYieldExpression(
458 start, FieldOrListContext(context)));
459 break;
460 case BinASTKind::YieldStarExpression:
461 MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(
462 start, FieldOrListContext(context)));
463 break;
464 default:
465 if (isInvalidKindPossible()) {
466 return raiseInvalidKind("Expression", kind);
467 } else {
468 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
469 "invalid BinASTKind should not appear");
470 }
471 }
472 return result;
473 }
474
475 /*
476 ExpressionOrSpreadElement ::= ArrayExpression
477 AssignmentExpression
478 AwaitExpression
479 BinaryExpression
480 CallExpression
481 ClassExpression
482 CompoundAssignmentExpression
483 ComputedMemberExpression
484 ConditionalExpression
485 EagerArrowExpressionWithExpression
486 EagerArrowExpressionWithFunctionBody
487 EagerFunctionExpression
488 IdentifierExpression
489 LazyArrowExpressionWithExpression
490 LazyArrowExpressionWithFunctionBody
491 LazyFunctionExpression
492 LiteralBooleanExpression
493 LiteralInfinityExpression
494 LiteralNullExpression
495 LiteralNumericExpression
496 LiteralRegExpExpression
497 LiteralStringExpression
498 NewExpression
499 NewTargetExpression
500 ObjectExpression
501 SpreadElement
502 StaticMemberExpression
503 TemplateExpression
504 ThisExpression
505 UnaryExpression
506 UpdateExpression
507 YieldExpression
508 YieldStarExpression
509 */
510 template <typename Tok>
parseExpressionOrSpreadElement(const ListContext & context)511 JS::Result<ParseNode*> BinASTParser<Tok>::parseExpressionOrSpreadElement(
512 const ListContext& context) {
513 BinASTKind kind = BinASTKind::_Uninitialized;
514 AutoTaggedTuple guard(*tokenizer_);
515 const auto start = tokenizer_->offset();
516
517 guard.init();
518 MOZ_TRY(tokenizer_->enterSum(kind, context));
519
520 BINJS_MOZ_TRY_DECL(result,
521 parseSumExpressionOrSpreadElement(start, kind, context));
522
523 MOZ_TRY(guard.done());
524 return result;
525 }
526
527 template <typename Tok>
parseSumExpressionOrSpreadElement(const size_t start,const BinASTKind kind,const ListContext & context)528 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumExpressionOrSpreadElement(
529 const size_t start, const BinASTKind kind, const ListContext& context) {
530 ParseNode* result;
531 switch (kind) {
532 case BinASTKind::ArrayExpression:
533 MOZ_TRY_VAR(result, parseInterfaceArrayExpression(
534 start, FieldOrListContext(context)));
535 break;
536 case BinASTKind::AssignmentExpression:
537 MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
538 start, FieldOrListContext(context)));
539 break;
540 case BinASTKind::AwaitExpression:
541 MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(
542 start, FieldOrListContext(context)));
543 break;
544 case BinASTKind::BinaryExpression:
545 MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(
546 start, FieldOrListContext(context)));
547 break;
548 case BinASTKind::CallExpression:
549 MOZ_TRY_VAR(result, parseInterfaceCallExpression(
550 start, FieldOrListContext(context)));
551 break;
552 case BinASTKind::ClassExpression:
553 MOZ_TRY_VAR(result, parseInterfaceClassExpression(
554 start, FieldOrListContext(context)));
555 break;
556 case BinASTKind::CompoundAssignmentExpression:
557 MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
558 start, FieldOrListContext(context)));
559 break;
560 case BinASTKind::ComputedMemberExpression:
561 MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
562 start, FieldOrListContext(context)));
563 break;
564 case BinASTKind::ConditionalExpression:
565 MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
566 start, FieldOrListContext(context)));
567 break;
568 case BinASTKind::EagerArrowExpressionWithExpression:
569 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
570 start, FieldOrListContext(context)));
571 break;
572 case BinASTKind::EagerArrowExpressionWithFunctionBody:
573 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
574 start, FieldOrListContext(context)));
575 break;
576 case BinASTKind::EagerFunctionExpression:
577 MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
578 start, FieldOrListContext(context)));
579 break;
580 case BinASTKind::IdentifierExpression:
581 MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
582 start, FieldOrListContext(context)));
583 break;
584 case BinASTKind::LazyArrowExpressionWithExpression:
585 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
586 start, FieldOrListContext(context)));
587 break;
588 case BinASTKind::LazyArrowExpressionWithFunctionBody:
589 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
590 start, FieldOrListContext(context)));
591 break;
592 case BinASTKind::LazyFunctionExpression:
593 MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
594 start, FieldOrListContext(context)));
595 break;
596 case BinASTKind::LiteralBooleanExpression:
597 MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
598 start, FieldOrListContext(context)));
599 break;
600 case BinASTKind::LiteralInfinityExpression:
601 MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
602 start, FieldOrListContext(context)));
603 break;
604 case BinASTKind::LiteralNullExpression:
605 MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
606 start, FieldOrListContext(context)));
607 break;
608 case BinASTKind::LiteralNumericExpression:
609 MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
610 start, FieldOrListContext(context)));
611 break;
612 case BinASTKind::LiteralRegExpExpression:
613 MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
614 start, FieldOrListContext(context)));
615 break;
616 case BinASTKind::LiteralStringExpression:
617 MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
618 start, FieldOrListContext(context)));
619 break;
620 case BinASTKind::NewExpression:
621 MOZ_TRY_VAR(result, parseInterfaceNewExpression(
622 start, FieldOrListContext(context)));
623 break;
624 case BinASTKind::NewTargetExpression:
625 MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(
626 start, FieldOrListContext(context)));
627 break;
628 case BinASTKind::ObjectExpression:
629 MOZ_TRY_VAR(result, parseInterfaceObjectExpression(
630 start, FieldOrListContext(context)));
631 break;
632 case BinASTKind::SpreadElement:
633 MOZ_TRY_VAR(result, parseInterfaceSpreadElement(start, context));
634 break;
635 case BinASTKind::StaticMemberExpression:
636 MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
637 start, FieldOrListContext(context)));
638 break;
639 case BinASTKind::TemplateExpression:
640 MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(
641 start, FieldOrListContext(context)));
642 break;
643 case BinASTKind::ThisExpression:
644 MOZ_TRY_VAR(result, parseInterfaceThisExpression(
645 start, FieldOrListContext(context)));
646 break;
647 case BinASTKind::UnaryExpression:
648 MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(
649 start, FieldOrListContext(context)));
650 break;
651 case BinASTKind::UpdateExpression:
652 MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(
653 start, FieldOrListContext(context)));
654 break;
655 case BinASTKind::YieldExpression:
656 MOZ_TRY_VAR(result, parseInterfaceYieldExpression(
657 start, FieldOrListContext(context)));
658 break;
659 case BinASTKind::YieldStarExpression:
660 MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(
661 start, FieldOrListContext(context)));
662 break;
663 default:
664 if (isInvalidKindPossible()) {
665 return raiseInvalidKind("ExpressionOrSpreadElement", kind);
666 } else {
667 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
668 "invalid BinASTKind should not appear");
669 }
670 }
671 return result;
672 }
673
674 /*
675 ExpressionOrSuper ::= ArrayExpression
676 AssignmentExpression
677 AwaitExpression
678 BinaryExpression
679 CallExpression
680 ClassExpression
681 CompoundAssignmentExpression
682 ComputedMemberExpression
683 ConditionalExpression
684 EagerArrowExpressionWithExpression
685 EagerArrowExpressionWithFunctionBody
686 EagerFunctionExpression
687 IdentifierExpression
688 LazyArrowExpressionWithExpression
689 LazyArrowExpressionWithFunctionBody
690 LazyFunctionExpression
691 LiteralBooleanExpression
692 LiteralInfinityExpression
693 LiteralNullExpression
694 LiteralNumericExpression
695 LiteralRegExpExpression
696 LiteralStringExpression
697 NewExpression
698 NewTargetExpression
699 ObjectExpression
700 StaticMemberExpression
701 Super
702 TemplateExpression
703 ThisExpression
704 UnaryExpression
705 UpdateExpression
706 YieldExpression
707 YieldStarExpression
708 */
709 template <typename Tok>
parseExpressionOrSuper(const FieldContext & context)710 JS::Result<ParseNode*> BinASTParser<Tok>::parseExpressionOrSuper(
711 const FieldContext& context) {
712 BinASTKind kind = BinASTKind::_Uninitialized;
713 AutoTaggedTuple guard(*tokenizer_);
714 const auto start = tokenizer_->offset();
715
716 guard.init();
717 MOZ_TRY(tokenizer_->enterSum(kind, context));
718
719 BINJS_MOZ_TRY_DECL(result, parseSumExpressionOrSuper(start, kind, context));
720
721 MOZ_TRY(guard.done());
722 return result;
723 }
724
725 template <typename Tok>
parseSumExpressionOrSuper(const size_t start,const BinASTKind kind,const FieldContext & context)726 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumExpressionOrSuper(
727 const size_t start, const BinASTKind kind, const FieldContext& context) {
728 ParseNode* result;
729 switch (kind) {
730 case BinASTKind::ArrayExpression:
731 MOZ_TRY_VAR(result, parseInterfaceArrayExpression(
732 start, FieldOrListContext(context)));
733 break;
734 case BinASTKind::AssignmentExpression:
735 MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
736 start, FieldOrListContext(context)));
737 break;
738 case BinASTKind::AwaitExpression:
739 MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(
740 start, FieldOrListContext(context)));
741 break;
742 case BinASTKind::BinaryExpression:
743 MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(
744 start, FieldOrListContext(context)));
745 break;
746 case BinASTKind::CallExpression:
747 MOZ_TRY_VAR(result, parseInterfaceCallExpression(
748 start, FieldOrListContext(context)));
749 break;
750 case BinASTKind::ClassExpression:
751 MOZ_TRY_VAR(result, parseInterfaceClassExpression(
752 start, FieldOrListContext(context)));
753 break;
754 case BinASTKind::CompoundAssignmentExpression:
755 MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
756 start, FieldOrListContext(context)));
757 break;
758 case BinASTKind::ComputedMemberExpression:
759 MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
760 start, FieldOrListContext(context)));
761 break;
762 case BinASTKind::ConditionalExpression:
763 MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
764 start, FieldOrListContext(context)));
765 break;
766 case BinASTKind::EagerArrowExpressionWithExpression:
767 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
768 start, FieldOrListContext(context)));
769 break;
770 case BinASTKind::EagerArrowExpressionWithFunctionBody:
771 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
772 start, FieldOrListContext(context)));
773 break;
774 case BinASTKind::EagerFunctionExpression:
775 MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
776 start, FieldOrListContext(context)));
777 break;
778 case BinASTKind::IdentifierExpression:
779 MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
780 start, FieldOrListContext(context)));
781 break;
782 case BinASTKind::LazyArrowExpressionWithExpression:
783 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
784 start, FieldOrListContext(context)));
785 break;
786 case BinASTKind::LazyArrowExpressionWithFunctionBody:
787 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
788 start, FieldOrListContext(context)));
789 break;
790 case BinASTKind::LazyFunctionExpression:
791 MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
792 start, FieldOrListContext(context)));
793 break;
794 case BinASTKind::LiteralBooleanExpression:
795 MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
796 start, FieldOrListContext(context)));
797 break;
798 case BinASTKind::LiteralInfinityExpression:
799 MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
800 start, FieldOrListContext(context)));
801 break;
802 case BinASTKind::LiteralNullExpression:
803 MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
804 start, FieldOrListContext(context)));
805 break;
806 case BinASTKind::LiteralNumericExpression:
807 MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
808 start, FieldOrListContext(context)));
809 break;
810 case BinASTKind::LiteralRegExpExpression:
811 MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
812 start, FieldOrListContext(context)));
813 break;
814 case BinASTKind::LiteralStringExpression:
815 MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
816 start, FieldOrListContext(context)));
817 break;
818 case BinASTKind::NewExpression:
819 MOZ_TRY_VAR(result, parseInterfaceNewExpression(
820 start, FieldOrListContext(context)));
821 break;
822 case BinASTKind::NewTargetExpression:
823 MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(
824 start, FieldOrListContext(context)));
825 break;
826 case BinASTKind::ObjectExpression:
827 MOZ_TRY_VAR(result, parseInterfaceObjectExpression(
828 start, FieldOrListContext(context)));
829 break;
830 case BinASTKind::StaticMemberExpression:
831 MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
832 start, FieldOrListContext(context)));
833 break;
834 case BinASTKind::Super:
835 MOZ_TRY_VAR(result, parseInterfaceSuper(start, context));
836 break;
837 case BinASTKind::TemplateExpression:
838 MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(
839 start, FieldOrListContext(context)));
840 break;
841 case BinASTKind::ThisExpression:
842 MOZ_TRY_VAR(result, parseInterfaceThisExpression(
843 start, FieldOrListContext(context)));
844 break;
845 case BinASTKind::UnaryExpression:
846 MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(
847 start, FieldOrListContext(context)));
848 break;
849 case BinASTKind::UpdateExpression:
850 MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(
851 start, FieldOrListContext(context)));
852 break;
853 case BinASTKind::YieldExpression:
854 MOZ_TRY_VAR(result, parseInterfaceYieldExpression(
855 start, FieldOrListContext(context)));
856 break;
857 case BinASTKind::YieldStarExpression:
858 MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(
859 start, FieldOrListContext(context)));
860 break;
861 default:
862 if (isInvalidKindPossible()) {
863 return raiseInvalidKind("ExpressionOrSuper", kind);
864 } else {
865 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
866 "invalid BinASTKind should not appear");
867 }
868 }
869 return result;
870 }
871
872 template <typename Tok>
873 JS::Result<ParseNode*>
parseSumExpressionOrVariableDeclaration(const size_t start,const BinASTKind kind,const FieldContext & context)874 BinASTParser<Tok>::parseSumExpressionOrVariableDeclaration(
875 const size_t start, const BinASTKind kind, const FieldContext& context) {
876 ParseNode* result;
877 switch (kind) {
878 case BinASTKind::ArrayExpression:
879 MOZ_TRY_VAR(result, parseInterfaceArrayExpression(
880 start, FieldOrListContext(context)));
881 break;
882 case BinASTKind::AssignmentExpression:
883 MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
884 start, FieldOrListContext(context)));
885 break;
886 case BinASTKind::AwaitExpression:
887 MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(
888 start, FieldOrListContext(context)));
889 break;
890 case BinASTKind::BinaryExpression:
891 MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(
892 start, FieldOrListContext(context)));
893 break;
894 case BinASTKind::CallExpression:
895 MOZ_TRY_VAR(result, parseInterfaceCallExpression(
896 start, FieldOrListContext(context)));
897 break;
898 case BinASTKind::ClassExpression:
899 MOZ_TRY_VAR(result, parseInterfaceClassExpression(
900 start, FieldOrListContext(context)));
901 break;
902 case BinASTKind::CompoundAssignmentExpression:
903 MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
904 start, FieldOrListContext(context)));
905 break;
906 case BinASTKind::ComputedMemberExpression:
907 MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
908 start, FieldOrListContext(context)));
909 break;
910 case BinASTKind::ConditionalExpression:
911 MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
912 start, FieldOrListContext(context)));
913 break;
914 case BinASTKind::EagerArrowExpressionWithExpression:
915 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
916 start, FieldOrListContext(context)));
917 break;
918 case BinASTKind::EagerArrowExpressionWithFunctionBody:
919 MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
920 start, FieldOrListContext(context)));
921 break;
922 case BinASTKind::EagerFunctionExpression:
923 MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
924 start, FieldOrListContext(context)));
925 break;
926 case BinASTKind::IdentifierExpression:
927 MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
928 start, FieldOrListContext(context)));
929 break;
930 case BinASTKind::LazyArrowExpressionWithExpression:
931 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
932 start, FieldOrListContext(context)));
933 break;
934 case BinASTKind::LazyArrowExpressionWithFunctionBody:
935 MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
936 start, FieldOrListContext(context)));
937 break;
938 case BinASTKind::LazyFunctionExpression:
939 MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
940 start, FieldOrListContext(context)));
941 break;
942 case BinASTKind::LiteralBooleanExpression:
943 MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
944 start, FieldOrListContext(context)));
945 break;
946 case BinASTKind::LiteralInfinityExpression:
947 MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
948 start, FieldOrListContext(context)));
949 break;
950 case BinASTKind::LiteralNullExpression:
951 MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
952 start, FieldOrListContext(context)));
953 break;
954 case BinASTKind::LiteralNumericExpression:
955 MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
956 start, FieldOrListContext(context)));
957 break;
958 case BinASTKind::LiteralRegExpExpression:
959 MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
960 start, FieldOrListContext(context)));
961 break;
962 case BinASTKind::LiteralStringExpression:
963 MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
964 start, FieldOrListContext(context)));
965 break;
966 case BinASTKind::NewExpression:
967 MOZ_TRY_VAR(result, parseInterfaceNewExpression(
968 start, FieldOrListContext(context)));
969 break;
970 case BinASTKind::NewTargetExpression:
971 MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(
972 start, FieldOrListContext(context)));
973 break;
974 case BinASTKind::ObjectExpression:
975 MOZ_TRY_VAR(result, parseInterfaceObjectExpression(
976 start, FieldOrListContext(context)));
977 break;
978 case BinASTKind::StaticMemberExpression:
979 MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
980 start, FieldOrListContext(context)));
981 break;
982 case BinASTKind::TemplateExpression:
983 MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(
984 start, FieldOrListContext(context)));
985 break;
986 case BinASTKind::ThisExpression:
987 MOZ_TRY_VAR(result, parseInterfaceThisExpression(
988 start, FieldOrListContext(context)));
989 break;
990 case BinASTKind::UnaryExpression:
991 MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(
992 start, FieldOrListContext(context)));
993 break;
994 case BinASTKind::UpdateExpression:
995 MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(
996 start, FieldOrListContext(context)));
997 break;
998 case BinASTKind::VariableDeclaration:
999 MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(
1000 start, FieldOrListContext(context)));
1001 break;
1002 case BinASTKind::YieldExpression:
1003 MOZ_TRY_VAR(result, parseInterfaceYieldExpression(
1004 start, FieldOrListContext(context)));
1005 break;
1006 case BinASTKind::YieldStarExpression:
1007 MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(
1008 start, FieldOrListContext(context)));
1009 break;
1010 default:
1011 if (isInvalidKindPossible()) {
1012 return raiseInvalidKind("ExpressionOrVariableDeclaration", kind);
1013 } else {
1014 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
1015 "invalid BinASTKind should not appear");
1016 }
1017 }
1018 return result;
1019 }
1020
1021 /*
1022 ObjectProperty ::= DataProperty
1023 EagerGetter
1024 EagerMethod
1025 EagerSetter
1026 LazyGetter
1027 LazyMethod
1028 LazySetter
1029 ShorthandProperty
1030 */
1031 template <typename Tok>
parseObjectProperty(const ListContext & context)1032 JS::Result<ParseNode*> BinASTParser<Tok>::parseObjectProperty(
1033 const ListContext& context) {
1034 BinASTKind kind = BinASTKind::_Uninitialized;
1035 AutoTaggedTuple guard(*tokenizer_);
1036 const auto start = tokenizer_->offset();
1037
1038 guard.init();
1039 MOZ_TRY(tokenizer_->enterSum(kind, context));
1040
1041 BINJS_MOZ_TRY_DECL(result, parseSumObjectProperty(start, kind, context));
1042
1043 MOZ_TRY(guard.done());
1044 return result;
1045 }
1046
1047 template <typename Tok>
parseSumObjectProperty(const size_t start,const BinASTKind kind,const ListContext & context)1048 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumObjectProperty(
1049 const size_t start, const BinASTKind kind, const ListContext& context) {
1050 ParseNode* result;
1051 switch (kind) {
1052 case BinASTKind::DataProperty:
1053 MOZ_TRY_VAR(result, parseInterfaceDataProperty(start, context));
1054 break;
1055 case BinASTKind::EagerGetter:
1056 MOZ_TRY_VAR(result, parseInterfaceEagerGetter(start, context));
1057 break;
1058 case BinASTKind::EagerMethod:
1059 MOZ_TRY_VAR(result, parseInterfaceEagerMethod(start, context));
1060 break;
1061 case BinASTKind::EagerSetter:
1062 MOZ_TRY_VAR(result, parseInterfaceEagerSetter(start, context));
1063 break;
1064 case BinASTKind::LazyGetter:
1065 MOZ_TRY_VAR(result, parseInterfaceLazyGetter(start, context));
1066 break;
1067 case BinASTKind::LazyMethod:
1068 MOZ_TRY_VAR(result, parseInterfaceLazyMethod(start, context));
1069 break;
1070 case BinASTKind::LazySetter:
1071 MOZ_TRY_VAR(result, parseInterfaceLazySetter(start, context));
1072 break;
1073 case BinASTKind::ShorthandProperty:
1074 MOZ_TRY_VAR(result, parseInterfaceShorthandProperty(start, context));
1075 break;
1076 default:
1077 if (isInvalidKindPossible()) {
1078 return raiseInvalidKind("ObjectProperty", kind);
1079 } else {
1080 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
1081 "invalid BinASTKind should not appear");
1082 }
1083 }
1084 return result;
1085 }
1086
1087 /*
1088 Parameter ::= ArrayBinding
1089 BindingIdentifier
1090 BindingWithInitializer
1091 ObjectBinding
1092 */
1093 template <typename Tok>
parseParameter(const FieldOrListContext & context)1094 JS::Result<ParseNode*> BinASTParser<Tok>::parseParameter(
1095 const FieldOrListContext& context) {
1096 BinASTKind kind = BinASTKind::_Uninitialized;
1097 AutoTaggedTuple guard(*tokenizer_);
1098 const auto start = tokenizer_->offset();
1099
1100 guard.init();
1101 MOZ_TRY(tokenizer_->enterSum(kind, context));
1102
1103 BINJS_MOZ_TRY_DECL(result, parseSumParameter(start, kind, context));
1104
1105 MOZ_TRY(guard.done());
1106 return result;
1107 }
1108
1109 template <typename Tok>
parseSumParameter(const size_t start,const BinASTKind kind,const FieldOrListContext & context)1110 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumParameter(
1111 const size_t start, const BinASTKind kind,
1112 const FieldOrListContext& context) {
1113 ParseNode* result;
1114 switch (kind) {
1115 case BinASTKind::ArrayBinding:
1116 MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, context));
1117 break;
1118 case BinASTKind::BindingIdentifier:
1119 MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, context));
1120 if (!pc_->positionalFormalParameterNames().append(
1121 result->template as<NameNode>().atom())) {
1122 return raiseOOM();
1123 }
1124 if (pc_->isFunctionBox()) {
1125 pc_->functionBox()->length++;
1126 }
1127 break;
1128 case BinASTKind::BindingWithInitializer:
1129 MOZ_TRY_VAR(result, parseInterfaceBindingWithInitializer(start, context));
1130 break;
1131 case BinASTKind::ObjectBinding:
1132 MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, context));
1133 break;
1134 default:
1135 if (isInvalidKindPossible()) {
1136 return raiseInvalidKind("Parameter", kind);
1137 } else {
1138 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
1139 "invalid BinASTKind should not appear");
1140 }
1141 }
1142 return result;
1143 }
1144
1145 /*
1146 Program ::= Module
1147 Script
1148 */
1149 template <typename Tok>
parseProgram(const RootContext & context)1150 JS::Result<ParseNode*> BinASTParser<Tok>::parseProgram(
1151 const RootContext& context) {
1152 BinASTKind kind = BinASTKind::_Uninitialized;
1153 AutoTaggedTuple guard(*tokenizer_);
1154 const auto start = tokenizer_->offset();
1155
1156 guard.init();
1157 MOZ_TRY(tokenizer_->enterSum(kind, context));
1158
1159 BINJS_MOZ_TRY_DECL(result, parseSumProgram(start, kind, context));
1160
1161 MOZ_TRY(guard.done());
1162 return result;
1163 }
1164
1165 template <typename Tok>
parseSumProgram(const size_t start,const BinASTKind kind,const RootContext & context)1166 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumProgram(
1167 const size_t start, const BinASTKind kind, const RootContext& context) {
1168 ParseNode* result;
1169 switch (kind) {
1170 case BinASTKind::Module:
1171 MOZ_TRY_VAR(result, parseInterfaceModule(start, context));
1172 break;
1173 case BinASTKind::Script:
1174 MOZ_TRY_VAR(result, parseInterfaceScript(start, context));
1175 break;
1176 default:
1177 if (isInvalidKindPossible()) {
1178 return raiseInvalidKind("Program", kind);
1179 } else {
1180 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
1181 "invalid BinASTKind should not appear");
1182 }
1183 }
1184 return result;
1185 }
1186
1187 /*
1188 PropertyName ::= ComputedPropertyName
1189 LiteralPropertyName
1190 */
1191 template <typename Tok>
parsePropertyName(const FieldContext & context)1192 JS::Result<ParseNode*> BinASTParser<Tok>::parsePropertyName(
1193 const FieldContext& context) {
1194 BinASTKind kind = BinASTKind::_Uninitialized;
1195 AutoTaggedTuple guard(*tokenizer_);
1196 const auto start = tokenizer_->offset();
1197
1198 guard.init();
1199 MOZ_TRY(tokenizer_->enterSum(kind, context));
1200
1201 BINJS_MOZ_TRY_DECL(result, parseSumPropertyName(start, kind, context));
1202
1203 MOZ_TRY(guard.done());
1204 return result;
1205 }
1206
1207 template <typename Tok>
parseSumPropertyName(const size_t start,const BinASTKind kind,const FieldContext & context)1208 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumPropertyName(
1209 const size_t start, const BinASTKind kind, const FieldContext& context) {
1210 ParseNode* result;
1211 switch (kind) {
1212 case BinASTKind::ComputedPropertyName:
1213 MOZ_TRY_VAR(result, parseInterfaceComputedPropertyName(start, context));
1214 break;
1215 case BinASTKind::LiteralPropertyName:
1216 MOZ_TRY_VAR(result, parseInterfaceLiteralPropertyName(start, context));
1217 break;
1218 default:
1219 if (isInvalidKindPossible()) {
1220 return raiseInvalidKind("PropertyName", kind);
1221 } else {
1222 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
1223 "invalid BinASTKind should not appear");
1224 }
1225 }
1226 return result;
1227 }
1228
1229 /*
1230 SimpleAssignmentTarget ::= AssignmentTargetIdentifier
1231 ComputedMemberAssignmentTarget
1232 StaticMemberAssignmentTarget
1233 */
1234 template <typename Tok>
parseSimpleAssignmentTarget(const FieldContext & context)1235 JS::Result<ParseNode*> BinASTParser<Tok>::parseSimpleAssignmentTarget(
1236 const FieldContext& context) {
1237 BinASTKind kind = BinASTKind::_Uninitialized;
1238 AutoTaggedTuple guard(*tokenizer_);
1239 const auto start = tokenizer_->offset();
1240
1241 guard.init();
1242 MOZ_TRY(tokenizer_->enterSum(kind, context));
1243
1244 BINJS_MOZ_TRY_DECL(result,
1245 parseSumSimpleAssignmentTarget(start, kind, context));
1246
1247 MOZ_TRY(guard.done());
1248 return result;
1249 }
1250
1251 template <typename Tok>
parseSumSimpleAssignmentTarget(const size_t start,const BinASTKind kind,const FieldContext & context)1252 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumSimpleAssignmentTarget(
1253 const size_t start, const BinASTKind kind, const FieldContext& context) {
1254 ParseNode* result;
1255 switch (kind) {
1256 case BinASTKind::AssignmentTargetIdentifier:
1257 MOZ_TRY_VAR(result,
1258 parseInterfaceAssignmentTargetIdentifier(start, context));
1259 break;
1260 case BinASTKind::ComputedMemberAssignmentTarget:
1261 MOZ_TRY_VAR(result,
1262 parseInterfaceComputedMemberAssignmentTarget(start, context));
1263 break;
1264 case BinASTKind::StaticMemberAssignmentTarget:
1265 MOZ_TRY_VAR(result,
1266 parseInterfaceStaticMemberAssignmentTarget(start, context));
1267 break;
1268 default:
1269 if (isInvalidKindPossible()) {
1270 return raiseInvalidKind("SimpleAssignmentTarget", kind);
1271 } else {
1272 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
1273 "invalid BinASTKind should not appear");
1274 }
1275 }
1276 return result;
1277 }
1278
1279 /*
1280 Statement ::= Block
1281 BreakStatement
1282 ClassDeclaration
1283 ContinueStatement
1284 DebuggerStatement
1285 DoWhileStatement
1286 EagerFunctionDeclaration
1287 EmptyStatement
1288 ExpressionStatement
1289 ForInStatement
1290 ForOfStatement
1291 ForStatement
1292 IfStatement
1293 LabelledStatement
1294 LazyFunctionDeclaration
1295 ReturnStatement
1296 SwitchStatement
1297 SwitchStatementWithDefault
1298 ThrowStatement
1299 TryCatchStatement
1300 TryFinallyStatement
1301 VariableDeclaration
1302 WhileStatement
1303 WithStatement
1304 */
1305 template <typename Tok>
parseStatement(const FieldOrListContext & context)1306 JS::Result<ParseNode*> BinASTParser<Tok>::parseStatement(
1307 const FieldOrListContext& context) {
1308 BinASTKind kind = BinASTKind::_Uninitialized;
1309 AutoTaggedTuple guard(*tokenizer_);
1310 const auto start = tokenizer_->offset();
1311
1312 guard.init();
1313 MOZ_TRY(tokenizer_->enterSum(kind, context));
1314
1315 BINJS_MOZ_TRY_DECL(result, parseSumStatement(start, kind, context));
1316
1317 MOZ_TRY(guard.done());
1318 return result;
1319 }
1320
1321 template <typename Tok>
parseSumStatement(const size_t start,const BinASTKind kind,const FieldOrListContext & context)1322 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumStatement(
1323 const size_t start, const BinASTKind kind,
1324 const FieldOrListContext& context) {
1325 ParseNode* result;
1326 switch (kind) {
1327 case BinASTKind::Block:
1328 MOZ_TRY_VAR(result, parseInterfaceBlock(start, context));
1329 break;
1330 case BinASTKind::BreakStatement:
1331 MOZ_TRY_VAR(result, parseInterfaceBreakStatement(start, context));
1332 break;
1333 case BinASTKind::ClassDeclaration:
1334 MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, context));
1335 break;
1336 case BinASTKind::ContinueStatement:
1337 MOZ_TRY_VAR(result, parseInterfaceContinueStatement(start, context));
1338 break;
1339 case BinASTKind::DebuggerStatement:
1340 MOZ_TRY_VAR(result, parseInterfaceDebuggerStatement(start, context));
1341 break;
1342 case BinASTKind::DoWhileStatement:
1343 MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, context));
1344 break;
1345 case BinASTKind::EagerFunctionDeclaration:
1346 MOZ_TRY_VAR(result,
1347 parseInterfaceEagerFunctionDeclaration(start, context));
1348 break;
1349 case BinASTKind::EmptyStatement:
1350 MOZ_TRY_VAR(result, parseInterfaceEmptyStatement(start, context));
1351 break;
1352 case BinASTKind::ExpressionStatement:
1353 MOZ_TRY_VAR(result, parseInterfaceExpressionStatement(start, context));
1354 break;
1355 case BinASTKind::ForInStatement:
1356 MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, context));
1357 break;
1358 case BinASTKind::ForOfStatement:
1359 MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, context));
1360 break;
1361 case BinASTKind::ForStatement:
1362 MOZ_TRY_VAR(result, parseInterfaceForStatement(start, context));
1363 break;
1364 case BinASTKind::IfStatement:
1365 MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, context));
1366 break;
1367 case BinASTKind::LabelledStatement:
1368 MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, context));
1369 break;
1370 case BinASTKind::LazyFunctionDeclaration:
1371 MOZ_TRY_VAR(result,
1372 parseInterfaceLazyFunctionDeclaration(start, context));
1373 break;
1374 case BinASTKind::ReturnStatement:
1375 MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, context));
1376 break;
1377 case BinASTKind::SwitchStatement:
1378 MOZ_TRY_VAR(result, parseInterfaceSwitchStatement(start, context));
1379 break;
1380 case BinASTKind::SwitchStatementWithDefault:
1381 MOZ_TRY_VAR(result,
1382 parseInterfaceSwitchStatementWithDefault(start, context));
1383 break;
1384 case BinASTKind::ThrowStatement:
1385 MOZ_TRY_VAR(result, parseInterfaceThrowStatement(start, context));
1386 break;
1387 case BinASTKind::TryCatchStatement:
1388 MOZ_TRY_VAR(result, parseInterfaceTryCatchStatement(start, context));
1389 break;
1390 case BinASTKind::TryFinallyStatement:
1391 MOZ_TRY_VAR(result, parseInterfaceTryFinallyStatement(start, context));
1392 break;
1393 case BinASTKind::VariableDeclaration:
1394 MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, context));
1395 break;
1396 case BinASTKind::WhileStatement:
1397 MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, context));
1398 break;
1399 case BinASTKind::WithStatement:
1400 MOZ_TRY_VAR(result, parseInterfaceWithStatement(start, context));
1401 break;
1402 default:
1403 if (isInvalidKindPossible()) {
1404 return raiseInvalidKind("Statement", kind);
1405 } else {
1406 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
1407 "invalid BinASTKind should not appear");
1408 }
1409 }
1410 return result;
1411 }
1412
1413 // ----- Interfaces (autogenerated, by lexicographical order)
1414 // When fields have a non-trivial type, implementation is deanonymized and
1415 // delegated to another parser.
1416 template <typename Tok>
parseInterfaceArrayAssignmentTarget(const size_t start,const FieldContext & context)1417 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceArrayAssignmentTarget(
1418 const size_t start, const FieldContext& context) {
1419 return raiseError(
1420 "FIXME: Not implemented yet in this preview release "
1421 "(ArrayAssignmentTarget)");
1422 }
1423
1424 template <typename Tok>
parseInterfaceArrayBinding(const size_t start,const FieldOrListContext & context)1425 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceArrayBinding(
1426 const size_t start, const FieldOrListContext& context) {
1427 return raiseError(
1428 "FIXME: Not implemented yet in this preview release (ArrayBinding)");
1429 }
1430
1431 template <typename Tok>
parseInterfaceArrayExpression(const size_t start,const FieldOrListContext & context)1432 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceArrayExpression(
1433 const size_t start, const FieldOrListContext& context) {
1434 BINJS_TRY(CheckRecursionLimit(cx_));
1435
1436 BINJS_MOZ_TRY_DECL(elements,
1437 parseListOfOptionalExpressionOrSpreadElement(FieldContext(
1438 BinASTInterfaceAndField::ArrayExpression__Elements)));
1439
1440 if (elements->empty()) {
1441 elements->setHasNonConstInitializer();
1442 }
1443 auto result = elements;
1444 return result;
1445 }
1446
1447 /*
1448 interface AssertedBlockScope : Node {
1449 FrozenArray<AssertedDeclaredName> declaredNames;
1450 bool hasDirectEval;
1451 }
1452 */
1453 template <typename Tok>
parseAssertedBlockScope(const FieldContext & context)1454 JS::Result<Ok> BinASTParser<Tok>::parseAssertedBlockScope(
1455 const FieldContext& context) {
1456 BinASTKind kind = BinASTKind::AssertedBlockScope;
1457 AutoTaggedTuple guard(*tokenizer_);
1458
1459 guard.init();
1460 MOZ_TRY(tokenizer_->enterInterface(kind, context));
1461 const auto start = tokenizer_->offset();
1462 BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBlockScope(start, context));
1463 MOZ_TRY(guard.done());
1464
1465 return result;
1466 }
1467
1468 template <typename Tok>
parseInterfaceAssertedBlockScope(const size_t start,const FieldContext & context)1469 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedBlockScope(
1470 const size_t start, const FieldContext& context) {
1471 BINJS_TRY(CheckRecursionLimit(cx_));
1472 const auto scopeKind = AssertedScopeKind::Block;
1473
1474 MOZ_TRY(parseListOfAssertedDeclaredName(
1475 scopeKind,
1476 FieldContext(
1477 BinASTInterfaceAndField::AssertedBlockScope__DeclaredNames)));
1478
1479 BINJS_MOZ_TRY_DECL(
1480 hasDirectEval,
1481 tokenizer_->readBool(FieldContext(
1482 BinASTInterfaceAndField::AssertedBlockScope__HasDirectEval)));
1483 if (hasDirectEval) {
1484 pc_->sc()->setHasDirectEval();
1485 pc_->sc()->setBindingsAccessedDynamically();
1486 }
1487 if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
1488 // In non-strict mode code, direct calls to eval can
1489 // add variables to the call object.
1490 pc_->functionBox()->setFunHasExtensibleScope();
1491 }
1492 auto result = Ok();
1493 return result;
1494 }
1495
1496 /*
1497 interface AssertedBoundName : Node {
1498 [IdentifierName] string name;
1499 bool isCaptured;
1500 }
1501 */
1502 template <typename Tok>
parseAssertedBoundName(AssertedScopeKind scopeKind,const ListContext & context)1503 JS::Result<Ok> BinASTParser<Tok>::parseAssertedBoundName(
1504 AssertedScopeKind scopeKind, const ListContext& context) {
1505 BinASTKind kind = BinASTKind::AssertedBoundName;
1506 AutoTaggedTuple guard(*tokenizer_);
1507
1508 guard.init();
1509 MOZ_TRY(tokenizer_->enterInterface(kind, context));
1510 const auto start = tokenizer_->offset();
1511 BINJS_MOZ_TRY_DECL(
1512 result, parseInterfaceAssertedBoundName(start, scopeKind, context));
1513 MOZ_TRY(guard.done());
1514
1515 return result;
1516 }
1517
1518 template <typename Tok>
parseInterfaceAssertedBoundName(const size_t start,AssertedScopeKind scopeKind,const ListContext & context)1519 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedBoundName(
1520 const size_t start, AssertedScopeKind scopeKind,
1521 const ListContext& context) {
1522 BINJS_TRY(CheckRecursionLimit(cx_));
1523 const bool allowDuplicateName = false;
1524
1525 RootedAtom name(cx_);
1526 MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(FieldContext(
1527 BinASTInterfaceAndField::AssertedBoundName__Name)));
1528
1529 BINJS_MOZ_TRY_DECL(
1530 isCaptured, tokenizer_->readBool(FieldContext(
1531 BinASTInterfaceAndField::AssertedBoundName__IsCaptured)));
1532 ParseContext::Scope* scope;
1533 DeclarationKind declKind;
1534 MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
1535 MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured,
1536 allowDuplicateName));
1537 auto result = Ok();
1538 return result;
1539 }
1540
1541 /*
1542 interface AssertedBoundNamesScope : Node {
1543 FrozenArray<AssertedBoundName> boundNames;
1544 bool hasDirectEval;
1545 }
1546 */
1547 template <typename Tok>
parseAssertedBoundNamesScope(const FieldContext & context)1548 JS::Result<Ok> BinASTParser<Tok>::parseAssertedBoundNamesScope(
1549 const FieldContext& context) {
1550 BinASTKind kind = BinASTKind::AssertedBoundNamesScope;
1551 AutoTaggedTuple guard(*tokenizer_);
1552
1553 guard.init();
1554 MOZ_TRY(tokenizer_->enterInterface(kind, context));
1555 const auto start = tokenizer_->offset();
1556 BINJS_MOZ_TRY_DECL(result,
1557 parseInterfaceAssertedBoundNamesScope(start, context));
1558 MOZ_TRY(guard.done());
1559
1560 return result;
1561 }
1562
1563 template <typename Tok>
parseInterfaceAssertedBoundNamesScope(const size_t start,const FieldContext & context)1564 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedBoundNamesScope(
1565 const size_t start, const FieldContext& context) {
1566 BINJS_TRY(CheckRecursionLimit(cx_));
1567 const auto scopeKind = AssertedScopeKind::Catch;
1568
1569 MOZ_TRY(parseListOfAssertedBoundName(
1570 scopeKind,
1571 FieldContext(
1572 BinASTInterfaceAndField::AssertedBoundNamesScope__BoundNames)));
1573
1574 BINJS_MOZ_TRY_DECL(
1575 hasDirectEval,
1576 tokenizer_->readBool(FieldContext(
1577 BinASTInterfaceAndField::AssertedBoundNamesScope__HasDirectEval)));
1578 if (hasDirectEval) {
1579 pc_->sc()->setHasDirectEval();
1580 pc_->sc()->setBindingsAccessedDynamically();
1581 }
1582 if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
1583 // In non-strict mode code, direct calls to eval can
1584 // add variables to the call object.
1585 pc_->functionBox()->setFunHasExtensibleScope();
1586 }
1587 auto result = Ok();
1588 return result;
1589 }
1590
1591 /*
1592 interface AssertedDeclaredName : Node {
1593 [IdentifierName] string name;
1594 AssertedDeclaredKind kind;
1595 bool isCaptured;
1596 }
1597 */
1598 template <typename Tok>
parseAssertedDeclaredName(AssertedScopeKind scopeKind,const ListContext & context)1599 JS::Result<Ok> BinASTParser<Tok>::parseAssertedDeclaredName(
1600 AssertedScopeKind scopeKind, const ListContext& context) {
1601 BinASTKind kind = BinASTKind::AssertedDeclaredName;
1602 AutoTaggedTuple guard(*tokenizer_);
1603
1604 guard.init();
1605 MOZ_TRY(tokenizer_->enterInterface(kind, context));
1606 const auto start = tokenizer_->offset();
1607 BINJS_MOZ_TRY_DECL(
1608 result, parseInterfaceAssertedDeclaredName(start, scopeKind, context));
1609 MOZ_TRY(guard.done());
1610
1611 return result;
1612 }
1613
1614 template <typename Tok>
parseInterfaceAssertedDeclaredName(const size_t start,AssertedScopeKind scopeKind,const ListContext & context)1615 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedDeclaredName(
1616 const size_t start, AssertedScopeKind scopeKind,
1617 const ListContext& context) {
1618 BINJS_TRY(CheckRecursionLimit(cx_));
1619 const bool allowDuplicateName = false;
1620
1621 RootedAtom name(cx_);
1622 MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(FieldContext(
1623 BinASTInterfaceAndField::AssertedDeclaredName__Name)));
1624
1625 BINJS_MOZ_TRY_DECL(kind_,
1626 parseAssertedDeclaredKind(FieldContext(
1627 BinASTInterfaceAndField::AssertedDeclaredName__Kind)));
1628 if (kind_ == AssertedDeclaredKind::NonConstLexical) {
1629 return raiseError("Let is not supported in this preview release");
1630 }
1631 if (kind_ == AssertedDeclaredKind::ConstLexical) {
1632 return raiseError("Const is not supported in this preview release");
1633 }
1634 BINJS_MOZ_TRY_DECL(
1635 isCaptured,
1636 tokenizer_->readBool(FieldContext(
1637 BinASTInterfaceAndField::AssertedDeclaredName__IsCaptured)));
1638 ParseContext::Scope* scope;
1639 DeclarationKind declKind;
1640 MOZ_TRY(getDeclaredScope(scopeKind, kind_, scope, declKind));
1641 MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured,
1642 allowDuplicateName));
1643 auto result = Ok();
1644 return result;
1645 }
1646
1647 /*
1648 interface AssertedParameterScope : Node {
1649 FrozenArray<AssertedMaybePositionalParameterName> paramNames;
1650 bool hasDirectEval;
1651 bool isSimpleParameterList;
1652 }
1653 */
1654 template <typename Tok>
parseAssertedParameterScope(MutableHandle<GCVector<JSAtom * >> positionalParams,const FieldContext & context)1655 JS::Result<Ok> BinASTParser<Tok>::parseAssertedParameterScope(
1656 MutableHandle<GCVector<JSAtom*>> positionalParams,
1657 const FieldContext& context) {
1658 BinASTKind kind = BinASTKind::AssertedParameterScope;
1659 AutoTaggedTuple guard(*tokenizer_);
1660
1661 guard.init();
1662 MOZ_TRY(tokenizer_->enterInterface(kind, context));
1663 const auto start = tokenizer_->offset();
1664 BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedParameterScope(
1665 start, positionalParams, context));
1666 MOZ_TRY(guard.done());
1667
1668 return result;
1669 }
1670
1671 template <typename Tok>
parseInterfaceAssertedParameterScope(const size_t start,MutableHandle<GCVector<JSAtom * >> positionalParams,const FieldContext & context)1672 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedParameterScope(
1673 const size_t start, MutableHandle<GCVector<JSAtom*>> positionalParams,
1674 const FieldContext& context) {
1675 BINJS_TRY(CheckRecursionLimit(cx_));
1676 const auto scopeKind = AssertedScopeKind::Parameter;
1677
1678 MOZ_TRY(parseListOfAssertedMaybePositionalParameterName(
1679 scopeKind, positionalParams,
1680 FieldContext(
1681 BinASTInterfaceAndField::AssertedParameterScope__ParamNames)));
1682
1683 BINJS_MOZ_TRY_DECL(
1684 hasDirectEval,
1685 tokenizer_->readBool(FieldContext(
1686 BinASTInterfaceAndField::AssertedParameterScope__HasDirectEval)));
1687 if (hasDirectEval) {
1688 pc_->sc()->setHasDirectEval();
1689 pc_->sc()->setBindingsAccessedDynamically();
1690 }
1691 BINJS_MOZ_TRY_DECL(isSimpleParameterList,
1692 tokenizer_->readBool(FieldContext(
1693 BinASTInterfaceAndField::
1694 AssertedParameterScope__IsSimpleParameterList)));
1695 (void)isSimpleParameterList;
1696 if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
1697 // In non-strict mode code, direct calls to eval can
1698 // add variables to the call object.
1699 pc_->functionBox()->setFunHasExtensibleScope();
1700 }
1701 auto result = Ok();
1702 return result;
1703 }
1704
1705 template <typename Tok>
parseInterfaceAssertedPositionalParameterName(const size_t start,AssertedScopeKind scopeKind,MutableHandle<GCVector<JSAtom * >> positionalParams,const ListContext & context)1706 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedPositionalParameterName(
1707 const size_t start, AssertedScopeKind scopeKind,
1708 MutableHandle<GCVector<JSAtom*>> positionalParams,
1709 const ListContext& context) {
1710 BINJS_TRY(CheckRecursionLimit(cx_));
1711 bool allowDuplicateName = !pc_->sc()->strict();
1712
1713 BINJS_MOZ_TRY_DECL(
1714 index,
1715 tokenizer_->readUnsignedLong(FieldContext(
1716 BinASTInterfaceAndField::AssertedPositionalParameterName__Index)));
1717
1718 RootedAtom name(cx_);
1719 MOZ_TRY_VAR(
1720 name,
1721 tokenizer_->readIdentifierName(FieldContext(
1722 BinASTInterfaceAndField::AssertedPositionalParameterName__Name)));
1723 // `positionalParams` vector can be shorter than the actual
1724 // parameter length. Resize on demand.
1725 // (see also ListOfAssertedMaybePositionalParameterName)
1726 size_t prevLength = positionalParams.get().length();
1727 if (index >= prevLength) {
1728 // This is implementation limit, which is not in the spec.
1729 if (index >= ARGNO_LIMIT - 1) {
1730 return raiseError("AssertedPositionalParameterName.index is too big");
1731 }
1732 size_t newLength = index + 1;
1733 BINJS_TRY(positionalParams.get().resize(newLength));
1734 for (uint32_t i = prevLength; i < newLength; i++) {
1735 positionalParams.get()[i] = nullptr;
1736 }
1737 }
1738
1739 if (positionalParams.get()[index]) {
1740 return raiseError(
1741 "AssertedPositionalParameterName has duplicate entry for the same "
1742 "index");
1743 }
1744 positionalParams.get()[index] = name;
1745 BINJS_MOZ_TRY_DECL(isCaptured,
1746 tokenizer_->readBool(FieldContext(
1747 BinASTInterfaceAndField::
1748 AssertedPositionalParameterName__IsCaptured)));
1749 ParseContext::Scope* scope;
1750 DeclarationKind declKind;
1751 MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
1752 MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured,
1753 allowDuplicateName));
1754 auto result = Ok();
1755 return result;
1756 }
1757
1758 /*
1759 interface AssertedScriptGlobalScope : Node {
1760 FrozenArray<AssertedDeclaredName> declaredNames;
1761 bool hasDirectEval;
1762 }
1763 */
1764 template <typename Tok>
parseAssertedScriptGlobalScope(const FieldContext & context)1765 JS::Result<Ok> BinASTParser<Tok>::parseAssertedScriptGlobalScope(
1766 const FieldContext& context) {
1767 BinASTKind kind = BinASTKind::AssertedScriptGlobalScope;
1768 AutoTaggedTuple guard(*tokenizer_);
1769
1770 guard.init();
1771 MOZ_TRY(tokenizer_->enterInterface(kind, context));
1772 const auto start = tokenizer_->offset();
1773 BINJS_MOZ_TRY_DECL(result,
1774 parseInterfaceAssertedScriptGlobalScope(start, context));
1775 MOZ_TRY(guard.done());
1776
1777 return result;
1778 }
1779
1780 template <typename Tok>
parseInterfaceAssertedScriptGlobalScope(const size_t start,const FieldContext & context)1781 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedScriptGlobalScope(
1782 const size_t start, const FieldContext& context) {
1783 BINJS_TRY(CheckRecursionLimit(cx_));
1784 const auto scopeKind = AssertedScopeKind::Global;
1785
1786 MOZ_TRY(parseListOfAssertedDeclaredName(
1787 scopeKind,
1788 FieldContext(
1789 BinASTInterfaceAndField::AssertedScriptGlobalScope__DeclaredNames)));
1790
1791 BINJS_MOZ_TRY_DECL(
1792 hasDirectEval,
1793 tokenizer_->readBool(FieldContext(
1794 BinASTInterfaceAndField::AssertedScriptGlobalScope__HasDirectEval)));
1795 if (hasDirectEval) {
1796 pc_->sc()->setHasDirectEval();
1797 pc_->sc()->setBindingsAccessedDynamically();
1798 }
1799 if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
1800 // In non-strict mode code, direct calls to eval can
1801 // add variables to the call object.
1802 pc_->functionBox()->setFunHasExtensibleScope();
1803 }
1804 auto result = Ok();
1805 return result;
1806 }
1807
1808 /*
1809 interface AssertedVarScope : Node {
1810 FrozenArray<AssertedDeclaredName> declaredNames;
1811 bool hasDirectEval;
1812 }
1813 */
1814 template <typename Tok>
parseAssertedVarScope(const FieldContext & context)1815 JS::Result<Ok> BinASTParser<Tok>::parseAssertedVarScope(
1816 const FieldContext& context) {
1817 BinASTKind kind = BinASTKind::AssertedVarScope;
1818 AutoTaggedTuple guard(*tokenizer_);
1819
1820 guard.init();
1821 MOZ_TRY(tokenizer_->enterInterface(kind, context));
1822 const auto start = tokenizer_->offset();
1823 BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedVarScope(start, context));
1824 MOZ_TRY(guard.done());
1825
1826 return result;
1827 }
1828
1829 template <typename Tok>
parseInterfaceAssertedVarScope(const size_t start,const FieldContext & context)1830 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedVarScope(
1831 const size_t start, const FieldContext& context) {
1832 BINJS_TRY(CheckRecursionLimit(cx_));
1833 const auto scopeKind = AssertedScopeKind::Var;
1834
1835 MOZ_TRY(parseListOfAssertedDeclaredName(
1836 scopeKind,
1837 FieldContext(BinASTInterfaceAndField::AssertedVarScope__DeclaredNames)));
1838
1839 BINJS_MOZ_TRY_DECL(
1840 hasDirectEval,
1841 tokenizer_->readBool(FieldContext(
1842 BinASTInterfaceAndField::AssertedVarScope__HasDirectEval)));
1843 if (hasDirectEval) {
1844 pc_->sc()->setHasDirectEval();
1845 pc_->sc()->setBindingsAccessedDynamically();
1846 }
1847 if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
1848 // In non-strict mode code, direct calls to eval can
1849 // add variables to the call object.
1850 pc_->functionBox()->setFunHasExtensibleScope();
1851 }
1852 auto result = Ok();
1853 return result;
1854 }
1855
1856 template <typename Tok>
parseInterfaceAssignmentExpression(const size_t start,const FieldOrListContext & context)1857 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAssignmentExpression(
1858 const size_t start, const FieldOrListContext& context) {
1859 BINJS_TRY(CheckRecursionLimit(cx_));
1860
1861 BINJS_MOZ_TRY_DECL(
1862 binding, parseAssignmentTarget(FieldContext(
1863 BinASTInterfaceAndField::AssignmentExpression__Binding)));
1864
1865 BINJS_MOZ_TRY_DECL(
1866 expression,
1867 parseExpression(FieldContext(
1868 BinASTInterfaceAndField::AssignmentExpression__Expression)));
1869
1870 BINJS_TRY_DECL(result, handler_.newAssignment(ParseNodeKind::AssignExpr,
1871 binding, expression));
1872 return result;
1873 }
1874
1875 template <typename Tok>
1876 JS::Result<ParseNode*>
parseInterfaceAssignmentTargetIdentifier(const size_t start,const FieldContext & context)1877 BinASTParser<Tok>::parseInterfaceAssignmentTargetIdentifier(
1878 const size_t start, const FieldContext& context) {
1879 BINJS_TRY(CheckRecursionLimit(cx_));
1880
1881 RootedAtom name(cx_);
1882 MOZ_TRY_VAR(name,
1883 tokenizer_->readIdentifierName(FieldContext(
1884 BinASTInterfaceAndField::AssignmentTargetIdentifier__Name)));
1885
1886 BINJS_TRY(usedNames_.noteUse(cx_, name, pc_->scriptId(),
1887 pc_->innermostScope()->id()));
1888 BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
1889 tokenizer_->pos(start), cx_));
1890 return result;
1891 }
1892
1893 template <typename Tok>
parseInterfaceAwaitExpression(const size_t start,const FieldOrListContext & context)1894 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAwaitExpression(
1895 const size_t start, const FieldOrListContext& context) {
1896 return raiseError(
1897 "FIXME: Not implemented yet in this preview release (AwaitExpression)");
1898 }
1899
1900 template <typename Tok>
parseInterfaceBinaryExpression(const size_t start,const FieldOrListContext & context)1901 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBinaryExpression(
1902 const size_t start, const FieldOrListContext& context) {
1903 BINJS_TRY(CheckRecursionLimit(cx_));
1904
1905 BINJS_MOZ_TRY_DECL(operator_,
1906 parseBinaryOperator(FieldContext(
1907 BinASTInterfaceAndField::BinaryExpression__Operator)));
1908
1909 BINJS_MOZ_TRY_DECL(
1910 left, parseExpression(
1911 FieldContext(BinASTInterfaceAndField::BinaryExpression__Left)));
1912
1913 BINJS_MOZ_TRY_DECL(right,
1914 parseExpression(FieldContext(
1915 BinASTInterfaceAndField::BinaryExpression__Right)));
1916
1917 ParseNodeKind pnk;
1918 switch (operator_) {
1919 case BinaryOperator::Comma:
1920 pnk = ParseNodeKind::CommaExpr;
1921 break;
1922 case BinaryOperator::LogicalOr:
1923 pnk = ParseNodeKind::OrExpr;
1924 break;
1925 case BinaryOperator::LogicalAnd:
1926 pnk = ParseNodeKind::AndExpr;
1927 break;
1928 case BinaryOperator::BitOr:
1929 pnk = ParseNodeKind::BitOrExpr;
1930 break;
1931 case BinaryOperator::BitXor:
1932 pnk = ParseNodeKind::BitXorExpr;
1933 break;
1934 case BinaryOperator::BitAnd:
1935 pnk = ParseNodeKind::BitAndExpr;
1936 break;
1937 case BinaryOperator::Eq:
1938 pnk = ParseNodeKind::EqExpr;
1939 break;
1940 case BinaryOperator::Neq:
1941 pnk = ParseNodeKind::NeExpr;
1942 break;
1943 case BinaryOperator::StrictEq:
1944 pnk = ParseNodeKind::StrictEqExpr;
1945 break;
1946 case BinaryOperator::StrictNeq:
1947 pnk = ParseNodeKind::StrictNeExpr;
1948 break;
1949 case BinaryOperator::LessThan:
1950 pnk = ParseNodeKind::LtExpr;
1951 break;
1952 case BinaryOperator::LeqThan:
1953 pnk = ParseNodeKind::LeExpr;
1954 break;
1955 case BinaryOperator::GreaterThan:
1956 pnk = ParseNodeKind::GtExpr;
1957 break;
1958 case BinaryOperator::GeqThan:
1959 pnk = ParseNodeKind::GeExpr;
1960 break;
1961 case BinaryOperator::In:
1962 pnk = ParseNodeKind::InExpr;
1963 break;
1964 case BinaryOperator::Instanceof:
1965 pnk = ParseNodeKind::InstanceOfExpr;
1966 break;
1967 case BinaryOperator::Lsh:
1968 pnk = ParseNodeKind::LshExpr;
1969 break;
1970 case BinaryOperator::Rsh:
1971 pnk = ParseNodeKind::RshExpr;
1972 break;
1973 case BinaryOperator::Ursh:
1974 pnk = ParseNodeKind::UrshExpr;
1975 break;
1976 case BinaryOperator::Plus:
1977 pnk = ParseNodeKind::AddExpr;
1978 break;
1979 case BinaryOperator::Minus:
1980 pnk = ParseNodeKind::SubExpr;
1981 break;
1982 case BinaryOperator::Mul:
1983 pnk = ParseNodeKind::MulExpr;
1984 break;
1985 case BinaryOperator::Div:
1986 pnk = ParseNodeKind::DivExpr;
1987 break;
1988 case BinaryOperator::Mod:
1989 pnk = ParseNodeKind::ModExpr;
1990 break;
1991 case BinaryOperator::Pow:
1992 pnk = ParseNodeKind::PowExpr;
1993 break;
1994 }
1995
1996 ParseNode* result;
1997 // ParseNodeKind::PowExpr is not left-associative
1998 if (left->isKind(pnk) && pnk != ParseNodeKind::PowExpr) {
1999 // Regroup left-associative operations into lists.
2000 left->template as<ListNode>().appendWithoutOrderAssumption(right);
2001 result = left;
2002 } else {
2003 BINJS_TRY_DECL(list, handler_.newList(pnk, tokenizer_->pos(start)));
2004
2005 list->appendWithoutOrderAssumption(left);
2006 list->appendWithoutOrderAssumption(right);
2007 result = list;
2008 }
2009 return result;
2010 }
2011
2012 /*
2013 interface BindingIdentifier : Node {
2014 [IdentifierName] string name;
2015 }
2016 */
2017 template <typename Tok>
parseBindingIdentifier(const FieldOrListContext & context)2018 JS::Result<ParseNode*> BinASTParser<Tok>::parseBindingIdentifier(
2019 const FieldOrListContext& context) {
2020 BinASTKind kind = BinASTKind::BindingIdentifier;
2021 AutoTaggedTuple guard(*tokenizer_);
2022
2023 guard.init();
2024 MOZ_TRY(tokenizer_->enterInterface(kind, context));
2025 const auto start = tokenizer_->offset();
2026 BINJS_MOZ_TRY_DECL(result, parseInterfaceBindingIdentifier(start, context));
2027 MOZ_TRY(guard.done());
2028
2029 return result;
2030 }
2031
2032 template <typename Tok>
parseInterfaceBindingIdentifier(const size_t start,const FieldOrListContext & context)2033 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBindingIdentifier(
2034 const size_t start, const FieldOrListContext& context) {
2035 BINJS_TRY(CheckRecursionLimit(cx_));
2036
2037 RootedAtom name(cx_);
2038 MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(FieldContext(
2039 BinASTInterfaceAndField::BindingIdentifier__Name)));
2040
2041 BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
2042 tokenizer_->pos(start), cx_));
2043 return result;
2044 }
2045
2046 template <typename Tok>
parseInterfaceBindingWithInitializer(const size_t start,const FieldOrListContext & context)2047 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBindingWithInitializer(
2048 const size_t start, const FieldOrListContext& context) {
2049 return raiseError(
2050 "FIXME: Not implemented yet in this preview release "
2051 "(BindingWithInitializer)");
2052 }
2053
2054 /*
2055 interface Block : Node {
2056 AssertedBlockScope scope;
2057 FrozenArray<Statement> statements;
2058 }
2059 */
2060 template <typename Tok>
parseBlock(const FieldOrListContext & context)2061 JS::Result<ParseNode*> BinASTParser<Tok>::parseBlock(
2062 const FieldOrListContext& context) {
2063 BinASTKind kind = BinASTKind::Block;
2064 AutoTaggedTuple guard(*tokenizer_);
2065
2066 guard.init();
2067 MOZ_TRY(tokenizer_->enterInterface(kind, context));
2068 const auto start = tokenizer_->offset();
2069 BINJS_MOZ_TRY_DECL(result, parseInterfaceBlock(start, context));
2070 MOZ_TRY(guard.done());
2071
2072 return result;
2073 }
2074
2075 template <typename Tok>
parseInterfaceBlock(const size_t start,const FieldOrListContext & context)2076 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBlock(
2077 const size_t start, const FieldOrListContext& context) {
2078 BINJS_TRY(CheckRecursionLimit(cx_));
2079 ParseContext::Statement stmt(pc_, StatementKind::Block);
2080 ParseContext::Scope currentScope(cx_, pc_, usedNames_);
2081 BINJS_TRY(currentScope.init(pc_));
2082
2083 MOZ_TRY(parseAssertedBlockScope(
2084 FieldContext(BinASTInterfaceAndField::Block__Scope)));
2085
2086 BINJS_MOZ_TRY_DECL(statements,
2087 parseListOfStatement(FieldContext(
2088 BinASTInterfaceAndField::Block__Statements)));
2089
2090 MOZ_TRY(checkClosedVars(currentScope));
2091 BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, pc_));
2092 BINJS_TRY_DECL(result, handler_.newLexicalScope(*bindings, statements));
2093 return result;
2094 }
2095
2096 template <typename Tok>
parseInterfaceBreakStatement(const size_t start,const FieldOrListContext & context)2097 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBreakStatement(
2098 const size_t start, const FieldOrListContext& context) {
2099 BINJS_TRY(CheckRecursionLimit(cx_));
2100 RootedAtom label(cx_);
2101 MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(FieldContext(
2102 BinASTInterfaceAndField::BreakStatement__Label)));
2103
2104 if (label) {
2105 if (!IsIdentifier(label)) {
2106 return raiseError("Invalid identifier");
2107 }
2108 }
2109
2110 auto validity =
2111 pc_->checkBreakStatement(label ? label->asPropertyName() : nullptr);
2112 if (validity.isErr()) {
2113 switch (validity.unwrapErr()) {
2114 case ParseContext::BreakStatementError::ToughBreak:
2115 this->error(JSMSG_TOUGH_BREAK);
2116 return cx_->alreadyReportedError();
2117 case ParseContext::BreakStatementError::LabelNotFound:
2118 this->error(JSMSG_LABEL_NOT_FOUND);
2119 return cx_->alreadyReportedError();
2120 }
2121 }
2122
2123 BINJS_TRY_DECL(result, handler_.newBreakStatement(
2124 label ? label->asPropertyName() : nullptr,
2125 tokenizer_->pos(start)));
2126 return result;
2127 }
2128
2129 template <typename Tok>
parseInterfaceCallExpression(const size_t start,const FieldOrListContext & context)2130 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceCallExpression(
2131 const size_t start, const FieldOrListContext& context) {
2132 BINJS_TRY(CheckRecursionLimit(cx_));
2133
2134 BINJS_MOZ_TRY_DECL(callee,
2135 parseExpressionOrSuper(FieldContext(
2136 BinASTInterfaceAndField::CallExpression__Callee)));
2137
2138 BINJS_MOZ_TRY_DECL(arguments,
2139 parseArguments(FieldContext(
2140 BinASTInterfaceAndField::CallExpression__Arguments)));
2141
2142 auto op = JSOp::Call;
2143
2144 // Try to optimize funcall and funapply at the bytecode level
2145 if (PropertyName* prop = handler_.maybeDottedProperty(callee)) {
2146 if (prop == cx_->names().apply) {
2147 op = JSOp::FunApply;
2148 if (pc_->isFunctionBox()) {
2149 pc_->functionBox()->usesApply = true;
2150 }
2151 } else if (prop == cx_->names().call) {
2152 op = JSOp::FunCall;
2153 }
2154 }
2155
2156 // Check for direct calls to `eval`.
2157 if (handler_.isEvalName(callee, cx_)) {
2158 if (!pc_->varScope().lookupDeclaredNameForAdd(cx_->names().eval) &&
2159 !pc_->innermostScope()->lookupDeclaredNameForAdd(cx_->names().eval)) {
2160 // This is a direct call to `eval`.
2161 if (!pc_->sc()->hasDirectEval()) {
2162 return raiseMissingDirectEvalInAssertedScope();
2163 }
2164
2165 op = pc_->sc()->strict() ? JSOp::StrictEval : JSOp::Eval;
2166 }
2167 }
2168
2169 BINJS_TRY_DECL(result, handler_.newCall(callee, arguments, op));
2170 return result;
2171 }
2172
2173 /*
2174 interface CatchClause : Node {
2175 AssertedBoundNamesScope bindingScope;
2176 Binding binding;
2177 Block body;
2178 }
2179 */
2180 template <typename Tok>
parseCatchClause(const FieldContext & context)2181 JS::Result<LexicalScopeNode*> BinASTParser<Tok>::parseCatchClause(
2182 const FieldContext& context) {
2183 BinASTKind kind = BinASTKind::CatchClause;
2184 AutoTaggedTuple guard(*tokenizer_);
2185
2186 guard.init();
2187 MOZ_TRY(tokenizer_->enterInterface(kind, context));
2188 const auto start = tokenizer_->offset();
2189 BINJS_MOZ_TRY_DECL(result, parseInterfaceCatchClause(start, context));
2190 MOZ_TRY(guard.done());
2191
2192 return result;
2193 }
2194
2195 template <typename Tok>
parseInterfaceCatchClause(const size_t start,const FieldContext & context)2196 JS::Result<LexicalScopeNode*> BinASTParser<Tok>::parseInterfaceCatchClause(
2197 const size_t start, const FieldContext& context) {
2198 BINJS_TRY(CheckRecursionLimit(cx_));
2199 ParseContext::Statement stmt(pc_, StatementKind::Catch);
2200 ParseContext::Scope currentScope(cx_, pc_, usedNames_);
2201 BINJS_TRY(currentScope.init(pc_));
2202
2203 MOZ_TRY(parseAssertedBoundNamesScope(
2204 FieldContext(BinASTInterfaceAndField::CatchClause__BindingScope)));
2205
2206 BINJS_MOZ_TRY_DECL(binding,
2207 parseBinding(FieldContext(
2208 BinASTInterfaceAndField::CatchClause__Binding)));
2209 if (!currentScope.lookupDeclaredName(
2210 binding->template as<NameNode>().atom())) {
2211 return raiseError("Missing catch variable in scope");
2212 }
2213 BINJS_MOZ_TRY_DECL(body, parseBlock(FieldOrListContext(FieldContext(
2214 BinASTInterfaceAndField::CatchClause__Body))));
2215
2216 MOZ_TRY(checkClosedVars(currentScope));
2217 BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, pc_));
2218 BINJS_TRY_DECL(result, handler_.newLexicalScope(*bindings, body));
2219 BINJS_TRY(handler_.setupCatchScope(result, binding, body));
2220 return result;
2221 }
2222
2223 template <typename Tok>
parseInterfaceClassDeclaration(const size_t start,const FieldOrListContext & context)2224 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceClassDeclaration(
2225 const size_t start, const FieldOrListContext& context) {
2226 return raiseError(
2227 "FIXME: Not implemented yet in this preview release (ClassDeclaration)");
2228 }
2229
2230 template <typename Tok>
parseInterfaceClassExpression(const size_t start,const FieldOrListContext & context)2231 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceClassExpression(
2232 const size_t start, const FieldOrListContext& context) {
2233 return raiseError(
2234 "FIXME: Not implemented yet in this preview release (ClassExpression)");
2235 }
2236
2237 template <typename Tok>
2238 JS::Result<ParseNode*>
parseInterfaceCompoundAssignmentExpression(const size_t start,const FieldOrListContext & context)2239 BinASTParser<Tok>::parseInterfaceCompoundAssignmentExpression(
2240 const size_t start, const FieldOrListContext& context) {
2241 BINJS_TRY(CheckRecursionLimit(cx_));
2242
2243 BINJS_MOZ_TRY_DECL(
2244 operator_,
2245 parseCompoundAssignmentOperator(FieldContext(
2246 BinASTInterfaceAndField::CompoundAssignmentExpression__Operator)));
2247
2248 BINJS_MOZ_TRY_DECL(
2249 binding,
2250 parseSimpleAssignmentTarget(FieldContext(
2251 BinASTInterfaceAndField::CompoundAssignmentExpression__Binding)));
2252
2253 BINJS_MOZ_TRY_DECL(
2254 expression,
2255 parseExpression(FieldContext(
2256 BinASTInterfaceAndField::CompoundAssignmentExpression__Expression)));
2257
2258 ParseNodeKind pnk;
2259 switch (operator_) {
2260 case CompoundAssignmentOperator::PlusAssign:
2261 pnk = ParseNodeKind::AddAssignExpr;
2262 break;
2263 case CompoundAssignmentOperator::MinusAssign:
2264 pnk = ParseNodeKind::SubAssignExpr;
2265 break;
2266 case CompoundAssignmentOperator::MulAssign:
2267 pnk = ParseNodeKind::MulAssignExpr;
2268 break;
2269 case CompoundAssignmentOperator::DivAssign:
2270 pnk = ParseNodeKind::DivAssignExpr;
2271 break;
2272 case CompoundAssignmentOperator::ModAssign:
2273 pnk = ParseNodeKind::ModAssignExpr;
2274 break;
2275 case CompoundAssignmentOperator::PowAssign:
2276 pnk = ParseNodeKind::PowAssignExpr;
2277 break;
2278 case CompoundAssignmentOperator::LshAssign:
2279 pnk = ParseNodeKind::LshAssignExpr;
2280 break;
2281 case CompoundAssignmentOperator::RshAssign:
2282 pnk = ParseNodeKind::RshAssignExpr;
2283 break;
2284 case CompoundAssignmentOperator::UrshAssign:
2285 pnk = ParseNodeKind::UrshAssignExpr;
2286 break;
2287 case CompoundAssignmentOperator::BitOrAssign:
2288 pnk = ParseNodeKind::BitOrAssignExpr;
2289 break;
2290 case CompoundAssignmentOperator::BitXorAssign:
2291 pnk = ParseNodeKind::BitXorAssignExpr;
2292 break;
2293 case CompoundAssignmentOperator::BitAndAssign:
2294 pnk = ParseNodeKind::BitAndAssignExpr;
2295 break;
2296 }
2297 BINJS_TRY_DECL(result, handler_.newAssignment(pnk, binding, expression));
2298 return result;
2299 }
2300
2301 template <typename Tok>
2302 JS::Result<ParseNode*>
parseInterfaceComputedMemberAssignmentTarget(const size_t start,const FieldContext & context)2303 BinASTParser<Tok>::parseInterfaceComputedMemberAssignmentTarget(
2304 const size_t start, const FieldContext& context) {
2305 BINJS_TRY(CheckRecursionLimit(cx_));
2306
2307 BINJS_MOZ_TRY_DECL(
2308 object,
2309 parseExpressionOrSuper(FieldContext(
2310 BinASTInterfaceAndField::ComputedMemberAssignmentTarget__Object)));
2311
2312 BINJS_MOZ_TRY_DECL(expression,
2313 parseExpression(FieldContext(
2314 BinASTInterfaceAndField::
2315 ComputedMemberAssignmentTarget__Expression)));
2316
2317 BINJS_TRY_DECL(result, handler_.newPropertyByValue(object, expression,
2318 tokenizer_->offset()));
2319 return result;
2320 }
2321
2322 template <typename Tok>
2323 JS::Result<ParseNode*>
parseInterfaceComputedMemberExpression(const size_t start,const FieldOrListContext & context)2324 BinASTParser<Tok>::parseInterfaceComputedMemberExpression(
2325 const size_t start, const FieldOrListContext& context) {
2326 BINJS_TRY(CheckRecursionLimit(cx_));
2327
2328 BINJS_MOZ_TRY_DECL(
2329 object, parseExpressionOrSuper(FieldContext(
2330 BinASTInterfaceAndField::ComputedMemberExpression__Object)));
2331
2332 BINJS_MOZ_TRY_DECL(
2333 expression,
2334 parseExpression(FieldContext(
2335 BinASTInterfaceAndField::ComputedMemberExpression__Expression)));
2336
2337 BINJS_TRY_DECL(result, handler_.newPropertyByValue(object, expression,
2338 tokenizer_->offset()));
2339 return result;
2340 }
2341
2342 template <typename Tok>
parseInterfaceComputedPropertyName(const size_t start,const FieldContext & context)2343 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceComputedPropertyName(
2344 const size_t start, const FieldContext& context) {
2345 return raiseError(
2346 "FIXME: Not implemented yet in this preview release "
2347 "(ComputedPropertyName)");
2348 }
2349
2350 template <typename Tok>
parseInterfaceConditionalExpression(const size_t start,const FieldOrListContext & context)2351 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceConditionalExpression(
2352 const size_t start, const FieldOrListContext& context) {
2353 BINJS_TRY(CheckRecursionLimit(cx_));
2354
2355 BINJS_MOZ_TRY_DECL(
2356 test, parseExpression(FieldContext(
2357 BinASTInterfaceAndField::ConditionalExpression__Test)));
2358
2359 BINJS_MOZ_TRY_DECL(
2360 consequent,
2361 parseExpression(FieldContext(
2362 BinASTInterfaceAndField::ConditionalExpression__Consequent)));
2363
2364 BINJS_MOZ_TRY_DECL(
2365 alternate,
2366 parseExpression(FieldContext(
2367 BinASTInterfaceAndField::ConditionalExpression__Alternate)));
2368
2369 BINJS_TRY_DECL(result, handler_.newConditional(test, consequent, alternate));
2370 return result;
2371 }
2372
2373 template <typename Tok>
parseInterfaceContinueStatement(const size_t start,const FieldOrListContext & context)2374 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceContinueStatement(
2375 const size_t start, const FieldOrListContext& context) {
2376 BINJS_TRY(CheckRecursionLimit(cx_));
2377 RootedAtom label(cx_);
2378 MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(FieldContext(
2379 BinASTInterfaceAndField::ContinueStatement__Label)));
2380
2381 if (label) {
2382 if (!IsIdentifier(label)) {
2383 return raiseError("ContinueStatement - Label MUST be an identifier");
2384 }
2385 }
2386
2387 auto validity =
2388 pc_->checkContinueStatement(label ? label->asPropertyName() : nullptr);
2389 if (validity.isErr()) {
2390 switch (validity.unwrapErr()) {
2391 case ParseContext::ContinueStatementError::NotInALoop:
2392 this->error(JSMSG_BAD_CONTINUE);
2393 return cx_->alreadyReportedError();
2394 case ParseContext::ContinueStatementError::LabelNotFound:
2395 this->error(JSMSG_LABEL_NOT_FOUND);
2396 return cx_->alreadyReportedError();
2397 }
2398 }
2399
2400 BINJS_TRY_DECL(result, handler_.newContinueStatement(
2401 label ? label->asPropertyName() : nullptr,
2402 tokenizer_->pos(start)));
2403 return result;
2404 }
2405
2406 template <typename Tok>
parseInterfaceDataProperty(const size_t start,const ListContext & context)2407 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDataProperty(
2408 const size_t start, const ListContext& context) {
2409 BINJS_TRY(CheckRecursionLimit(cx_));
2410
2411 BINJS_MOZ_TRY_DECL(name, parsePropertyName(FieldContext(
2412 BinASTInterfaceAndField::DataProperty__Name)));
2413
2414 BINJS_MOZ_TRY_DECL(expression,
2415 parseExpression(FieldContext(
2416 BinASTInterfaceAndField::DataProperty__Expression)));
2417
2418 if (!handler_.isUsableAsObjectPropertyName(name)) {
2419 return raiseError("DataProperty key kind");
2420 }
2421
2422 ParseNode* result;
2423 if (name->template is<NameNode>() &&
2424 name->template as<NameNode>().atom() == cx_->names().proto) {
2425 BINJS_TRY_VAR(result, handler_.newUnary(ParseNodeKind::MutateProto, start,
2426 expression));
2427 } else {
2428 BINJS_TRY_VAR(result, handler_.newObjectMethodOrPropertyDefinition(
2429 name, expression, AccessorType::None));
2430 }
2431 return result;
2432 }
2433
2434 template <typename Tok>
parseInterfaceDebuggerStatement(const size_t start,const FieldOrListContext & context)2435 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDebuggerStatement(
2436 const size_t start, const FieldOrListContext& context) {
2437 return raiseError(
2438 "FIXME: Not implemented yet in this preview release (DebuggerStatement)");
2439 }
2440
2441 /*
2442 interface Directive : Node {
2443 string rawValue;
2444 }
2445 */
2446 template <typename Tok>
parseDirective(const ListContext & context)2447 JS::Result<ParseNode*> BinASTParser<Tok>::parseDirective(
2448 const ListContext& context) {
2449 BinASTKind kind = BinASTKind::Directive;
2450 AutoTaggedTuple guard(*tokenizer_);
2451
2452 guard.init();
2453 MOZ_TRY(tokenizer_->enterInterface(kind, context));
2454 const auto start = tokenizer_->offset();
2455 BINJS_MOZ_TRY_DECL(result, parseInterfaceDirective(start, context));
2456 MOZ_TRY(guard.done());
2457
2458 return result;
2459 }
2460
2461 template <typename Tok>
parseInterfaceDirective(const size_t start,const ListContext & context)2462 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDirective(
2463 const size_t start, const ListContext& context) {
2464 BINJS_TRY(CheckRecursionLimit(cx_));
2465
2466 RootedAtom rawValue(cx_);
2467 MOZ_TRY_VAR(rawValue, tokenizer_->readAtom(FieldContext(
2468 BinASTInterfaceAndField::Directive__RawValue)));
2469
2470 TokenPos pos = tokenizer_->pos(start);
2471 BINJS_TRY_DECL(result, handler_.newStringLiteral(rawValue, pos));
2472 return result;
2473 }
2474
2475 template <typename Tok>
parseInterfaceDoWhileStatement(const size_t start,const FieldOrListContext & context)2476 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDoWhileStatement(
2477 const size_t start, const FieldOrListContext& context) {
2478 BINJS_TRY(CheckRecursionLimit(cx_));
2479 ParseContext::Statement stmt(pc_, StatementKind::DoLoop);
2480
2481 BINJS_MOZ_TRY_DECL(
2482 test, parseExpression(
2483 FieldContext(BinASTInterfaceAndField::DoWhileStatement__Test)));
2484
2485 BINJS_MOZ_TRY_DECL(body,
2486 parseStatement(FieldOrListContext(FieldContext(
2487 BinASTInterfaceAndField::DoWhileStatement__Body))));
2488
2489 BINJS_TRY_DECL(
2490 result, handler_.newDoWhileStatement(body, test, tokenizer_->pos(start)));
2491 return result;
2492 }
2493
2494 template <typename Tok>
2495 JS::Result<ParseNode*>
parseInterfaceEagerArrowExpressionWithExpression(const size_t start,const FieldOrListContext & context)2496 BinASTParser<Tok>::parseInterfaceEagerArrowExpressionWithExpression(
2497 const size_t start, const FieldOrListContext& context) {
2498 return raiseError(
2499 "FIXME: Not implemented yet in this preview release "
2500 "(EagerArrowExpressionWithExpression)");
2501 }
2502
2503 template <typename Tok>
2504 JS::Result<ParseNode*>
parseInterfaceEagerArrowExpressionWithFunctionBody(const size_t start,const FieldOrListContext & context)2505 BinASTParser<Tok>::parseInterfaceEagerArrowExpressionWithFunctionBody(
2506 const size_t start, const FieldOrListContext& context) {
2507 return raiseError(
2508 "FIXME: Not implemented yet in this preview release "
2509 "(EagerArrowExpressionWithFunctionBody)");
2510 }
2511
2512 template <typename Tok>
2513 JS::Result<ParseNode*>
parseInterfaceEagerFunctionDeclaration(const size_t start,const FieldOrListContext & context)2514 BinASTParser<Tok>::parseInterfaceEagerFunctionDeclaration(
2515 const size_t start, const FieldOrListContext& context) {
2516 BINJS_TRY(CheckRecursionLimit(cx_));
2517 const auto syntax = FunctionSyntaxKind::Statement;
2518
2519 BINJS_MOZ_TRY_DECL(
2520 isAsync,
2521 tokenizer_->readBool(FieldContext(
2522 BinASTInterfaceAndField::EagerFunctionDeclaration__IsAsync)));
2523 if (isAsync) {
2524 return raiseError(
2525 "Async function is not supported in this preview release");
2526 }
2527 BINJS_MOZ_TRY_DECL(
2528 isGenerator,
2529 tokenizer_->readBool(FieldContext(
2530 BinASTInterfaceAndField::EagerFunctionDeclaration__IsGenerator)));
2531 if (isGenerator) {
2532 return raiseError("Generator is not supported in this preview release");
2533 }
2534 BINJS_MOZ_TRY_DECL(
2535 name, parseBindingIdentifier(FieldOrListContext(FieldContext(
2536 BinASTInterfaceAndField::EagerFunctionDeclaration__Name))));
2537
2538 BINJS_MOZ_TRY_DECL(
2539 length, tokenizer_->readUnsignedLong(FieldContext(
2540 BinASTInterfaceAndField::EagerFunctionDeclaration__Length)));
2541
2542 BINJS_MOZ_TRY_DECL(
2543 directives,
2544 parseListOfDirective(FieldContext(
2545 BinASTInterfaceAndField::EagerFunctionDeclaration__Directives)));
2546
2547 BINJS_MOZ_TRY_DECL(funbox,
2548 buildFunctionBox(isGenerator ? GeneratorKind::Generator
2549 : GeneratorKind::NotGenerator,
2550 isAsync ? FunctionAsyncKind::AsyncFunction
2551 : FunctionAsyncKind::SyncFunction,
2552 syntax,
2553 (syntax != FunctionSyntaxKind::Setter &&
2554 syntax != FunctionSyntaxKind::Getter)
2555 ? name
2556 : nullptr));
2557
2558 forceStrictIfNecessary(funbox, directives);
2559
2560 pc_->sc()->setHasInnerFunctions();
2561
2562 // Push a new ParseContext. It will be used to parse `scope`, the arguments,
2563 // the function.
2564 BinASTParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
2565 BINJS_TRY(funpc.init());
2566 pc_->functionScope().useAsVarScope(pc_);
2567 MOZ_ASSERT(pc_->isFunctionBox());
2568
2569 ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
2570 BINJS_TRY(lexicalScope.init(pc_));
2571 ListNode* params;
2572 ListNode* body;
2573 MOZ_TRY(parseFunctionOrMethodContents(
2574 length, ¶ms, &body,
2575 FieldOrRootContext(FieldContext(
2576 BinASTInterfaceAndField::EagerFunctionDeclaration__Contents))));
2577 MOZ_TRY(prependDirectivesToBody(body, directives));
2578 uint32_t nargs = params->count();
2579
2580 BINJS_TRY_DECL(lexicalScopeData,
2581 NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
2582 BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
2583 BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(start, syntax, funbox));
2584 MOZ_TRY(setFunctionParametersAndBody(result, params, bodyScope));
2585 MOZ_TRY(finishEagerFunction(funbox, nargs));
2586 return result;
2587 }
2588
2589 template <typename Tok>
parseInterfaceEagerFunctionExpression(const size_t start,const FieldOrListContext & context)2590 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerFunctionExpression(
2591 const size_t start, const FieldOrListContext& context) {
2592 BINJS_TRY(CheckRecursionLimit(cx_));
2593 const auto syntax = FunctionSyntaxKind::Expression;
2594
2595 BINJS_MOZ_TRY_DECL(
2596 isAsync, tokenizer_->readBool(FieldContext(
2597 BinASTInterfaceAndField::EagerFunctionExpression__IsAsync)));
2598 if (isAsync) {
2599 return raiseError(
2600 "Async function is not supported in this preview release");
2601 }
2602 BINJS_MOZ_TRY_DECL(
2603 isGenerator,
2604 tokenizer_->readBool(FieldContext(
2605 BinASTInterfaceAndField::EagerFunctionExpression__IsGenerator)));
2606 if (isGenerator) {
2607 return raiseError("Generator is not supported in this preview release");
2608 }
2609 BINJS_MOZ_TRY_DECL(
2610 name, parseOptionalBindingIdentifier(FieldContext(
2611 BinASTInterfaceAndField::EagerFunctionExpression__Name)));
2612
2613 BINJS_MOZ_TRY_DECL(
2614 length, tokenizer_->readUnsignedLong(FieldContext(
2615 BinASTInterfaceAndField::EagerFunctionExpression__Length)));
2616
2617 BINJS_MOZ_TRY_DECL(
2618 directives,
2619 parseListOfDirective(FieldContext(
2620 BinASTInterfaceAndField::EagerFunctionExpression__Directives)));
2621
2622 BINJS_MOZ_TRY_DECL(funbox,
2623 buildFunctionBox(isGenerator ? GeneratorKind::Generator
2624 : GeneratorKind::NotGenerator,
2625 isAsync ? FunctionAsyncKind::AsyncFunction
2626 : FunctionAsyncKind::SyncFunction,
2627 syntax,
2628 (syntax != FunctionSyntaxKind::Setter &&
2629 syntax != FunctionSyntaxKind::Getter)
2630 ? name
2631 : nullptr));
2632
2633 forceStrictIfNecessary(funbox, directives);
2634
2635 pc_->sc()->setHasInnerFunctions();
2636
2637 // Push a new ParseContext. It will be used to parse `scope`, the arguments,
2638 // the function.
2639 BinASTParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
2640 BINJS_TRY(funpc.init());
2641 pc_->functionScope().useAsVarScope(pc_);
2642 MOZ_ASSERT(pc_->isFunctionBox());
2643
2644 ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
2645 BINJS_TRY(lexicalScope.init(pc_));
2646 ListNode* params;
2647 ListNode* body;
2648 MOZ_TRY(parseFunctionExpressionContents(
2649 length, ¶ms, &body,
2650 FieldOrRootContext(FieldContext(
2651 BinASTInterfaceAndField::EagerFunctionExpression__Contents))));
2652 MOZ_TRY(prependDirectivesToBody(body, directives));
2653 uint32_t nargs = params->count();
2654
2655 BINJS_TRY_DECL(lexicalScopeData,
2656 NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
2657 BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
2658 BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(start, syntax, funbox));
2659 MOZ_TRY(setFunctionParametersAndBody(result, params, bodyScope));
2660 MOZ_TRY(finishEagerFunction(funbox, nargs));
2661 return result;
2662 }
2663
2664 template <typename Tok>
parseInterfaceEagerGetter(const size_t start,const ListContext & context)2665 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerGetter(
2666 const size_t start, const ListContext& context) {
2667 BINJS_TRY(CheckRecursionLimit(cx_));
2668 const auto syntax = FunctionSyntaxKind::Setter;
2669 const bool isGenerator = false;
2670 const bool isAsync = false;
2671 const auto accessorType = AccessorType::Getter;
2672 const uint32_t length = 0;
2673
2674 BINJS_MOZ_TRY_DECL(name, parsePropertyName(FieldContext(
2675 BinASTInterfaceAndField::EagerGetter__Name)));
2676
2677 BINJS_MOZ_TRY_DECL(directives,
2678 parseListOfDirective(FieldContext(
2679 BinASTInterfaceAndField::EagerGetter__Directives)));
2680
2681 BINJS_MOZ_TRY_DECL(funbox,
2682 buildFunctionBox(isGenerator ? GeneratorKind::Generator
2683 : GeneratorKind::NotGenerator,
2684 isAsync ? FunctionAsyncKind::AsyncFunction
2685 : FunctionAsyncKind::SyncFunction,
2686 syntax,
2687 (syntax != FunctionSyntaxKind::Setter &&
2688 syntax != FunctionSyntaxKind::Getter)
2689 ? name
2690 : nullptr));
2691
2692 forceStrictIfNecessary(funbox, directives);
2693
2694 pc_->sc()->setHasInnerFunctions();
2695
2696 // Push a new ParseContext. It will be used to parse `scope`, the arguments,
2697 // the function.
2698 BinASTParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
2699 BINJS_TRY(funpc.init());
2700 pc_->functionScope().useAsVarScope(pc_);
2701 MOZ_ASSERT(pc_->isFunctionBox());
2702
2703 ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
2704 BINJS_TRY(lexicalScope.init(pc_));
2705 ListNode* params;
2706 ListNode* body;
2707 MOZ_TRY(parseGetterContents(
2708 length, ¶ms, &body,
2709 FieldContext(BinASTInterfaceAndField::EagerGetter__Contents)));
2710 MOZ_TRY(prependDirectivesToBody(body, directives));
2711 uint32_t nargs = params->count();
2712
2713 BINJS_TRY_DECL(lexicalScopeData,
2714 NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
2715 BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
2716 BINJS_MOZ_TRY_DECL(method, makeEmptyFunctionNode(start, syntax, funbox));
2717 MOZ_TRY(setFunctionParametersAndBody(method, params, bodyScope));
2718 BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
2719 name, method, accessorType));
2720 MOZ_TRY(finishEagerFunction(funbox, nargs));
2721 return result;
2722 }
2723
2724 template <typename Tok>
parseInterfaceEagerMethod(const size_t start,const ListContext & context)2725 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerMethod(
2726 const size_t start, const ListContext& context) {
2727 BINJS_TRY(CheckRecursionLimit(cx_));
2728 const auto syntax = FunctionSyntaxKind::Method;
2729 const auto accessorType = AccessorType::None;
2730
2731 BINJS_MOZ_TRY_DECL(isAsync,
2732 tokenizer_->readBool(FieldContext(
2733 BinASTInterfaceAndField::EagerMethod__IsAsync)));
2734 if (isAsync) {
2735 return raiseError(
2736 "Async function is not supported in this preview release");
2737 }
2738 BINJS_MOZ_TRY_DECL(isGenerator,
2739 tokenizer_->readBool(FieldContext(
2740 BinASTInterfaceAndField::EagerMethod__IsGenerator)));
2741 if (isGenerator) {
2742 return raiseError("Generator is not supported in this preview release");
2743 }
2744 BINJS_MOZ_TRY_DECL(name, parsePropertyName(FieldContext(
2745 BinASTInterfaceAndField::EagerMethod__Name)));
2746
2747 BINJS_MOZ_TRY_DECL(
2748 length, tokenizer_->readUnsignedLong(
2749 FieldContext(BinASTInterfaceAndField::EagerMethod__Length)));
2750
2751 BINJS_MOZ_TRY_DECL(directives,
2752 parseListOfDirective(FieldContext(
2753 BinASTInterfaceAndField::EagerMethod__Directives)));
2754
2755 BINJS_MOZ_TRY_DECL(funbox,
2756 buildFunctionBox(isGenerator ? GeneratorKind::Generator
2757 : GeneratorKind::NotGenerator,
2758 isAsync ? FunctionAsyncKind::AsyncFunction
2759 : FunctionAsyncKind::SyncFunction,
2760 syntax,
2761 (syntax != FunctionSyntaxKind::Setter &&
2762 syntax != FunctionSyntaxKind::Getter)
2763 ? name
2764 : nullptr));
2765
2766 forceStrictIfNecessary(funbox, directives);
2767
2768 pc_->sc()->setHasInnerFunctions();
2769
2770 // Push a new ParseContext. It will be used to parse `scope`, the arguments,
2771 // the function.
2772 BinASTParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
2773 BINJS_TRY(funpc.init());
2774 pc_->functionScope().useAsVarScope(pc_);
2775 MOZ_ASSERT(pc_->isFunctionBox());
2776
2777 ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
2778 BINJS_TRY(lexicalScope.init(pc_));
2779 ListNode* params;
2780 ListNode* body;
2781 MOZ_TRY(parseFunctionOrMethodContents(
2782 length, ¶ms, &body,
2783 FieldOrRootContext(
2784 FieldContext(BinASTInterfaceAndField::EagerMethod__Contents))));
2785 MOZ_TRY(prependDirectivesToBody(body, directives));
2786 uint32_t nargs = params->count();
2787
2788 BINJS_TRY_DECL(lexicalScopeData,
2789 NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
2790 BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
2791 BINJS_MOZ_TRY_DECL(method, makeEmptyFunctionNode(start, syntax, funbox));
2792 MOZ_TRY(setFunctionParametersAndBody(method, params, bodyScope));
2793 BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
2794 name, method, accessorType));
2795 MOZ_TRY(finishEagerFunction(funbox, nargs));
2796 return result;
2797 }
2798
2799 template <typename Tok>
parseInterfaceEagerSetter(const size_t start,const ListContext & context)2800 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerSetter(
2801 const size_t start, const ListContext& context) {
2802 BINJS_TRY(CheckRecursionLimit(cx_));
2803 const auto syntax = FunctionSyntaxKind::Setter;
2804 const bool isGenerator = false;
2805 const bool isAsync = false;
2806 const auto accessorType = AccessorType::Setter;
2807
2808 BINJS_MOZ_TRY_DECL(name, parsePropertyName(FieldContext(
2809 BinASTInterfaceAndField::EagerSetter__Name)));
2810
2811 BINJS_MOZ_TRY_DECL(
2812 length, tokenizer_->readUnsignedLong(
2813 FieldContext(BinASTInterfaceAndField::EagerSetter__Length)));
2814
2815 BINJS_MOZ_TRY_DECL(directives,
2816 parseListOfDirective(FieldContext(
2817 BinASTInterfaceAndField::EagerSetter__Directives)));
2818
2819 BINJS_MOZ_TRY_DECL(funbox,
2820 buildFunctionBox(isGenerator ? GeneratorKind::Generator
2821 : GeneratorKind::NotGenerator,
2822 isAsync ? FunctionAsyncKind::AsyncFunction
2823 : FunctionAsyncKind::SyncFunction,
2824 syntax,
2825 (syntax != FunctionSyntaxKind::Setter &&
2826 syntax != FunctionSyntaxKind::Getter)
2827 ? name
2828 : nullptr));
2829
2830 forceStrictIfNecessary(funbox, directives);
2831
2832 pc_->sc()->setHasInnerFunctions();
2833
2834 // Push a new ParseContext. It will be used to parse `scope`, the arguments,
2835 // the function.
2836 BinASTParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
2837 BINJS_TRY(funpc.init());
2838 pc_->functionScope().useAsVarScope(pc_);
2839 MOZ_ASSERT(pc_->isFunctionBox());
2840
2841 ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
2842 BINJS_TRY(lexicalScope.init(pc_));
2843 ListNode* params;
2844 ListNode* body;
2845 MOZ_TRY(parseSetterContents(
2846 length, ¶ms, &body,
2847 FieldContext(BinASTInterfaceAndField::EagerSetter__Contents)));
2848 MOZ_TRY(prependDirectivesToBody(body, directives));
2849 uint32_t nargs = params->count();
2850
2851 BINJS_TRY_DECL(lexicalScopeData,
2852 NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
2853 BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
2854 BINJS_MOZ_TRY_DECL(method, makeEmptyFunctionNode(start, syntax, funbox));
2855 MOZ_TRY(setFunctionParametersAndBody(method, params, bodyScope));
2856 BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
2857 name, method, accessorType));
2858 MOZ_TRY(finishEagerFunction(funbox, nargs));
2859 return result;
2860 }
2861
2862 template <typename Tok>
parseInterfaceEmptyStatement(const size_t start,const FieldOrListContext & context)2863 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEmptyStatement(
2864 const size_t start, const FieldOrListContext& context) {
2865 BINJS_TRY(CheckRecursionLimit(cx_));
2866
2867 BINJS_TRY_DECL(result, handler_.newEmptyStatement(tokenizer_->pos(start)));
2868 return result;
2869 }
2870
2871 template <typename Tok>
parseInterfaceExpressionStatement(const size_t start,const FieldOrListContext & context)2872 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceExpressionStatement(
2873 const size_t start, const FieldOrListContext& context) {
2874 BINJS_TRY(CheckRecursionLimit(cx_));
2875
2876 BINJS_MOZ_TRY_DECL(
2877 expression,
2878 parseExpression(FieldContext(
2879 BinASTInterfaceAndField::ExpressionStatement__Expression)));
2880
2881 BINJS_TRY_DECL(result, handler_.newExprStatement(expression));
2882 return result;
2883 }
2884
2885 template <typename Tok>
parseInterfaceForInOfBinding(const size_t start,const FieldContext & context)2886 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForInOfBinding(
2887 const size_t start, const FieldContext& context) {
2888 BINJS_TRY(CheckRecursionLimit(cx_));
2889 AutoVariableDeclarationKind kindGuard(this);
2890
2891 BINJS_MOZ_TRY_DECL(
2892 kind_, parseVariableDeclarationKind(
2893 FieldContext(BinASTInterfaceAndField::ForInOfBinding__Kind)));
2894
2895 BINJS_MOZ_TRY_DECL(binding,
2896 parseBinding(FieldContext(
2897 BinASTInterfaceAndField::ForInOfBinding__Binding)));
2898
2899 // Restored by `kindGuard`.
2900 variableDeclarationKind_ = kind_;
2901 MOZ_TRY(
2902 checkBinding(binding->template as<NameNode>().atom()->asPropertyName()));
2903 ParseNodeKind pnk;
2904 switch (kind_) {
2905 case VariableDeclarationKind::Var:
2906 pnk = ParseNodeKind::VarStmt;
2907 break;
2908 case VariableDeclarationKind::Let:
2909 return raiseError("Let is not supported in this preview release");
2910 case VariableDeclarationKind::Const:
2911 return raiseError("Const is not supported in this preview release");
2912 }
2913 BINJS_TRY_DECL(result,
2914 handler_.newDeclarationList(pnk, tokenizer_->pos(start)));
2915 handler_.addList(result, binding);
2916 return result;
2917 }
2918
2919 template <typename Tok>
parseInterfaceForInStatement(const size_t start,const FieldOrListContext & context)2920 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForInStatement(
2921 const size_t start, const FieldOrListContext& context) {
2922 BINJS_TRY(CheckRecursionLimit(cx_));
2923 ParseContext::Statement stmt(pc_, StatementKind::ForInLoop);
2924
2925 // Implicit scope around the `for`, used to store `for (let x in ...)`
2926 // or `for (const x in ...)`-style declarations. Detail on the
2927 // declaration is stored as part of `scope`.
2928 ParseContext::Scope scope(cx_, pc_, usedNames_);
2929 BINJS_TRY(scope.init(pc_));
2930
2931 BINJS_MOZ_TRY_DECL(left, parseAssignmentTargetOrForInOfBinding(FieldContext(
2932 BinASTInterfaceAndField::ForInStatement__Left)));
2933
2934 BINJS_MOZ_TRY_DECL(
2935 right, parseExpression(
2936 FieldContext(BinASTInterfaceAndField::ForInStatement__Right)));
2937
2938 BINJS_MOZ_TRY_DECL(
2939 body, parseStatement(FieldOrListContext(
2940 FieldContext(BinASTInterfaceAndField::ForInStatement__Body))));
2941
2942 BINJS_TRY_DECL(forHead,
2943 handler_.newForInOrOfHead(ParseNodeKind::ForIn, left, right,
2944 tokenizer_->pos(start)));
2945 ParseNode* result;
2946 BINJS_TRY_VAR(result, handler_.newForStatement(start, forHead, body,
2947 /* iflags = */ 0));
2948
2949 if (!scope.isEmpty()) {
2950 BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, pc_));
2951 BINJS_TRY_VAR(result, handler_.newLexicalScope(*bindings, result));
2952 }
2953 return result;
2954 }
2955
2956 template <typename Tok>
parseInterfaceForOfStatement(const size_t start,const FieldOrListContext & context)2957 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForOfStatement(
2958 const size_t start, const FieldOrListContext& context) {
2959 return raiseError(
2960 "FIXME: Not implemented yet in this preview release (ForOfStatement)");
2961 }
2962
2963 template <typename Tok>
parseInterfaceForStatement(const size_t start,const FieldOrListContext & context)2964 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForStatement(
2965 const size_t start, const FieldOrListContext& context) {
2966 BINJS_TRY(CheckRecursionLimit(cx_));
2967 ParseContext::Statement stmt(pc_, StatementKind::ForLoop);
2968
2969 // Implicit scope around the `for`, used to store `for (let x; ...; ...)`
2970 // or `for (const x; ...; ...)`-style declarations. Detail on the
2971 // declaration is stored as part of `BINJS_Scope`.
2972 ParseContext::Scope scope(cx_, pc_, usedNames_);
2973 BINJS_TRY(scope.init(pc_));
2974
2975 BINJS_MOZ_TRY_DECL(
2976 init, parseOptionalExpressionOrVariableDeclaration(
2977 FieldContext(BinASTInterfaceAndField::ForStatement__Init)));
2978
2979 BINJS_MOZ_TRY_DECL(test, parseOptionalExpression(FieldContext(
2980 BinASTInterfaceAndField::ForStatement__Test)));
2981
2982 BINJS_MOZ_TRY_DECL(
2983 update, parseOptionalExpression(
2984 FieldContext(BinASTInterfaceAndField::ForStatement__Update)));
2985
2986 BINJS_MOZ_TRY_DECL(body, parseStatement(FieldOrListContext(FieldContext(
2987 BinASTInterfaceAndField::ForStatement__Body))));
2988
2989 BINJS_TRY_DECL(
2990 forHead, handler_.newForHead(init, test, update, tokenizer_->pos(start)));
2991 ParseNode* result;
2992 BINJS_TRY_VAR(result, handler_.newForStatement(start, forHead, body,
2993 /* iflags = */ 0));
2994
2995 if (!scope.isEmpty()) {
2996 BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, pc_));
2997 BINJS_TRY_VAR(result, handler_.newLexicalScope(*bindings, result));
2998 }
2999 return result;
3000 }
3001
3002 /*
3003 interface FormalParameters : Node {
3004 FrozenArray<Parameter> items;
3005 Binding? rest;
3006 }
3007 */
3008 template <typename Tok>
parseFormalParameters(const FieldContext & context)3009 JS::Result<ListNode*> BinASTParser<Tok>::parseFormalParameters(
3010 const FieldContext& context) {
3011 BinASTKind kind = BinASTKind::FormalParameters;
3012 AutoTaggedTuple guard(*tokenizer_);
3013
3014 guard.init();
3015 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3016 const auto start = tokenizer_->offset();
3017 BINJS_MOZ_TRY_DECL(result, parseInterfaceFormalParameters(start, context));
3018 MOZ_TRY(guard.done());
3019
3020 return result;
3021 }
3022
3023 template <typename Tok>
parseInterfaceFormalParameters(const size_t start,const FieldContext & context)3024 JS::Result<ListNode*> BinASTParser<Tok>::parseInterfaceFormalParameters(
3025 const size_t start, const FieldContext& context) {
3026 BINJS_TRY(CheckRecursionLimit(cx_));
3027
3028 BINJS_MOZ_TRY_DECL(items,
3029 parseListOfParameter(FieldContext(
3030 BinASTInterfaceAndField::FormalParameters__Items)));
3031
3032 BINJS_MOZ_TRY_DECL(
3033 rest, parseOptionalBinding(
3034 FieldContext(BinASTInterfaceAndField::FormalParameters__Rest)));
3035
3036 auto result = items;
3037 if (rest) {
3038 return raiseError(
3039 "Rest parameter is not supported in this preview release");
3040 }
3041 return result;
3042 }
3043
3044 /*
3045 interface FunctionExpressionContents : Node {
3046 bool isFunctionNameCaptured;
3047 bool isThisCaptured;
3048 AssertedParameterScope parameterScope;
3049 FormalParameters params;
3050 AssertedVarScope bodyScope;
3051 FunctionBody body;
3052 }
3053 */
3054 template <typename Tok>
parseFunctionExpressionContents(uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldOrRootContext & context)3055 JS::Result<Ok> BinASTParser<Tok>::parseFunctionExpressionContents(
3056 uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
3057 const FieldOrRootContext& context) {
3058 BinASTKind kind = BinASTKind::FunctionExpressionContents;
3059 AutoTaggedTuple guard(*tokenizer_);
3060
3061 guard.init();
3062 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3063 const auto start = tokenizer_->offset();
3064 BINJS_MOZ_TRY_DECL(result,
3065 parseInterfaceFunctionExpressionContents(
3066 start, funLength, paramsOut, bodyOut, context));
3067 MOZ_TRY(guard.done());
3068
3069 return result;
3070 }
3071
3072 template <typename Tok>
parseInterfaceFunctionExpressionContents(const size_t start,uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldOrRootContext & context)3073 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceFunctionExpressionContents(
3074 const size_t start, uint32_t funLength, ListNode** paramsOut,
3075 ListNode** bodyOut, const FieldOrRootContext& context) {
3076 BINJS_TRY(CheckRecursionLimit(cx_));
3077
3078 BINJS_MOZ_TRY_DECL(
3079 isFunctionNameCaptured,
3080 tokenizer_->readBool(FieldContext(
3081 BinASTInterfaceAndField::
3082 FunctionExpressionContents__IsFunctionNameCaptured)));
3083 // Per spec, isFunctionNameCaptured can be true for anonymous
3084 // function. Check isFunctionNameCaptured only for named
3085 // function.
3086 if (pc_->functionBox()->isNamedLambda() && isFunctionNameCaptured) {
3087 captureFunctionName();
3088 }
3089 BINJS_MOZ_TRY_DECL(isThisCaptured,
3090 tokenizer_->readBool(FieldContext(
3091 BinASTInterfaceAndField::
3092 FunctionExpressionContents__IsThisCaptured)));
3093 // TODO: Use this in BinASTParser::buildFunction.
3094 (void)isThisCaptured;
3095 Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
3096 MOZ_TRY(parseAssertedParameterScope(
3097 &positionalParams,
3098 FieldContext(BinASTInterfaceAndField::
3099 FunctionExpressionContents__ParameterScope)));
3100
3101 BINJS_MOZ_TRY_DECL(
3102 params,
3103 parseFormalParameters(FieldContext(
3104 BinASTInterfaceAndField::FunctionExpressionContents__Params)));
3105 MOZ_TRY(checkFunctionLength(funLength));
3106 MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
3107 MOZ_TRY(parseAssertedVarScope(FieldContext(
3108 BinASTInterfaceAndField::FunctionExpressionContents__BodyScope)));
3109
3110 BINJS_MOZ_TRY_DECL(
3111 body, parseFunctionBody(FieldContext(
3112 BinASTInterfaceAndField::FunctionExpressionContents__Body)));
3113
3114 *paramsOut = params;
3115 *bodyOut = body;
3116 auto result = Ok();
3117 return result;
3118 }
3119
3120 /*
3121 interface FunctionOrMethodContents : Node {
3122 bool isThisCaptured;
3123 AssertedParameterScope parameterScope;
3124 FormalParameters params;
3125 AssertedVarScope bodyScope;
3126 FunctionBody body;
3127 }
3128 */
3129 template <typename Tok>
parseFunctionOrMethodContents(uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldOrRootContext & context)3130 JS::Result<Ok> BinASTParser<Tok>::parseFunctionOrMethodContents(
3131 uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
3132 const FieldOrRootContext& context) {
3133 BinASTKind kind = BinASTKind::FunctionOrMethodContents;
3134 AutoTaggedTuple guard(*tokenizer_);
3135
3136 guard.init();
3137 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3138 const auto start = tokenizer_->offset();
3139 BINJS_MOZ_TRY_DECL(result,
3140 parseInterfaceFunctionOrMethodContents(
3141 start, funLength, paramsOut, bodyOut, context));
3142 MOZ_TRY(guard.done());
3143
3144 return result;
3145 }
3146
3147 template <typename Tok>
parseInterfaceFunctionOrMethodContents(const size_t start,uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldOrRootContext & context)3148 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceFunctionOrMethodContents(
3149 const size_t start, uint32_t funLength, ListNode** paramsOut,
3150 ListNode** bodyOut, const FieldOrRootContext& context) {
3151 BINJS_TRY(CheckRecursionLimit(cx_));
3152
3153 BINJS_MOZ_TRY_DECL(
3154 isThisCaptured,
3155 tokenizer_->readBool(FieldContext(
3156 BinASTInterfaceAndField::FunctionOrMethodContents__IsThisCaptured)));
3157 // TODO: Use this in BinASTParser::buildFunction.
3158 (void)isThisCaptured;
3159 Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
3160 MOZ_TRY(parseAssertedParameterScope(
3161 &positionalParams,
3162 FieldContext(
3163 BinASTInterfaceAndField::FunctionOrMethodContents__ParameterScope)));
3164
3165 BINJS_MOZ_TRY_DECL(
3166 params, parseFormalParameters(FieldContext(
3167 BinASTInterfaceAndField::FunctionOrMethodContents__Params)));
3168 MOZ_TRY(checkFunctionLength(funLength));
3169 MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
3170 MOZ_TRY(parseAssertedVarScope(FieldContext(
3171 BinASTInterfaceAndField::FunctionOrMethodContents__BodyScope)));
3172
3173 BINJS_MOZ_TRY_DECL(
3174 body, parseFunctionBody(FieldContext(
3175 BinASTInterfaceAndField::FunctionOrMethodContents__Body)));
3176
3177 *paramsOut = params;
3178 *bodyOut = body;
3179 auto result = Ok();
3180 return result;
3181 }
3182
3183 /*
3184 interface GetterContents : Node {
3185 bool isThisCaptured;
3186 AssertedVarScope bodyScope;
3187 FunctionBody body;
3188 }
3189 */
3190 template <typename Tok>
parseGetterContents(uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldContext & context)3191 JS::Result<Ok> BinASTParser<Tok>::parseGetterContents(
3192 uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
3193 const FieldContext& context) {
3194 BinASTKind kind = BinASTKind::GetterContents;
3195 AutoTaggedTuple guard(*tokenizer_);
3196
3197 guard.init();
3198 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3199 const auto start = tokenizer_->offset();
3200 BINJS_MOZ_TRY_DECL(
3201 result, parseInterfaceGetterContents(start, funLength, paramsOut, bodyOut,
3202 context));
3203 MOZ_TRY(guard.done());
3204
3205 return result;
3206 }
3207
3208 template <typename Tok>
parseInterfaceGetterContents(const size_t start,uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldContext & context)3209 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceGetterContents(
3210 const size_t start, uint32_t funLength, ListNode** paramsOut,
3211 ListNode** bodyOut, const FieldContext& context) {
3212 BINJS_TRY(CheckRecursionLimit(cx_));
3213
3214 BINJS_MOZ_TRY_DECL(
3215 isThisCaptured,
3216 tokenizer_->readBool(FieldContext(
3217 BinASTInterfaceAndField::GetterContents__IsThisCaptured)));
3218 // TODO: Use this in BinASTParser::buildFunction.
3219 (void)isThisCaptured;
3220 MOZ_TRY(parseAssertedVarScope(
3221 FieldContext(BinASTInterfaceAndField::GetterContents__BodyScope)));
3222
3223 BINJS_TRY_DECL(params, handler_.newParamsBody(tokenizer_->pos(start)));
3224 BINJS_MOZ_TRY_DECL(body, parseFunctionBody(FieldContext(
3225 BinASTInterfaceAndField::GetterContents__Body)));
3226
3227 *paramsOut = params;
3228 *bodyOut = body;
3229 auto result = Ok();
3230 return result;
3231 }
3232
3233 /*
3234 interface IdentifierExpression : Node {
3235 [IdentifierName] string name;
3236 }
3237 */
3238 template <typename Tok>
parseIdentifierExpression(const FieldOrListContext & context)3239 JS::Result<ParseNode*> BinASTParser<Tok>::parseIdentifierExpression(
3240 const FieldOrListContext& context) {
3241 BinASTKind kind = BinASTKind::IdentifierExpression;
3242 AutoTaggedTuple guard(*tokenizer_);
3243
3244 guard.init();
3245 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3246 const auto start = tokenizer_->offset();
3247 BINJS_MOZ_TRY_DECL(result,
3248 parseInterfaceIdentifierExpression(start, context));
3249 MOZ_TRY(guard.done());
3250
3251 return result;
3252 }
3253
3254 template <typename Tok>
parseInterfaceIdentifierExpression(const size_t start,const FieldOrListContext & context)3255 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceIdentifierExpression(
3256 const size_t start, const FieldOrListContext& context) {
3257 BINJS_TRY(CheckRecursionLimit(cx_));
3258
3259 RootedAtom name(cx_);
3260 MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(FieldContext(
3261 BinASTInterfaceAndField::IdentifierExpression__Name)));
3262
3263 BINJS_TRY(usedNames_.noteUse(cx_, name, pc_->scriptId(),
3264 pc_->innermostScope()->id()));
3265 BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
3266 tokenizer_->pos(start), cx_));
3267 return result;
3268 }
3269
3270 template <typename Tok>
parseInterfaceIfStatement(const size_t start,const FieldOrListContext & context)3271 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceIfStatement(
3272 const size_t start, const FieldOrListContext& context) {
3273 BINJS_TRY(CheckRecursionLimit(cx_));
3274
3275 BINJS_MOZ_TRY_DECL(test, parseExpression(FieldContext(
3276 BinASTInterfaceAndField::IfStatement__Test)));
3277
3278 BINJS_MOZ_TRY_DECL(consequent,
3279 parseStatement(FieldOrListContext(FieldContext(
3280 BinASTInterfaceAndField::IfStatement__Consequent))));
3281
3282 BINJS_MOZ_TRY_DECL(alternate,
3283 parseOptionalStatement(FieldContext(
3284 BinASTInterfaceAndField::IfStatement__Alternate)));
3285
3286 BINJS_TRY_DECL(result,
3287 handler_.newIfStatement(start, test, consequent, alternate));
3288 return result;
3289 }
3290
3291 template <typename Tok>
parseInterfaceLabelledStatement(const size_t start,const FieldOrListContext & context)3292 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLabelledStatement(
3293 const size_t start, const FieldOrListContext& context) {
3294 BINJS_TRY(CheckRecursionLimit(cx_));
3295
3296 RootedAtom label(cx_);
3297 MOZ_TRY_VAR(label, tokenizer_->readAtom(FieldContext(
3298 BinASTInterfaceAndField::LabelledStatement__Label)));
3299 if (!IsIdentifier(label)) {
3300 return raiseError("Invalid identifier");
3301 }
3302 ParseContext::LabelStatement stmt(pc_, label);
3303 BINJS_MOZ_TRY_DECL(body,
3304 parseStatement(FieldOrListContext(FieldContext(
3305 BinASTInterfaceAndField::LabelledStatement__Body))));
3306
3307 BINJS_TRY_DECL(result, handler_.newLabeledStatement(label->asPropertyName(),
3308 body, start));
3309 return result;
3310 }
3311
3312 template <typename Tok>
3313 JS::Result<ParseNode*>
parseInterfaceLazyArrowExpressionWithExpression(const size_t start,const FieldOrListContext & context)3314 BinASTParser<Tok>::parseInterfaceLazyArrowExpressionWithExpression(
3315 const size_t start, const FieldOrListContext& context) {
3316 return raiseError(
3317 "FIXME: Not implemented yet in this preview release "
3318 "(LazyArrowExpressionWithExpression)");
3319 }
3320
3321 template <typename Tok>
3322 JS::Result<ParseNode*>
parseInterfaceLazyArrowExpressionWithFunctionBody(const size_t start,const FieldOrListContext & context)3323 BinASTParser<Tok>::parseInterfaceLazyArrowExpressionWithFunctionBody(
3324 const size_t start, const FieldOrListContext& context) {
3325 return raiseError(
3326 "FIXME: Not implemented yet in this preview release "
3327 "(LazyArrowExpressionWithFunctionBody)");
3328 }
3329
3330 template <typename Tok>
parseInterfaceLazyFunctionDeclaration(const size_t start,const FieldOrListContext & context)3331 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyFunctionDeclaration(
3332 const size_t start, const FieldOrListContext& context) {
3333 BINJS_TRY(CheckRecursionLimit(cx_));
3334 const auto syntax = FunctionSyntaxKind::Statement;
3335
3336 BINJS_MOZ_TRY_DECL(
3337 isAsync, tokenizer_->readBool(FieldContext(
3338 BinASTInterfaceAndField::LazyFunctionDeclaration__IsAsync)));
3339 if (isAsync) {
3340 return raiseError(
3341 "Async function is not supported in this preview release");
3342 }
3343 BINJS_MOZ_TRY_DECL(
3344 isGenerator,
3345 tokenizer_->readBool(FieldContext(
3346 BinASTInterfaceAndField::LazyFunctionDeclaration__IsGenerator)));
3347 if (isGenerator) {
3348 return raiseError("Generator is not supported in this preview release");
3349 }
3350 BINJS_MOZ_TRY_DECL(
3351 name, parseBindingIdentifier(FieldOrListContext(FieldContext(
3352 BinASTInterfaceAndField::LazyFunctionDeclaration__Name))));
3353
3354 BINJS_MOZ_TRY_DECL(
3355 length, tokenizer_->readUnsignedLong(FieldContext(
3356 BinASTInterfaceAndField::LazyFunctionDeclaration__Length)));
3357
3358 BINJS_MOZ_TRY_DECL(
3359 directives,
3360 parseListOfDirective(FieldContext(
3361 BinASTInterfaceAndField::LazyFunctionDeclaration__Directives)));
3362
3363 BINJS_MOZ_TRY_DECL(
3364 contentsSkip,
3365 tokenizer_->readSkippableSubTree(FieldContext(
3366 BinASTInterfaceAndField::LazyFunctionDeclaration__ContentsSkip)));
3367 // Don't parse the contents until we delazify.
3368
3369 // TODO: This will become incorrect in the face of ES6 features.
3370 uint32_t nargs = length;
3371
3372 BINJS_MOZ_TRY_DECL(funbox,
3373 buildFunctionBox(isGenerator ? GeneratorKind::Generator
3374 : GeneratorKind::NotGenerator,
3375 isAsync ? FunctionAsyncKind::AsyncFunction
3376 : FunctionAsyncKind::SyncFunction,
3377 syntax, name));
3378
3379 forceStrictIfNecessary(funbox, directives);
3380
3381 pc_->sc()->setHasInnerFunctions();
3382
3383 BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(start, syntax, funbox));
3384
3385 auto skipStart = contentsSkip.startOffset();
3386 auto skipEnd = skipStart + contentsSkip.length();
3387 MOZ_TRY(finishLazyFunction(funbox, nargs, skipStart, skipEnd));
3388 return result;
3389 }
3390
3391 template <typename Tok>
parseInterfaceLazyFunctionExpression(const size_t start,const FieldOrListContext & context)3392 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyFunctionExpression(
3393 const size_t start, const FieldOrListContext& context) {
3394 BINJS_TRY(CheckRecursionLimit(cx_));
3395 const auto syntax = FunctionSyntaxKind::Expression;
3396
3397 BINJS_MOZ_TRY_DECL(
3398 isAsync, tokenizer_->readBool(FieldContext(
3399 BinASTInterfaceAndField::LazyFunctionExpression__IsAsync)));
3400 if (isAsync) {
3401 return raiseError(
3402 "Async function is not supported in this preview release");
3403 }
3404 BINJS_MOZ_TRY_DECL(
3405 isGenerator,
3406 tokenizer_->readBool(FieldContext(
3407 BinASTInterfaceAndField::LazyFunctionExpression__IsGenerator)));
3408 if (isGenerator) {
3409 return raiseError("Generator is not supported in this preview release");
3410 }
3411 BINJS_MOZ_TRY_DECL(
3412 name, parseOptionalBindingIdentifier(FieldContext(
3413 BinASTInterfaceAndField::LazyFunctionExpression__Name)));
3414
3415 BINJS_MOZ_TRY_DECL(
3416 length, tokenizer_->readUnsignedLong(FieldContext(
3417 BinASTInterfaceAndField::LazyFunctionExpression__Length)));
3418
3419 BINJS_MOZ_TRY_DECL(
3420 directives,
3421 parseListOfDirective(FieldContext(
3422 BinASTInterfaceAndField::LazyFunctionExpression__Directives)));
3423
3424 BINJS_MOZ_TRY_DECL(
3425 contentsSkip,
3426 tokenizer_->readSkippableSubTree(FieldContext(
3427 BinASTInterfaceAndField::LazyFunctionExpression__ContentsSkip)));
3428 // Don't parse the contents until we delazify.
3429
3430 // TODO: This will become incorrect in the face of ES6 features.
3431 uint32_t nargs = length;
3432
3433 BINJS_MOZ_TRY_DECL(funbox,
3434 buildFunctionBox(isGenerator ? GeneratorKind::Generator
3435 : GeneratorKind::NotGenerator,
3436 isAsync ? FunctionAsyncKind::AsyncFunction
3437 : FunctionAsyncKind::SyncFunction,
3438 syntax, name));
3439
3440 forceStrictIfNecessary(funbox, directives);
3441
3442 pc_->sc()->setHasInnerFunctions();
3443
3444 BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(start, syntax, funbox));
3445
3446 auto skipStart = contentsSkip.startOffset();
3447 auto skipEnd = skipStart + contentsSkip.length();
3448 MOZ_TRY(finishLazyFunction(funbox, nargs, skipStart, skipEnd));
3449 return result;
3450 }
3451
3452 template <typename Tok>
parseInterfaceLazyGetter(const size_t start,const ListContext & context)3453 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyGetter(
3454 const size_t start, const ListContext& context) {
3455 return raiseError(
3456 "FIXME: Not implemented yet in this preview release (LazyGetter)");
3457 }
3458
3459 template <typename Tok>
parseInterfaceLazyMethod(const size_t start,const ListContext & context)3460 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyMethod(
3461 const size_t start, const ListContext& context) {
3462 return raiseError(
3463 "FIXME: Not implemented yet in this preview release (LazyMethod)");
3464 }
3465
3466 template <typename Tok>
parseInterfaceLazySetter(const size_t start,const ListContext & context)3467 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazySetter(
3468 const size_t start, const ListContext& context) {
3469 return raiseError(
3470 "FIXME: Not implemented yet in this preview release (LazySetter)");
3471 }
3472
3473 template <typename Tok>
3474 JS::Result<ParseNode*>
parseInterfaceLiteralBooleanExpression(const size_t start,const FieldOrListContext & context)3475 BinASTParser<Tok>::parseInterfaceLiteralBooleanExpression(
3476 const size_t start, const FieldOrListContext& context) {
3477 BINJS_TRY(CheckRecursionLimit(cx_));
3478
3479 BINJS_MOZ_TRY_DECL(
3480 value, tokenizer_->readBool(FieldContext(
3481 BinASTInterfaceAndField::LiteralBooleanExpression__Value)));
3482
3483 BINJS_TRY_DECL(result,
3484 handler_.newBooleanLiteral(value, tokenizer_->pos(start)));
3485 return result;
3486 }
3487
3488 template <typename Tok>
3489 JS::Result<ParseNode*>
parseInterfaceLiteralInfinityExpression(const size_t start,const FieldOrListContext & context)3490 BinASTParser<Tok>::parseInterfaceLiteralInfinityExpression(
3491 const size_t start, const FieldOrListContext& context) {
3492 return raiseError(
3493 "FIXME: Not implemented yet in this preview release "
3494 "(LiteralInfinityExpression)");
3495 }
3496
3497 template <typename Tok>
parseInterfaceLiteralNullExpression(const size_t start,const FieldOrListContext & context)3498 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralNullExpression(
3499 const size_t start, const FieldOrListContext& context) {
3500 BINJS_TRY(CheckRecursionLimit(cx_));
3501
3502 BINJS_TRY_DECL(result, handler_.newNullLiteral(tokenizer_->pos(start)));
3503 return result;
3504 }
3505
3506 template <typename Tok>
3507 JS::Result<ParseNode*>
parseInterfaceLiteralNumericExpression(const size_t start,const FieldOrListContext & context)3508 BinASTParser<Tok>::parseInterfaceLiteralNumericExpression(
3509 const size_t start, const FieldOrListContext& context) {
3510 BINJS_TRY(CheckRecursionLimit(cx_));
3511
3512 BINJS_MOZ_TRY_DECL(
3513 value, tokenizer_->readDouble(FieldContext(
3514 BinASTInterfaceAndField::LiteralNumericExpression__Value)));
3515
3516 BINJS_TRY_DECL(result, handler_.newNumber(value, DecimalPoint::HasDecimal,
3517 tokenizer_->pos(start)));
3518 return result;
3519 }
3520
3521 template <typename Tok>
parseInterfaceLiteralPropertyName(const size_t start,const FieldContext & context)3522 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralPropertyName(
3523 const size_t start, const FieldContext& context) {
3524 BINJS_TRY(CheckRecursionLimit(cx_));
3525
3526 RootedAtom value(cx_);
3527 MOZ_TRY_VAR(value, tokenizer_->readAtom(FieldContext(
3528 BinASTInterfaceAndField::LiteralPropertyName__Value)));
3529
3530 ParseNode* result;
3531 uint32_t index;
3532 if (value->isIndex(&index)) {
3533 BINJS_TRY_VAR(result,
3534 handler_.newNumber(index, NoDecimal,
3535 TokenPos(start, tokenizer_->offset())));
3536 } else {
3537 BINJS_TRY_VAR(result, handler_.newObjectLiteralPropertyName(
3538 value, tokenizer_->pos(start)));
3539 }
3540 return result;
3541 }
3542
3543 template <typename Tok>
parseInterfaceLiteralRegExpExpression(const size_t start,const FieldOrListContext & context)3544 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralRegExpExpression(
3545 const size_t start, const FieldOrListContext& context) {
3546 BINJS_TRY(CheckRecursionLimit(cx_));
3547
3548 RootedAtom pattern(cx_);
3549 MOZ_TRY_VAR(pattern,
3550 tokenizer_->readAtom(FieldContext(
3551 BinASTInterfaceAndField::LiteralRegExpExpression__Pattern)));
3552 RegExpFlags reflags = JS::RegExpFlag::NoFlags;
3553 auto flagsContext =
3554 FieldContext(BinASTInterfaceAndField::LiteralRegExpExpression__Flags);
3555 if constexpr (std::is_same_v<Tok, BinASTTokenReaderContext>) {
3556 // Hack: optimized `readChars` is not implemented for
3557 // `BinASTTokenReaderContext`.
3558 RootedAtom flags(cx_);
3559 MOZ_TRY_VAR(flags, tokenizer_->readAtom(flagsContext));
3560 if (!this->parseRegExpFlags(flags, &reflags)) {
3561 return raiseError("Invalid regexp flags");
3562 }
3563 } else {
3564 Chars flags(cx_);
3565 MOZ_TRY(tokenizer_->readChars(flags, flagsContext));
3566 if (!this->parseRegExpFlags(flags, &reflags)) {
3567 return raiseError("Invalid regexp flags");
3568 }
3569 }
3570
3571 // Validate the RegExp pattern is valid.
3572 {
3573 JS::CompileOptions dummyOptions(cx_);
3574 DummyTokenStream dummyTokenStream(cx_, dummyOptions);
3575
3576 LifoAllocScope allocScope(&cx_->tempLifoAlloc());
3577 #ifdef ENABLE_NEW_REGEXP
3578 BINJS_TRY(
3579 irregexp::CheckPatternSyntax(cx_, dummyTokenStream, pattern, reflags));
3580 #else
3581 BINJS_TRY(irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(),
3582 pattern, reflags.unicode()));
3583 #endif
3584 }
3585
3586 RegExpIndex index(this->getCompilationInfo().regExpData.length());
3587 BINJS_TRY(this->getCompilationInfo().regExpData.emplaceBack());
3588 BINJS_TRY(
3589 this->getCompilationInfo().regExpData[index].init(cx_, pattern, reflags));
3590
3591 return handler_.newRegExp(index, tokenizer_->pos(start));
3592 }
3593
3594 template <typename Tok>
parseInterfaceLiteralStringExpression(const size_t start,const FieldOrListContext & context)3595 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralStringExpression(
3596 const size_t start, const FieldOrListContext& context) {
3597 BINJS_TRY(CheckRecursionLimit(cx_));
3598
3599 RootedAtom value(cx_);
3600 MOZ_TRY_VAR(value,
3601 tokenizer_->readAtom(FieldContext(
3602 BinASTInterfaceAndField::LiteralStringExpression__Value)));
3603
3604 BINJS_TRY_DECL(result,
3605 handler_.newStringLiteral(value, tokenizer_->pos(start)));
3606 return result;
3607 }
3608
3609 template <typename Tok>
parseInterfaceModule(const size_t start,const RootContext & context)3610 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceModule(
3611 const size_t start, const RootContext& context) {
3612 return raiseError(
3613 "FIXME: Not implemented yet in this preview release (Module)");
3614 }
3615
3616 template <typename Tok>
parseInterfaceNewExpression(const size_t start,const FieldOrListContext & context)3617 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceNewExpression(
3618 const size_t start, const FieldOrListContext& context) {
3619 BINJS_TRY(CheckRecursionLimit(cx_));
3620
3621 BINJS_MOZ_TRY_DECL(callee,
3622 parseExpression(FieldContext(
3623 BinASTInterfaceAndField::NewExpression__Callee)));
3624
3625 BINJS_MOZ_TRY_DECL(arguments,
3626 parseArguments(FieldContext(
3627 BinASTInterfaceAndField::NewExpression__Arguments)));
3628
3629 BINJS_TRY_DECL(result,
3630 handler_.newNewExpression(tokenizer_->pos(start).begin, callee,
3631 arguments, /* isSpread = */ false));
3632 return result;
3633 }
3634
3635 template <typename Tok>
parseInterfaceNewTargetExpression(const size_t start,const FieldOrListContext & context)3636 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceNewTargetExpression(
3637 const size_t start, const FieldOrListContext& context) {
3638 return raiseError(
3639 "FIXME: Not implemented yet in this preview release "
3640 "(NewTargetExpression)");
3641 }
3642
3643 template <typename Tok>
parseInterfaceObjectAssignmentTarget(const size_t start,const FieldContext & context)3644 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceObjectAssignmentTarget(
3645 const size_t start, const FieldContext& context) {
3646 return raiseError(
3647 "FIXME: Not implemented yet in this preview release "
3648 "(ObjectAssignmentTarget)");
3649 }
3650
3651 template <typename Tok>
parseInterfaceObjectBinding(const size_t start,const FieldOrListContext & context)3652 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceObjectBinding(
3653 const size_t start, const FieldOrListContext& context) {
3654 return raiseError(
3655 "FIXME: Not implemented yet in this preview release (ObjectBinding)");
3656 }
3657
3658 template <typename Tok>
parseInterfaceObjectExpression(const size_t start,const FieldOrListContext & context)3659 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceObjectExpression(
3660 const size_t start, const FieldOrListContext& context) {
3661 BINJS_TRY(CheckRecursionLimit(cx_));
3662
3663 BINJS_MOZ_TRY_DECL(
3664 properties, parseListOfObjectProperty(FieldContext(
3665 BinASTInterfaceAndField::ObjectExpression__Properties)));
3666
3667 auto result = properties;
3668 return result;
3669 }
3670
3671 template <typename Tok>
parseInterfaceReturnStatement(const size_t start,const FieldOrListContext & context)3672 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceReturnStatement(
3673 const size_t start, const FieldOrListContext& context) {
3674 BINJS_TRY(CheckRecursionLimit(cx_));
3675 if (!pc_->isFunctionBox()) {
3676 // Return statements are permitted only inside functions.
3677 return raiseInvalidKind("Toplevel Statement", BinASTKind::ReturnStatement);
3678 }
3679
3680 pc_->functionBox()->usesReturn = true;
3681
3682 BINJS_MOZ_TRY_DECL(
3683 expression, parseOptionalExpression(FieldContext(
3684 BinASTInterfaceAndField::ReturnStatement__Expression)));
3685
3686 BINJS_TRY_DECL(
3687 result, handler_.newReturnStatement(expression, tokenizer_->pos(start)));
3688 return result;
3689 }
3690
3691 template <typename Tok>
parseInterfaceScript(const size_t start,const RootContext & context)3692 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceScript(
3693 const size_t start, const RootContext& context) {
3694 BINJS_TRY(CheckRecursionLimit(cx_));
3695
3696 MOZ_TRY(parseAssertedScriptGlobalScope(
3697 FieldContext(BinASTInterfaceAndField::Script__Scope)));
3698
3699 BINJS_MOZ_TRY_DECL(directives,
3700 parseListOfDirective(FieldContext(
3701 BinASTInterfaceAndField::Script__Directives)));
3702 forceStrictIfNecessary(pc_->sc(), directives);
3703 BINJS_MOZ_TRY_DECL(statements,
3704 parseListOfStatement(FieldContext(
3705 BinASTInterfaceAndField::Script__Statements)));
3706
3707 MOZ_TRY(checkClosedVars(pc_->varScope()));
3708 MOZ_TRY(prependDirectivesToBody(/* body = */ statements, directives));
3709 auto result = statements;
3710 return result;
3711 }
3712
3713 /*
3714 interface SetterContents : Node {
3715 bool isThisCaptured;
3716 AssertedParameterScope parameterScope;
3717 Parameter param;
3718 AssertedVarScope bodyScope;
3719 FunctionBody body;
3720 }
3721 */
3722 template <typename Tok>
parseSetterContents(uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldContext & context)3723 JS::Result<Ok> BinASTParser<Tok>::parseSetterContents(
3724 uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
3725 const FieldContext& context) {
3726 BinASTKind kind = BinASTKind::SetterContents;
3727 AutoTaggedTuple guard(*tokenizer_);
3728
3729 guard.init();
3730 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3731 const auto start = tokenizer_->offset();
3732 BINJS_MOZ_TRY_DECL(
3733 result, parseInterfaceSetterContents(start, funLength, paramsOut, bodyOut,
3734 context));
3735 MOZ_TRY(guard.done());
3736
3737 return result;
3738 }
3739
3740 template <typename Tok>
parseInterfaceSetterContents(const size_t start,uint32_t funLength,ListNode ** paramsOut,ListNode ** bodyOut,const FieldContext & context)3741 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceSetterContents(
3742 const size_t start, uint32_t funLength, ListNode** paramsOut,
3743 ListNode** bodyOut, const FieldContext& context) {
3744 BINJS_TRY(CheckRecursionLimit(cx_));
3745
3746 BINJS_MOZ_TRY_DECL(
3747 isThisCaptured,
3748 tokenizer_->readBool(FieldContext(
3749 BinASTInterfaceAndField::SetterContents__IsThisCaptured)));
3750 // TODO: Use this in BinASTParser::buildFunction.
3751 (void)isThisCaptured;
3752 Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
3753 MOZ_TRY(parseAssertedParameterScope(
3754 &positionalParams,
3755 FieldContext(BinASTInterfaceAndField::SetterContents__ParameterScope)));
3756
3757 BINJS_MOZ_TRY_DECL(param,
3758 parseParameter(FieldOrListContext(FieldContext(
3759 BinASTInterfaceAndField::SetterContents__Param))));
3760 BINJS_TRY_DECL(params, handler_.newParamsBody(param->pn_pos));
3761 handler_.addList(params, param);
3762 MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
3763 MOZ_TRY(parseAssertedVarScope(
3764 FieldContext(BinASTInterfaceAndField::SetterContents__BodyScope)));
3765
3766 BINJS_MOZ_TRY_DECL(body, parseFunctionBody(FieldContext(
3767 BinASTInterfaceAndField::SetterContents__Body)));
3768
3769 *paramsOut = params;
3770 *bodyOut = body;
3771 auto result = Ok();
3772 return result;
3773 }
3774
3775 template <typename Tok>
parseInterfaceShorthandProperty(const size_t start,const ListContext & context)3776 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceShorthandProperty(
3777 const size_t start, const ListContext& context) {
3778 BINJS_TRY(CheckRecursionLimit(cx_));
3779
3780 BINJS_MOZ_TRY_DECL(name,
3781 parseIdentifierExpression(FieldOrListContext(FieldContext(
3782 BinASTInterfaceAndField::ShorthandProperty__Name))));
3783
3784 MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
3785 MOZ_ASSERT(!handler_.isUsableAsObjectPropertyName(name));
3786 BINJS_TRY_DECL(propName, handler_.newObjectLiteralPropertyName(
3787 name->template as<NameNode>().name(),
3788 tokenizer_->pos(start)));
3789
3790 BINJS_TRY_DECL(result,
3791 handler_.newShorthandPropertyDefinition(propName, name));
3792 return result;
3793 }
3794
3795 template <typename Tok>
parseInterfaceSpreadElement(const size_t start,const ListContext & context)3796 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceSpreadElement(
3797 const size_t start, const ListContext& context) {
3798 return raiseError(
3799 "FIXME: Not implemented yet in this preview release (SpreadElement)");
3800 }
3801
3802 template <typename Tok>
3803 JS::Result<ParseNode*>
parseInterfaceStaticMemberAssignmentTarget(const size_t start,const FieldContext & context)3804 BinASTParser<Tok>::parseInterfaceStaticMemberAssignmentTarget(
3805 const size_t start, const FieldContext& context) {
3806 BINJS_TRY(CheckRecursionLimit(cx_));
3807 size_t nameStart;
3808
3809 BINJS_MOZ_TRY_DECL(
3810 object,
3811 parseExpressionOrSuper(FieldContext(
3812 BinASTInterfaceAndField::StaticMemberAssignmentTarget__Object)));
3813
3814 RootedAtom property(cx_);
3815 {
3816 nameStart = tokenizer_->offset();
3817 MOZ_TRY_VAR(
3818 property,
3819 tokenizer_->readPropertyKey(FieldContext(
3820 BinASTInterfaceAndField::StaticMemberAssignmentTarget__Property)));
3821 }
3822
3823 BINJS_TRY_DECL(name, handler_.newPropertyName(property->asPropertyName(),
3824 tokenizer_->pos(nameStart)));
3825 BINJS_TRY_DECL(result, handler_.newPropertyAccess(object, name));
3826 return result;
3827 }
3828
3829 template <typename Tok>
parseInterfaceStaticMemberExpression(const size_t start,const FieldOrListContext & context)3830 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceStaticMemberExpression(
3831 const size_t start, const FieldOrListContext& context) {
3832 BINJS_TRY(CheckRecursionLimit(cx_));
3833 size_t nameStart;
3834
3835 BINJS_MOZ_TRY_DECL(
3836 object, parseExpressionOrSuper(FieldContext(
3837 BinASTInterfaceAndField::StaticMemberExpression__Object)));
3838
3839 RootedAtom property(cx_);
3840 {
3841 nameStart = tokenizer_->offset();
3842 MOZ_TRY_VAR(
3843 property,
3844 tokenizer_->readPropertyKey(FieldContext(
3845 BinASTInterfaceAndField::StaticMemberExpression__Property)));
3846 }
3847
3848 BINJS_TRY_DECL(name, handler_.newPropertyName(property->asPropertyName(),
3849 tokenizer_->pos(nameStart)));
3850 BINJS_TRY_DECL(result, handler_.newPropertyAccess(object, name));
3851 return result;
3852 }
3853
3854 template <typename Tok>
parseInterfaceSuper(const size_t start,const FieldContext & context)3855 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceSuper(
3856 const size_t start, const FieldContext& context) {
3857 return raiseError(
3858 "FIXME: Not implemented yet in this preview release (Super)");
3859 }
3860
3861 /*
3862 interface SwitchCase : Node {
3863 Expression test;
3864 FrozenArray<Statement> consequent;
3865 }
3866 */
3867 template <typename Tok>
parseSwitchCase(const ListContext & context)3868 JS::Result<CaseClause*> BinASTParser<Tok>::parseSwitchCase(
3869 const ListContext& context) {
3870 BinASTKind kind = BinASTKind::SwitchCase;
3871 AutoTaggedTuple guard(*tokenizer_);
3872
3873 guard.init();
3874 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3875 const auto start = tokenizer_->offset();
3876 BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchCase(start, context));
3877 MOZ_TRY(guard.done());
3878
3879 return result;
3880 }
3881
3882 template <typename Tok>
parseInterfaceSwitchCase(const size_t start,const ListContext & context)3883 JS::Result<CaseClause*> BinASTParser<Tok>::parseInterfaceSwitchCase(
3884 const size_t start, const ListContext& context) {
3885 BINJS_TRY(CheckRecursionLimit(cx_));
3886
3887 BINJS_MOZ_TRY_DECL(
3888 test,
3889 parseExpression(FieldContext(BinASTInterfaceAndField::SwitchCase__Test)));
3890
3891 BINJS_MOZ_TRY_DECL(consequent,
3892 parseListOfStatement(FieldContext(
3893 BinASTInterfaceAndField::SwitchCase__Consequent)));
3894
3895 BINJS_TRY_DECL(result, handler_.newCaseOrDefault(start, test, consequent));
3896 return result;
3897 }
3898
3899 /*
3900 interface SwitchDefault : Node {
3901 FrozenArray<Statement> consequent;
3902 }
3903 */
3904 template <typename Tok>
parseSwitchDefault(const FieldContext & context)3905 JS::Result<ParseNode*> BinASTParser<Tok>::parseSwitchDefault(
3906 const FieldContext& context) {
3907 BinASTKind kind = BinASTKind::SwitchDefault;
3908 AutoTaggedTuple guard(*tokenizer_);
3909
3910 guard.init();
3911 MOZ_TRY(tokenizer_->enterInterface(kind, context));
3912 const auto start = tokenizer_->offset();
3913 BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchDefault(start, context));
3914 MOZ_TRY(guard.done());
3915
3916 return result;
3917 }
3918
3919 template <typename Tok>
parseInterfaceSwitchDefault(const size_t start,const FieldContext & context)3920 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceSwitchDefault(
3921 const size_t start, const FieldContext& context) {
3922 BINJS_TRY(CheckRecursionLimit(cx_));
3923
3924 BINJS_MOZ_TRY_DECL(consequent,
3925 parseListOfStatement(FieldContext(
3926 BinASTInterfaceAndField::SwitchDefault__Consequent)));
3927
3928 BINJS_TRY_DECL(result, handler_.newCaseOrDefault(start, nullptr, consequent));
3929 return result;
3930 }
3931
3932 template <typename Tok>
parseInterfaceSwitchStatement(const size_t start,const FieldOrListContext & context)3933 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceSwitchStatement(
3934 const size_t start, const FieldOrListContext& context) {
3935 BINJS_TRY(CheckRecursionLimit(cx_));
3936
3937 BINJS_MOZ_TRY_DECL(
3938 discriminant,
3939 parseExpression(FieldContext(
3940 BinASTInterfaceAndField::SwitchStatement__Discriminant)));
3941 ParseContext::Statement stmt(pc_, StatementKind::Switch);
3942 BINJS_MOZ_TRY_DECL(cases,
3943 parseListOfSwitchCase(FieldContext(
3944 BinASTInterfaceAndField::SwitchStatement__Cases)));
3945
3946 BINJS_TRY_DECL(scope, handler_.newLexicalScope(nullptr, cases));
3947 BINJS_TRY_DECL(result, handler_.newSwitchStatement(start, discriminant, scope,
3948 /* hasDefault = */ false));
3949 return result;
3950 }
3951
3952 template <typename Tok>
3953 JS::Result<ParseNode*>
parseInterfaceSwitchStatementWithDefault(const size_t start,const FieldOrListContext & context)3954 BinASTParser<Tok>::parseInterfaceSwitchStatementWithDefault(
3955 const size_t start, const FieldOrListContext& context) {
3956 BINJS_TRY(CheckRecursionLimit(cx_));
3957
3958 BINJS_MOZ_TRY_DECL(
3959 discriminant,
3960 parseExpression(FieldContext(
3961 BinASTInterfaceAndField::SwitchStatementWithDefault__Discriminant)));
3962 ParseContext::Statement stmt(pc_, StatementKind::Switch);
3963 BINJS_MOZ_TRY_DECL(preDefaultCases,
3964 parseListOfSwitchCase(FieldContext(
3965 BinASTInterfaceAndField::
3966 SwitchStatementWithDefault__PreDefaultCases)));
3967
3968 BINJS_MOZ_TRY_DECL(
3969 defaultCase,
3970 parseSwitchDefault(FieldContext(
3971 BinASTInterfaceAndField::SwitchStatementWithDefault__DefaultCase)));
3972
3973 BINJS_MOZ_TRY_DECL(postDefaultCases,
3974 parseListOfSwitchCase(FieldContext(
3975 BinASTInterfaceAndField::
3976 SwitchStatementWithDefault__PostDefaultCases)));
3977
3978 // Concatenate `preDefaultCase`, `defaultCase`, `postDefaultCase`
3979 auto cases = preDefaultCases;
3980 handler_.addList(cases, defaultCase);
3981 ParseNode* iter = postDefaultCases->head();
3982 while (iter) {
3983 ParseNode* next = iter->pn_next;
3984 handler_.addList(cases, iter);
3985 iter = next;
3986 }
3987 BINJS_TRY_DECL(scope, handler_.newLexicalScope(nullptr, cases));
3988 BINJS_TRY_DECL(result, handler_.newSwitchStatement(start, discriminant, scope,
3989 /* hasDefault = */ true));
3990 return result;
3991 }
3992
3993 template <typename Tok>
parseInterfaceTemplateExpression(const size_t start,const FieldOrListContext & context)3994 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceTemplateExpression(
3995 const size_t start, const FieldOrListContext& context) {
3996 return raiseError(
3997 "FIXME: Not implemented yet in this preview release "
3998 "(TemplateExpression)");
3999 }
4000
4001 template <typename Tok>
parseInterfaceThisExpression(const size_t start,const FieldOrListContext & context)4002 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceThisExpression(
4003 const size_t start, const FieldOrListContext& context) {
4004 BINJS_TRY(CheckRecursionLimit(cx_));
4005
4006 if (pc_->isFunctionBox()) {
4007 pc_->functionBox()->usesThis = true;
4008 }
4009
4010 TokenPos pos = tokenizer_->pos(start);
4011 ParseNode* thisName(nullptr);
4012 if (pc_->sc()->hasFunctionThisBinding()) {
4013 HandlePropertyName dotThis = cx_->names().dotThis;
4014 BINJS_TRY(usedNames_.noteUse(cx_, dotThis, pc_->scriptId(),
4015 pc_->innermostScope()->id()));
4016 BINJS_TRY_VAR(thisName, handler_.newName(dotThis, pos, cx_));
4017 }
4018
4019 BINJS_TRY_DECL(result, handler_.newThisLiteral(pos, thisName));
4020 return result;
4021 }
4022
4023 template <typename Tok>
parseInterfaceThrowStatement(const size_t start,const FieldOrListContext & context)4024 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceThrowStatement(
4025 const size_t start, const FieldOrListContext& context) {
4026 BINJS_TRY(CheckRecursionLimit(cx_));
4027
4028 BINJS_MOZ_TRY_DECL(expression,
4029 parseExpression(FieldContext(
4030 BinASTInterfaceAndField::ThrowStatement__Expression)));
4031
4032 BINJS_TRY_DECL(
4033 result, handler_.newThrowStatement(expression, tokenizer_->pos(start)));
4034 return result;
4035 }
4036
4037 template <typename Tok>
parseInterfaceTryCatchStatement(const size_t start,const FieldOrListContext & context)4038 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceTryCatchStatement(
4039 const size_t start, const FieldOrListContext& context) {
4040 BINJS_TRY(CheckRecursionLimit(cx_));
4041
4042 ParseNode* body;
4043 {
4044 ParseContext::Statement stmt(pc_, StatementKind::Try);
4045 ParseContext::Scope scope(cx_, pc_, usedNames_);
4046 BINJS_TRY(scope.init(pc_));
4047 MOZ_TRY_VAR(body, parseBlock(FieldOrListContext(FieldContext(
4048 BinASTInterfaceAndField::TryCatchStatement__Body))));
4049 }
4050
4051 BINJS_MOZ_TRY_DECL(
4052 catchClause,
4053 parseCatchClause(FieldContext(
4054 BinASTInterfaceAndField::TryCatchStatement__CatchClause)));
4055
4056 BINJS_TRY_DECL(result,
4057 handler_.newTryStatement(start, body, catchClause,
4058 /* finallyBlock = */ nullptr));
4059 return result;
4060 }
4061
4062 template <typename Tok>
parseInterfaceTryFinallyStatement(const size_t start,const FieldOrListContext & context)4063 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceTryFinallyStatement(
4064 const size_t start, const FieldOrListContext& context) {
4065 BINJS_TRY(CheckRecursionLimit(cx_));
4066
4067 ParseNode* body;
4068 {
4069 ParseContext::Statement stmt(pc_, StatementKind::Try);
4070 ParseContext::Scope scope(cx_, pc_, usedNames_);
4071 BINJS_TRY(scope.init(pc_));
4072 MOZ_TRY_VAR(body,
4073 parseBlock(FieldOrListContext(FieldContext(
4074 BinASTInterfaceAndField::TryFinallyStatement__Body))));
4075 }
4076
4077 BINJS_MOZ_TRY_DECL(
4078 catchClause,
4079 parseOptionalCatchClause(FieldContext(
4080 BinASTInterfaceAndField::TryFinallyStatement__CatchClause)));
4081
4082 ParseNode* finalizer;
4083 {
4084 ParseContext::Statement stmt(pc_, StatementKind::Finally);
4085 ParseContext::Scope scope(cx_, pc_, usedNames_);
4086 BINJS_TRY(scope.init(pc_));
4087 MOZ_TRY_VAR(finalizer,
4088 parseBlock(FieldOrListContext(FieldContext(
4089 BinASTInterfaceAndField::TryFinallyStatement__Finalizer))));
4090 }
4091
4092 BINJS_TRY_DECL(result,
4093 handler_.newTryStatement(start, body, catchClause, finalizer));
4094 return result;
4095 }
4096
4097 template <typename Tok>
parseInterfaceUnaryExpression(const size_t start,const FieldOrListContext & context)4098 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceUnaryExpression(
4099 const size_t start, const FieldOrListContext& context) {
4100 BINJS_TRY(CheckRecursionLimit(cx_));
4101
4102 BINJS_MOZ_TRY_DECL(operator_,
4103 parseUnaryOperator(FieldContext(
4104 BinASTInterfaceAndField::UnaryExpression__Operator)));
4105
4106 BINJS_MOZ_TRY_DECL(operand,
4107 parseExpression(FieldContext(
4108 BinASTInterfaceAndField::UnaryExpression__Operand)));
4109
4110 ParseNodeKind pnk;
4111 switch (operator_) {
4112 case UnaryOperator::Minus:
4113 pnk = ParseNodeKind::NegExpr;
4114 break;
4115 case UnaryOperator::Plus:
4116 pnk = ParseNodeKind::PosExpr;
4117 break;
4118 case UnaryOperator::Not:
4119 pnk = ParseNodeKind::NotExpr;
4120 break;
4121 case UnaryOperator::BitNot:
4122 pnk = ParseNodeKind::BitNotExpr;
4123 break;
4124 case UnaryOperator::Typeof: {
4125 if (operand->isKind(ParseNodeKind::Name)) {
4126 pnk = ParseNodeKind::TypeOfNameExpr;
4127 } else {
4128 pnk = ParseNodeKind::TypeOfExpr;
4129 }
4130 break;
4131 }
4132 case UnaryOperator::Void:
4133 pnk = ParseNodeKind::VoidExpr;
4134 break;
4135 case UnaryOperator::Delete: {
4136 switch (operand->getKind()) {
4137 case ParseNodeKind::Name:
4138 pnk = ParseNodeKind::DeleteNameExpr;
4139 BINJS_TRY(this->strictModeError(JSMSG_DEPRECATED_DELETE_OPERAND));
4140 pc_->sc()->setBindingsAccessedDynamically();
4141 break;
4142 case ParseNodeKind::DotExpr:
4143 pnk = ParseNodeKind::DeletePropExpr;
4144 break;
4145 case ParseNodeKind::ElemExpr:
4146 pnk = ParseNodeKind::DeleteElemExpr;
4147 break;
4148 default:
4149 pnk = ParseNodeKind::DeleteExpr;
4150 }
4151 break;
4152 }
4153 }
4154 BINJS_TRY_DECL(result, handler_.newUnary(pnk, start, operand));
4155 return result;
4156 }
4157
4158 template <typename Tok>
parseInterfaceUpdateExpression(const size_t start,const FieldOrListContext & context)4159 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceUpdateExpression(
4160 const size_t start, const FieldOrListContext& context) {
4161 BINJS_TRY(CheckRecursionLimit(cx_));
4162
4163 BINJS_MOZ_TRY_DECL(isPrefix,
4164 tokenizer_->readBool(FieldContext(
4165 BinASTInterfaceAndField::UpdateExpression__IsPrefix)));
4166
4167 BINJS_MOZ_TRY_DECL(operator_,
4168 parseUpdateOperator(FieldContext(
4169 BinASTInterfaceAndField::UpdateExpression__Operator)));
4170
4171 BINJS_MOZ_TRY_DECL(operand,
4172 parseSimpleAssignmentTarget(FieldContext(
4173 BinASTInterfaceAndField::UpdateExpression__Operand)));
4174
4175 ParseNodeKind pnk;
4176 switch (operator_) {
4177 case UpdateOperator::Incr:
4178 pnk = isPrefix ? ParseNodeKind::PreIncrementExpr
4179 : ParseNodeKind::PostIncrementExpr;
4180 break;
4181 case UpdateOperator::Decr:
4182 pnk = isPrefix ? ParseNodeKind::PreDecrementExpr
4183 : ParseNodeKind::PostDecrementExpr;
4184 break;
4185 }
4186 BINJS_TRY_DECL(result, handler_.newUnary(pnk, start, operand));
4187 return result;
4188 }
4189
4190 template <typename Tok>
parseInterfaceVariableDeclaration(const size_t start,const FieldOrListContext & context)4191 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclaration(
4192 const size_t start, const FieldOrListContext& context) {
4193 BINJS_TRY(CheckRecursionLimit(cx_));
4194 AutoVariableDeclarationKind kindGuard(this);
4195
4196 BINJS_MOZ_TRY_DECL(kind_,
4197 parseVariableDeclarationKind(FieldContext(
4198 BinASTInterfaceAndField::VariableDeclaration__Kind)));
4199 // Restored by `kindGuard`.
4200 variableDeclarationKind_ = kind_;
4201 ParseNodeKind declarationListKind;
4202 switch (kind_) {
4203 case VariableDeclarationKind::Var:
4204 declarationListKind = ParseNodeKind::VarStmt;
4205 break;
4206 case VariableDeclarationKind::Let:
4207 return raiseError("Let is not supported in this preview release");
4208 case VariableDeclarationKind::Const:
4209 return raiseError("Const is not supported in this preview release");
4210 }
4211 BINJS_MOZ_TRY_DECL(
4212 declarators,
4213 parseListOfVariableDeclarator(
4214 declarationListKind,
4215 FieldContext(
4216 BinASTInterfaceAndField::VariableDeclaration__Declarators)));
4217
4218 // By specification, the list may not be empty.
4219 if (declarators->empty()) {
4220 return raiseEmpty("VariableDeclaration");
4221 }
4222
4223 auto result = declarators;
4224 return result;
4225 }
4226
4227 /*
4228 interface VariableDeclarator : Node {
4229 Binding binding;
4230 Expression? init;
4231 }
4232 */
4233 template <typename Tok>
parseVariableDeclarator(const ListContext & context)4234 JS::Result<ParseNode*> BinASTParser<Tok>::parseVariableDeclarator(
4235 const ListContext& context) {
4236 BinASTKind kind = BinASTKind::VariableDeclarator;
4237 AutoTaggedTuple guard(*tokenizer_);
4238
4239 guard.init();
4240 MOZ_TRY(tokenizer_->enterInterface(kind, context));
4241 const auto start = tokenizer_->offset();
4242 BINJS_MOZ_TRY_DECL(result, parseInterfaceVariableDeclarator(start, context));
4243 MOZ_TRY(guard.done());
4244
4245 return result;
4246 }
4247
4248 template <typename Tok>
parseInterfaceVariableDeclarator(const size_t start,const ListContext & context)4249 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclarator(
4250 const size_t start, const ListContext& context) {
4251 BINJS_TRY(CheckRecursionLimit(cx_));
4252
4253 BINJS_MOZ_TRY_DECL(
4254 binding, parseBinding(FieldContext(
4255 BinASTInterfaceAndField::VariableDeclarator__Binding)));
4256
4257 BINJS_MOZ_TRY_DECL(init,
4258 parseOptionalExpression(FieldContext(
4259 BinASTInterfaceAndField::VariableDeclarator__Init)));
4260
4261 ParseNode* result;
4262 if (binding->isKind(ParseNodeKind::Name)) {
4263 // `var foo [= bar]``
4264 NameNode* bindingNameNode = &binding->template as<NameNode>();
4265 MOZ_TRY(checkBinding(bindingNameNode->atom()->asPropertyName()));
4266 if (init) {
4267 BINJS_TRY_VAR(
4268 result, handler_.finishInitializerAssignment(bindingNameNode, init));
4269 } else {
4270 result = bindingNameNode;
4271 }
4272 } else {
4273 // `var pattern = bar`
4274 if (!init) {
4275 // Here, `init` is required.
4276 return raiseMissingField("VariableDeclarator (with non-trivial pattern)",
4277 BinASTField::Init);
4278 }
4279
4280 MOZ_CRASH(
4281 "Unimplemented: AssertedScope check for BindingPattern variable "
4282 "declaration");
4283 BINJS_TRY_VAR(result, handler_.newAssignment(ParseNodeKind::AssignExpr,
4284 binding, init));
4285 }
4286 return result;
4287 }
4288
4289 template <typename Tok>
parseInterfaceWhileStatement(const size_t start,const FieldOrListContext & context)4290 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceWhileStatement(
4291 const size_t start, const FieldOrListContext& context) {
4292 BINJS_TRY(CheckRecursionLimit(cx_));
4293 ParseContext::Statement stmt(pc_, StatementKind::WhileLoop);
4294
4295 BINJS_MOZ_TRY_DECL(test, parseExpression(FieldContext(
4296 BinASTInterfaceAndField::WhileStatement__Test)));
4297
4298 BINJS_MOZ_TRY_DECL(
4299 body, parseStatement(FieldOrListContext(
4300 FieldContext(BinASTInterfaceAndField::WhileStatement__Body))));
4301
4302 BINJS_TRY_DECL(result, handler_.newWhileStatement(start, test, body));
4303 return result;
4304 }
4305
4306 template <typename Tok>
parseInterfaceWithStatement(const size_t start,const FieldOrListContext & context)4307 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceWithStatement(
4308 const size_t start, const FieldOrListContext& context) {
4309 BINJS_TRY(CheckRecursionLimit(cx_));
4310
4311 BINJS_MOZ_TRY_DECL(object,
4312 parseExpression(FieldContext(
4313 BinASTInterfaceAndField::WithStatement__Object)));
4314
4315 ParseContext::Statement stmt(pc_, StatementKind::With);
4316 BINJS_MOZ_TRY_DECL(body, parseStatement(FieldOrListContext(FieldContext(
4317 BinASTInterfaceAndField::WithStatement__Body))));
4318
4319 pc_->sc()->setBindingsAccessedDynamically();
4320 BINJS_TRY_DECL(result, handler_.newWithStatement(start, object, body));
4321 return result;
4322 }
4323
4324 template <typename Tok>
parseInterfaceYieldExpression(const size_t start,const FieldOrListContext & context)4325 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceYieldExpression(
4326 const size_t start, const FieldOrListContext& context) {
4327 return raiseError(
4328 "FIXME: Not implemented yet in this preview release (YieldExpression)");
4329 }
4330
4331 template <typename Tok>
parseInterfaceYieldStarExpression(const size_t start,const FieldOrListContext & context)4332 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceYieldStarExpression(
4333 const size_t start, const FieldOrListContext& context) {
4334 return raiseError(
4335 "FIXME: Not implemented yet in this preview release "
4336 "(YieldStarExpression)");
4337 }
4338
4339 // ----- String enums (autogenerated, by lexicographical order)
4340 /*
4341 enum AssertedDeclaredKind {
4342 "var",
4343 "non-const lexical",
4344 "const lexical"
4345 };
4346 */
4347 template <typename Tok>
4348 JS::Result<typename BinASTParser<Tok>::AssertedDeclaredKind>
parseAssertedDeclaredKind(const FieldContext & context)4349 BinASTParser<Tok>::parseAssertedDeclaredKind(const FieldContext& context) {
4350 BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant(context));
4351
4352 switch (variant) {
4353 case BinASTVariant::AssertedDeclaredKindOrVariableDeclarationKindVar:
4354 return AssertedDeclaredKind::Var;
4355 case BinASTVariant::AssertedDeclaredKindNonConstLexical:
4356 return AssertedDeclaredKind::NonConstLexical;
4357 case BinASTVariant::AssertedDeclaredKindConstLexical:
4358 return AssertedDeclaredKind::ConstLexical;
4359 default:
4360 if (isInvalidVariantPossible()) {
4361 return raiseInvalidVariant("AssertedDeclaredKind", variant);
4362 } else {
4363 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4364 "invalid BinASTVariant should not appear");
4365 }
4366 }
4367 }
4368
4369 /*
4370 enum BinaryOperator {
4371 ",",
4372 "||",
4373 "&&",
4374 "|",
4375 "^",
4376 "&",
4377 "==",
4378 "!=",
4379 "===",
4380 "!==",
4381 "<",
4382 "<=",
4383 ">",
4384 ">=",
4385 "in",
4386 "instanceof",
4387 "<<",
4388 ">>",
4389 ">>>",
4390 "+",
4391 "-",
4392 "*",
4393 "/",
4394 "%",
4395 "**"
4396 };
4397 */
4398 template <typename Tok>
4399 JS::Result<typename BinASTParser<Tok>::BinaryOperator>
parseBinaryOperator(const FieldContext & context)4400 BinASTParser<Tok>::parseBinaryOperator(const FieldContext& context) {
4401 BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant(context));
4402
4403 switch (variant) {
4404 case BinASTVariant::BinaryOperatorComma:
4405 return BinaryOperator::Comma;
4406 case BinASTVariant::BinaryOperatorLogicalOr:
4407 return BinaryOperator::LogicalOr;
4408 case BinASTVariant::BinaryOperatorLogicalAnd:
4409 return BinaryOperator::LogicalAnd;
4410 case BinASTVariant::BinaryOperatorBitOr:
4411 return BinaryOperator::BitOr;
4412 case BinASTVariant::BinaryOperatorBitXor:
4413 return BinaryOperator::BitXor;
4414 case BinASTVariant::BinaryOperatorBitAnd:
4415 return BinaryOperator::BitAnd;
4416 case BinASTVariant::BinaryOperatorEq:
4417 return BinaryOperator::Eq;
4418 case BinASTVariant::BinaryOperatorNeq:
4419 return BinaryOperator::Neq;
4420 case BinASTVariant::BinaryOperatorStrictEq:
4421 return BinaryOperator::StrictEq;
4422 case BinASTVariant::BinaryOperatorStrictNeq:
4423 return BinaryOperator::StrictNeq;
4424 case BinASTVariant::BinaryOperatorLessThan:
4425 return BinaryOperator::LessThan;
4426 case BinASTVariant::BinaryOperatorLeqThan:
4427 return BinaryOperator::LeqThan;
4428 case BinASTVariant::BinaryOperatorGreaterThan:
4429 return BinaryOperator::GreaterThan;
4430 case BinASTVariant::BinaryOperatorGeqThan:
4431 return BinaryOperator::GeqThan;
4432 case BinASTVariant::BinaryOperatorIn:
4433 return BinaryOperator::In;
4434 case BinASTVariant::BinaryOperatorInstanceof:
4435 return BinaryOperator::Instanceof;
4436 case BinASTVariant::BinaryOperatorLsh:
4437 return BinaryOperator::Lsh;
4438 case BinASTVariant::BinaryOperatorRsh:
4439 return BinaryOperator::Rsh;
4440 case BinASTVariant::BinaryOperatorUrsh:
4441 return BinaryOperator::Ursh;
4442 case BinASTVariant::BinaryOperatorOrUnaryOperatorPlus:
4443 return BinaryOperator::Plus;
4444 case BinASTVariant::BinaryOperatorOrUnaryOperatorMinus:
4445 return BinaryOperator::Minus;
4446 case BinASTVariant::BinaryOperatorMul:
4447 return BinaryOperator::Mul;
4448 case BinASTVariant::BinaryOperatorDiv:
4449 return BinaryOperator::Div;
4450 case BinASTVariant::BinaryOperatorMod:
4451 return BinaryOperator::Mod;
4452 case BinASTVariant::BinaryOperatorPow:
4453 return BinaryOperator::Pow;
4454 default:
4455 if (isInvalidVariantPossible()) {
4456 return raiseInvalidVariant("BinaryOperator", variant);
4457 } else {
4458 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4459 "invalid BinASTVariant should not appear");
4460 }
4461 }
4462 }
4463
4464 /*
4465 enum CompoundAssignmentOperator {
4466 "+=",
4467 "-=",
4468 "*=",
4469 "/=",
4470 "%=",
4471 "**=",
4472 "<<=",
4473 ">>=",
4474 ">>>=",
4475 "|=",
4476 "^=",
4477 "&="
4478 };
4479 */
4480 template <typename Tok>
4481 JS::Result<typename BinASTParser<Tok>::CompoundAssignmentOperator>
parseCompoundAssignmentOperator(const FieldContext & context)4482 BinASTParser<Tok>::parseCompoundAssignmentOperator(
4483 const FieldContext& context) {
4484 BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant(context));
4485
4486 switch (variant) {
4487 case BinASTVariant::CompoundAssignmentOperatorPlusAssign:
4488 return CompoundAssignmentOperator::PlusAssign;
4489 case BinASTVariant::CompoundAssignmentOperatorMinusAssign:
4490 return CompoundAssignmentOperator::MinusAssign;
4491 case BinASTVariant::CompoundAssignmentOperatorMulAssign:
4492 return CompoundAssignmentOperator::MulAssign;
4493 case BinASTVariant::CompoundAssignmentOperatorDivAssign:
4494 return CompoundAssignmentOperator::DivAssign;
4495 case BinASTVariant::CompoundAssignmentOperatorModAssign:
4496 return CompoundAssignmentOperator::ModAssign;
4497 case BinASTVariant::CompoundAssignmentOperatorPowAssign:
4498 return CompoundAssignmentOperator::PowAssign;
4499 case BinASTVariant::CompoundAssignmentOperatorLshAssign:
4500 return CompoundAssignmentOperator::LshAssign;
4501 case BinASTVariant::CompoundAssignmentOperatorRshAssign:
4502 return CompoundAssignmentOperator::RshAssign;
4503 case BinASTVariant::CompoundAssignmentOperatorUrshAssign:
4504 return CompoundAssignmentOperator::UrshAssign;
4505 case BinASTVariant::CompoundAssignmentOperatorBitOrAssign:
4506 return CompoundAssignmentOperator::BitOrAssign;
4507 case BinASTVariant::CompoundAssignmentOperatorBitXorAssign:
4508 return CompoundAssignmentOperator::BitXorAssign;
4509 case BinASTVariant::CompoundAssignmentOperatorBitAndAssign:
4510 return CompoundAssignmentOperator::BitAndAssign;
4511 default:
4512 if (isInvalidVariantPossible()) {
4513 return raiseInvalidVariant("CompoundAssignmentOperator", variant);
4514 } else {
4515 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4516 "invalid BinASTVariant should not appear");
4517 }
4518 }
4519 }
4520
4521 /*
4522 enum UnaryOperator {
4523 "+",
4524 "-",
4525 "!",
4526 "~",
4527 "typeof",
4528 "void",
4529 "delete"
4530 };
4531 */
4532 template <typename Tok>
4533 JS::Result<typename BinASTParser<Tok>::UnaryOperator>
parseUnaryOperator(const FieldContext & context)4534 BinASTParser<Tok>::parseUnaryOperator(const FieldContext& context) {
4535 BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant(context));
4536
4537 switch (variant) {
4538 case BinASTVariant::BinaryOperatorOrUnaryOperatorPlus:
4539 return UnaryOperator::Plus;
4540 case BinASTVariant::BinaryOperatorOrUnaryOperatorMinus:
4541 return UnaryOperator::Minus;
4542 case BinASTVariant::UnaryOperatorNot:
4543 return UnaryOperator::Not;
4544 case BinASTVariant::UnaryOperatorBitNot:
4545 return UnaryOperator::BitNot;
4546 case BinASTVariant::UnaryOperatorTypeof:
4547 return UnaryOperator::Typeof;
4548 case BinASTVariant::UnaryOperatorVoid:
4549 return UnaryOperator::Void;
4550 case BinASTVariant::UnaryOperatorDelete:
4551 return UnaryOperator::Delete;
4552 default:
4553 if (isInvalidVariantPossible()) {
4554 return raiseInvalidVariant("UnaryOperator", variant);
4555 } else {
4556 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4557 "invalid BinASTVariant should not appear");
4558 }
4559 }
4560 }
4561
4562 /*
4563 enum UpdateOperator {
4564 "++",
4565 "--"
4566 };
4567 */
4568 template <typename Tok>
4569 JS::Result<typename BinASTParser<Tok>::UpdateOperator>
parseUpdateOperator(const FieldContext & context)4570 BinASTParser<Tok>::parseUpdateOperator(const FieldContext& context) {
4571 BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant(context));
4572
4573 switch (variant) {
4574 case BinASTVariant::UpdateOperatorIncr:
4575 return UpdateOperator::Incr;
4576 case BinASTVariant::UpdateOperatorDecr:
4577 return UpdateOperator::Decr;
4578 default:
4579 if (isInvalidVariantPossible()) {
4580 return raiseInvalidVariant("UpdateOperator", variant);
4581 } else {
4582 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4583 "invalid BinASTVariant should not appear");
4584 }
4585 }
4586 }
4587
4588 /*
4589 enum VariableDeclarationKind {
4590 "var",
4591 "let",
4592 "const"
4593 };
4594 */
4595 template <typename Tok>
4596 JS::Result<typename BinASTParser<Tok>::VariableDeclarationKind>
parseVariableDeclarationKind(const FieldContext & context)4597 BinASTParser<Tok>::parseVariableDeclarationKind(const FieldContext& context) {
4598 BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant(context));
4599
4600 switch (variant) {
4601 case BinASTVariant::AssertedDeclaredKindOrVariableDeclarationKindVar:
4602 return VariableDeclarationKind::Var;
4603 case BinASTVariant::VariableDeclarationKindLet:
4604 return VariableDeclarationKind::Let;
4605 case BinASTVariant::VariableDeclarationKindConst:
4606 return VariableDeclarationKind::Const;
4607 default:
4608 if (isInvalidVariantPossible()) {
4609 return raiseInvalidVariant("VariableDeclarationKind", variant);
4610 } else {
4611 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4612 "invalid BinASTVariant should not appear");
4613 }
4614 }
4615 }
4616
4617 // ----- Lists (autogenerated, by lexicographical order)
4618
4619 template <typename Tok>
parseArguments(const FieldContext & context)4620 JS::Result<ParseNode*> BinASTParser<Tok>::parseArguments(
4621 const FieldContext& context) {
4622 uint32_t length;
4623 AutoList guard(*tokenizer_);
4624
4625 const auto start = tokenizer_->offset();
4626 const auto childContext =
4627 ListContext(context.position_, BinASTList::Arguments);
4628 guard.init();
4629 MOZ_TRY(tokenizer_->enterList(length, childContext));
4630 BINJS_TRY_DECL(result, handler_.newList(ParseNodeKind::Arguments,
4631 tokenizer_->pos(start)));
4632
4633 for (uint32_t i = 0; i < length; ++i) {
4634 BINJS_MOZ_TRY_DECL(item, parseExpressionOrSpreadElement(childContext));
4635 handler_.addList(/* list = */ result, /* kid = */ item);
4636 }
4637
4638 MOZ_TRY(guard.done());
4639 return result;
4640 }
4641
4642 template <typename Tok>
parseFunctionBody(const FieldContext & context)4643 JS::Result<ListNode*> BinASTParser<Tok>::parseFunctionBody(
4644 const FieldContext& context) {
4645 uint32_t length;
4646 AutoList guard(*tokenizer_);
4647
4648 const auto start = tokenizer_->offset();
4649 const auto childContext =
4650 ListContext(context.position_, BinASTList::ListOfStatement);
4651 guard.init();
4652 MOZ_TRY(tokenizer_->enterList(length, childContext));
4653 BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
4654
4655 for (uint32_t i = 0; i < length; ++i) {
4656 BINJS_MOZ_TRY_DECL(item, parseStatement(FieldOrListContext(childContext)));
4657 handler_.addStatementToList(result, item);
4658 }
4659
4660 MOZ_TRY(guard.done());
4661 return result;
4662 }
4663
4664 template <typename Tok>
parseListOfAssertedBoundName(AssertedScopeKind scopeKind,const FieldContext & context)4665 JS::Result<Ok> BinASTParser<Tok>::parseListOfAssertedBoundName(
4666 AssertedScopeKind scopeKind, const FieldContext& context) {
4667 uint32_t length;
4668 AutoList guard(*tokenizer_);
4669
4670 const auto start = tokenizer_->offset();
4671 const auto childContext =
4672 ListContext(context.position_, BinASTList::ListOfAssertedBoundName);
4673 guard.init();
4674 MOZ_TRY(tokenizer_->enterList(length, childContext));
4675 (void)start;
4676 auto result = Ok();
4677
4678 for (uint32_t i = 0; i < length; ++i) {
4679 MOZ_TRY(parseAssertedBoundName(scopeKind, childContext));
4680 // Nothing to do here.
4681 }
4682
4683 MOZ_TRY(guard.done());
4684 return result;
4685 }
4686
4687 template <typename Tok>
parseListOfAssertedDeclaredName(AssertedScopeKind scopeKind,const FieldContext & context)4688 JS::Result<Ok> BinASTParser<Tok>::parseListOfAssertedDeclaredName(
4689 AssertedScopeKind scopeKind, const FieldContext& context) {
4690 uint32_t length;
4691 AutoList guard(*tokenizer_);
4692
4693 const auto start = tokenizer_->offset();
4694 const auto childContext =
4695 ListContext(context.position_, BinASTList::ListOfAssertedDeclaredName);
4696 guard.init();
4697 MOZ_TRY(tokenizer_->enterList(length, childContext));
4698 (void)start;
4699 auto result = Ok();
4700
4701 for (uint32_t i = 0; i < length; ++i) {
4702 MOZ_TRY(parseAssertedDeclaredName(scopeKind, childContext));
4703 // Nothing to do here.
4704 }
4705
4706 MOZ_TRY(guard.done());
4707 return result;
4708 }
4709
4710 template <typename Tok>
4711 JS::Result<Ok>
parseListOfAssertedMaybePositionalParameterName(AssertedScopeKind scopeKind,MutableHandle<GCVector<JSAtom * >> positionalParams,const FieldContext & context)4712 BinASTParser<Tok>::parseListOfAssertedMaybePositionalParameterName(
4713 AssertedScopeKind scopeKind,
4714 MutableHandle<GCVector<JSAtom*>> positionalParams,
4715 const FieldContext& context) {
4716 uint32_t length;
4717 AutoList guard(*tokenizer_);
4718
4719 const auto start = tokenizer_->offset();
4720 const auto childContext =
4721 ListContext(context.position_,
4722 BinASTList::ListOfAssertedMaybePositionalParameterName);
4723 guard.init();
4724 MOZ_TRY(tokenizer_->enterList(length, childContext));
4725 (void)start;
4726 auto result = Ok();
4727 // This list contains also destructuring parameters, and the number of
4728 // list items can be greater than the actual parameters, or more than
4729 // ARGNO_LIMIT even if the number of parameters fits into ARGNO_LIMIT.
4730 // Also, the number of parameters can be greater than this list's length
4731 // if one of destructuring parameter is empty.
4732 //
4733 // We resize `positionalParams` vector on demand, to keep the vector
4734 // length match to the known maximum positional parameter index + 1.
4735
4736 for (uint32_t i = 0; i < length; ++i) {
4737 MOZ_TRY(parseAssertedMaybePositionalParameterName(
4738 scopeKind, positionalParams, childContext));
4739 // Nothing to do here.
4740 }
4741
4742 MOZ_TRY(guard.done());
4743 return result;
4744 }
4745
4746 template <typename Tok>
parseListOfDirective(const FieldContext & context)4747 JS::Result<ListNode*> BinASTParser<Tok>::parseListOfDirective(
4748 const FieldContext& context) {
4749 uint32_t length;
4750 AutoList guard(*tokenizer_);
4751
4752 const auto start = tokenizer_->offset();
4753 const auto childContext =
4754 ListContext(context.position_, BinASTList::ListOfDirective);
4755 guard.init();
4756 MOZ_TRY(tokenizer_->enterList(length, childContext));
4757 BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
4758
4759 for (uint32_t i = 0; i < length; ++i) {
4760 BINJS_MOZ_TRY_DECL(item, parseDirective(childContext));
4761 handler_.addStatementToList(result, item);
4762 }
4763
4764 MOZ_TRY(guard.done());
4765 return result;
4766 }
4767
4768 template <typename Tok>
parseListOfObjectProperty(const FieldContext & context)4769 JS::Result<ListNode*> BinASTParser<Tok>::parseListOfObjectProperty(
4770 const FieldContext& context) {
4771 uint32_t length;
4772 AutoList guard(*tokenizer_);
4773
4774 const auto start = tokenizer_->offset();
4775 const auto childContext =
4776 ListContext(context.position_, BinASTList::ListOfObjectProperty);
4777 guard.init();
4778 MOZ_TRY(tokenizer_->enterList(length, childContext));
4779 BINJS_TRY_DECL(result, handler_.newObjectLiteral(start));
4780
4781 for (uint32_t i = 0; i < length; ++i) {
4782 BINJS_MOZ_TRY_DECL(item, parseObjectProperty(childContext));
4783 if (!item->isConstant()) result->setHasNonConstInitializer();
4784 result->appendWithoutOrderAssumption(item);
4785 }
4786
4787 MOZ_TRY(guard.done());
4788 return result;
4789 }
4790
4791 template <typename Tok>
4792 JS::Result<ListNode*>
parseListOfOptionalExpressionOrSpreadElement(const FieldContext & context)4793 BinASTParser<Tok>::parseListOfOptionalExpressionOrSpreadElement(
4794 const FieldContext& context) {
4795 uint32_t length;
4796 AutoList guard(*tokenizer_);
4797
4798 const auto start = tokenizer_->offset();
4799 const auto childContext = ListContext(
4800 context.position_, BinASTList::ListOfOptionalExpressionOrSpreadElement);
4801 guard.init();
4802 MOZ_TRY(tokenizer_->enterList(length, childContext));
4803 BINJS_TRY_DECL(result, handler_.newArrayLiteral(start));
4804
4805 for (uint32_t i = 0; i < length; ++i) {
4806 BINJS_MOZ_TRY_DECL(item,
4807 parseOptionalExpressionOrSpreadElement(childContext));
4808 if (item) {
4809 handler_.addArrayElement(result, item); // Infallible.
4810 } else {
4811 BINJS_TRY(handler_.addElision(result, tokenizer_->pos(start)));
4812 }
4813 }
4814
4815 MOZ_TRY(guard.done());
4816 return result;
4817 }
4818
4819 template <typename Tok>
parseListOfParameter(const FieldContext & context)4820 JS::Result<ListNode*> BinASTParser<Tok>::parseListOfParameter(
4821 const FieldContext& context) {
4822 uint32_t length;
4823 AutoList guard(*tokenizer_);
4824
4825 const auto start = tokenizer_->offset();
4826 const auto childContext =
4827 ListContext(context.position_, BinASTList::ListOfParameter);
4828 guard.init();
4829 MOZ_TRY(tokenizer_->enterList(length, childContext));
4830 BINJS_TRY_DECL(result, handler_.newParamsBody(tokenizer_->pos(start)));
4831
4832 for (uint32_t i = 0; i < length; ++i) {
4833 BINJS_MOZ_TRY_DECL(item, parseParameter(FieldOrListContext(childContext)));
4834 handler_.addList(/* list = */ result, /* kid = */ item);
4835 }
4836
4837 MOZ_TRY(guard.done());
4838 return result;
4839 }
4840
4841 template <typename Tok>
parseListOfStatement(const FieldContext & context)4842 JS::Result<ListNode*> BinASTParser<Tok>::parseListOfStatement(
4843 const FieldContext& context) {
4844 uint32_t length;
4845 AutoList guard(*tokenizer_);
4846
4847 const auto start = tokenizer_->offset();
4848 const auto childContext =
4849 ListContext(context.position_, BinASTList::ListOfStatement);
4850 guard.init();
4851 MOZ_TRY(tokenizer_->enterList(length, childContext));
4852 BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
4853
4854 for (uint32_t i = 0; i < length; ++i) {
4855 BINJS_MOZ_TRY_DECL(item, parseStatement(FieldOrListContext(childContext)));
4856 handler_.addStatementToList(result, item);
4857 }
4858
4859 MOZ_TRY(guard.done());
4860 return result;
4861 }
4862
4863 template <typename Tok>
parseListOfSwitchCase(const FieldContext & context)4864 JS::Result<ListNode*> BinASTParser<Tok>::parseListOfSwitchCase(
4865 const FieldContext& context) {
4866 uint32_t length;
4867 AutoList guard(*tokenizer_);
4868
4869 const auto start = tokenizer_->offset();
4870 const auto childContext =
4871 ListContext(context.position_, BinASTList::ListOfSwitchCase);
4872 guard.init();
4873 MOZ_TRY(tokenizer_->enterList(length, childContext));
4874 BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
4875
4876 for (uint32_t i = 0; i < length; ++i) {
4877 BINJS_MOZ_TRY_DECL(item, parseSwitchCase(childContext));
4878 handler_.addCaseStatementToList(result, item);
4879 }
4880
4881 MOZ_TRY(guard.done());
4882 return result;
4883 }
4884
4885 template <typename Tok>
parseListOfVariableDeclarator(ParseNodeKind declarationListKind,const FieldContext & context)4886 JS::Result<ListNode*> BinASTParser<Tok>::parseListOfVariableDeclarator(
4887 ParseNodeKind declarationListKind, const FieldContext& context) {
4888 uint32_t length;
4889 AutoList guard(*tokenizer_);
4890
4891 const auto start = tokenizer_->offset();
4892 const auto childContext =
4893 ListContext(context.position_, BinASTList::ListOfVariableDeclarator);
4894 guard.init();
4895 MOZ_TRY(tokenizer_->enterList(length, childContext));
4896 BINJS_TRY_DECL(result, handler_.newDeclarationList(declarationListKind,
4897 tokenizer_->pos(start)));
4898
4899 for (uint32_t i = 0; i < length; ++i) {
4900 BINJS_MOZ_TRY_DECL(item, parseVariableDeclarator(childContext));
4901 result->appendWithoutOrderAssumption(item);
4902 }
4903
4904 MOZ_TRY(guard.done());
4905 return result;
4906 }
4907
4908 // ----- Default values (by lexicographical order)
4909 template <typename Tok>
parseOptionalBinding(const FieldContext & context)4910 JS::Result<ParseNode*> BinASTParser<Tok>::parseOptionalBinding(
4911 const FieldContext& context) {
4912 BinASTKind kind = BinASTKind::_Uninitialized;
4913 AutoTaggedTuple guard(*tokenizer_);
4914
4915 guard.init();
4916 MOZ_TRY(tokenizer_->enterSum(kind, context));
4917 ParseNode* result;
4918 if (kind == BinASTKind::_Null) {
4919 result = nullptr;
4920 } else {
4921 const auto start = tokenizer_->offset();
4922 MOZ_TRY_VAR(result, parseSumBinding(start, kind, context));
4923 }
4924 MOZ_TRY(guard.done());
4925
4926 return result;
4927 }
4928
4929 template <typename Tok>
parseOptionalBindingIdentifier(const FieldContext & context)4930 JS::Result<ParseNode*> BinASTParser<Tok>::parseOptionalBindingIdentifier(
4931 const FieldContext& context) {
4932 BinASTKind kind = BinASTKind::_Uninitialized;
4933 AutoTaggedTuple guard(*tokenizer_);
4934
4935 guard.init();
4936 MOZ_TRY(tokenizer_->enterOptionalInterface(kind, context));
4937 ParseNode* result;
4938 if (kind == BinASTKind::_Null) {
4939 result = nullptr;
4940 } else if (!isInvalidKindPossible() ||
4941 kind == BinASTKind::BindingIdentifier) {
4942 const auto start = tokenizer_->offset();
4943 MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(
4944 start, FieldOrListContext(context)));
4945 } else {
4946 if (isInvalidKindPossible()) {
4947 return raiseInvalidKind("BindingIdentifier", kind);
4948 } else {
4949 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4950 "invalid BinASTKind should not appear");
4951 }
4952 }
4953 MOZ_TRY(guard.done());
4954
4955 return result;
4956 }
4957
4958 template <typename Tok>
parseOptionalCatchClause(const FieldContext & context)4959 JS::Result<LexicalScopeNode*> BinASTParser<Tok>::parseOptionalCatchClause(
4960 const FieldContext& context) {
4961 BinASTKind kind = BinASTKind::_Uninitialized;
4962 AutoTaggedTuple guard(*tokenizer_);
4963
4964 guard.init();
4965 MOZ_TRY(tokenizer_->enterOptionalInterface(kind, context));
4966 LexicalScopeNode* result;
4967 if (kind == BinASTKind::_Null) {
4968 result = nullptr;
4969 } else if (!isInvalidKindPossible() || kind == BinASTKind::CatchClause) {
4970 const auto start = tokenizer_->offset();
4971 MOZ_TRY_VAR(result, parseInterfaceCatchClause(start, context));
4972 } else {
4973 if (isInvalidKindPossible()) {
4974 return raiseInvalidKind("CatchClause", kind);
4975 } else {
4976 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
4977 "invalid BinASTKind should not appear");
4978 }
4979 }
4980 MOZ_TRY(guard.done());
4981
4982 return result;
4983 }
4984
4985 template <typename Tok>
parseOptionalExpression(const FieldContext & context)4986 JS::Result<ParseNode*> BinASTParser<Tok>::parseOptionalExpression(
4987 const FieldContext& context) {
4988 BinASTKind kind = BinASTKind::_Uninitialized;
4989 AutoTaggedTuple guard(*tokenizer_);
4990
4991 guard.init();
4992 MOZ_TRY(tokenizer_->enterSum(kind, context));
4993 ParseNode* result;
4994 if (kind == BinASTKind::_Null) {
4995 result = nullptr;
4996 } else {
4997 const auto start = tokenizer_->offset();
4998 MOZ_TRY_VAR(result, parseSumExpression(start, kind, context));
4999 }
5000 MOZ_TRY(guard.done());
5001
5002 return result;
5003 }
5004
5005 template <typename Tok>
5006 JS::Result<ParseNode*>
parseOptionalExpressionOrSpreadElement(const ListContext & context)5007 BinASTParser<Tok>::parseOptionalExpressionOrSpreadElement(
5008 const ListContext& context) {
5009 BinASTKind kind = BinASTKind::_Uninitialized;
5010 AutoTaggedTuple guard(*tokenizer_);
5011
5012 guard.init();
5013 MOZ_TRY(tokenizer_->enterSum(kind, context));
5014 ParseNode* result;
5015 if (kind == BinASTKind::_Null) {
5016 result = nullptr;
5017 } else {
5018 const auto start = tokenizer_->offset();
5019 MOZ_TRY_VAR(result,
5020 parseSumExpressionOrSpreadElement(start, kind, context));
5021 }
5022 MOZ_TRY(guard.done());
5023
5024 return result;
5025 }
5026
5027 template <typename Tok>
5028 JS::Result<ParseNode*>
parseOptionalExpressionOrVariableDeclaration(const FieldContext & context)5029 BinASTParser<Tok>::parseOptionalExpressionOrVariableDeclaration(
5030 const FieldContext& context) {
5031 BinASTKind kind = BinASTKind::_Uninitialized;
5032 AutoTaggedTuple guard(*tokenizer_);
5033
5034 guard.init();
5035 MOZ_TRY(tokenizer_->enterSum(kind, context));
5036 ParseNode* result;
5037 if (kind == BinASTKind::_Null) {
5038 result = nullptr;
5039 } else {
5040 const auto start = tokenizer_->offset();
5041 MOZ_TRY_VAR(result,
5042 parseSumExpressionOrVariableDeclaration(start, kind, context));
5043 }
5044 MOZ_TRY(guard.done());
5045
5046 return result;
5047 }
5048
5049 template <typename Tok>
parseOptionalStatement(const FieldContext & context)5050 JS::Result<ParseNode*> BinASTParser<Tok>::parseOptionalStatement(
5051 const FieldContext& context) {
5052 BinASTKind kind = BinASTKind::_Uninitialized;
5053 AutoTaggedTuple guard(*tokenizer_);
5054
5055 guard.init();
5056 MOZ_TRY(tokenizer_->enterSum(kind, context));
5057 ParseNode* result;
5058 if (kind == BinASTKind::_Null) {
5059 result = nullptr;
5060 } else {
5061 const auto start = tokenizer_->offset();
5062 MOZ_TRY_VAR(result,
5063 parseSumStatement(start, kind, FieldOrListContext(context)));
5064 }
5065 MOZ_TRY(guard.done());
5066
5067 return result;
5068 }
5069
5070 // Force class instantiation.
5071 // This ensures that the symbols are built, without having to export all our
5072 // code (and its baggage of #include and macros) in the header.
5073 template class BinASTParser<BinASTTokenReaderContext>;
5074 template class BinASTParser<BinASTTokenReaderMultipart>;
5075
5076 } // namespace js::frontend
5077