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, &params, &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, &params, &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, &params, &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, &params, &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, &params, &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