Parser.cpp (416735B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* 8 * JS parser. 9 * 10 * This is a recursive-descent parser for the JavaScript language specified by 11 * "The ECMAScript Language Specification" (Standard ECMA-262). It uses 12 * lexical and semantic feedback to disambiguate non-LL(1) structures. It 13 * generates trees of nodes induced by the recursive parsing (not precise 14 * syntax trees, see Parser.h). After tree construction, it rewrites trees to 15 * fold constants and evaluate compile-time expressions. 16 * 17 * This parser attempts no error recovery. 18 */ 19 20 #include "frontend/Parser.h" 21 22 #include "mozilla/ArrayUtils.h" 23 #include "mozilla/Assertions.h" 24 #include "mozilla/Casting.h" 25 #include "mozilla/Range.h" 26 #include "mozilla/Sprintf.h" 27 #include "mozilla/Try.h" // MOZ_TRY* 28 #include "mozilla/Utf8.h" 29 #include "mozilla/Variant.h" 30 31 #include <memory> 32 #include <new> 33 #include <type_traits> 34 35 #include "jsnum.h" 36 #include "jstypes.h" 37 38 #include "frontend/FoldConstants.h" 39 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind 40 #include "frontend/ModuleSharedContext.h" 41 #include "frontend/ParseNode.h" 42 #include "frontend/ParseNodeVerify.h" 43 #include "frontend/Parser-macros.h" // MOZ_TRY_VAR_OR_RETURN 44 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex, ParserAtomsTable, ParserAtom 45 #include "frontend/ScriptIndex.h" // ScriptIndex 46 #include "frontend/TokenStream.h" // IsKeyword, ReservedWordTokenKind, ReservedWordToCharZ, DeprecatedContent, *TokenStream*, CharBuffer, TokenKindToDesc 47 #include "irregexp/RegExpAPI.h" 48 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOneOrigin 49 #include "js/ErrorReport.h" // JSErrorBase 50 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* 51 #include "js/HashTable.h" 52 #include "js/RegExpFlags.h" // JS::RegExpFlags 53 #include "js/Stack.h" // JS::NativeStackLimit 54 #include "util/DifferentialTesting.h" 55 #include "util/StringBuilder.h" // StringBuilder 56 #include "vm/BytecodeUtil.h" 57 #include "vm/FunctionFlags.h" // js::FunctionFlags 58 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind 59 #include "vm/JSContext.h" 60 #include "vm/JSScript.h" 61 #include "vm/ModuleBuilder.h" // js::ModuleBuilder 62 #include "vm/Scope.h" // GetScopeDataTrailingNames 63 #include "wasm/AsmJS.h" 64 65 #include "frontend/ParseContext-inl.h" 66 #include "frontend/SharedContext-inl.h" 67 68 using namespace js; 69 70 using mozilla::AssertedCast; 71 using mozilla::AsVariant; 72 using mozilla::Maybe; 73 using mozilla::Nothing; 74 using mozilla::PointerRangeSize; 75 using mozilla::Some; 76 using mozilla::Utf8Unit; 77 78 using JS::ReadOnlyCompileOptions; 79 using JS::RegExpFlags; 80 81 namespace js::frontend { 82 83 using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr; 84 using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr; 85 using BindingIter = ParseContext::Scope::BindingIter; 86 using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr; 87 88 using ParserBindingNameVector = Vector<ParserBindingName, 6>; 89 90 static inline void PropagateTransitiveParseFlags(const FunctionBox* inner, 91 SharedContext* outer) { 92 if (inner->bindingsAccessedDynamically()) { 93 outer->setBindingsAccessedDynamically(); 94 } 95 if (inner->hasDirectEval()) { 96 outer->setHasDirectEval(); 97 } 98 } 99 100 static bool StatementKindIsBraced(StatementKind kind) { 101 return kind == StatementKind::Block || kind == StatementKind::Switch || 102 kind == StatementKind::Try || kind == StatementKind::Catch || 103 kind == StatementKind::Finally; 104 } 105 106 template <class ParseHandler, typename Unit> 107 inline typename GeneralParser<ParseHandler, Unit>::FinalParser* 108 GeneralParser<ParseHandler, Unit>::asFinalParser() { 109 static_assert( 110 std::is_base_of_v<GeneralParser<ParseHandler, Unit>, FinalParser>, 111 "inheritance relationship required by the static_cast<> below"); 112 113 return static_cast<FinalParser*>(this); 114 } 115 116 template <class ParseHandler, typename Unit> 117 inline const typename GeneralParser<ParseHandler, Unit>::FinalParser* 118 GeneralParser<ParseHandler, Unit>::asFinalParser() const { 119 static_assert( 120 std::is_base_of_v<GeneralParser<ParseHandler, Unit>, FinalParser>, 121 "inheritance relationship required by the static_cast<> below"); 122 123 return static_cast<const FinalParser*>(this); 124 } 125 126 template <class ParseHandler, typename Unit> 127 template <typename ConditionT, typename ErrorReportT> 128 bool GeneralParser<ParseHandler, Unit>::mustMatchTokenInternal( 129 ConditionT condition, ErrorReportT errorReport) { 130 MOZ_ASSERT(condition(TokenKind::Div) == false); 131 MOZ_ASSERT(condition(TokenKind::DivAssign) == false); 132 MOZ_ASSERT(condition(TokenKind::RegExp) == false); 133 134 TokenKind actual; 135 if (!tokenStream.getToken(&actual, TokenStream::SlashIsInvalid)) { 136 return false; 137 } 138 if (!condition(actual)) { 139 errorReport(actual); 140 return false; 141 } 142 return true; 143 } 144 145 ParserSharedBase::ParserSharedBase(FrontendContext* fc, 146 CompilationState& compilationState, 147 Kind kind) 148 : fc_(fc), 149 alloc_(compilationState.parserAllocScope.alloc()), 150 compilationState_(compilationState), 151 pc_(nullptr), 152 usedNames_(compilationState.usedNames) { 153 fc_->nameCollectionPool().addActiveCompilation(); 154 } 155 156 ParserSharedBase::~ParserSharedBase() { 157 fc_->nameCollectionPool().removeActiveCompilation(); 158 } 159 160 #if defined(DEBUG) || defined(JS_JITSPEW) 161 void ParserSharedBase::dumpAtom(TaggedParserAtomIndex index) const { 162 parserAtoms().dump(index); 163 } 164 #endif 165 166 ParserBase::ParserBase(FrontendContext* fc, 167 const ReadOnlyCompileOptions& options, 168 CompilationState& compilationState) 169 : ParserSharedBase(fc, compilationState, ParserSharedBase::Kind::Parser), 170 anyChars(fc, options, this), 171 ss(nullptr), 172 #ifdef DEBUG 173 checkOptionsCalled_(false), 174 #endif 175 isUnexpectedEOF_(false), 176 awaitHandling_(AwaitIsName), 177 inParametersOfAsyncFunction_(false) { 178 } 179 180 bool ParserBase::checkOptions() { 181 #ifdef DEBUG 182 checkOptionsCalled_ = true; 183 #endif 184 185 return anyChars.checkOptions(); 186 } 187 188 ParserBase::~ParserBase() { MOZ_ASSERT(checkOptionsCalled_); } 189 190 JSAtom* ParserBase::liftParserAtomToJSAtom(TaggedParserAtomIndex index) { 191 JSContext* cx = fc_->maybeCurrentJSContext(); 192 MOZ_ASSERT(cx); 193 return parserAtoms().toJSAtom(cx, fc_, index, 194 compilationState_.input.atomCache); 195 } 196 197 template <class ParseHandler> 198 PerHandlerParser<ParseHandler>::PerHandlerParser( 199 FrontendContext* fc, const ReadOnlyCompileOptions& options, 200 CompilationState& compilationState, void* internalSyntaxParser) 201 : ParserBase(fc, options, compilationState), 202 handler_(fc, compilationState), 203 internalSyntaxParser_(internalSyntaxParser) { 204 MOZ_ASSERT(compilationState.isInitialStencil() == 205 compilationState.input.isInitialStencil()); 206 } 207 208 template <class ParseHandler, typename Unit> 209 GeneralParser<ParseHandler, Unit>::GeneralParser( 210 FrontendContext* fc, const ReadOnlyCompileOptions& options, 211 const Unit* units, size_t length, CompilationState& compilationState, 212 SyntaxParser* syntaxParser) 213 : Base(fc, options, compilationState, syntaxParser), 214 tokenStream(fc, &compilationState.parserAtoms, options, units, length) {} 215 216 template <typename Unit> 217 void Parser<SyntaxParseHandler, Unit>::setAwaitHandling( 218 AwaitHandling awaitHandling) { 219 this->awaitHandling_ = awaitHandling; 220 } 221 222 template <typename Unit> 223 void Parser<FullParseHandler, Unit>::setAwaitHandling( 224 AwaitHandling awaitHandling) { 225 this->awaitHandling_ = awaitHandling; 226 if (SyntaxParser* syntaxParser = getSyntaxParser()) { 227 syntaxParser->setAwaitHandling(awaitHandling); 228 } 229 } 230 231 template <class ParseHandler, typename Unit> 232 inline void GeneralParser<ParseHandler, Unit>::setAwaitHandling( 233 AwaitHandling awaitHandling) { 234 asFinalParser()->setAwaitHandling(awaitHandling); 235 } 236 237 template <typename Unit> 238 void Parser<SyntaxParseHandler, Unit>::setInParametersOfAsyncFunction( 239 bool inParameters) { 240 this->inParametersOfAsyncFunction_ = inParameters; 241 } 242 243 template <typename Unit> 244 void Parser<FullParseHandler, Unit>::setInParametersOfAsyncFunction( 245 bool inParameters) { 246 this->inParametersOfAsyncFunction_ = inParameters; 247 if (SyntaxParser* syntaxParser = getSyntaxParser()) { 248 syntaxParser->setInParametersOfAsyncFunction(inParameters); 249 } 250 } 251 252 template <class ParseHandler, typename Unit> 253 inline void GeneralParser<ParseHandler, Unit>::setInParametersOfAsyncFunction( 254 bool inParameters) { 255 asFinalParser()->setInParametersOfAsyncFunction(inParameters); 256 } 257 258 template <class ParseHandler> 259 FunctionBox* PerHandlerParser<ParseHandler>::newFunctionBox( 260 FunctionNodeType funNode, TaggedParserAtomIndex explicitName, 261 FunctionFlags flags, uint32_t toStringStart, Directives inheritedDirectives, 262 GeneratorKind generatorKind, FunctionAsyncKind asyncKind) { 263 MOZ_ASSERT(funNode); 264 265 ScriptIndex index = ScriptIndex(compilationState_.scriptData.length()); 266 if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) { 267 ReportAllocationOverflow(fc_); 268 return nullptr; 269 } 270 if (!compilationState_.appendScriptStencilAndData(fc_)) { 271 return nullptr; 272 } 273 274 bool isInitialStencil = compilationState_.isInitialStencil(); 275 276 // This source extent will be further filled in during the remainder of parse. 277 SourceExtent extent; 278 extent.toStringStart = toStringStart; 279 280 FunctionBox* funbox = alloc_.new_<FunctionBox>( 281 fc_, extent, compilationState_, inheritedDirectives, generatorKind, 282 asyncKind, isInitialStencil, explicitName, flags, index); 283 if (!funbox) { 284 ReportOutOfMemory(fc_); 285 return nullptr; 286 } 287 288 handler_.setFunctionBox(funNode, funbox); 289 290 return funbox; 291 } 292 293 template <class ParseHandler> 294 FunctionBox* PerHandlerParser<ParseHandler>::newFunctionBox( 295 FunctionNodeType funNode, const ScriptStencil& cachedScriptData, 296 const ScriptStencilExtra& cachedScriptExtra) { 297 MOZ_ASSERT(funNode); 298 299 ScriptIndex index = ScriptIndex(compilationState_.scriptData.length()); 300 if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) { 301 ReportAllocationOverflow(fc_); 302 return nullptr; 303 } 304 if (!compilationState_.appendScriptStencilAndData(fc_)) { 305 return nullptr; 306 } 307 308 FunctionBox* funbox = alloc_.new_<FunctionBox>( 309 fc_, cachedScriptExtra.extent, compilationState_, 310 Directives(/* strict = */ false), cachedScriptExtra.generatorKind(), 311 cachedScriptExtra.asyncKind(), compilationState_.isInitialStencil(), 312 cachedScriptData.functionAtom, cachedScriptData.functionFlags, index); 313 if (!funbox) { 314 ReportOutOfMemory(fc_); 315 return nullptr; 316 } 317 318 handler_.setFunctionBox(funNode, funbox); 319 funbox->initFromScriptStencilExtra(cachedScriptExtra); 320 321 return funbox; 322 } 323 324 bool ParserBase::setSourceMapInfo() { 325 // If support for source pragmas have been fully disabled, we can skip 326 // processing of all of these values. 327 if (!options().sourcePragmas()) { 328 return true; 329 } 330 331 // Not all clients initialize ss. Can't update info to an object that isn't 332 // there. 333 if (!ss) { 334 return true; 335 } 336 337 if (anyChars.hasDisplayURL()) { 338 if (!ss->setDisplayURL(fc_, anyChars.displayURL())) { 339 return false; 340 } 341 } 342 343 if (anyChars.hasSourceMapURL()) { 344 MOZ_ASSERT(!ss->hasSourceMapURL()); 345 if (!ss->setSourceMapURL(fc_, anyChars.sourceMapURL())) { 346 return false; 347 } 348 } 349 350 /* 351 * Source map URLs passed as a compile option (usually via a HTTP source map 352 * header) override any source map urls passed as comment pragmas. 353 */ 354 if (options().sourceMapURL()) { 355 // Warn about the replacement, but use the new one. 356 if (ss->hasSourceMapURL()) { 357 if (!warningNoOffset(JSMSG_ALREADY_HAS_PRAGMA, ss->filename(), 358 "//# sourceMappingURL")) { 359 return false; 360 } 361 } 362 363 if (!ss->setSourceMapURL(fc_, options().sourceMapURL())) { 364 return false; 365 } 366 } 367 368 return true; 369 } 370 371 /* 372 * Parse a top-level JS script. 373 */ 374 template <class ParseHandler, typename Unit> 375 typename ParseHandler::ListNodeResult 376 GeneralParser<ParseHandler, Unit>::parse() { 377 MOZ_ASSERT(checkOptionsCalled_); 378 379 SourceExtent extent = SourceExtent::makeGlobalExtent( 380 /* len = */ 0, options().lineno, 381 JS::LimitedColumnNumberOneOrigin::fromUnlimited( 382 JS::ColumnNumberOneOrigin(options().column))); 383 Directives directives(options().forceStrictMode()); 384 GlobalSharedContext globalsc(this->fc_, ScopeKind::Global, options(), 385 directives, extent); 386 SourceParseContext globalpc(this, &globalsc, /* newDirectives = */ nullptr); 387 if (!globalpc.init()) { 388 return errorResult(); 389 } 390 391 ParseContext::VarScope varScope(this); 392 if (!varScope.init(pc_)) { 393 return errorResult(); 394 } 395 396 ListNodeType stmtList = MOZ_TRY(statementList(YieldIsName)); 397 398 TokenKind tt; 399 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 400 return errorResult(); 401 } 402 if (tt != TokenKind::Eof) { 403 error(JSMSG_GARBAGE_AFTER_INPUT, "script", TokenKindToDesc(tt)); 404 return errorResult(); 405 } 406 407 if (!CheckParseTree(this->fc_, alloc_, stmtList)) { 408 return errorResult(); 409 } 410 411 return stmtList; 412 } 413 414 /* 415 * Strict mode forbids introducing new definitions for 'eval', 'arguments', 416 * 'let', 'static', 'yield', or for any strict mode reserved word. 417 */ 418 bool ParserBase::isValidStrictBinding(TaggedParserAtomIndex name) { 419 TokenKind tt = ReservedWordTokenKind(name); 420 if (tt == TokenKind::Limit) { 421 return name != TaggedParserAtomIndex::WellKnown::eval() && 422 name != TaggedParserAtomIndex::WellKnown::arguments(); 423 } 424 return tt != TokenKind::Let && tt != TokenKind::Static && 425 tt != TokenKind::Yield && !TokenKindIsStrictReservedWord(tt); 426 } 427 428 /* 429 * Returns true if all parameter names are valid strict mode binding names and 430 * no duplicate parameter names are present. 431 */ 432 bool ParserBase::hasValidSimpleStrictParameterNames() { 433 MOZ_ASSERT(pc_->isFunctionBox() && 434 pc_->functionBox()->hasSimpleParameterList()); 435 436 if (pc_->functionBox()->hasDuplicateParameters) { 437 return false; 438 } 439 440 for (auto name : pc_->positionalFormalParameterNames()) { 441 MOZ_ASSERT(name); 442 if (!isValidStrictBinding(name)) { 443 return false; 444 } 445 } 446 return true; 447 } 448 449 template <class ParseHandler, typename Unit> 450 void GeneralParser<ParseHandler, Unit>::reportMissingClosing( 451 unsigned errorNumber, unsigned noteNumber, uint32_t openedPos) { 452 auto notes = MakeUnique<JSErrorNotes>(); 453 if (!notes) { 454 ReportOutOfMemory(this->fc_); 455 return; 456 } 457 458 uint32_t line; 459 JS::LimitedColumnNumberOneOrigin column; 460 tokenStream.computeLineAndColumn(openedPos, &line, &column); 461 462 const size_t MaxWidth = sizeof("4294967295"); 463 char columnNumber[MaxWidth]; 464 SprintfLiteral(columnNumber, "%" PRIu32, column.oneOriginValue()); 465 char lineNumber[MaxWidth]; 466 SprintfLiteral(lineNumber, "%" PRIu32, line); 467 468 if (!notes->addNoteASCII(this->fc_, getFilename().c_str(), 0, line, 469 JS::ColumnNumberOneOrigin(column), GetErrorMessage, 470 nullptr, noteNumber, lineNumber, columnNumber)) { 471 return; 472 } 473 474 errorWithNotes(std::move(notes), errorNumber); 475 } 476 477 template <class ParseHandler, typename Unit> 478 void GeneralParser<ParseHandler, Unit>::reportRedeclarationHelper( 479 TaggedParserAtomIndex& name, DeclarationKind& prevKind, TokenPos& pos, 480 uint32_t& prevPos, const unsigned& errorNumber, 481 const unsigned& noteErrorNumber) { 482 UniqueChars bytes = this->parserAtoms().toPrintableString(name); 483 if (!bytes) { 484 ReportOutOfMemory(this->fc_); 485 return; 486 } 487 488 if (prevPos == DeclaredNameInfo::npos) { 489 errorAt(pos.begin, errorNumber, DeclarationKindString(prevKind), 490 bytes.get()); 491 return; 492 } 493 494 auto notes = MakeUnique<JSErrorNotes>(); 495 if (!notes) { 496 ReportOutOfMemory(this->fc_); 497 return; 498 } 499 500 uint32_t line; 501 JS::LimitedColumnNumberOneOrigin column; 502 tokenStream.computeLineAndColumn(prevPos, &line, &column); 503 504 const size_t MaxWidth = sizeof("4294967295"); 505 char columnNumber[MaxWidth]; 506 SprintfLiteral(columnNumber, "%" PRIu32, column.oneOriginValue()); 507 char lineNumber[MaxWidth]; 508 SprintfLiteral(lineNumber, "%" PRIu32, line); 509 510 if (!notes->addNoteASCII(this->fc_, getFilename().c_str(), 0, line, 511 JS::ColumnNumberOneOrigin(column), GetErrorMessage, 512 nullptr, noteErrorNumber, lineNumber, 513 columnNumber)) { 514 return; 515 } 516 517 errorWithNotesAt(std::move(notes), pos.begin, errorNumber, 518 DeclarationKindString(prevKind), bytes.get()); 519 } 520 521 template <class ParseHandler, typename Unit> 522 void GeneralParser<ParseHandler, Unit>::reportRedeclaration( 523 TaggedParserAtomIndex name, DeclarationKind prevKind, TokenPos pos, 524 uint32_t prevPos) { 525 reportRedeclarationHelper(name, prevKind, pos, prevPos, JSMSG_REDECLARED_VAR, 526 JSMSG_PREV_DECLARATION); 527 } 528 529 template <class ParseHandler, typename Unit> 530 void GeneralParser<ParseHandler, Unit>::reportMismatchedPlacement( 531 TaggedParserAtomIndex name, DeclarationKind prevKind, TokenPos pos, 532 uint32_t prevPos) { 533 reportRedeclarationHelper(name, prevKind, pos, prevPos, 534 JSMSG_MISMATCHED_PLACEMENT, JSMSG_PREV_DECLARATION); 535 } 536 537 // notePositionalFormalParameter is called for both the arguments of a regular 538 // function definition and the arguments specified by the Function 539 // constructor. 540 // 541 // The 'disallowDuplicateParams' bool indicates whether the use of another 542 // feature (destructuring or default arguments) disables duplicate arguments. 543 // (ECMA-262 requires us to support duplicate parameter names, but, for newer 544 // features, we consider the code to have "opted in" to higher standards and 545 // forbid duplicates.) 546 template <class ParseHandler, typename Unit> 547 bool GeneralParser<ParseHandler, Unit>::notePositionalFormalParameter( 548 FunctionNodeType funNode, TaggedParserAtomIndex name, uint32_t beginPos, 549 bool disallowDuplicateParams, bool* duplicatedParam) { 550 if (AddDeclaredNamePtr p = 551 pc_->functionScope().lookupDeclaredNameForAdd(name)) { 552 if (disallowDuplicateParams) { 553 error(JSMSG_BAD_DUP_ARGS); 554 return false; 555 } 556 557 // Strict-mode disallows duplicate args. We may not know whether we are 558 // in strict mode or not (since the function body hasn't been parsed). 559 // In such cases, report will queue up the potential error and return 560 // 'true'. 561 if (pc_->sc()->strict()) { 562 UniqueChars bytes = this->parserAtoms().toPrintableString(name); 563 if (!bytes) { 564 ReportOutOfMemory(this->fc_); 565 return false; 566 } 567 if (!strictModeError(JSMSG_DUPLICATE_FORMAL, bytes.get())) { 568 return false; 569 } 570 } 571 572 *duplicatedParam = true; 573 } else { 574 DeclarationKind kind = DeclarationKind::PositionalFormalParameter; 575 if (!pc_->functionScope().addDeclaredName(pc_, p, name, kind, beginPos)) { 576 return false; 577 } 578 } 579 580 if (!pc_->positionalFormalParameterNames().append( 581 TrivialTaggedParserAtomIndex::from(name))) { 582 ReportOutOfMemory(this->fc_); 583 return false; 584 } 585 586 NameNodeType paramNode; 587 MOZ_TRY_VAR_OR_RETURN(paramNode, newName(name), false); 588 589 handler_.addFunctionFormalParameter(funNode, paramNode); 590 return true; 591 } 592 593 template <class ParseHandler> 594 bool PerHandlerParser<ParseHandler>::noteDestructuredPositionalFormalParameter( 595 FunctionNodeType funNode, Node destruct) { 596 // Append an empty name to the positional formals vector to keep track of 597 // argument slots when making FunctionScope::ParserData. 598 if (!pc_->positionalFormalParameterNames().append( 599 TrivialTaggedParserAtomIndex::null())) { 600 ReportOutOfMemory(fc_); 601 return false; 602 } 603 604 handler_.addFunctionFormalParameter(funNode, destruct); 605 return true; 606 } 607 608 template <class ParseHandler, typename Unit> 609 bool GeneralParser<ParseHandler, Unit>::noteDeclaredName( 610 TaggedParserAtomIndex name, DeclarationKind kind, TokenPos pos, 611 ClosedOver isClosedOver) { 612 // The asm.js validator does all its own symbol-table management so, as an 613 // optimization, avoid doing any work here. 614 if (pc_->useAsmOrInsideUseAsm()) { 615 return true; 616 } 617 618 switch (kind) { 619 case DeclarationKind::Var: 620 case DeclarationKind::BodyLevelFunction: { 621 Maybe<DeclarationKind> redeclaredKind; 622 uint32_t prevPos; 623 if (!pc_->tryDeclareVar(name, this, kind, pos.begin, &redeclaredKind, 624 &prevPos)) { 625 return false; 626 } 627 628 if (redeclaredKind) { 629 reportRedeclaration(name, *redeclaredKind, pos, prevPos); 630 return false; 631 } 632 633 break; 634 } 635 636 case DeclarationKind::ModuleBodyLevelFunction: { 637 MOZ_ASSERT(pc_->atModuleLevel()); 638 639 AddDeclaredNamePtr p = pc_->varScope().lookupDeclaredNameForAdd(name); 640 if (p) { 641 reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos()); 642 return false; 643 } 644 645 if (!pc_->varScope().addDeclaredName(pc_, p, name, kind, pos.begin, 646 isClosedOver)) { 647 return false; 648 } 649 650 // Body-level functions in modules are always closed over. 651 pc_->varScope().lookupDeclaredName(name)->value()->setClosedOver(); 652 653 break; 654 } 655 656 case DeclarationKind::FormalParameter: { 657 // It is an early error if any non-positional formal parameter name 658 // (e.g., destructuring formal parameter) is duplicated. 659 660 AddDeclaredNamePtr p = 661 pc_->functionScope().lookupDeclaredNameForAdd(name); 662 if (p) { 663 error(JSMSG_BAD_DUP_ARGS); 664 return false; 665 } 666 667 if (!pc_->functionScope().addDeclaredName(pc_, p, name, kind, pos.begin, 668 isClosedOver)) { 669 return false; 670 } 671 672 break; 673 } 674 675 case DeclarationKind::LexicalFunction: 676 case DeclarationKind::PrivateName: 677 case DeclarationKind::Synthetic: 678 case DeclarationKind::PrivateMethod: { 679 ParseContext::Scope* scope = pc_->innermostScope(); 680 AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name); 681 if (p) { 682 reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos()); 683 return false; 684 } 685 686 if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin, 687 isClosedOver)) { 688 return false; 689 } 690 691 break; 692 } 693 694 case DeclarationKind::SloppyLexicalFunction: { 695 // Functions in block have complex allowances in sloppy mode for being 696 // labelled that other lexical declarations do not have. Those checks 697 // are done in functionStmt. 698 699 ParseContext::Scope* scope = pc_->innermostScope(); 700 if (AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name)) { 701 // It is usually an early error if there is another declaration 702 // with the same name in the same scope. 703 // 704 // Sloppy lexical functions may redeclare other sloppy lexical 705 // functions for web compatibility reasons. 706 if (p->value()->kind() != DeclarationKind::SloppyLexicalFunction) { 707 reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos()); 708 return false; 709 } 710 } else { 711 if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin, 712 isClosedOver)) { 713 return false; 714 } 715 } 716 717 break; 718 } 719 720 case DeclarationKind::Let: 721 case DeclarationKind::Const: 722 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 723 case DeclarationKind::Using: 724 case DeclarationKind::AwaitUsing: 725 #endif 726 case DeclarationKind::Class: 727 // The BoundNames of LexicalDeclaration and ForDeclaration must not 728 // contain 'let'. (CatchParameter is the only lexical binding form 729 // without this restriction.) 730 if (name == TaggedParserAtomIndex::WellKnown::let()) { 731 errorAt(pos.begin, JSMSG_LEXICAL_DECL_DEFINES_LET); 732 return false; 733 } 734 735 // For body-level lexically declared names in a function, it is an 736 // early error if there is a formal parameter of the same name. This 737 // needs a special check if there is an extra var scope due to 738 // parameter expressions. 739 if (pc_->isFunctionExtraBodyVarScopeInnermost()) { 740 DeclaredNamePtr p = pc_->functionScope().lookupDeclaredName(name); 741 if (p && DeclarationKindIsParameter(p->value()->kind())) { 742 reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos()); 743 return false; 744 } 745 } 746 747 [[fallthrough]]; 748 749 case DeclarationKind::Import: 750 // Module code is always strict, so 'let' is always a keyword and never a 751 // name. 752 MOZ_ASSERT(name != TaggedParserAtomIndex::WellKnown::let()); 753 [[fallthrough]]; 754 755 case DeclarationKind::SimpleCatchParameter: 756 case DeclarationKind::CatchParameter: { 757 ParseContext::Scope* scope = pc_->innermostScope(); 758 759 // It is an early error if there is another declaration with the same 760 // name in the same scope. 761 AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name); 762 if (p) { 763 reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos()); 764 return false; 765 } 766 767 if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin, 768 isClosedOver)) { 769 return false; 770 } 771 772 break; 773 } 774 775 case DeclarationKind::CoverArrowParameter: 776 // CoverArrowParameter is only used as a placeholder declaration kind. 777 break; 778 779 case DeclarationKind::PositionalFormalParameter: 780 MOZ_CRASH( 781 "Positional formal parameter names should use " 782 "notePositionalFormalParameter"); 783 break; 784 785 case DeclarationKind::VarForAnnexBLexicalFunction: 786 MOZ_CRASH( 787 "Synthesized Annex B vars should go through " 788 "addPossibleAnnexBFunctionBox, and " 789 "propagateAndMarkAnnexBFunctionBoxes"); 790 break; 791 } 792 793 return true; 794 } 795 796 template <class ParseHandler, typename Unit> 797 bool GeneralParser<ParseHandler, Unit>::noteDeclaredPrivateName( 798 Node nameNode, TaggedParserAtomIndex name, PropertyType propType, 799 FieldPlacement placement, TokenPos pos) { 800 ParseContext::Scope* scope = pc_->innermostScope(); 801 AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name); 802 803 DeclarationKind declKind = DeclarationKind::PrivateName; 804 805 // Our strategy for enabling debugger functionality is to mark names as closed 806 // over, even if they don't necessarily need to be, to ensure that they are 807 // included in the environment object. This allows us to easily look them up 808 // by name when needed, even if there is no corresponding property on an 809 // object, as is the case with getter, setters and private methods. 810 ClosedOver closedOver = ClosedOver::Yes; 811 PrivateNameKind kind; 812 switch (propType) { 813 case PropertyType::Field: 814 kind = PrivateNameKind::Field; 815 closedOver = ClosedOver::No; 816 break; 817 case PropertyType::FieldWithAccessor: 818 // In this case, we create a new private field for the underlying storage, 819 // and use the current name for the getter and setter. 820 kind = PrivateNameKind::GetterSetter; 821 break; 822 case PropertyType::Method: 823 case PropertyType::GeneratorMethod: 824 case PropertyType::AsyncMethod: 825 case PropertyType::AsyncGeneratorMethod: 826 if (placement == FieldPlacement::Instance) { 827 // Optimized private method. Non-optimized paths still get 828 // DeclarationKind::Synthetic. 829 declKind = DeclarationKind::PrivateMethod; 830 } 831 kind = PrivateNameKind::Method; 832 break; 833 case PropertyType::Getter: 834 kind = PrivateNameKind::Getter; 835 break; 836 case PropertyType::Setter: 837 kind = PrivateNameKind::Setter; 838 break; 839 default: 840 MOZ_CRASH("Invalid Property Type for noteDeclarePrivateName"); 841 } 842 843 if (p) { 844 PrivateNameKind prevKind = p->value()->privateNameKind(); 845 if ((prevKind == PrivateNameKind::Getter && 846 kind == PrivateNameKind::Setter) || 847 (prevKind == PrivateNameKind::Setter && 848 kind == PrivateNameKind::Getter)) { 849 // Private methods demands that 850 // 851 // class A { 852 // static set #x(_) {} 853 // get #x() { } 854 // } 855 // 856 // Report a SyntaxError. 857 if (placement == p->value()->placement()) { 858 p->value()->setPrivateNameKind(PrivateNameKind::GetterSetter); 859 handler_.setPrivateNameKind(nameNode, PrivateNameKind::GetterSetter); 860 return true; 861 } 862 } 863 864 reportMismatchedPlacement(name, p->value()->kind(), pos, p->value()->pos()); 865 return false; 866 } 867 868 if (!scope->addDeclaredName(pc_, p, name, declKind, pos.begin, closedOver)) { 869 return false; 870 } 871 872 DeclaredNamePtr declared = scope->lookupDeclaredName(name); 873 declared->value()->setPrivateNameKind(kind); 874 declared->value()->setFieldPlacement(placement); 875 handler_.setPrivateNameKind(nameNode, kind); 876 877 return true; 878 } 879 880 bool ParserBase::noteUsedNameInternal(TaggedParserAtomIndex name, 881 NameVisibility visibility, 882 mozilla::Maybe<TokenPos> tokenPosition) { 883 // The asm.js validator does all its own symbol-table management so, as an 884 // optimization, avoid doing any work here. 885 if (pc_->useAsmOrInsideUseAsm()) { 886 return true; 887 } 888 889 // Global bindings are properties and not actual bindings; we don't need 890 // to know if they are closed over. So no need to track used name at the 891 // global scope. It is not incorrect to track them, this is an 892 // optimization. 893 // 894 // Exceptions: 895 // (a) Track private name references, as the used names tracker is used to 896 // provide early errors for undeclared private name references 897 // (b) If the script has extra bindings, track all references to detect 898 // references to extra bindings 899 ParseContext::Scope* scope = pc_->innermostScope(); 900 if (pc_->sc()->isGlobalContext() && scope == &pc_->varScope() && 901 visibility == NameVisibility::Public && 902 !this->compilationState_.input.hasExtraBindings()) { 903 return true; 904 } 905 906 return usedNames_.noteUse(fc_, name, visibility, pc_->scriptId(), scope->id(), 907 tokenPosition); 908 } 909 910 template <class ParseHandler> 911 bool PerHandlerParser<ParseHandler>:: 912 propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope) { 913 // Now that we have all the declared names in the scope, check which 914 // functions should exhibit Annex B semantics. 915 if (!scope.propagateAndMarkAnnexBFunctionBoxes(pc_, this)) { 916 return false; 917 } 918 919 if (handler_.reuseClosedOverBindings()) { 920 MOZ_ASSERT(pc_->isOutermostOfCurrentCompile()); 921 922 // Closed over bindings for all scopes are stored in a contiguous array, in 923 // the same order as the order in which scopes are visited, and seprated by 924 // TaggedParserAtomIndex::null(). 925 uint32_t slotCount = scope.declaredCount(); 926 while (auto parserAtom = handler_.nextLazyClosedOverBinding()) { 927 scope.lookupDeclaredName(parserAtom)->value()->setClosedOver(); 928 MOZ_ASSERT(slotCount > 0); 929 slotCount--; 930 } 931 932 if (pc_->isGeneratorOrAsync()) { 933 scope.setOwnStackSlotCount(slotCount); 934 } 935 return true; 936 } 937 938 constexpr bool isSyntaxParser = 939 std::is_same_v<ParseHandler, SyntaxParseHandler>; 940 uint32_t scriptId = pc_->scriptId(); 941 uint32_t scopeId = scope.id(); 942 943 uint32_t slotCount = 0; 944 for (BindingIter bi = scope.bindings(pc_); bi; bi++) { 945 bool closedOver = false; 946 if (UsedNamePtr p = usedNames_.lookup(bi.name())) { 947 p->value().noteBoundInScope(scriptId, scopeId, &closedOver); 948 if (closedOver) { 949 bi.setClosedOver(); 950 951 if constexpr (isSyntaxParser) { 952 if (!pc_->closedOverBindingsForLazy().append( 953 TrivialTaggedParserAtomIndex::from(bi.name()))) { 954 ReportOutOfMemory(fc_); 955 return false; 956 } 957 } 958 } 959 } 960 961 if constexpr (!isSyntaxParser) { 962 if (!closedOver) { 963 slotCount++; 964 } 965 } 966 } 967 if constexpr (!isSyntaxParser) { 968 if (pc_->isGeneratorOrAsync()) { 969 scope.setOwnStackSlotCount(slotCount); 970 } 971 } 972 973 // Append a nullptr to denote end-of-scope. 974 if constexpr (isSyntaxParser) { 975 if (!pc_->closedOverBindingsForLazy().append( 976 TrivialTaggedParserAtomIndex::null())) { 977 ReportOutOfMemory(fc_); 978 return false; 979 } 980 } 981 982 return true; 983 } 984 985 template <typename Unit> 986 bool Parser<FullParseHandler, Unit>::checkStatementsEOF() { 987 // This is designed to be paired with parsing a statement list at the top 988 // level. 989 // 990 // The statementList() call breaks on TokenKind::RightCurly, so make sure 991 // we've reached EOF here. 992 TokenKind tt; 993 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 994 return false; 995 } 996 if (tt != TokenKind::Eof) { 997 error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt)); 998 return false; 999 } 1000 return true; 1001 } 1002 1003 template <typename ScopeT> 1004 typename ScopeT::ParserData* NewEmptyBindingData(FrontendContext* fc, 1005 LifoAlloc& alloc, 1006 uint32_t numBindings) { 1007 using Data = typename ScopeT::ParserData; 1008 size_t allocSize = SizeOfScopeData<Data>(numBindings); 1009 auto* bindings = alloc.newWithSize<Data>(allocSize, numBindings); 1010 if (!bindings) { 1011 ReportOutOfMemory(fc); 1012 } 1013 return bindings; 1014 } 1015 1016 GlobalScope::ParserData* NewEmptyGlobalScopeData(FrontendContext* fc, 1017 LifoAlloc& alloc, 1018 uint32_t numBindings) { 1019 return NewEmptyBindingData<GlobalScope>(fc, alloc, numBindings); 1020 } 1021 1022 LexicalScope::ParserData* NewEmptyLexicalScopeData(FrontendContext* fc, 1023 LifoAlloc& alloc, 1024 uint32_t numBindings) { 1025 return NewEmptyBindingData<LexicalScope>(fc, alloc, numBindings); 1026 } 1027 1028 FunctionScope::ParserData* NewEmptyFunctionScopeData(FrontendContext* fc, 1029 LifoAlloc& alloc, 1030 uint32_t numBindings) { 1031 return NewEmptyBindingData<FunctionScope>(fc, alloc, numBindings); 1032 } 1033 1034 namespace detail { 1035 1036 template <class SlotInfo> 1037 static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings( 1038 SlotInfo& slotInfo, ParserBindingName* start, ParserBindingName* cursor) { 1039 return cursor; 1040 } 1041 1042 template <class SlotInfo, typename UnsignedInteger, typename... Step> 1043 static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings( 1044 SlotInfo& slotInfo, ParserBindingName* start, ParserBindingName* cursor, 1045 UnsignedInteger SlotInfo::* field, const ParserBindingNameVector& bindings, 1046 Step&&... step) { 1047 slotInfo.*field = 1048 AssertedCast<UnsignedInteger>(PointerRangeSize(start, cursor)); 1049 1050 ParserBindingName* newCursor = 1051 std::uninitialized_copy(bindings.begin(), bindings.end(), cursor); 1052 1053 return InitializeIndexedBindings(slotInfo, start, newCursor, 1054 std::forward<Step>(step)...); 1055 } 1056 1057 } // namespace detail 1058 1059 // Initialize the trailing name bindings of |data|, then set |data->length| to 1060 // the count of bindings added (which must equal |count|). 1061 // 1062 // First, |firstBindings| are added to the trailing names. Then any 1063 // "steps" present are performed first to last. Each step is 1) a pointer to a 1064 // member of |data| to be set to the current number of bindings added, and 2) a 1065 // vector of |ParserBindingName|s to then copy into |data->trailingNames|. 1066 // (Thus each |data| member field indicates where the corresponding vector's 1067 // names start.) 1068 template <class Data, typename... Step> 1069 static MOZ_ALWAYS_INLINE void InitializeBindingData( 1070 Data* data, uint32_t count, const ParserBindingNameVector& firstBindings, 1071 Step&&... step) { 1072 MOZ_ASSERT(data->length == 0, "data shouldn't be filled yet"); 1073 1074 ParserBindingName* start = GetScopeDataTrailingNamesPointer(data); 1075 ParserBindingName* cursor = std::uninitialized_copy( 1076 firstBindings.begin(), firstBindings.end(), start); 1077 1078 #ifdef DEBUG 1079 ParserBindingName* end = 1080 #endif 1081 detail::InitializeIndexedBindings(data->slotInfo, start, cursor, 1082 std::forward<Step>(step)...); 1083 1084 MOZ_ASSERT(PointerRangeSize(start, end) == count); 1085 data->length = count; 1086 } 1087 1088 static Maybe<GlobalScope::ParserData*> NewGlobalScopeData( 1089 FrontendContext* fc, ParseContext::Scope& scope, LifoAlloc& alloc, 1090 ParseContext* pc) { 1091 ParserBindingNameVector vars(fc); 1092 ParserBindingNameVector lets(fc); 1093 ParserBindingNameVector consts(fc); 1094 1095 bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver(); 1096 for (BindingIter bi = scope.bindings(pc); bi; bi++) { 1097 bool closedOver = allBindingsClosedOver || bi.closedOver(); 1098 1099 switch (bi.kind()) { 1100 case BindingKind::Var: { 1101 bool isTopLevelFunction = 1102 bi.declarationKind() == DeclarationKind::BodyLevelFunction; 1103 1104 ParserBindingName binding(bi.name(), closedOver, isTopLevelFunction); 1105 if (!vars.append(binding)) { 1106 return Nothing(); 1107 } 1108 break; 1109 } 1110 case BindingKind::Let: { 1111 ParserBindingName binding(bi.name(), closedOver); 1112 if (!lets.append(binding)) { 1113 return Nothing(); 1114 } 1115 break; 1116 } 1117 case BindingKind::Const: { 1118 ParserBindingName binding(bi.name(), closedOver); 1119 if (!consts.append(binding)) { 1120 return Nothing(); 1121 } 1122 break; 1123 } 1124 default: 1125 MOZ_CRASH("Bad global scope BindingKind"); 1126 } 1127 } 1128 1129 GlobalScope::ParserData* bindings = nullptr; 1130 uint32_t numBindings = vars.length() + lets.length() + consts.length(); 1131 1132 if (numBindings > 0) { 1133 bindings = NewEmptyBindingData<GlobalScope>(fc, alloc, numBindings); 1134 if (!bindings) { 1135 return Nothing(); 1136 } 1137 1138 // The ordering here is important. See comments in GlobalScope. 1139 InitializeBindingData(bindings, numBindings, vars, 1140 &ParserGlobalScopeSlotInfo::letStart, lets, 1141 &ParserGlobalScopeSlotInfo::constStart, consts); 1142 } 1143 1144 return Some(bindings); 1145 } 1146 1147 Maybe<GlobalScope::ParserData*> ParserBase::newGlobalScopeData( 1148 ParseContext::Scope& scope) { 1149 return NewGlobalScopeData(fc_, scope, stencilAlloc(), pc_); 1150 } 1151 1152 static Maybe<ModuleScope::ParserData*> NewModuleScopeData( 1153 FrontendContext* fc, ParseContext::Scope& scope, LifoAlloc& alloc, 1154 ParseContext* pc) { 1155 ParserBindingNameVector imports(fc); 1156 ParserBindingNameVector vars(fc); 1157 ParserBindingNameVector lets(fc); 1158 ParserBindingNameVector consts(fc); 1159 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1160 ParserBindingNameVector usings(fc); 1161 #endif 1162 1163 bool allBindingsClosedOver = 1164 pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize(); 1165 1166 for (BindingIter bi = scope.bindings(pc); bi; bi++) { 1167 // Imports are indirect bindings and must not be given known slots. 1168 ParserBindingName binding(bi.name(), 1169 (allBindingsClosedOver || bi.closedOver()) && 1170 bi.kind() != BindingKind::Import); 1171 switch (bi.kind()) { 1172 case BindingKind::Import: 1173 if (!imports.append(binding)) { 1174 return Nothing(); 1175 } 1176 break; 1177 case BindingKind::Var: 1178 if (!vars.append(binding)) { 1179 return Nothing(); 1180 } 1181 break; 1182 case BindingKind::Let: 1183 if (!lets.append(binding)) { 1184 return Nothing(); 1185 } 1186 break; 1187 case BindingKind::Const: 1188 if (!consts.append(binding)) { 1189 return Nothing(); 1190 } 1191 break; 1192 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1193 case BindingKind::Using: 1194 if (!usings.append(binding)) { 1195 return Nothing(); 1196 } 1197 break; 1198 #endif 1199 default: 1200 MOZ_CRASH("Bad module scope BindingKind"); 1201 } 1202 } 1203 1204 ModuleScope::ParserData* bindings = nullptr; 1205 uint32_t numBindings = imports.length() + vars.length() + lets.length() + 1206 consts.length() 1207 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1208 + usings.length() 1209 #endif 1210 ; 1211 1212 if (numBindings > 0) { 1213 bindings = NewEmptyBindingData<ModuleScope>(fc, alloc, numBindings); 1214 if (!bindings) { 1215 return Nothing(); 1216 } 1217 1218 // The ordering here is important. See comments in ModuleScope. 1219 InitializeBindingData(bindings, numBindings, imports, 1220 &ParserModuleScopeSlotInfo::varStart, vars, 1221 &ParserModuleScopeSlotInfo::letStart, lets, 1222 &ParserModuleScopeSlotInfo::constStart, consts 1223 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1224 , 1225 &ParserModuleScopeSlotInfo::usingStart, usings 1226 #endif 1227 ); 1228 } 1229 1230 return Some(bindings); 1231 } 1232 1233 Maybe<ModuleScope::ParserData*> ParserBase::newModuleScopeData( 1234 ParseContext::Scope& scope) { 1235 return NewModuleScopeData(fc_, scope, stencilAlloc(), pc_); 1236 } 1237 1238 static Maybe<EvalScope::ParserData*> NewEvalScopeData( 1239 FrontendContext* fc, ParseContext::Scope& scope, LifoAlloc& alloc, 1240 ParseContext* pc) { 1241 ParserBindingNameVector vars(fc); 1242 1243 // Treat all bindings as closed over in non-strict eval. 1244 bool allBindingsClosedOver = 1245 !pc->sc()->strict() || pc->sc()->allBindingsClosedOver(); 1246 for (BindingIter bi = scope.bindings(pc); bi; bi++) { 1247 // Eval scopes only contain 'var' bindings. 1248 MOZ_ASSERT(bi.kind() == BindingKind::Var); 1249 bool isTopLevelFunction = 1250 bi.declarationKind() == DeclarationKind::BodyLevelFunction; 1251 bool closedOver = allBindingsClosedOver || bi.closedOver(); 1252 1253 ParserBindingName binding(bi.name(), closedOver, isTopLevelFunction); 1254 if (!vars.append(binding)) { 1255 return Nothing(); 1256 } 1257 } 1258 1259 EvalScope::ParserData* bindings = nullptr; 1260 uint32_t numBindings = vars.length(); 1261 1262 if (numBindings > 0) { 1263 bindings = NewEmptyBindingData<EvalScope>(fc, alloc, numBindings); 1264 if (!bindings) { 1265 return Nothing(); 1266 } 1267 1268 InitializeBindingData(bindings, numBindings, vars); 1269 } 1270 1271 return Some(bindings); 1272 } 1273 1274 Maybe<EvalScope::ParserData*> ParserBase::newEvalScopeData( 1275 ParseContext::Scope& scope) { 1276 return NewEvalScopeData(fc_, scope, stencilAlloc(), pc_); 1277 } 1278 1279 Maybe<FunctionScope::ParserData*> ParserBase::newFunctionScopeData( 1280 ParseContext::Scope& scope, bool hasParameterExprs) { 1281 ParserBindingNameVector positionalFormals(fc_); 1282 ParserBindingNameVector formals(fc_); 1283 ParserBindingNameVector vars(fc_); 1284 1285 bool allBindingsClosedOver = 1286 pc_->sc()->allBindingsClosedOver() || scope.tooBigToOptimize(); 1287 bool argumentBindingsClosedOver = 1288 allBindingsClosedOver || pc_->isGeneratorOrAsync(); 1289 bool hasDuplicateParams = pc_->functionBox()->hasDuplicateParameters; 1290 1291 // Positional parameter names must be added in order of appearance as they are 1292 // referenced using argument slots. 1293 for (size_t i = 0; i < pc_->positionalFormalParameterNames().length(); i++) { 1294 TaggedParserAtomIndex name = pc_->positionalFormalParameterNames()[i]; 1295 1296 ParserBindingName bindName; 1297 if (name) { 1298 DeclaredNamePtr p = scope.lookupDeclaredName(name); 1299 1300 // Do not consider any positional formal parameters closed over if 1301 // there are parameter defaults. It is the binding in the defaults 1302 // scope that is closed over instead. 1303 bool closedOver = 1304 argumentBindingsClosedOver || (p && p->value()->closedOver()); 1305 1306 // If the parameter name has duplicates, only the final parameter 1307 // name should be on the environment, as otherwise the environment 1308 // object would have multiple, same-named properties. 1309 if (hasDuplicateParams) { 1310 for (size_t j = pc_->positionalFormalParameterNames().length() - 1; 1311 j > i; j--) { 1312 if (TaggedParserAtomIndex(pc_->positionalFormalParameterNames()[j]) == 1313 name) { 1314 closedOver = false; 1315 break; 1316 } 1317 } 1318 } 1319 1320 bindName = ParserBindingName(name, closedOver); 1321 } 1322 1323 if (!positionalFormals.append(bindName)) { 1324 return Nothing(); 1325 } 1326 } 1327 1328 for (BindingIter bi = scope.bindings(pc_); bi; bi++) { 1329 ParserBindingName binding(bi.name(), 1330 allBindingsClosedOver || bi.closedOver()); 1331 switch (bi.kind()) { 1332 case BindingKind::FormalParameter: 1333 // Positional parameter names are already handled above. 1334 if (bi.declarationKind() == DeclarationKind::FormalParameter) { 1335 if (!formals.append(binding)) { 1336 return Nothing(); 1337 } 1338 } 1339 break; 1340 case BindingKind::Var: 1341 // The only vars in the function scope when there are parameter 1342 // exprs, which induces a separate var environment, should be the 1343 // special bindings. 1344 MOZ_ASSERT_IF(hasParameterExprs, 1345 FunctionScope::isSpecialName(bi.name())); 1346 if (!vars.append(binding)) { 1347 return Nothing(); 1348 } 1349 break; 1350 case BindingKind::Let: 1351 case BindingKind::Const: 1352 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1353 case BindingKind::Using: 1354 #endif 1355 break; 1356 default: 1357 MOZ_CRASH("bad function scope BindingKind"); 1358 break; 1359 } 1360 } 1361 1362 // This should already be checked by GeneralParser::functionArguments. 1363 MOZ_ASSERT(positionalFormals.length() <= UINT16_MAX); 1364 1365 if (positionalFormals.length() + formals.length() > UINT16_MAX) { 1366 error(JSMSG_TOO_MANY_FUN_ARGS); 1367 return Nothing(); 1368 } 1369 1370 FunctionScope::ParserData* bindings = nullptr; 1371 uint32_t numBindings = 1372 positionalFormals.length() + formals.length() + vars.length(); 1373 1374 if (numBindings > 0) { 1375 bindings = 1376 NewEmptyBindingData<FunctionScope>(fc_, stencilAlloc(), numBindings); 1377 if (!bindings) { 1378 return Nothing(); 1379 } 1380 1381 // The ordering here is important. See comments in FunctionScope. 1382 InitializeBindingData( 1383 bindings, numBindings, positionalFormals, 1384 &ParserFunctionScopeSlotInfo::nonPositionalFormalStart, formals, 1385 &ParserFunctionScopeSlotInfo::varStart, vars); 1386 } 1387 1388 return Some(bindings); 1389 } 1390 1391 // Compute if `newFunctionScopeData` would return any binding list with any 1392 // entry marked as closed-over. This is done without the need to allocate the 1393 // binding list. If true, an EnvironmentObject will be needed at runtime. 1394 bool FunctionScopeHasClosedOverBindings(ParseContext* pc) { 1395 bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver() || 1396 pc->functionScope().tooBigToOptimize(); 1397 1398 for (BindingIter bi = pc->functionScope().bindings(pc); bi; bi++) { 1399 switch (bi.kind()) { 1400 case BindingKind::FormalParameter: 1401 case BindingKind::Var: 1402 if (allBindingsClosedOver || bi.closedOver()) { 1403 return true; 1404 } 1405 break; 1406 1407 default: 1408 break; 1409 } 1410 } 1411 1412 return false; 1413 } 1414 1415 VarScope::ParserData* NewEmptyVarScopeData(FrontendContext* fc, 1416 LifoAlloc& alloc, 1417 uint32_t numBindings) { 1418 return NewEmptyBindingData<VarScope>(fc, alloc, numBindings); 1419 } 1420 1421 static Maybe<VarScope::ParserData*> NewVarScopeData(FrontendContext* fc, 1422 ParseContext::Scope& scope, 1423 LifoAlloc& alloc, 1424 ParseContext* pc) { 1425 ParserBindingNameVector vars(fc); 1426 1427 bool allBindingsClosedOver = 1428 pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize(); 1429 1430 for (BindingIter bi = scope.bindings(pc); bi; bi++) { 1431 if (bi.kind() == BindingKind::Var) { 1432 ParserBindingName binding(bi.name(), 1433 allBindingsClosedOver || bi.closedOver()); 1434 if (!vars.append(binding)) { 1435 return Nothing(); 1436 } 1437 } else { 1438 MOZ_ASSERT(bi.kind() == BindingKind::Let || 1439 bi.kind() == BindingKind::Const 1440 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1441 || bi.kind() == BindingKind::Using 1442 #endif 1443 , 1444 "bad var scope BindingKind"); 1445 } 1446 } 1447 1448 VarScope::ParserData* bindings = nullptr; 1449 uint32_t numBindings = vars.length(); 1450 1451 if (numBindings > 0) { 1452 bindings = NewEmptyBindingData<VarScope>(fc, alloc, numBindings); 1453 if (!bindings) { 1454 return Nothing(); 1455 } 1456 1457 InitializeBindingData(bindings, numBindings, vars); 1458 } 1459 1460 return Some(bindings); 1461 } 1462 1463 // Compute if `NewVarScopeData` would return any binding list. This is done 1464 // without allocate the binding list. 1465 static bool VarScopeHasBindings(ParseContext* pc) { 1466 for (BindingIter bi = pc->varScope().bindings(pc); bi; bi++) { 1467 if (bi.kind() == BindingKind::Var) { 1468 return true; 1469 } 1470 } 1471 1472 return false; 1473 } 1474 1475 Maybe<VarScope::ParserData*> ParserBase::newVarScopeData( 1476 ParseContext::Scope& scope) { 1477 return NewVarScopeData(fc_, scope, stencilAlloc(), pc_); 1478 } 1479 1480 static Maybe<LexicalScope::ParserData*> NewLexicalScopeData( 1481 FrontendContext* fc, ParseContext::Scope& scope, LifoAlloc& alloc, 1482 ParseContext* pc) { 1483 ParserBindingNameVector lets(fc); 1484 ParserBindingNameVector consts(fc); 1485 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1486 ParserBindingNameVector usings(fc); 1487 #endif 1488 1489 bool allBindingsClosedOver = 1490 pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize(); 1491 1492 for (BindingIter bi = scope.bindings(pc); bi; bi++) { 1493 ParserBindingName binding(bi.name(), 1494 allBindingsClosedOver || bi.closedOver()); 1495 switch (bi.kind()) { 1496 case BindingKind::Let: 1497 if (!lets.append(binding)) { 1498 return Nothing(); 1499 } 1500 break; 1501 case BindingKind::Const: 1502 if (!consts.append(binding)) { 1503 return Nothing(); 1504 } 1505 break; 1506 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1507 case BindingKind::Using: 1508 if (!usings.append(binding)) { 1509 return Nothing(); 1510 } 1511 break; 1512 #endif 1513 case BindingKind::Var: 1514 case BindingKind::FormalParameter: 1515 break; 1516 default: 1517 MOZ_CRASH("Bad lexical scope BindingKind"); 1518 break; 1519 } 1520 } 1521 1522 LexicalScope::ParserData* bindings = nullptr; 1523 uint32_t numBindings = lets.length() + consts.length() 1524 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1525 + usings.length() 1526 #endif 1527 ; 1528 1529 if (numBindings > 0) { 1530 bindings = NewEmptyBindingData<LexicalScope>(fc, alloc, numBindings); 1531 if (!bindings) { 1532 return Nothing(); 1533 } 1534 1535 // The ordering here is important. See comments in LexicalScope. 1536 InitializeBindingData(bindings, numBindings, lets, 1537 &ParserLexicalScopeSlotInfo::constStart, consts 1538 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 1539 , 1540 &ParserLexicalScopeSlotInfo::usingStart, usings 1541 #endif 1542 ); 1543 } 1544 1545 return Some(bindings); 1546 } 1547 1548 // Compute if `NewLexicalScopeData` would return any binding list with any entry 1549 // marked as closed-over. This is done without the need to allocate the binding 1550 // list. If true, an EnvironmentObject will be needed at runtime. 1551 bool LexicalScopeHasClosedOverBindings(ParseContext* pc, 1552 ParseContext::Scope& scope) { 1553 bool allBindingsClosedOver = 1554 pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize(); 1555 1556 for (BindingIter bi = scope.bindings(pc); bi; bi++) { 1557 switch (bi.kind()) { 1558 case BindingKind::Let: 1559 case BindingKind::Const: 1560 if (allBindingsClosedOver || bi.closedOver()) { 1561 return true; 1562 } 1563 break; 1564 1565 default: 1566 break; 1567 } 1568 } 1569 1570 return false; 1571 } 1572 1573 Maybe<LexicalScope::ParserData*> ParserBase::newLexicalScopeData( 1574 ParseContext::Scope& scope) { 1575 return NewLexicalScopeData(fc_, scope, stencilAlloc(), pc_); 1576 } 1577 1578 static Maybe<ClassBodyScope::ParserData*> NewClassBodyScopeData( 1579 FrontendContext* fc, ParseContext::Scope& scope, LifoAlloc& alloc, 1580 ParseContext* pc) { 1581 ParserBindingNameVector privateBrand(fc); 1582 ParserBindingNameVector synthetics(fc); 1583 ParserBindingNameVector privateMethods(fc); 1584 1585 bool allBindingsClosedOver = 1586 pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize(); 1587 1588 for (BindingIter bi = scope.bindings(pc); bi; bi++) { 1589 ParserBindingName binding(bi.name(), 1590 allBindingsClosedOver || bi.closedOver()); 1591 switch (bi.kind()) { 1592 case BindingKind::Synthetic: 1593 if (bi.name() == 1594 TaggedParserAtomIndex::WellKnown::dot_privateBrand_()) { 1595 MOZ_ASSERT(privateBrand.empty()); 1596 if (!privateBrand.append(binding)) { 1597 return Nothing(); 1598 } 1599 } else { 1600 if (!synthetics.append(binding)) { 1601 return Nothing(); 1602 } 1603 } 1604 break; 1605 1606 case BindingKind::PrivateMethod: 1607 if (!privateMethods.append(binding)) { 1608 return Nothing(); 1609 } 1610 break; 1611 1612 default: 1613 MOZ_CRASH("bad class body scope BindingKind"); 1614 break; 1615 } 1616 } 1617 1618 // We should have zero or one private brands. 1619 MOZ_ASSERT(privateBrand.length() == 0 || privateBrand.length() == 1); 1620 1621 ClassBodyScope::ParserData* bindings = nullptr; 1622 uint32_t numBindings = 1623 privateBrand.length() + synthetics.length() + privateMethods.length(); 1624 1625 if (numBindings > 0) { 1626 bindings = NewEmptyBindingData<ClassBodyScope>(fc, alloc, numBindings); 1627 if (!bindings) { 1628 return Nothing(); 1629 } 1630 // To simplify initialization of the bindings, we concatenate the 1631 // synthetics+privateBrand vector such that the private brand is always the 1632 // first element, as ordering is important. See comments in ClassBodyScope. 1633 ParserBindingNameVector brandAndSynthetics(fc); 1634 if (!brandAndSynthetics.appendAll(privateBrand)) { 1635 return Nothing(); 1636 } 1637 if (!brandAndSynthetics.appendAll(synthetics)) { 1638 return Nothing(); 1639 } 1640 1641 // The ordering here is important. See comments in ClassBodyScope. 1642 InitializeBindingData(bindings, numBindings, brandAndSynthetics, 1643 &ParserClassBodyScopeSlotInfo::privateMethodStart, 1644 privateMethods); 1645 } 1646 1647 // `EmitterScope::lookupPrivate()` requires `.privateBrand` to be stored in a 1648 // predictable slot: the first slot available in the environment object, 1649 // `ClassBodyLexicalEnvironmentObject::privateBrandSlot()`. We assume that 1650 // if `.privateBrand` is first in the scope, it will be stored there. 1651 MOZ_ASSERT_IF(!privateBrand.empty(), 1652 GetScopeDataTrailingNames(bindings)[0].name() == 1653 TaggedParserAtomIndex::WellKnown::dot_privateBrand_()); 1654 1655 return Some(bindings); 1656 } 1657 1658 Maybe<ClassBodyScope::ParserData*> ParserBase::newClassBodyScopeData( 1659 ParseContext::Scope& scope) { 1660 return NewClassBodyScopeData(fc_, scope, stencilAlloc(), pc_); 1661 } 1662 1663 template <> 1664 SyntaxParseHandler::LexicalScopeNodeResult 1665 PerHandlerParser<SyntaxParseHandler>::finishLexicalScope( 1666 ParseContext::Scope& scope, Node body, ScopeKind kind) { 1667 if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) { 1668 return errorResult(); 1669 } 1670 1671 return handler_.newLexicalScope(body); 1672 } 1673 1674 template <> 1675 FullParseHandler::LexicalScopeNodeResult 1676 PerHandlerParser<FullParseHandler>::finishLexicalScope( 1677 ParseContext::Scope& scope, ParseNode* body, ScopeKind kind) { 1678 if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) { 1679 return errorResult(); 1680 } 1681 1682 Maybe<LexicalScope::ParserData*> bindings = newLexicalScopeData(scope); 1683 if (!bindings) { 1684 return errorResult(); 1685 } 1686 1687 return handler_.newLexicalScope(*bindings, body, kind); 1688 } 1689 1690 template <> 1691 SyntaxParseHandler::ClassBodyScopeNodeResult 1692 PerHandlerParser<SyntaxParseHandler>::finishClassBodyScope( 1693 ParseContext::Scope& scope, ListNodeType body) { 1694 if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) { 1695 return errorResult(); 1696 } 1697 1698 return handler_.newClassBodyScope(body); 1699 } 1700 1701 template <> 1702 FullParseHandler::ClassBodyScopeNodeResult 1703 PerHandlerParser<FullParseHandler>::finishClassBodyScope( 1704 ParseContext::Scope& scope, ListNode* body) { 1705 if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) { 1706 return errorResult(); 1707 } 1708 1709 Maybe<ClassBodyScope::ParserData*> bindings = newClassBodyScopeData(scope); 1710 if (!bindings) { 1711 return errorResult(); 1712 } 1713 1714 return handler_.newClassBodyScope(*bindings, body); 1715 } 1716 1717 template <class ParseHandler> 1718 bool PerHandlerParser<ParseHandler>::checkForUndefinedPrivateFields( 1719 EvalSharedContext* evalSc) { 1720 if (!this->compilationState_.isInitialStencil()) { 1721 // We're delazifying -- so we already checked private names during first 1722 // parse. 1723 return true; 1724 } 1725 1726 Vector<UnboundPrivateName, 8> unboundPrivateNames(fc_); 1727 if (!usedNames_.getUnboundPrivateNames(unboundPrivateNames)) { 1728 return false; 1729 } 1730 1731 // No unbound names, let's get out of here! 1732 if (unboundPrivateNames.empty()) { 1733 return true; 1734 } 1735 1736 // It is an early error if there's private name references unbound, 1737 // unless it's an eval, in which case we need to check the scope 1738 // chain. 1739 if (!evalSc) { 1740 // The unbound private names are sorted, so just grab the first one. 1741 UnboundPrivateName minimum = unboundPrivateNames[0]; 1742 UniqueChars str = this->parserAtoms().toPrintableString(minimum.atom); 1743 if (!str) { 1744 ReportOutOfMemory(this->fc_); 1745 return false; 1746 } 1747 1748 errorAt(minimum.position.begin, JSMSG_MISSING_PRIVATE_DECL, str.get()); 1749 return false; 1750 } 1751 1752 // It's important that the unbound private names are sorted, as we 1753 // want our errors to always be issued to the first textually. 1754 for (UnboundPrivateName unboundName : unboundPrivateNames) { 1755 // If the enclosingScope is non-syntactic, then we are in a 1756 // Debugger.Frame.prototype.eval call. In order to find the declared private 1757 // names, we must use the effective scope that was determined when creating 1758 // the scopeContext. 1759 if (!this->compilationState_.scopeContext 1760 .effectiveScopePrivateFieldCacheHas(unboundName.atom)) { 1761 UniqueChars str = this->parserAtoms().toPrintableString(unboundName.atom); 1762 if (!str) { 1763 ReportOutOfMemory(this->fc_); 1764 return false; 1765 } 1766 errorAt(unboundName.position.begin, JSMSG_MISSING_PRIVATE_DECL, 1767 str.get()); 1768 return false; 1769 } 1770 } 1771 1772 return true; 1773 } 1774 1775 template <typename Unit> 1776 FullParseHandler::LexicalScopeNodeResult 1777 Parser<FullParseHandler, Unit>::evalBody(EvalSharedContext* evalsc) { 1778 SourceParseContext evalpc(this, evalsc, /* newDirectives = */ nullptr); 1779 if (!evalpc.init()) { 1780 return errorResult(); 1781 } 1782 1783 ParseContext::VarScope varScope(this); 1784 if (!varScope.init(pc_)) { 1785 return errorResult(); 1786 } 1787 1788 LexicalScopeNode* body; 1789 { 1790 // All evals have an implicit non-extensible lexical scope. 1791 ParseContext::Scope lexicalScope(this); 1792 if (!lexicalScope.init(pc_)) { 1793 return errorResult(); 1794 } 1795 1796 ListNode* list = MOZ_TRY(statementList(YieldIsName)); 1797 1798 if (!checkStatementsEOF()) { 1799 return errorResult(); 1800 } 1801 1802 // Private names not lexically defined must trigger a syntax error. 1803 if (!checkForUndefinedPrivateFields(evalsc)) { 1804 return errorResult(); 1805 } 1806 1807 body = MOZ_TRY(finishLexicalScope(lexicalScope, list)); 1808 } 1809 1810 #ifdef DEBUG 1811 if (evalpc.superScopeNeedsHomeObject() && 1812 !this->compilationState_.input.enclosingScope.isNull()) { 1813 // If superScopeNeedsHomeObject_ is set and we are an entry-point 1814 // ParseContext, then we must be emitting an eval script, and the 1815 // outer function must already be marked as needing a home object 1816 // since it contains an eval. 1817 MOZ_ASSERT( 1818 this->compilationState_.scopeContext.hasFunctionNeedsHomeObjectOnChain, 1819 "Eval must have found an enclosing function box scope that " 1820 "allows super.property"); 1821 } 1822 #endif 1823 1824 if (!CheckParseTree(this->fc_, alloc_, body)) { 1825 return errorResult(); 1826 } 1827 1828 ParseNode* node = body; 1829 // Don't constant-fold inside "use asm" code, as this could create a parse 1830 // tree that doesn't type-check as asm.js. 1831 if (!pc_->useAsmOrInsideUseAsm()) { 1832 if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, 1833 &handler_)) { 1834 return errorResult(); 1835 } 1836 } 1837 body = handler_.asLexicalScopeNode(node); 1838 1839 if (!this->setSourceMapInfo()) { 1840 return errorResult(); 1841 } 1842 1843 if (pc_->sc()->strict()) { 1844 if (!propagateFreeNamesAndMarkClosedOverBindings(varScope)) { 1845 return errorResult(); 1846 } 1847 } else { 1848 // For non-strict eval scripts, since all bindings are automatically 1849 // considered closed over, we don't need to call propagateFreeNames- 1850 // AndMarkClosedOverBindings. However, Annex B.3.3 functions still need to 1851 // be marked. 1852 if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc_, this)) { 1853 return errorResult(); 1854 } 1855 } 1856 1857 Maybe<EvalScope::ParserData*> bindings = newEvalScopeData(pc_->varScope()); 1858 if (!bindings) { 1859 return errorResult(); 1860 } 1861 evalsc->bindings = *bindings; 1862 1863 return body; 1864 } 1865 1866 template <typename Unit> 1867 FullParseHandler::ListNodeResult Parser<FullParseHandler, Unit>::globalBody( 1868 GlobalSharedContext* globalsc) { 1869 SourceParseContext globalpc(this, globalsc, /* newDirectives = */ nullptr); 1870 if (!globalpc.init()) { 1871 return errorResult(); 1872 } 1873 1874 ParseContext::VarScope varScope(this); 1875 if (!varScope.init(pc_)) { 1876 return errorResult(); 1877 } 1878 1879 ListNode* body = MOZ_TRY(statementList(YieldIsName)); 1880 1881 if (!checkStatementsEOF()) { 1882 return errorResult(); 1883 } 1884 1885 if (!CheckParseTree(this->fc_, alloc_, body)) { 1886 return errorResult(); 1887 } 1888 1889 if (!checkForUndefinedPrivateFields()) { 1890 return errorResult(); 1891 } 1892 1893 ParseNode* node = body; 1894 // Don't constant-fold inside "use asm" code, as this could create a parse 1895 // tree that doesn't type-check as asm.js. 1896 if (!pc_->useAsmOrInsideUseAsm()) { 1897 if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, 1898 &handler_)) { 1899 return errorResult(); 1900 } 1901 } 1902 body = &node->as<ListNode>(); 1903 1904 if (!this->setSourceMapInfo()) { 1905 return errorResult(); 1906 } 1907 1908 // For global scripts, whether bindings are closed over or not doesn't 1909 // matter, so no need to call propagateFreeNamesAndMarkClosedOver- 1910 // Bindings. However, Annex B.3.3 functions still need to be marked. 1911 if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc_, this)) { 1912 return errorResult(); 1913 } 1914 1915 Maybe<GlobalScope::ParserData*> bindings = 1916 newGlobalScopeData(pc_->varScope()); 1917 if (!bindings) { 1918 return errorResult(); 1919 } 1920 globalsc->bindings = *bindings; 1921 1922 return body; 1923 } 1924 1925 template <typename Unit> 1926 FullParseHandler::ModuleNodeResult Parser<FullParseHandler, Unit>::moduleBody( 1927 ModuleSharedContext* modulesc) { 1928 MOZ_ASSERT(checkOptionsCalled_); 1929 1930 this->compilationState_.moduleMetadata = 1931 fc_->getAllocator()->template new_<StencilModuleMetadata>(); 1932 if (!this->compilationState_.moduleMetadata) { 1933 return errorResult(); 1934 } 1935 1936 SourceParseContext modulepc(this, modulesc, nullptr); 1937 if (!modulepc.init()) { 1938 return errorResult(); 1939 } 1940 1941 ParseContext::VarScope varScope(this); 1942 if (!varScope.init(pc_)) { 1943 return errorResult(); 1944 } 1945 1946 ModuleNodeType moduleNode = MOZ_TRY(handler_.newModule(pos())); 1947 1948 AutoAwaitIsKeyword<FullParseHandler, Unit> awaitIsKeyword( 1949 this, AwaitIsModuleKeyword); 1950 ListNode* stmtList = MOZ_TRY(statementList(YieldIsName)); 1951 1952 MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList)); 1953 moduleNode->setBody(&stmtList->template as<ListNode>()); 1954 1955 if (pc_->isAsync()) { 1956 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_generator_())) { 1957 return errorResult(); 1958 } 1959 1960 if (!pc_->declareTopLevelDotGeneratorName()) { 1961 return errorResult(); 1962 } 1963 } 1964 1965 TokenKind tt; 1966 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 1967 return errorResult(); 1968 } 1969 if (tt != TokenKind::Eof) { 1970 error(JSMSG_GARBAGE_AFTER_INPUT, "module", TokenKindToDesc(tt)); 1971 return errorResult(); 1972 } 1973 1974 // Set the module to async if an await keyword was found at the top level. 1975 if (pc_->isAsync()) { 1976 pc_->sc()->asModuleContext()->builder.noteAsync( 1977 *this->compilationState_.moduleMetadata); 1978 } 1979 1980 // Generate the Import/Export tables and store in CompilationState. 1981 if (!modulesc->builder.buildTables(*this->compilationState_.moduleMetadata)) { 1982 return errorResult(); 1983 } 1984 1985 // Check exported local bindings exist and mark them as closed over. 1986 StencilModuleMetadata& moduleMetadata = 1987 *this->compilationState_.moduleMetadata; 1988 for (auto entry : moduleMetadata.localExportEntries) { 1989 DeclaredNamePtr p = modulepc.varScope().lookupDeclaredName(entry.localName); 1990 if (!p) { 1991 UniqueChars str = this->parserAtoms().toPrintableString(entry.localName); 1992 if (!str) { 1993 ReportOutOfMemory(this->fc_); 1994 return errorResult(); 1995 } 1996 1997 errorNoOffset(JSMSG_MISSING_EXPORT, str.get()); 1998 return errorResult(); 1999 } 2000 2001 p->value()->setClosedOver(); 2002 } 2003 2004 // Reserve an environment slot for a "*namespace*" psuedo-binding and mark as 2005 // closed-over. We do not know until module linking if this will be used. 2006 if (!noteDeclaredName( 2007 TaggedParserAtomIndex::WellKnown::star_namespace_star_(), 2008 DeclarationKind::Const, pos())) { 2009 return errorResult(); 2010 } 2011 modulepc.varScope() 2012 .lookupDeclaredName( 2013 TaggedParserAtomIndex::WellKnown::star_namespace_star_()) 2014 ->value() 2015 ->setClosedOver(); 2016 2017 if (!CheckParseTree(this->fc_, alloc_, stmtList)) { 2018 return errorResult(); 2019 } 2020 2021 ParseNode* node = stmtList; 2022 // Don't constant-fold inside "use asm" code, as this could create a parse 2023 // tree that doesn't type-check as asm.js. 2024 if (!pc_->useAsmOrInsideUseAsm()) { 2025 if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, 2026 &handler_)) { 2027 return errorResult(); 2028 } 2029 } 2030 stmtList = &node->as<ListNode>(); 2031 2032 if (!this->setSourceMapInfo()) { 2033 return errorResult(); 2034 } 2035 2036 // Private names not lexically defined must trigger a syntax error. 2037 if (!checkForUndefinedPrivateFields()) { 2038 return errorResult(); 2039 } 2040 2041 if (!propagateFreeNamesAndMarkClosedOverBindings(modulepc.varScope())) { 2042 return errorResult(); 2043 } 2044 2045 Maybe<ModuleScope::ParserData*> bindings = 2046 newModuleScopeData(modulepc.varScope()); 2047 if (!bindings) { 2048 return errorResult(); 2049 } 2050 2051 modulesc->bindings = *bindings; 2052 return moduleNode; 2053 } 2054 2055 template <typename Unit> 2056 SyntaxParseHandler::ModuleNodeResult 2057 Parser<SyntaxParseHandler, Unit>::moduleBody(ModuleSharedContext* modulesc) { 2058 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 2059 return errorResult(); 2060 } 2061 2062 template <class ParseHandler> 2063 typename ParseHandler::NameNodeResult 2064 PerHandlerParser<ParseHandler>::newInternalDotName(TaggedParserAtomIndex name) { 2065 NameNodeType nameNode = MOZ_TRY(newName(name)); 2066 if (!noteUsedName(name)) { 2067 return errorResult(); 2068 } 2069 return nameNode; 2070 } 2071 2072 template <class ParseHandler> 2073 typename ParseHandler::NameNodeResult 2074 PerHandlerParser<ParseHandler>::newThisName() { 2075 return newInternalDotName(TaggedParserAtomIndex::WellKnown::dot_this_()); 2076 } 2077 2078 template <class ParseHandler> 2079 typename ParseHandler::NameNodeResult 2080 PerHandlerParser<ParseHandler>::newNewTargetName() { 2081 return newInternalDotName(TaggedParserAtomIndex::WellKnown::dot_newTarget_()); 2082 } 2083 2084 template <class ParseHandler> 2085 typename ParseHandler::NameNodeResult 2086 PerHandlerParser<ParseHandler>::newDotGeneratorName() { 2087 return newInternalDotName(TaggedParserAtomIndex::WellKnown::dot_generator_()); 2088 } 2089 2090 template <class ParseHandler> 2091 bool PerHandlerParser<ParseHandler>::finishFunctionScopes( 2092 bool isStandaloneFunction) { 2093 FunctionBox* funbox = pc_->functionBox(); 2094 2095 if (funbox->hasParameterExprs) { 2096 if (!propagateFreeNamesAndMarkClosedOverBindings(pc_->functionScope())) { 2097 return false; 2098 } 2099 2100 // Functions with parameter expressions utilize the FunctionScope for vars 2101 // generated by sloppy-direct-evals, as well as arguments (which are 2102 // lexicals bindings). If the function body has var bindings (or has a 2103 // sloppy-direct-eval that might), then an extra VarScope must be created 2104 // for them. 2105 if (VarScopeHasBindings(pc_) || 2106 funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings()) { 2107 funbox->setFunctionHasExtraBodyVarScope(); 2108 } 2109 } 2110 2111 // See: JSFunction::needsCallObject() 2112 if (FunctionScopeHasClosedOverBindings(pc_) || 2113 funbox->needsCallObjectRegardlessOfBindings()) { 2114 funbox->setNeedsFunctionEnvironmentObjects(); 2115 } 2116 2117 if (funbox->isNamedLambda() && !isStandaloneFunction) { 2118 if (!propagateFreeNamesAndMarkClosedOverBindings(pc_->namedLambdaScope())) { 2119 return false; 2120 } 2121 2122 // See: JSFunction::needsNamedLambdaEnvironment() 2123 if (LexicalScopeHasClosedOverBindings(pc_, pc_->namedLambdaScope())) { 2124 funbox->setNeedsFunctionEnvironmentObjects(); 2125 } 2126 } 2127 2128 return true; 2129 } 2130 2131 template <> 2132 bool PerHandlerParser<FullParseHandler>::finishFunction( 2133 bool isStandaloneFunction /* = false */) { 2134 if (!finishFunctionScopes(isStandaloneFunction)) { 2135 return false; 2136 } 2137 2138 FunctionBox* funbox = pc_->functionBox(); 2139 ScriptStencil& script = funbox->functionStencil(); 2140 2141 if (funbox->isInterpreted()) { 2142 // BCE will need to generate bytecode for this. 2143 funbox->emitBytecode = true; 2144 this->compilationState_.nonLazyFunctionCount++; 2145 } 2146 2147 bool hasParameterExprs = funbox->hasParameterExprs; 2148 2149 if (hasParameterExprs) { 2150 Maybe<VarScope::ParserData*> bindings = newVarScopeData(pc_->varScope()); 2151 if (!bindings) { 2152 return false; 2153 } 2154 funbox->setExtraVarScopeBindings(*bindings); 2155 2156 MOZ_ASSERT(bool(*bindings) == VarScopeHasBindings(pc_)); 2157 MOZ_ASSERT_IF(!funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings(), 2158 bool(*bindings) == funbox->functionHasExtraBodyVarScope()); 2159 } 2160 2161 { 2162 Maybe<FunctionScope::ParserData*> bindings = 2163 newFunctionScopeData(pc_->functionScope(), hasParameterExprs); 2164 if (!bindings) { 2165 return false; 2166 } 2167 funbox->setFunctionScopeBindings(*bindings); 2168 } 2169 2170 if (funbox->isNamedLambda() && !isStandaloneFunction) { 2171 Maybe<LexicalScope::ParserData*> bindings = 2172 newLexicalScopeData(pc_->namedLambdaScope()); 2173 if (!bindings) { 2174 return false; 2175 } 2176 funbox->setNamedLambdaBindings(*bindings); 2177 } 2178 2179 funbox->finishScriptFlags(); 2180 funbox->copyFunctionFields(script); 2181 2182 if (this->compilationState_.isInitialStencil()) { 2183 ScriptStencilExtra& scriptExtra = funbox->functionExtraStencil(); 2184 funbox->copyFunctionExtraFields(scriptExtra); 2185 funbox->copyScriptExtraFields(scriptExtra); 2186 } 2187 2188 return true; 2189 } 2190 2191 template <> 2192 bool PerHandlerParser<SyntaxParseHandler>::finishFunction( 2193 bool isStandaloneFunction /* = false */) { 2194 // The BaseScript for a lazily parsed function needs to know its set of 2195 // free variables and inner functions so that when it is fully parsed, we 2196 // can skip over any already syntax parsed inner functions and still 2197 // retain correct scope information. 2198 2199 if (!finishFunctionScopes(isStandaloneFunction)) { 2200 return false; 2201 } 2202 2203 FunctionBox* funbox = pc_->functionBox(); 2204 ScriptStencil& script = funbox->functionStencil(); 2205 2206 funbox->finishScriptFlags(); 2207 funbox->copyFunctionFields(script); 2208 2209 ScriptStencilExtra& scriptExtra = funbox->functionExtraStencil(); 2210 funbox->copyFunctionExtraFields(scriptExtra); 2211 funbox->copyScriptExtraFields(scriptExtra); 2212 2213 // Elide nullptr sentinels from end of binding list. These are inserted for 2214 // each scope regardless of if any bindings are actually closed over. 2215 { 2216 AtomVector& closedOver = pc_->closedOverBindingsForLazy(); 2217 while (!closedOver.empty() && !closedOver.back()) { 2218 closedOver.popBack(); 2219 } 2220 } 2221 2222 // Check if we will overflow the `ngcthings` field later. 2223 mozilla::CheckedUint32 ngcthings = 2224 mozilla::CheckedUint32(pc_->innerFunctionIndexesForLazy.length()) + 2225 mozilla::CheckedUint32(pc_->closedOverBindingsForLazy().length()); 2226 if (!ngcthings.isValid()) { 2227 ReportAllocationOverflow(fc_); 2228 return false; 2229 } 2230 2231 // If there are no script-things, we can return early without allocating. 2232 if (ngcthings.value() == 0) { 2233 MOZ_ASSERT(!script.hasGCThings()); 2234 return true; 2235 } 2236 2237 TaggedScriptThingIndex* cursor = nullptr; 2238 if (!this->compilationState_.allocateGCThingsUninitialized( 2239 fc_, funbox->index(), ngcthings.value(), &cursor)) { 2240 return false; 2241 } 2242 2243 // Copy inner-function and closed-over-binding info for the stencil. The order 2244 // is important here. We emit functions first, followed by the bindings info. 2245 // The bindings list uses nullptr as delimiter to separates the bindings per 2246 // scope. 2247 // 2248 // See: FullParseHandler::nextLazyInnerFunction(), 2249 // FullParseHandler::nextLazyClosedOverBinding() 2250 for (const ScriptIndex& index : pc_->innerFunctionIndexesForLazy) { 2251 void* raw = &(*cursor++); 2252 new (raw) TaggedScriptThingIndex(index); 2253 } 2254 for (auto binding : pc_->closedOverBindingsForLazy()) { 2255 void* raw = &(*cursor++); 2256 if (binding) { 2257 this->parserAtoms().markUsedByStencil(binding, ParserAtom::Atomize::Yes); 2258 new (raw) TaggedScriptThingIndex(binding); 2259 } else { 2260 new (raw) TaggedScriptThingIndex(); 2261 } 2262 } 2263 2264 return true; 2265 } 2266 2267 static YieldHandling GetYieldHandling(GeneratorKind generatorKind) { 2268 if (generatorKind == GeneratorKind::NotGenerator) { 2269 return YieldIsName; 2270 } 2271 return YieldIsKeyword; 2272 } 2273 2274 static AwaitHandling GetAwaitHandling(FunctionAsyncKind asyncKind) { 2275 if (asyncKind == FunctionAsyncKind::SyncFunction) { 2276 return AwaitIsName; 2277 } 2278 return AwaitIsKeyword; 2279 } 2280 2281 static FunctionFlags InitialFunctionFlags(FunctionSyntaxKind kind, 2282 GeneratorKind generatorKind, 2283 FunctionAsyncKind asyncKind, 2284 bool isSelfHosting) { 2285 FunctionFlags flags = {}; 2286 2287 switch (kind) { 2288 case FunctionSyntaxKind::Expression: 2289 flags = (generatorKind == GeneratorKind::NotGenerator && 2290 asyncKind == FunctionAsyncKind::SyncFunction 2291 ? FunctionFlags::INTERPRETED_LAMBDA 2292 : FunctionFlags::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC); 2293 break; 2294 case FunctionSyntaxKind::Arrow: 2295 flags = FunctionFlags::INTERPRETED_LAMBDA_ARROW; 2296 break; 2297 case FunctionSyntaxKind::Method: 2298 case FunctionSyntaxKind::FieldInitializer: 2299 case FunctionSyntaxKind::StaticClassBlock: 2300 flags = FunctionFlags::INTERPRETED_METHOD; 2301 break; 2302 case FunctionSyntaxKind::ClassConstructor: 2303 case FunctionSyntaxKind::DerivedClassConstructor: 2304 flags = FunctionFlags::INTERPRETED_CLASS_CTOR; 2305 break; 2306 case FunctionSyntaxKind::Getter: 2307 flags = FunctionFlags::INTERPRETED_GETTER; 2308 break; 2309 case FunctionSyntaxKind::Setter: 2310 flags = FunctionFlags::INTERPRETED_SETTER; 2311 break; 2312 default: 2313 MOZ_ASSERT(kind == FunctionSyntaxKind::Statement); 2314 flags = (generatorKind == GeneratorKind::NotGenerator && 2315 asyncKind == FunctionAsyncKind::SyncFunction 2316 ? FunctionFlags::INTERPRETED_NORMAL 2317 : FunctionFlags::INTERPRETED_GENERATOR_OR_ASYNC); 2318 } 2319 2320 if (isSelfHosting) { 2321 flags.setIsSelfHostedBuiltin(); 2322 } 2323 2324 return flags; 2325 } 2326 2327 template <typename Unit> 2328 FullParseHandler::FunctionNodeResult 2329 Parser<FullParseHandler, Unit>::standaloneFunction( 2330 const Maybe<uint32_t>& parameterListEnd, FunctionSyntaxKind syntaxKind, 2331 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, 2332 Directives inheritedDirectives, Directives* newDirectives) { 2333 MOZ_ASSERT(checkOptionsCalled_); 2334 // Skip prelude. 2335 TokenKind tt; 2336 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 2337 return errorResult(); 2338 } 2339 if (asyncKind == FunctionAsyncKind::AsyncFunction) { 2340 MOZ_ASSERT(tt == TokenKind::Async); 2341 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 2342 return errorResult(); 2343 } 2344 } 2345 MOZ_ASSERT(tt == TokenKind::Function); 2346 2347 if (!tokenStream.getToken(&tt)) { 2348 return errorResult(); 2349 } 2350 if (generatorKind == GeneratorKind::Generator) { 2351 MOZ_ASSERT(tt == TokenKind::Mul); 2352 if (!tokenStream.getToken(&tt)) { 2353 return errorResult(); 2354 } 2355 } 2356 2357 // Skip function name, if present. 2358 TaggedParserAtomIndex explicitName; 2359 if (TokenKindIsPossibleIdentifierName(tt)) { 2360 explicitName = anyChars.currentName(); 2361 } else { 2362 anyChars.ungetToken(); 2363 } 2364 2365 FunctionNodeType funNode = MOZ_TRY(handler_.newFunction(syntaxKind, pos())); 2366 2367 ParamsBodyNodeType argsbody = MOZ_TRY(handler_.newParamsBody(pos())); 2368 funNode->setBody(argsbody); 2369 2370 bool isSelfHosting = options().selfHostingMode; 2371 FunctionFlags flags = 2372 InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting); 2373 FunctionBox* funbox = 2374 newFunctionBox(funNode, explicitName, flags, /* toStringStart = */ 0, 2375 inheritedDirectives, generatorKind, asyncKind); 2376 if (!funbox) { 2377 return errorResult(); 2378 } 2379 2380 // Function is not syntactically part of another script. 2381 MOZ_ASSERT(funbox->index() == CompilationStencil::TopLevelIndex); 2382 2383 funbox->initStandalone(this->compilationState_.scopeContext, syntaxKind); 2384 2385 SourceParseContext funpc(this, funbox, newDirectives); 2386 if (!funpc.init()) { 2387 return errorResult(); 2388 } 2389 2390 YieldHandling yieldHandling = GetYieldHandling(generatorKind); 2391 AwaitHandling awaitHandling = GetAwaitHandling(asyncKind); 2392 AutoAwaitIsKeyword<FullParseHandler, Unit> awaitIsKeyword(this, 2393 awaitHandling); 2394 if (!functionFormalParametersAndBody(InAllowed, yieldHandling, &funNode, 2395 syntaxKind, parameterListEnd, 2396 /* isStandaloneFunction = */ true)) { 2397 return errorResult(); 2398 } 2399 2400 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 2401 return errorResult(); 2402 } 2403 if (tt != TokenKind::Eof) { 2404 error(JSMSG_GARBAGE_AFTER_INPUT, "function body", TokenKindToDesc(tt)); 2405 return errorResult(); 2406 } 2407 2408 if (!CheckParseTree(this->fc_, alloc_, funNode)) { 2409 return errorResult(); 2410 } 2411 2412 ParseNode* node = funNode; 2413 // Don't constant-fold inside "use asm" code, as this could create a parse 2414 // tree that doesn't type-check as asm.js. 2415 if (!pc_->useAsmOrInsideUseAsm()) { 2416 if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, 2417 &handler_)) { 2418 return errorResult(); 2419 } 2420 } 2421 funNode = &node->as<FunctionNode>(); 2422 2423 if (!checkForUndefinedPrivateFields(nullptr)) { 2424 return errorResult(); 2425 } 2426 2427 if (!this->setSourceMapInfo()) { 2428 return errorResult(); 2429 } 2430 2431 return funNode; 2432 } 2433 2434 template <class ParseHandler, typename Unit> 2435 typename ParseHandler::LexicalScopeNodeResult 2436 GeneralParser<ParseHandler, Unit>::functionBody(InHandling inHandling, 2437 YieldHandling yieldHandling, 2438 FunctionSyntaxKind kind, 2439 FunctionBodyType type) { 2440 MOZ_ASSERT(pc_->isFunctionBox()); 2441 2442 #ifdef DEBUG 2443 uint32_t startYieldOffset = pc_->lastYieldOffset; 2444 #endif 2445 2446 Node body; 2447 if (type == StatementListBody) { 2448 bool inheritedStrict = pc_->sc()->strict(); 2449 body = MOZ_TRY(statementList(yieldHandling)); 2450 2451 // When we transitioned from non-strict to strict mode, we need to 2452 // validate that all parameter names are valid strict mode names. 2453 if (!inheritedStrict && pc_->sc()->strict()) { 2454 MOZ_ASSERT(pc_->sc()->hasExplicitUseStrict(), 2455 "strict mode should only change when a 'use strict' directive " 2456 "is present"); 2457 if (!hasValidSimpleStrictParameterNames()) { 2458 // Request that this function be reparsed as strict to report 2459 // the invalid parameter name at the correct source location. 2460 pc_->newDirectives->setStrict(); 2461 return errorResult(); 2462 } 2463 } 2464 } else { 2465 MOZ_ASSERT(type == ExpressionBody); 2466 2467 // Async functions are implemented as generators, and generators are 2468 // assumed to be statement lists, to prepend initial `yield`. 2469 ListNodeType stmtList = null(); 2470 if (pc_->isAsync()) { 2471 stmtList = MOZ_TRY(handler_.newStatementList(pos())); 2472 } 2473 2474 Node kid = 2475 MOZ_TRY(assignExpr(inHandling, yieldHandling, TripledotProhibited)); 2476 2477 body = MOZ_TRY(handler_.newExpressionBody(kid)); 2478 2479 if (pc_->isAsync()) { 2480 handler_.addStatementToList(stmtList, body); 2481 body = stmtList; 2482 } 2483 } 2484 2485 MOZ_ASSERT_IF(!pc_->isGenerator() && !pc_->isAsync(), 2486 pc_->lastYieldOffset == startYieldOffset); 2487 MOZ_ASSERT_IF(pc_->isGenerator(), kind != FunctionSyntaxKind::Arrow); 2488 MOZ_ASSERT_IF(pc_->isGenerator(), type == StatementListBody); 2489 2490 if (pc_->needsDotGeneratorName()) { 2491 MOZ_ASSERT_IF(!pc_->isAsync(), type == StatementListBody); 2492 if (!pc_->declareDotGeneratorName()) { 2493 return errorResult(); 2494 } 2495 if (pc_->isGenerator()) { 2496 NameNodeType generator = MOZ_TRY(newDotGeneratorName()); 2497 if (!handler_.prependInitialYield(handler_.asListNode(body), generator)) { 2498 return errorResult(); 2499 } 2500 } 2501 } 2502 2503 if (pc_->numberOfArgumentsNames > 0 || kind == FunctionSyntaxKind::Arrow) { 2504 MOZ_ASSERT(pc_->isFunctionBox()); 2505 pc_->sc()->setIneligibleForArgumentsLength(); 2506 } 2507 2508 // Declare the 'arguments', 'this', and 'new.target' bindings if necessary 2509 // before finishing up the scope so these special bindings get marked as 2510 // closed over if necessary. Arrow functions don't have these bindings. 2511 if (kind != FunctionSyntaxKind::Arrow) { 2512 bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings(); 2513 if (!pc_->declareFunctionArgumentsObject(usedNames_, 2514 canSkipLazyClosedOverBindings)) { 2515 return errorResult(); 2516 } 2517 if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) { 2518 return errorResult(); 2519 } 2520 if (!pc_->declareNewTarget(usedNames_, canSkipLazyClosedOverBindings)) { 2521 return errorResult(); 2522 } 2523 } 2524 2525 return finishLexicalScope(pc_->varScope(), body, ScopeKind::FunctionLexical); 2526 } 2527 2528 template <class ParseHandler, typename Unit> 2529 bool GeneralParser<ParseHandler, Unit>::matchOrInsertSemicolon( 2530 Modifier modifier /* = TokenStream::SlashIsRegExp */) { 2531 TokenKind tt = TokenKind::Eof; 2532 if (!tokenStream.peekTokenSameLine(&tt, modifier)) { 2533 return false; 2534 } 2535 if (tt != TokenKind::Eof && tt != TokenKind::Eol && tt != TokenKind::Semi && 2536 tt != TokenKind::RightCurly) { 2537 /* 2538 * When current token is `await` and it's outside of async function, 2539 * it's possibly intended to be an await expression. 2540 * 2541 * await f(); 2542 * ^ 2543 * | 2544 * tried to insert semicolon here 2545 * 2546 * Detect this situation and throw an understandable error. Otherwise 2547 * we'd throw a confusing "unexpected token: (unexpected token)" error. 2548 */ 2549 if (!pc_->isAsync() && anyChars.currentToken().type == TokenKind::Await) { 2550 error(JSMSG_AWAIT_OUTSIDE_ASYNC_OR_MODULE); 2551 return false; 2552 } 2553 if (!yieldExpressionsSupported() && 2554 anyChars.currentToken().type == TokenKind::Yield) { 2555 error(JSMSG_YIELD_OUTSIDE_GENERATOR); 2556 return false; 2557 } 2558 2559 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 2560 if (options().explicitResourceManagement() && 2561 anyChars.currentToken().type == TokenKind::Using && 2562 !this->pc_->isUsingSyntaxAllowed()) { 2563 error(JSMSG_USING_OUTSIDE_BLOCK_OR_MODULE); 2564 return false; 2565 } 2566 #endif 2567 2568 /* Advance the scanner for proper error location reporting. */ 2569 tokenStream.consumeKnownToken(tt, modifier); 2570 error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(tt)); 2571 return false; 2572 } 2573 bool matched; 2574 return tokenStream.matchToken(&matched, TokenKind::Semi, modifier); 2575 } 2576 2577 bool ParserBase::leaveInnerFunction(ParseContext* outerpc) { 2578 MOZ_ASSERT(pc_ != outerpc); 2579 2580 MOZ_ASSERT_IF(outerpc->isFunctionBox(), 2581 outerpc->functionBox()->index() < pc_->functionBox()->index()); 2582 2583 // If the current function allows super.property but cannot have a home 2584 // object, i.e., it is an arrow function, we need to propagate the flag to 2585 // the outer ParseContext. 2586 if (pc_->superScopeNeedsHomeObject()) { 2587 if (!pc_->isArrowFunction()) { 2588 MOZ_ASSERT(pc_->functionBox()->needsHomeObject()); 2589 } else { 2590 outerpc->setSuperScopeNeedsHomeObject(); 2591 } 2592 } 2593 2594 // Lazy functions inner to another lazy function need to be remembered by 2595 // the inner function so that if the outer function is eventually parsed 2596 // we do not need any further parsing or processing of the inner function. 2597 // 2598 // Append the inner function index here unconditionally; the vector is only 2599 // used if the Parser using outerpc is a syntax parsing. See 2600 // GeneralParser<SyntaxParseHandler>::finishFunction. 2601 if (!outerpc->innerFunctionIndexesForLazy.append( 2602 pc_->functionBox()->index())) { 2603 return false; 2604 } 2605 2606 PropagateTransitiveParseFlags(pc_->functionBox(), outerpc->sc()); 2607 2608 return true; 2609 } 2610 2611 TaggedParserAtomIndex ParserBase::prefixAccessorName( 2612 PropertyType propType, TaggedParserAtomIndex propAtom) { 2613 StringBuilder prefixed(fc_); 2614 if (propType == PropertyType::Setter) { 2615 if (!prefixed.append("set ")) { 2616 return TaggedParserAtomIndex::null(); 2617 } 2618 } else { 2619 if (!prefixed.append("get ")) { 2620 return TaggedParserAtomIndex::null(); 2621 } 2622 } 2623 if (!prefixed.append(this->parserAtoms(), propAtom)) { 2624 return TaggedParserAtomIndex::null(); 2625 } 2626 return prefixed.finishParserAtom(this->parserAtoms(), fc_); 2627 } 2628 2629 template <class ParseHandler, typename Unit> 2630 void GeneralParser<ParseHandler, Unit>::setFunctionStartAtPosition( 2631 FunctionBox* funbox, TokenPos pos) const { 2632 uint32_t startLine; 2633 JS::LimitedColumnNumberOneOrigin startColumn; 2634 tokenStream.computeLineAndColumn(pos.begin, &startLine, &startColumn); 2635 2636 // NOTE: `Debugger::CallData::findScripts` relies on sourceStart and 2637 // lineno/column referring to the same location. 2638 funbox->setStart(pos.begin, startLine, startColumn); 2639 } 2640 2641 template <class ParseHandler, typename Unit> 2642 void GeneralParser<ParseHandler, Unit>::setFunctionStartAtCurrentToken( 2643 FunctionBox* funbox) const { 2644 setFunctionStartAtPosition(funbox, anyChars.currentToken().pos); 2645 } 2646 2647 template <class ParseHandler, typename Unit> 2648 bool GeneralParser<ParseHandler, Unit>::functionArguments( 2649 YieldHandling yieldHandling, FunctionSyntaxKind kind, 2650 FunctionNodeType funNode) { 2651 FunctionBox* funbox = pc_->functionBox(); 2652 2653 // Modifier for the following tokens. 2654 // TokenStream::SlashIsDiv for the following cases: 2655 // async a => 1 2656 // ^ 2657 // 2658 // (a) => 1 2659 // ^ 2660 // 2661 // async (a) => 1 2662 // ^ 2663 // 2664 // function f(a) {} 2665 // ^ 2666 // 2667 // TokenStream::SlashIsRegExp for the following case: 2668 // a => 1 2669 // ^ 2670 Modifier firstTokenModifier = 2671 kind != FunctionSyntaxKind::Arrow || funbox->isAsync() 2672 ? TokenStream::SlashIsDiv 2673 : TokenStream::SlashIsRegExp; 2674 TokenKind tt; 2675 if (!tokenStream.getToken(&tt, firstTokenModifier)) { 2676 return false; 2677 } 2678 2679 if (kind == FunctionSyntaxKind::Arrow && TokenKindIsPossibleIdentifier(tt)) { 2680 // Record the start of function source (for FunctionToString). 2681 setFunctionStartAtCurrentToken(funbox); 2682 2683 ParamsBodyNodeType argsbody; 2684 MOZ_TRY_VAR_OR_RETURN(argsbody, handler_.newParamsBody(pos()), false); 2685 handler_.setFunctionFormalParametersAndBody(funNode, argsbody); 2686 2687 TaggedParserAtomIndex name = bindingIdentifier(yieldHandling); 2688 if (!name) { 2689 return false; 2690 } 2691 2692 constexpr bool disallowDuplicateParams = true; 2693 bool duplicatedParam = false; 2694 if (!notePositionalFormalParameter(funNode, name, pos().begin, 2695 disallowDuplicateParams, 2696 &duplicatedParam)) { 2697 return false; 2698 } 2699 MOZ_ASSERT(!duplicatedParam); 2700 MOZ_ASSERT(pc_->positionalFormalParameterNames().length() == 1); 2701 2702 funbox->setLength(1); 2703 funbox->setArgCount(1); 2704 return true; 2705 } 2706 2707 if (tt != TokenKind::LeftParen) { 2708 error(kind == FunctionSyntaxKind::Arrow ? JSMSG_BAD_ARROW_ARGS 2709 : JSMSG_PAREN_BEFORE_FORMAL); 2710 return false; 2711 } 2712 2713 // Record the start of function source (for FunctionToString). 2714 setFunctionStartAtCurrentToken(funbox); 2715 2716 ParamsBodyNodeType argsbody; 2717 MOZ_TRY_VAR_OR_RETURN(argsbody, handler_.newParamsBody(pos()), false); 2718 handler_.setFunctionFormalParametersAndBody(funNode, argsbody); 2719 2720 bool matched; 2721 if (!tokenStream.matchToken(&matched, TokenKind::RightParen, 2722 TokenStream::SlashIsRegExp)) { 2723 return false; 2724 } 2725 if (!matched) { 2726 bool hasRest = false; 2727 bool hasDefault = false; 2728 bool duplicatedParam = false; 2729 bool disallowDuplicateParams = 2730 kind == FunctionSyntaxKind::Arrow || 2731 kind == FunctionSyntaxKind::Method || 2732 kind == FunctionSyntaxKind::FieldInitializer || 2733 kind == FunctionSyntaxKind::ClassConstructor; 2734 AtomVector& positionalFormals = pc_->positionalFormalParameterNames(); 2735 2736 if (kind == FunctionSyntaxKind::Getter) { 2737 error(JSMSG_ACCESSOR_WRONG_ARGS, "getter", "no", "s"); 2738 return false; 2739 } 2740 2741 while (true) { 2742 if (hasRest) { 2743 error(JSMSG_PARAMETER_AFTER_REST); 2744 return false; 2745 } 2746 2747 TokenKind tt; 2748 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 2749 return false; 2750 } 2751 2752 if (tt == TokenKind::TripleDot) { 2753 if (kind == FunctionSyntaxKind::Setter) { 2754 error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", ""); 2755 return false; 2756 } 2757 2758 disallowDuplicateParams = true; 2759 if (duplicatedParam) { 2760 // Has duplicated args before the rest parameter. 2761 error(JSMSG_BAD_DUP_ARGS); 2762 return false; 2763 } 2764 2765 hasRest = true; 2766 funbox->setHasRest(); 2767 2768 if (!tokenStream.getToken(&tt)) { 2769 return false; 2770 } 2771 2772 if (!TokenKindIsPossibleIdentifier(tt) && 2773 tt != TokenKind::LeftBracket && tt != TokenKind::LeftCurly) { 2774 error(JSMSG_NO_REST_NAME); 2775 return false; 2776 } 2777 } 2778 2779 switch (tt) { 2780 case TokenKind::LeftBracket: 2781 case TokenKind::LeftCurly: { 2782 disallowDuplicateParams = true; 2783 if (duplicatedParam) { 2784 // Has duplicated args before the destructuring parameter. 2785 error(JSMSG_BAD_DUP_ARGS); 2786 return false; 2787 } 2788 2789 funbox->hasDestructuringArgs = true; 2790 2791 Node destruct; 2792 MOZ_TRY_VAR_OR_RETURN( 2793 destruct, 2794 destructuringDeclarationWithoutYieldOrAwait( 2795 DeclarationKind::FormalParameter, yieldHandling, tt), 2796 false); 2797 2798 if (!noteDestructuredPositionalFormalParameter(funNode, destruct)) { 2799 return false; 2800 } 2801 2802 break; 2803 } 2804 2805 default: { 2806 if (!TokenKindIsPossibleIdentifier(tt)) { 2807 error(JSMSG_MISSING_FORMAL); 2808 return false; 2809 } 2810 2811 TaggedParserAtomIndex name = bindingIdentifier(yieldHandling); 2812 if (!name) { 2813 return false; 2814 } 2815 2816 if (!notePositionalFormalParameter(funNode, name, pos().begin, 2817 disallowDuplicateParams, 2818 &duplicatedParam)) { 2819 return false; 2820 } 2821 if (duplicatedParam) { 2822 funbox->hasDuplicateParameters = true; 2823 } 2824 2825 break; 2826 } 2827 } 2828 2829 if (positionalFormals.length() >= ARGNO_LIMIT) { 2830 error(JSMSG_TOO_MANY_FUN_ARGS); 2831 return false; 2832 } 2833 2834 bool matched; 2835 if (!tokenStream.matchToken(&matched, TokenKind::Assign, 2836 TokenStream::SlashIsRegExp)) { 2837 return false; 2838 } 2839 if (matched) { 2840 if (hasRest) { 2841 error(JSMSG_REST_WITH_DEFAULT); 2842 return false; 2843 } 2844 disallowDuplicateParams = true; 2845 if (duplicatedParam) { 2846 error(JSMSG_BAD_DUP_ARGS); 2847 return false; 2848 } 2849 2850 if (!hasDefault) { 2851 hasDefault = true; 2852 2853 // The Function.length property is the number of formals 2854 // before the first default argument. 2855 funbox->setLength(positionalFormals.length() - 1); 2856 } 2857 funbox->hasParameterExprs = true; 2858 2859 Node def_expr; 2860 MOZ_TRY_VAR_OR_RETURN( 2861 def_expr, assignExprWithoutYieldOrAwait(yieldHandling), false); 2862 if (!handler_.setLastFunctionFormalParameterDefault(funNode, 2863 def_expr)) { 2864 return false; 2865 } 2866 } 2867 2868 // Setter syntax uniquely requires exactly one argument. 2869 if (kind == FunctionSyntaxKind::Setter) { 2870 break; 2871 } 2872 2873 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 2874 TokenStream::SlashIsRegExp)) { 2875 return false; 2876 } 2877 if (!matched) { 2878 break; 2879 } 2880 2881 if (!hasRest) { 2882 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 2883 return false; 2884 } 2885 if (tt == TokenKind::RightParen) { 2886 break; 2887 } 2888 } 2889 } 2890 2891 TokenKind tt; 2892 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 2893 return false; 2894 } 2895 if (tt != TokenKind::RightParen) { 2896 if (kind == FunctionSyntaxKind::Setter) { 2897 error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", ""); 2898 return false; 2899 } 2900 2901 error(JSMSG_PAREN_AFTER_FORMAL); 2902 return false; 2903 } 2904 2905 if (!hasDefault) { 2906 funbox->setLength(positionalFormals.length() - hasRest); 2907 } 2908 2909 funbox->setArgCount(positionalFormals.length()); 2910 } else if (kind == FunctionSyntaxKind::Setter) { 2911 error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", ""); 2912 return false; 2913 } 2914 2915 return true; 2916 } 2917 2918 template <typename Unit> 2919 bool Parser<FullParseHandler, Unit>::skipLazyInnerFunction( 2920 FunctionNode* funNode, uint32_t toStringStart, bool tryAnnexB) { 2921 // When a lazily-parsed function is called, we only fully parse (and emit) 2922 // that function, not any of its nested children. The initial syntax-only 2923 // parse recorded the free variables of nested functions and their extents, 2924 // so we can skip over them after accounting for their free variables. 2925 2926 MOZ_ASSERT(pc_->isOutermostOfCurrentCompile()); 2927 handler_.nextLazyInnerFunction(); 2928 const ScriptStencil& cachedData = handler_.cachedScriptData(); 2929 const ScriptStencilExtra& cachedExtra = handler_.cachedScriptExtra(); 2930 MOZ_ASSERT(toStringStart == cachedExtra.extent.toStringStart); 2931 2932 FunctionBox* funbox = newFunctionBox(funNode, cachedData, cachedExtra); 2933 if (!funbox) { 2934 return false; 2935 } 2936 2937 ScriptStencil& script = funbox->functionStencil(); 2938 funbox->copyFunctionFields(script); 2939 2940 // If the inner lazy function is class constructor, connect it to the class 2941 // statement/expression we are parsing. 2942 if (funbox->isClassConstructor()) { 2943 auto classStmt = 2944 pc_->template findInnermostStatement<ParseContext::ClassStatement>(); 2945 MOZ_ASSERT(!classStmt->constructorBox); 2946 classStmt->constructorBox = funbox; 2947 } 2948 2949 MOZ_ASSERT_IF(pc_->isFunctionBox(), 2950 pc_->functionBox()->index() < funbox->index()); 2951 2952 PropagateTransitiveParseFlags(funbox, pc_->sc()); 2953 2954 if (!tokenStream.advance(funbox->extent().sourceEnd)) { 2955 return false; 2956 } 2957 2958 // Append possible Annex B function box only upon successfully parsing. 2959 if (tryAnnexB && 2960 !pc_->innermostScope()->addPossibleAnnexBFunctionBox(pc_, funbox)) { 2961 return false; 2962 } 2963 2964 return true; 2965 } 2966 2967 template <typename Unit> 2968 bool Parser<SyntaxParseHandler, Unit>::skipLazyInnerFunction( 2969 FunctionNodeType funNode, uint32_t toStringStart, bool tryAnnexB) { 2970 MOZ_CRASH("Cannot skip lazy inner functions when syntax parsing"); 2971 } 2972 2973 template <class ParseHandler, typename Unit> 2974 bool GeneralParser<ParseHandler, Unit>::skipLazyInnerFunction( 2975 FunctionNodeType funNode, uint32_t toStringStart, bool tryAnnexB) { 2976 return asFinalParser()->skipLazyInnerFunction(funNode, toStringStart, 2977 tryAnnexB); 2978 } 2979 2980 template <class ParseHandler, typename Unit> 2981 bool GeneralParser<ParseHandler, Unit>::addExprAndGetNextTemplStrToken( 2982 YieldHandling yieldHandling, ListNodeType nodeList, TokenKind* ttp) { 2983 Node pn; 2984 MOZ_TRY_VAR_OR_RETURN(pn, expr(InAllowed, yieldHandling, TripledotProhibited), 2985 false); 2986 handler_.addList(nodeList, pn); 2987 2988 TokenKind tt; 2989 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 2990 return false; 2991 } 2992 if (tt != TokenKind::RightCurly) { 2993 error(JSMSG_TEMPLSTR_UNTERM_EXPR); 2994 return false; 2995 } 2996 2997 return tokenStream.getTemplateToken(ttp); 2998 } 2999 3000 template <class ParseHandler, typename Unit> 3001 bool GeneralParser<ParseHandler, Unit>::taggedTemplate( 3002 YieldHandling yieldHandling, ListNodeType tagArgsList, TokenKind tt) { 3003 CallSiteNodeType callSiteObjNode; 3004 MOZ_TRY_VAR_OR_RETURN(callSiteObjNode, 3005 handler_.newCallSiteObject(pos().begin), false); 3006 handler_.addList(tagArgsList, callSiteObjNode); 3007 3008 pc_->sc()->setHasCallSiteObj(); 3009 3010 while (true) { 3011 if (!appendToCallSiteObj(callSiteObjNode)) { 3012 return false; 3013 } 3014 if (tt != TokenKind::TemplateHead) { 3015 break; 3016 } 3017 3018 if (!addExprAndGetNextTemplStrToken(yieldHandling, tagArgsList, &tt)) { 3019 return false; 3020 } 3021 } 3022 handler_.setEndPosition(tagArgsList, callSiteObjNode); 3023 return true; 3024 } 3025 3026 template <class ParseHandler, typename Unit> 3027 typename ParseHandler::ListNodeResult 3028 GeneralParser<ParseHandler, Unit>::templateLiteral( 3029 YieldHandling yieldHandling) { 3030 NameNodeType literal = MOZ_TRY(noSubstitutionUntaggedTemplate()); 3031 3032 ListNodeType nodeList = 3033 MOZ_TRY(handler_.newList(ParseNodeKind::TemplateStringListExpr, literal)); 3034 3035 TokenKind tt; 3036 do { 3037 if (!addExprAndGetNextTemplStrToken(yieldHandling, nodeList, &tt)) { 3038 return errorResult(); 3039 } 3040 3041 literal = MOZ_TRY(noSubstitutionUntaggedTemplate()); 3042 3043 handler_.addList(nodeList, literal); 3044 } while (tt == TokenKind::TemplateHead); 3045 return nodeList; 3046 } 3047 3048 template <class ParseHandler, typename Unit> 3049 typename ParseHandler::FunctionNodeResult 3050 GeneralParser<ParseHandler, Unit>::functionDefinition( 3051 FunctionNodeType funNode, uint32_t toStringStart, InHandling inHandling, 3052 YieldHandling yieldHandling, TaggedParserAtomIndex funName, 3053 FunctionSyntaxKind kind, GeneratorKind generatorKind, 3054 FunctionAsyncKind asyncKind, bool tryAnnexB /* = false */) { 3055 MOZ_ASSERT_IF(kind == FunctionSyntaxKind::Statement, funName); 3056 3057 // If we see any inner function, note it on our current context. The bytecode 3058 // emitter may eliminate the function later, but we use a conservative 3059 // definition for consistency between lazy and full parsing. 3060 pc_->sc()->setHasInnerFunctions(); 3061 3062 // When fully parsing a lazy script, we do not fully reparse its inner 3063 // functions, which are also lazy. Instead, their free variables and source 3064 // extents are recorded and may be skipped. 3065 if (handler_.reuseLazyInnerFunctions()) { 3066 if (!skipLazyInnerFunction(funNode, toStringStart, tryAnnexB)) { 3067 return errorResult(); 3068 } 3069 3070 return funNode; 3071 } 3072 3073 bool isSelfHosting = options().selfHostingMode; 3074 FunctionFlags flags = 3075 InitialFunctionFlags(kind, generatorKind, asyncKind, isSelfHosting); 3076 3077 // Self-hosted functions with special function names require extended slots 3078 // for various purposes. 3079 bool forceExtended = 3080 isSelfHosting && funName && 3081 this->parserAtoms().isExtendedUnclonedSelfHostedFunctionName(funName); 3082 if (forceExtended) { 3083 flags.setIsExtended(); 3084 } 3085 3086 // Speculatively parse using the directives of the parent parsing context. 3087 // If a directive is encountered (e.g., "use strict") that changes how the 3088 // function should have been parsed, we backup and reparse with the new set 3089 // of directives. 3090 Directives directives(pc_); 3091 Directives newDirectives = directives; 3092 3093 Position start(tokenStream); 3094 auto startObj = this->compilationState_.getPosition(); 3095 3096 // Parse the inner function. The following is a loop as we may attempt to 3097 // reparse a function due to failed syntax parsing and encountering new 3098 // "use foo" directives. 3099 while (true) { 3100 if (trySyntaxParseInnerFunction(&funNode, funName, flags, toStringStart, 3101 inHandling, yieldHandling, kind, 3102 generatorKind, asyncKind, tryAnnexB, 3103 directives, &newDirectives)) { 3104 break; 3105 } 3106 3107 // Return on error. 3108 if (anyChars.hadError() || directives == newDirectives) { 3109 return errorResult(); 3110 } 3111 3112 // Assignment must be monotonic to prevent infinitely attempting to 3113 // reparse. 3114 MOZ_ASSERT_IF(directives.strict(), newDirectives.strict()); 3115 MOZ_ASSERT_IF(directives.asmJS(), newDirectives.asmJS()); 3116 directives = newDirectives; 3117 3118 // Rewind to retry parsing with new directives applied. 3119 tokenStream.rewind(start); 3120 this->compilationState_.rewind(startObj); 3121 3122 // functionFormalParametersAndBody may have already set body before failing. 3123 handler_.setFunctionFormalParametersAndBody(funNode, null()); 3124 } 3125 3126 return funNode; 3127 } 3128 3129 template <typename Unit> 3130 bool Parser<FullParseHandler, Unit>::advancePastSyntaxParsedFunction( 3131 SyntaxParser* syntaxParser) { 3132 MOZ_ASSERT(getSyntaxParser() == syntaxParser); 3133 3134 // Advance this parser over tokens processed by the syntax parser. 3135 Position currentSyntaxPosition(syntaxParser->tokenStream); 3136 if (!tokenStream.fastForward(currentSyntaxPosition, syntaxParser->anyChars)) { 3137 return false; 3138 } 3139 3140 anyChars.adoptState(syntaxParser->anyChars); 3141 tokenStream.adoptState(syntaxParser->tokenStream); 3142 return true; 3143 } 3144 3145 template <typename Unit> 3146 bool Parser<FullParseHandler, Unit>::trySyntaxParseInnerFunction( 3147 FunctionNode** funNode, TaggedParserAtomIndex explicitName, 3148 FunctionFlags flags, uint32_t toStringStart, InHandling inHandling, 3149 YieldHandling yieldHandling, FunctionSyntaxKind kind, 3150 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB, 3151 Directives inheritedDirectives, Directives* newDirectives) { 3152 // Try a syntax parse for this inner function. 3153 do { 3154 // If we're assuming this function is an IIFE, always perform a full 3155 // parse to avoid the overhead of a lazy syntax-only parse. Although 3156 // the prediction may be incorrect, IIFEs are common enough that it 3157 // pays off for lots of code. 3158 if ((*funNode)->isLikelyIIFE() && 3159 generatorKind == GeneratorKind::NotGenerator && 3160 asyncKind == FunctionAsyncKind::SyncFunction) { 3161 break; 3162 } 3163 3164 SyntaxParser* syntaxParser = getSyntaxParser(); 3165 if (!syntaxParser) { 3166 break; 3167 } 3168 3169 UsedNameTracker::RewindToken token = usedNames_.getRewindToken(); 3170 auto statePosition = this->compilationState_.getPosition(); 3171 3172 // Move the syntax parser to the current position in the stream. In the 3173 // common case this seeks forward, but it'll also seek backward *at least* 3174 // when arrow functions appear inside arrow function argument defaults 3175 // (because we rewind to reparse arrow functions once we're certain they're 3176 // arrow functions): 3177 // 3178 // var x = (y = z => 2) => q; 3179 // // ^ we first seek to here to syntax-parse this function 3180 // // ^ then we seek back to here to syntax-parse the outer function 3181 Position currentPosition(tokenStream); 3182 if (!syntaxParser->tokenStream.seekTo(currentPosition, anyChars)) { 3183 return false; 3184 } 3185 3186 // Make a FunctionBox before we enter the syntax parser, because |pn| 3187 // still expects a FunctionBox to be attached to it during BCE, and 3188 // the syntax parser cannot attach one to it. 3189 FunctionBox* funbox = 3190 newFunctionBox(*funNode, explicitName, flags, toStringStart, 3191 inheritedDirectives, generatorKind, asyncKind); 3192 if (!funbox) { 3193 return false; 3194 } 3195 funbox->initWithEnclosingParseContext(pc_, kind); 3196 3197 auto syntaxNodeResult = syntaxParser->innerFunctionForFunctionBox( 3198 SyntaxParseHandler::Node::NodeGeneric, pc_, funbox, inHandling, 3199 yieldHandling, kind, newDirectives); 3200 if (syntaxNodeResult.isErr()) { 3201 if (syntaxParser->hadAbortedSyntaxParse()) { 3202 // Try again with a full parse. UsedNameTracker needs to be 3203 // rewound to just before we tried the syntax parse for 3204 // correctness. 3205 syntaxParser->clearAbortedSyntaxParse(); 3206 usedNames_.rewind(token); 3207 this->compilationState_.rewind(statePosition); 3208 MOZ_ASSERT(!fc_->hadErrors()); 3209 break; 3210 } 3211 return false; 3212 } 3213 3214 if (!advancePastSyntaxParsedFunction(syntaxParser)) { 3215 return false; 3216 } 3217 3218 // Update the end position of the parse node. 3219 (*funNode)->pn_pos.end = anyChars.currentToken().pos.end; 3220 3221 // Append possible Annex B function box only upon successfully parsing. 3222 if (tryAnnexB) { 3223 if (!pc_->innermostScope()->addPossibleAnnexBFunctionBox(pc_, funbox)) { 3224 return false; 3225 } 3226 } 3227 3228 return true; 3229 } while (false); 3230 3231 // We failed to do a syntax parse above, so do the full parse. 3232 FunctionNodeType innerFunc; 3233 MOZ_TRY_VAR_OR_RETURN( 3234 innerFunc, 3235 innerFunction(*funNode, pc_, explicitName, flags, toStringStart, 3236 inHandling, yieldHandling, kind, generatorKind, asyncKind, 3237 tryAnnexB, inheritedDirectives, newDirectives), 3238 false); 3239 3240 *funNode = innerFunc; 3241 return true; 3242 } 3243 3244 template <typename Unit> 3245 bool Parser<SyntaxParseHandler, Unit>::trySyntaxParseInnerFunction( 3246 FunctionNodeType* funNode, TaggedParserAtomIndex explicitName, 3247 FunctionFlags flags, uint32_t toStringStart, InHandling inHandling, 3248 YieldHandling yieldHandling, FunctionSyntaxKind kind, 3249 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB, 3250 Directives inheritedDirectives, Directives* newDirectives) { 3251 // This is already a syntax parser, so just parse the inner function. 3252 FunctionNodeType innerFunc; 3253 MOZ_TRY_VAR_OR_RETURN( 3254 innerFunc, 3255 innerFunction(*funNode, pc_, explicitName, flags, toStringStart, 3256 inHandling, yieldHandling, kind, generatorKind, asyncKind, 3257 tryAnnexB, inheritedDirectives, newDirectives), 3258 false); 3259 3260 *funNode = innerFunc; 3261 return true; 3262 } 3263 3264 template <class ParseHandler, typename Unit> 3265 inline bool GeneralParser<ParseHandler, Unit>::trySyntaxParseInnerFunction( 3266 FunctionNodeType* funNode, TaggedParserAtomIndex explicitName, 3267 FunctionFlags flags, uint32_t toStringStart, InHandling inHandling, 3268 YieldHandling yieldHandling, FunctionSyntaxKind kind, 3269 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB, 3270 Directives inheritedDirectives, Directives* newDirectives) { 3271 return asFinalParser()->trySyntaxParseInnerFunction( 3272 funNode, explicitName, flags, toStringStart, inHandling, yieldHandling, 3273 kind, generatorKind, asyncKind, tryAnnexB, inheritedDirectives, 3274 newDirectives); 3275 } 3276 3277 template <class ParseHandler, typename Unit> 3278 typename ParseHandler::FunctionNodeResult 3279 GeneralParser<ParseHandler, Unit>::innerFunctionForFunctionBox( 3280 FunctionNodeType funNode, ParseContext* outerpc, FunctionBox* funbox, 3281 InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind, 3282 Directives* newDirectives) { 3283 // Note that it is possible for outerpc != this->pc_, as we may be 3284 // attempting to syntax parse an inner function from an outer full 3285 // parser. In that case, outerpc is a SourceParseContext from the full parser 3286 // instead of the current top of the stack of the syntax parser. 3287 3288 // Push a new ParseContext. 3289 SourceParseContext funpc(this, funbox, newDirectives); 3290 if (!funpc.init()) { 3291 return errorResult(); 3292 } 3293 3294 if (!functionFormalParametersAndBody(inHandling, yieldHandling, &funNode, 3295 kind)) { 3296 return errorResult(); 3297 } 3298 3299 if (!leaveInnerFunction(outerpc)) { 3300 return errorResult(); 3301 } 3302 3303 return funNode; 3304 } 3305 3306 template <class ParseHandler, typename Unit> 3307 typename ParseHandler::FunctionNodeResult 3308 GeneralParser<ParseHandler, Unit>::innerFunction( 3309 FunctionNodeType funNode, ParseContext* outerpc, 3310 TaggedParserAtomIndex explicitName, FunctionFlags flags, 3311 uint32_t toStringStart, InHandling inHandling, YieldHandling yieldHandling, 3312 FunctionSyntaxKind kind, GeneratorKind generatorKind, 3313 FunctionAsyncKind asyncKind, bool tryAnnexB, Directives inheritedDirectives, 3314 Directives* newDirectives) { 3315 // Note that it is possible for outerpc != this->pc_, as we may be 3316 // attempting to syntax parse an inner function from an outer full 3317 // parser. In that case, outerpc is a SourceParseContext from the full parser 3318 // instead of the current top of the stack of the syntax parser. 3319 3320 FunctionBox* funbox = 3321 newFunctionBox(funNode, explicitName, flags, toStringStart, 3322 inheritedDirectives, generatorKind, asyncKind); 3323 if (!funbox) { 3324 return errorResult(); 3325 } 3326 funbox->initWithEnclosingParseContext(outerpc, kind); 3327 3328 FunctionNodeType innerFunc = 3329 MOZ_TRY(innerFunctionForFunctionBox(funNode, outerpc, funbox, inHandling, 3330 yieldHandling, kind, newDirectives)); 3331 3332 // Append possible Annex B function box only upon successfully parsing. 3333 if (tryAnnexB) { 3334 if (!pc_->innermostScope()->addPossibleAnnexBFunctionBox(pc_, funbox)) { 3335 return errorResult(); 3336 } 3337 } 3338 3339 return innerFunc; 3340 } 3341 3342 template <class ParseHandler, typename Unit> 3343 bool GeneralParser<ParseHandler, Unit>::appendToCallSiteObj( 3344 CallSiteNodeType callSiteObj) { 3345 Node cookedNode; 3346 MOZ_TRY_VAR_OR_RETURN(cookedNode, noSubstitutionTaggedTemplate(), false); 3347 3348 auto atom = tokenStream.getRawTemplateStringAtom(); 3349 if (!atom) { 3350 return false; 3351 } 3352 NameNodeType rawNode; 3353 MOZ_TRY_VAR_OR_RETURN(rawNode, handler_.newTemplateStringLiteral(atom, pos()), 3354 false); 3355 3356 handler_.addToCallSiteObject(callSiteObj, rawNode, cookedNode); 3357 return true; 3358 } 3359 3360 template <typename Unit> 3361 FullParseHandler::FunctionNodeResult 3362 Parser<FullParseHandler, Unit>::standaloneLazyFunction( 3363 CompilationInput& input, uint32_t toStringStart, bool strict, 3364 GeneratorKind generatorKind, FunctionAsyncKind asyncKind) { 3365 MOZ_ASSERT(checkOptionsCalled_); 3366 3367 FunctionSyntaxKind syntaxKind = input.functionSyntaxKind(); 3368 FunctionNodeType funNode = MOZ_TRY(handler_.newFunction(syntaxKind, pos())); 3369 3370 TaggedParserAtomIndex displayAtom = 3371 this->getCompilationState().previousParseCache.displayAtom(); 3372 3373 Directives directives(strict); 3374 FunctionBox* funbox = 3375 newFunctionBox(funNode, displayAtom, input.functionFlags(), toStringStart, 3376 directives, generatorKind, asyncKind); 3377 if (!funbox) { 3378 return errorResult(); 3379 } 3380 const ScriptStencilExtra& funExtra = 3381 this->getCompilationState().previousParseCache.funExtra(); 3382 funbox->initFromLazyFunction( 3383 funExtra, this->getCompilationState().scopeContext, syntaxKind); 3384 if (funbox->useMemberInitializers()) { 3385 funbox->setMemberInitializers(funExtra.memberInitializers()); 3386 } 3387 3388 Directives newDirectives = directives; 3389 SourceParseContext funpc(this, funbox, &newDirectives); 3390 if (!funpc.init()) { 3391 return errorResult(); 3392 } 3393 3394 // Our tokenStream has no current token, so funNode's position is garbage. 3395 // Substitute the position of the first token in our source. If the 3396 // function is a not-async arrow, use TokenStream::SlashIsRegExp to keep 3397 // verifyConsistentModifier from complaining (we will use 3398 // TokenStream::SlashIsRegExp in functionArguments). 3399 Modifier modifier = (input.functionFlags().isArrow() && 3400 asyncKind == FunctionAsyncKind::SyncFunction) 3401 ? TokenStream::SlashIsRegExp 3402 : TokenStream::SlashIsDiv; 3403 if (!tokenStream.peekTokenPos(&funNode->pn_pos, modifier)) { 3404 return errorResult(); 3405 } 3406 3407 YieldHandling yieldHandling = GetYieldHandling(generatorKind); 3408 3409 if (funbox->isSyntheticFunction()) { 3410 // Currently default class constructors are the only synthetic function that 3411 // supports delazification. 3412 MOZ_ASSERT(funbox->isClassConstructor()); 3413 MOZ_ASSERT(funbox->extent().toStringStart == funbox->extent().sourceStart); 3414 3415 HasHeritage hasHeritage = funbox->isDerivedClassConstructor() 3416 ? HasHeritage::Yes 3417 : HasHeritage::No; 3418 TokenPos synthesizedBodyPos(funbox->extent().toStringStart, 3419 funbox->extent().toStringEnd); 3420 3421 // Reset pos() to the `class` keyword for predictable results. 3422 tokenStream.consumeKnownToken(TokenKind::Class); 3423 3424 if (!this->synthesizeConstructorBody(synthesizedBodyPos, hasHeritage, 3425 funNode, funbox)) { 3426 return errorResult(); 3427 } 3428 } else { 3429 if (!functionFormalParametersAndBody(InAllowed, yieldHandling, &funNode, 3430 syntaxKind)) { 3431 MOZ_ASSERT(directives == newDirectives); 3432 return errorResult(); 3433 } 3434 } 3435 3436 if (!CheckParseTree(this->fc_, alloc_, funNode)) { 3437 return errorResult(); 3438 } 3439 3440 ParseNode* node = funNode; 3441 // Don't constant-fold inside "use asm" code, as this could create a parse 3442 // tree that doesn't type-check as asm.js. 3443 if (!pc_->useAsmOrInsideUseAsm()) { 3444 if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, 3445 &handler_)) { 3446 return errorResult(); 3447 } 3448 } 3449 funNode = &node->as<FunctionNode>(); 3450 3451 return funNode; 3452 } 3453 3454 void ParserBase::setFunctionEndFromCurrentToken(FunctionBox* funbox) const { 3455 if (compilationState_.isInitialStencil()) { 3456 MOZ_ASSERT(anyChars.currentToken().type != TokenKind::Eof); 3457 MOZ_ASSERT(anyChars.currentToken().type < TokenKind::Limit); 3458 funbox->setEnd(anyChars.currentToken().pos.end); 3459 } else { 3460 // If we're delazifying an arrow function with expression body and 3461 // the expression is also a function, we arrive here immediately after 3462 // skipping the function by Parser::skipLazyInnerFunction. 3463 // 3464 // a => b => c 3465 // ^ 3466 // | 3467 // we're here 3468 // 3469 // In that case, the current token's type field is either Limit or 3470 // poisoned. 3471 // We shouldn't read the value if it's poisoned. 3472 // See TokenStreamSpecific<Unit, AnyCharsAccess>::advance and 3473 // mfbt/MemoryChecking.h for more details. 3474 // 3475 // Also, in delazification, the FunctionBox should already have the 3476 // correct extent, and we shouldn't overwrite it here. 3477 // See ScriptStencil variant of PerHandlerParser::newFunctionBox. 3478 #if !defined(MOZ_ASAN) && !defined(MOZ_MSAN) && !defined(MOZ_VALGRIND) 3479 MOZ_ASSERT(anyChars.currentToken().type != TokenKind::Eof); 3480 #endif 3481 MOZ_ASSERT(funbox->extent().sourceEnd == anyChars.currentToken().pos.end); 3482 } 3483 } 3484 3485 template <class ParseHandler, typename Unit> 3486 bool GeneralParser<ParseHandler, Unit>::functionFormalParametersAndBody( 3487 InHandling inHandling, YieldHandling yieldHandling, 3488 FunctionNodeType* funNode, FunctionSyntaxKind kind, 3489 const Maybe<uint32_t>& parameterListEnd /* = Nothing() */, 3490 bool isStandaloneFunction /* = false */) { 3491 // Given a properly initialized parse context, try to parse an actual 3492 // function without concern for conversion to strict mode, use of lazy 3493 // parsing and such. 3494 3495 FunctionBox* funbox = pc_->functionBox(); 3496 3497 if (kind == FunctionSyntaxKind::ClassConstructor || 3498 kind == FunctionSyntaxKind::DerivedClassConstructor) { 3499 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { 3500 return false; 3501 } 3502 #ifdef ENABLE_DECORATORS 3503 if (!noteUsedName(TaggedParserAtomIndex::WellKnown:: 3504 dot_instanceExtraInitializers_())) { 3505 return false; 3506 } 3507 #endif 3508 } 3509 3510 // See below for an explanation why arrow function parameters and arrow 3511 // function bodies are parsed with different yield/await settings. 3512 { 3513 AwaitHandling awaitHandling = 3514 kind == FunctionSyntaxKind::StaticClassBlock ? AwaitIsDisallowed 3515 : (funbox->isAsync() || 3516 (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword())) 3517 ? AwaitIsKeyword 3518 : AwaitIsName; 3519 AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(this, awaitHandling); 3520 AutoInParametersOfAsyncFunction<ParseHandler, Unit> inParameters( 3521 this, funbox->isAsync()); 3522 if (!functionArguments(yieldHandling, kind, *funNode)) { 3523 return false; 3524 } 3525 } 3526 3527 Maybe<ParseContext::VarScope> varScope; 3528 if (funbox->hasParameterExprs) { 3529 varScope.emplace(this); 3530 if (!varScope->init(pc_)) { 3531 return false; 3532 } 3533 } else { 3534 pc_->functionScope().useAsVarScope(pc_); 3535 } 3536 3537 if (kind == FunctionSyntaxKind::Arrow) { 3538 TokenKind tt; 3539 if (!tokenStream.peekTokenSameLine(&tt)) { 3540 return false; 3541 } 3542 3543 if (tt == TokenKind::Eol) { 3544 error(JSMSG_UNEXPECTED_TOKEN, 3545 "'=>' on the same line after an argument list", 3546 TokenKindToDesc(tt)); 3547 return false; 3548 } 3549 if (tt != TokenKind::Arrow) { 3550 error(JSMSG_BAD_ARROW_ARGS); 3551 return false; 3552 } 3553 tokenStream.consumeKnownToken(TokenKind::Arrow); 3554 } 3555 3556 // When parsing something for new Function() we have to make sure to 3557 // only treat a certain part of the source as a parameter list. 3558 if (parameterListEnd.isSome() && parameterListEnd.value() != pos().begin) { 3559 error(JSMSG_UNEXPECTED_PARAMLIST_END); 3560 return false; 3561 } 3562 3563 // Parse the function body. 3564 FunctionBodyType bodyType = StatementListBody; 3565 TokenKind tt; 3566 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 3567 return false; 3568 } 3569 uint32_t openedPos = 0; 3570 if (tt != TokenKind::LeftCurly) { 3571 if (kind != FunctionSyntaxKind::Arrow) { 3572 error(JSMSG_CURLY_BEFORE_BODY); 3573 return false; 3574 } 3575 3576 anyChars.ungetToken(); 3577 bodyType = ExpressionBody; 3578 funbox->setHasExprBody(); 3579 } else { 3580 openedPos = pos().begin; 3581 } 3582 3583 // Arrow function parameters inherit yieldHandling from the enclosing 3584 // context, but the arrow body doesn't. E.g. in |(a = yield) => yield|, 3585 // |yield| in the parameters is either a name or keyword, depending on 3586 // whether the arrow function is enclosed in a generator function or not. 3587 // Whereas the |yield| in the function body is always parsed as a name. 3588 // The same goes when parsing |await| in arrow functions. 3589 YieldHandling bodyYieldHandling = GetYieldHandling(pc_->generatorKind()); 3590 AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc_->asyncKind()); 3591 bool inheritedStrict = pc_->sc()->strict(); 3592 LexicalScopeNodeType body; 3593 { 3594 AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(this, 3595 bodyAwaitHandling); 3596 AutoInParametersOfAsyncFunction<ParseHandler, Unit> inParameters(this, 3597 false); 3598 MOZ_TRY_VAR_OR_RETURN( 3599 body, functionBody(inHandling, bodyYieldHandling, kind, bodyType), 3600 false); 3601 } 3602 3603 // Revalidate the function name when we transitioned to strict mode. 3604 if ((kind == FunctionSyntaxKind::Statement || 3605 kind == FunctionSyntaxKind::Expression) && 3606 funbox->explicitName() && !inheritedStrict && pc_->sc()->strict()) { 3607 MOZ_ASSERT(pc_->sc()->hasExplicitUseStrict(), 3608 "strict mode should only change when a 'use strict' directive " 3609 "is present"); 3610 3611 auto propertyName = funbox->explicitName(); 3612 YieldHandling nameYieldHandling; 3613 if (kind == FunctionSyntaxKind::Expression) { 3614 // Named lambda has binding inside it. 3615 nameYieldHandling = bodyYieldHandling; 3616 } else { 3617 // Otherwise YieldHandling cannot be checked at this point 3618 // because of different context. 3619 // It should already be checked before this point. 3620 nameYieldHandling = YieldIsName; 3621 } 3622 3623 // We already use the correct await-handling at this point, therefore 3624 // we don't need call AutoAwaitIsKeyword here. 3625 3626 uint32_t nameOffset = handler_.getFunctionNameOffset(*funNode, anyChars); 3627 if (!checkBindingIdentifier(propertyName, nameOffset, nameYieldHandling)) { 3628 return false; 3629 } 3630 } 3631 3632 if (bodyType == StatementListBody) { 3633 // Cannot use mustMatchToken here because of internal compiler error on 3634 // gcc 6.4.0, with linux 64 SM hazard build. 3635 TokenKind actual; 3636 if (!tokenStream.getToken(&actual, TokenStream::SlashIsRegExp)) { 3637 return false; 3638 } 3639 if (actual != TokenKind::RightCurly) { 3640 reportMissingClosing(JSMSG_CURLY_AFTER_BODY, JSMSG_CURLY_OPENED, 3641 openedPos); 3642 return false; 3643 } 3644 3645 setFunctionEndFromCurrentToken(funbox); 3646 } else { 3647 MOZ_ASSERT(kind == FunctionSyntaxKind::Arrow); 3648 3649 if (anyChars.hadError()) { 3650 return false; 3651 } 3652 3653 setFunctionEndFromCurrentToken(funbox); 3654 3655 if (kind == FunctionSyntaxKind::Statement) { 3656 if (!matchOrInsertSemicolon()) { 3657 return false; 3658 } 3659 } 3660 } 3661 3662 if (IsMethodDefinitionKind(kind) && pc_->superScopeNeedsHomeObject()) { 3663 funbox->setNeedsHomeObject(); 3664 } 3665 3666 if (!finishFunction(isStandaloneFunction)) { 3667 return false; 3668 } 3669 3670 handler_.setEndPosition(body, pos().begin); 3671 handler_.setEndPosition(*funNode, pos().end); 3672 handler_.setFunctionBody(*funNode, body); 3673 3674 return true; 3675 } 3676 3677 template <class ParseHandler, typename Unit> 3678 typename ParseHandler::FunctionNodeResult 3679 GeneralParser<ParseHandler, Unit>::functionStmt(uint32_t toStringStart, 3680 YieldHandling yieldHandling, 3681 DefaultHandling defaultHandling, 3682 FunctionAsyncKind asyncKind) { 3683 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); 3684 3685 // In sloppy mode, Annex B.3.2 allows labelled function declarations. 3686 // Otherwise it's a parse error. 3687 ParseContext::Statement* declaredInStmt = pc_->innermostStatement(); 3688 if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) { 3689 MOZ_ASSERT(!pc_->sc()->strict(), 3690 "labeled functions shouldn't be parsed in strict mode"); 3691 3692 // Find the innermost non-label statement. Report an error if it's 3693 // unbraced: functions can't appear in it. Otherwise the statement 3694 // (or its absence) determines the scope the function's bound in. 3695 while (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) { 3696 declaredInStmt = declaredInStmt->enclosing(); 3697 } 3698 3699 if (declaredInStmt && !StatementKindIsBraced(declaredInStmt->kind())) { 3700 error(JSMSG_SLOPPY_FUNCTION_LABEL); 3701 return errorResult(); 3702 } 3703 } 3704 3705 TokenKind tt; 3706 if (!tokenStream.getToken(&tt)) { 3707 return errorResult(); 3708 } 3709 3710 GeneratorKind generatorKind = GeneratorKind::NotGenerator; 3711 if (tt == TokenKind::Mul) { 3712 generatorKind = GeneratorKind::Generator; 3713 if (!tokenStream.getToken(&tt)) { 3714 return errorResult(); 3715 } 3716 } 3717 3718 TaggedParserAtomIndex name; 3719 if (TokenKindIsPossibleIdentifier(tt)) { 3720 name = bindingIdentifier(yieldHandling); 3721 if (!name) { 3722 return errorResult(); 3723 } 3724 } else if (defaultHandling == AllowDefaultName) { 3725 name = TaggedParserAtomIndex::WellKnown::default_(); 3726 anyChars.ungetToken(); 3727 } else { 3728 /* Unnamed function expressions are forbidden in statement context. */ 3729 error(JSMSG_UNNAMED_FUNCTION_STMT); 3730 return errorResult(); 3731 } 3732 3733 // Note the declared name and check for early errors. 3734 DeclarationKind kind; 3735 if (declaredInStmt) { 3736 MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label); 3737 MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind())); 3738 3739 kind = 3740 (!pc_->sc()->strict() && generatorKind == GeneratorKind::NotGenerator && 3741 asyncKind == FunctionAsyncKind::SyncFunction) 3742 ? DeclarationKind::SloppyLexicalFunction 3743 : DeclarationKind::LexicalFunction; 3744 } else { 3745 kind = pc_->atModuleLevel() ? DeclarationKind::ModuleBodyLevelFunction 3746 : DeclarationKind::BodyLevelFunction; 3747 } 3748 3749 if (!noteDeclaredName(name, kind, pos())) { 3750 return errorResult(); 3751 } 3752 3753 FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Statement; 3754 FunctionNodeType funNode = MOZ_TRY(handler_.newFunction(syntaxKind, pos())); 3755 3756 // Under sloppy mode, try Annex B.3.3 semantics. If making an additional 3757 // 'var' binding of the same name does not throw an early error, do so. 3758 // This 'var' binding would be assigned the function object when its 3759 // declaration is reached, not at the start of the block. 3760 // 3761 // This semantics is implemented upon Scope exit in 3762 // Scope::propagateAndMarkAnnexBFunctionBoxes. 3763 bool tryAnnexB = kind == DeclarationKind::SloppyLexicalFunction; 3764 3765 YieldHandling newYieldHandling = GetYieldHandling(generatorKind); 3766 return functionDefinition(funNode, toStringStart, InAllowed, newYieldHandling, 3767 name, syntaxKind, generatorKind, asyncKind, 3768 tryAnnexB); 3769 } 3770 3771 template <class ParseHandler, typename Unit> 3772 typename ParseHandler::FunctionNodeResult 3773 GeneralParser<ParseHandler, Unit>::functionExpr(uint32_t toStringStart, 3774 InvokedPrediction invoked, 3775 FunctionAsyncKind asyncKind) { 3776 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); 3777 3778 AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword( 3779 this, GetAwaitHandling(asyncKind)); 3780 GeneratorKind generatorKind = GeneratorKind::NotGenerator; 3781 TokenKind tt; 3782 if (!tokenStream.getToken(&tt)) { 3783 return errorResult(); 3784 } 3785 3786 if (tt == TokenKind::Mul) { 3787 generatorKind = GeneratorKind::Generator; 3788 if (!tokenStream.getToken(&tt)) { 3789 return errorResult(); 3790 } 3791 } 3792 3793 YieldHandling yieldHandling = GetYieldHandling(generatorKind); 3794 3795 TaggedParserAtomIndex name; 3796 if (TokenKindIsPossibleIdentifier(tt)) { 3797 name = bindingIdentifier(yieldHandling); 3798 if (!name) { 3799 return errorResult(); 3800 } 3801 } else { 3802 anyChars.ungetToken(); 3803 } 3804 3805 FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Expression; 3806 FunctionNodeType funNode = MOZ_TRY(handler_.newFunction(syntaxKind, pos())); 3807 3808 if (invoked) { 3809 funNode = handler_.setLikelyIIFE(funNode); 3810 } 3811 3812 return functionDefinition(funNode, toStringStart, InAllowed, yieldHandling, 3813 name, syntaxKind, generatorKind, asyncKind); 3814 } 3815 3816 /* 3817 * Return true if this node, known to be an unparenthesized string literal 3818 * that never contain escape sequences, could be the string of a directive in a 3819 * Directive Prologue. Directive strings never contain escape sequences or line 3820 * continuations. 3821 */ 3822 static inline bool IsUseStrictDirective(const TokenPos& pos, 3823 TaggedParserAtomIndex atom) { 3824 // the length of "use strict", including quotation. 3825 static constexpr size_t useStrictLength = 12; 3826 return atom == TaggedParserAtomIndex::WellKnown::use_strict_() && 3827 pos.begin + useStrictLength == pos.end; 3828 } 3829 static inline bool IsUseAsmDirective(const TokenPos& pos, 3830 TaggedParserAtomIndex atom) { 3831 // the length of "use asm", including quotation. 3832 static constexpr size_t useAsmLength = 9; 3833 return atom == TaggedParserAtomIndex::WellKnown::use_asm_() && 3834 pos.begin + useAsmLength == pos.end; 3835 } 3836 3837 template <typename Unit> 3838 bool Parser<SyntaxParseHandler, Unit>::asmJS(TokenPos directivePos, 3839 ListNodeType list) { 3840 // While asm.js could technically be validated and compiled during syntax 3841 // parsing, we have no guarantee that some later JS wouldn't abort the 3842 // syntax parse and cause us to re-parse (and re-compile) the asm.js module. 3843 // For simplicity, unconditionally abort the syntax parse when "use asm" is 3844 // encountered so that asm.js is always validated/compiled exactly once 3845 // during a full parse. 3846 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 3847 return false; 3848 } 3849 3850 template <typename Unit> 3851 bool Parser<FullParseHandler, Unit>::asmJS(TokenPos directivePos, 3852 ListNodeType list) { 3853 // Disable syntax parsing in anything nested inside the asm.js module. 3854 disableSyntaxParser(); 3855 3856 // We should be encountering the "use asm" directive for the first time; if 3857 // the directive is already, we must have failed asm.js validation and we're 3858 // reparsing. In that case, don't try to validate again. A non-null 3859 // newDirectives means we're not in a normal function. 3860 if (!pc_->newDirectives || pc_->newDirectives->asmJS()) { 3861 return true; 3862 } 3863 3864 // If there is no ScriptSource, then we are doing a non-compiling parse and 3865 // so we shouldn't (and can't, without a ScriptSource) compile. 3866 if (ss == nullptr) { 3867 return true; 3868 } 3869 3870 // Mark this function as being in a "use asm" directive. 3871 if (!pc_->functionBox()->setUseAsm()) { 3872 return false; 3873 } 3874 3875 // Attempt to validate and compile this asm.js module. On success, the 3876 // tokenStream has been advanced to the closing }. On failure, the 3877 // tokenStream is in an indeterminate state and we must reparse the 3878 // function from the beginning. Reparsing is triggered by marking that a 3879 // new directive has been encountered and returning 'false'. 3880 bool validated; 3881 if (!CompileAsmJS(this->fc_, this->parserAtoms(), *this, list, &validated)) { 3882 return false; 3883 } 3884 3885 // Warn about asm.js deprecation even if we failed validation. Do this after 3886 // compilation so that this warning is the last one we emit. This makes 3887 // testing in asm.js/disabled-warning.js easier. 3888 if (!js::SupportDifferentialTesting() && 3889 JS::Prefs::warn_asmjs_deprecation()) { 3890 if (!warningAt(directivePos.begin, JSMSG_USE_ASM_DEPRECATED)) { 3891 return false; 3892 } 3893 } 3894 3895 // If we failed validation, trigger a reparse. See above. 3896 if (!validated) { 3897 pc_->newDirectives->setAsmJS(); 3898 return false; 3899 } 3900 3901 return true; 3902 } 3903 3904 template <class ParseHandler, typename Unit> 3905 inline bool GeneralParser<ParseHandler, Unit>::asmJS(TokenPos directivePos, 3906 ListNodeType list) { 3907 return asFinalParser()->asmJS(directivePos, list); 3908 } 3909 3910 /* 3911 * Recognize Directive Prologue members and directives. Assuming |pn| is a 3912 * candidate for membership in a directive prologue, recognize directives and 3913 * set |pc_|'s flags accordingly. If |pn| is indeed part of a prologue, set its 3914 * |prologue| flag. 3915 * 3916 * Note that the following is a strict mode function: 3917 * 3918 * function foo() { 3919 * "blah" // inserted semi colon 3920 * "blurgh" 3921 * "use\x20loose" 3922 * "use strict" 3923 * } 3924 * 3925 * That is, even though "use\x20loose" can never be a directive, now or in the 3926 * future (because of the hex escape), the Directive Prologue extends through it 3927 * to the "use strict" statement, which is indeed a directive. 3928 */ 3929 template <class ParseHandler, typename Unit> 3930 bool GeneralParser<ParseHandler, Unit>::maybeParseDirective( 3931 ListNodeType list, Node possibleDirective, bool* cont) { 3932 TokenPos directivePos; 3933 TaggedParserAtomIndex directive = 3934 handler_.isStringExprStatement(possibleDirective, &directivePos); 3935 3936 *cont = !!directive; 3937 if (!*cont) { 3938 return true; 3939 } 3940 3941 if (IsUseStrictDirective(directivePos, directive)) { 3942 // Functions with non-simple parameter lists (destructuring, 3943 // default or rest parameters) must not contain a "use strict" 3944 // directive. 3945 if (pc_->isFunctionBox()) { 3946 FunctionBox* funbox = pc_->functionBox(); 3947 if (!funbox->hasSimpleParameterList()) { 3948 const char* parameterKind = funbox->hasDestructuringArgs 3949 ? "destructuring" 3950 : funbox->hasParameterExprs ? "default" 3951 : "rest"; 3952 errorAt(directivePos.begin, JSMSG_STRICT_NON_SIMPLE_PARAMS, 3953 parameterKind); 3954 return false; 3955 } 3956 } 3957 3958 // We're going to be in strict mode. Note that this scope explicitly 3959 // had "use strict"; 3960 pc_->sc()->setExplicitUseStrict(); 3961 if (!pc_->sc()->strict()) { 3962 // Some strict mode violations can appear before a Use Strict Directive 3963 // is applied. (See the |DeprecatedContent| enum initializers.) These 3964 // violations can manifest in two ways. 3965 // 3966 // First, the violation can appear *before* the Use Strict Directive. 3967 // Numeric literals (and therefore octal literals) can only precede a 3968 // Use Strict Directive if this function's parameter list is not simple, 3969 // but we reported an error for non-simple parameter lists above, so 3970 // octal literals present no issue. But octal escapes and \8 and \9 can 3971 // appear in the directive prologue before a Use Strict Directive: 3972 // 3973 // function f() 3974 // { 3975 // "hell\157 world"; // octal escape 3976 // "\8"; "\9"; // NonOctalDecimalEscape 3977 // "use strict"; // retroactively makes all the above errors 3978 // } 3979 // 3980 // Second, the violation can appear *after* the Use Strict Directive but 3981 // *before* the directive is recognized as terminated. This only 3982 // happens when a directive is terminated by ASI, and the next token 3983 // contains a violation: 3984 // 3985 // function a() 3986 // { 3987 // "use strict" // ASI 3988 // 0755; 3989 // } 3990 // function b() 3991 // { 3992 // "use strict" // ASI 3993 // "hell\157 world"; 3994 // } 3995 // function c() 3996 // { 3997 // "use strict" // ASI 3998 // "\8"; 3999 // } 4000 // 4001 // We note such violations when tokenizing. Then, if a violation has 4002 // been observed at the time a "use strict" is applied, we report the 4003 // error. 4004 switch (anyChars.sawDeprecatedContent()) { 4005 case DeprecatedContent::None: 4006 break; 4007 case DeprecatedContent::OctalLiteral: 4008 error(JSMSG_DEPRECATED_OCTAL_LITERAL); 4009 return false; 4010 case DeprecatedContent::OctalEscape: 4011 error(JSMSG_DEPRECATED_OCTAL_ESCAPE); 4012 return false; 4013 case DeprecatedContent::EightOrNineEscape: 4014 error(JSMSG_DEPRECATED_EIGHT_OR_NINE_ESCAPE); 4015 return false; 4016 } 4017 4018 pc_->sc()->setStrictScript(); 4019 } 4020 } else if (IsUseAsmDirective(directivePos, directive)) { 4021 if (pc_->isFunctionBox()) { 4022 return asmJS(directivePos, list); 4023 } 4024 return warningAt(directivePos.begin, JSMSG_USE_ASM_DIRECTIVE_FAIL); 4025 } 4026 return true; 4027 } 4028 4029 template <class ParseHandler, typename Unit> 4030 typename ParseHandler::ListNodeResult 4031 GeneralParser<ParseHandler, Unit>::statementList(YieldHandling yieldHandling) { 4032 AutoCheckRecursionLimit recursion(this->fc_); 4033 if (!recursion.check(this->fc_)) { 4034 return errorResult(); 4035 } 4036 4037 ListNodeType stmtList = MOZ_TRY(handler_.newStatementList(pos())); 4038 4039 bool canHaveDirectives = pc_->atBodyLevel(); 4040 if (canHaveDirectives) { 4041 // Clear flags for deprecated content that might have been seen in an 4042 // enclosing context. 4043 anyChars.clearSawDeprecatedContent(); 4044 } 4045 4046 bool canHaveHashbangComment = pc_->atTopLevel(); 4047 if (canHaveHashbangComment) { 4048 tokenStream.consumeOptionalHashbangComment(); 4049 } 4050 4051 bool afterReturn = false; 4052 bool warnedAboutStatementsAfterReturn = false; 4053 uint32_t statementBegin = 0; 4054 for (;;) { 4055 TokenKind tt = TokenKind::Eof; 4056 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 4057 if (anyChars.isEOF()) { 4058 isUnexpectedEOF_ = true; 4059 } 4060 return errorResult(); 4061 } 4062 if (tt == TokenKind::Eof || tt == TokenKind::RightCurly) { 4063 TokenPos pos; 4064 if (!tokenStream.peekTokenPos(&pos, TokenStream::SlashIsRegExp)) { 4065 return errorResult(); 4066 } 4067 handler_.setListEndPosition(stmtList, pos); 4068 break; 4069 } 4070 if (afterReturn) { 4071 if (!tokenStream.peekOffset(&statementBegin, 4072 TokenStream::SlashIsRegExp)) { 4073 return errorResult(); 4074 } 4075 } 4076 auto nextResult = statementListItem(yieldHandling, canHaveDirectives); 4077 if (nextResult.isErr()) { 4078 if (anyChars.isEOF()) { 4079 isUnexpectedEOF_ = true; 4080 } 4081 return errorResult(); 4082 } 4083 Node next = nextResult.unwrap(); 4084 if (!warnedAboutStatementsAfterReturn) { 4085 if (afterReturn) { 4086 if (!handler_.isStatementPermittedAfterReturnStatement(next)) { 4087 if (!warningAt(statementBegin, JSMSG_STMT_AFTER_RETURN)) { 4088 return errorResult(); 4089 } 4090 4091 warnedAboutStatementsAfterReturn = true; 4092 } 4093 } else if (handler_.isReturnStatement(next)) { 4094 afterReturn = true; 4095 } 4096 } 4097 4098 if (canHaveDirectives) { 4099 if (!maybeParseDirective(stmtList, next, &canHaveDirectives)) { 4100 return errorResult(); 4101 } 4102 } 4103 4104 handler_.addStatementToList(stmtList, next); 4105 } 4106 4107 return stmtList; 4108 } 4109 4110 template <class ParseHandler, typename Unit> 4111 typename ParseHandler::NodeResult GeneralParser<ParseHandler, Unit>::condition( 4112 InHandling inHandling, YieldHandling yieldHandling) { 4113 if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_COND)) { 4114 return errorResult(); 4115 } 4116 4117 Node pn = 4118 MOZ_TRY(exprInParens(inHandling, yieldHandling, TripledotProhibited)); 4119 4120 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_COND)) { 4121 return errorResult(); 4122 } 4123 4124 return pn; 4125 } 4126 4127 template <class ParseHandler, typename Unit> 4128 bool GeneralParser<ParseHandler, Unit>::matchLabel( 4129 YieldHandling yieldHandling, TaggedParserAtomIndex* labelOut) { 4130 MOZ_ASSERT(labelOut != nullptr); 4131 TokenKind tt = TokenKind::Eof; 4132 if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) { 4133 return false; 4134 } 4135 4136 if (TokenKindIsPossibleIdentifier(tt)) { 4137 tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); 4138 4139 *labelOut = labelIdentifier(yieldHandling); 4140 if (!*labelOut) { 4141 return false; 4142 } 4143 } else { 4144 *labelOut = TaggedParserAtomIndex::null(); 4145 } 4146 return true; 4147 } 4148 4149 template <class ParseHandler, typename Unit> 4150 GeneralParser<ParseHandler, Unit>::PossibleError::PossibleError( 4151 GeneralParser<ParseHandler, Unit>& parser) 4152 : parser_(parser) {} 4153 4154 template <class ParseHandler, typename Unit> 4155 typename GeneralParser<ParseHandler, Unit>::PossibleError::Error& 4156 GeneralParser<ParseHandler, Unit>::PossibleError::error(ErrorKind kind) { 4157 if (kind == ErrorKind::Expression) { 4158 return exprError_; 4159 } 4160 if (kind == ErrorKind::Destructuring) { 4161 return destructuringError_; 4162 } 4163 MOZ_ASSERT(kind == ErrorKind::DestructuringWarning); 4164 return destructuringWarning_; 4165 } 4166 4167 template <class ParseHandler, typename Unit> 4168 void GeneralParser<ParseHandler, Unit>::PossibleError::setResolved( 4169 ErrorKind kind) { 4170 error(kind).state_ = ErrorState::None; 4171 } 4172 4173 template <class ParseHandler, typename Unit> 4174 bool GeneralParser<ParseHandler, Unit>::PossibleError::hasError( 4175 ErrorKind kind) { 4176 return error(kind).state_ == ErrorState::Pending; 4177 } 4178 4179 template <class ParseHandler, typename Unit> 4180 bool GeneralParser<ParseHandler, 4181 Unit>::PossibleError::hasPendingDestructuringError() { 4182 return hasError(ErrorKind::Destructuring); 4183 } 4184 4185 template <class ParseHandler, typename Unit> 4186 void GeneralParser<ParseHandler, Unit>::PossibleError::setPending( 4187 ErrorKind kind, const TokenPos& pos, unsigned errorNumber) { 4188 // Don't overwrite a previously recorded error. 4189 if (hasError(kind)) { 4190 return; 4191 } 4192 4193 // If we report an error later, we'll do it from the position where we set 4194 // the state to pending. 4195 Error& err = error(kind); 4196 err.offset_ = pos.begin; 4197 err.errorNumber_ = errorNumber; 4198 err.state_ = ErrorState::Pending; 4199 } 4200 4201 template <class ParseHandler, typename Unit> 4202 void GeneralParser<ParseHandler, Unit>::PossibleError:: 4203 setPendingDestructuringErrorAt(const TokenPos& pos, unsigned errorNumber) { 4204 setPending(ErrorKind::Destructuring, pos, errorNumber); 4205 } 4206 4207 template <class ParseHandler, typename Unit> 4208 void GeneralParser<ParseHandler, Unit>::PossibleError:: 4209 setPendingDestructuringWarningAt(const TokenPos& pos, 4210 unsigned errorNumber) { 4211 setPending(ErrorKind::DestructuringWarning, pos, errorNumber); 4212 } 4213 4214 template <class ParseHandler, typename Unit> 4215 void GeneralParser<ParseHandler, Unit>::PossibleError:: 4216 setPendingExpressionErrorAt(const TokenPos& pos, unsigned errorNumber) { 4217 setPending(ErrorKind::Expression, pos, errorNumber); 4218 } 4219 4220 template <class ParseHandler, typename Unit> 4221 bool GeneralParser<ParseHandler, Unit>::PossibleError::checkForError( 4222 ErrorKind kind) { 4223 if (!hasError(kind)) { 4224 return true; 4225 } 4226 4227 Error& err = error(kind); 4228 parser_.errorAt(err.offset_, err.errorNumber_); 4229 return false; 4230 } 4231 4232 template <class ParseHandler, typename Unit> 4233 bool GeneralParser<ParseHandler, 4234 Unit>::PossibleError::checkForDestructuringErrorOrWarning() { 4235 // Clear pending expression error, because we're definitely not in an 4236 // expression context. 4237 setResolved(ErrorKind::Expression); 4238 4239 // Report any pending destructuring error. 4240 return checkForError(ErrorKind::Destructuring); 4241 } 4242 4243 template <class ParseHandler, typename Unit> 4244 bool GeneralParser<ParseHandler, 4245 Unit>::PossibleError::checkForExpressionError() { 4246 // Clear pending destructuring error, because we're definitely not 4247 // in a destructuring context. 4248 setResolved(ErrorKind::Destructuring); 4249 setResolved(ErrorKind::DestructuringWarning); 4250 4251 // Report any pending expression error. 4252 return checkForError(ErrorKind::Expression); 4253 } 4254 4255 template <class ParseHandler, typename Unit> 4256 void GeneralParser<ParseHandler, Unit>::PossibleError::transferErrorTo( 4257 ErrorKind kind, PossibleError* other) { 4258 if (hasError(kind) && !other->hasError(kind)) { 4259 Error& err = error(kind); 4260 Error& otherErr = other->error(kind); 4261 otherErr.offset_ = err.offset_; 4262 otherErr.errorNumber_ = err.errorNumber_; 4263 otherErr.state_ = err.state_; 4264 } 4265 } 4266 4267 template <class ParseHandler, typename Unit> 4268 void GeneralParser<ParseHandler, Unit>::PossibleError::transferErrorsTo( 4269 PossibleError* other) { 4270 MOZ_ASSERT(other); 4271 MOZ_ASSERT(this != other); 4272 MOZ_ASSERT(&parser_ == &other->parser_, 4273 "Can't transfer fields to an instance which belongs to a " 4274 "different parser"); 4275 4276 transferErrorTo(ErrorKind::Destructuring, other); 4277 transferErrorTo(ErrorKind::Expression, other); 4278 } 4279 4280 template <class ParseHandler, typename Unit> 4281 typename ParseHandler::BinaryNodeResult 4282 GeneralParser<ParseHandler, Unit>::bindingInitializer( 4283 Node lhs, DeclarationKind kind, YieldHandling yieldHandling) { 4284 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assign)); 4285 4286 if (kind == DeclarationKind::FormalParameter) { 4287 pc_->functionBox()->hasParameterExprs = true; 4288 } 4289 4290 Node rhs = MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited)); 4291 4292 BinaryNodeType assign = 4293 MOZ_TRY(handler_.newAssignment(ParseNodeKind::AssignExpr, lhs, rhs)); 4294 4295 return assign; 4296 } 4297 4298 template <class ParseHandler, typename Unit> 4299 typename ParseHandler::NameNodeResult 4300 GeneralParser<ParseHandler, Unit>::bindingIdentifier( 4301 DeclarationKind kind, YieldHandling yieldHandling) { 4302 TaggedParserAtomIndex name = bindingIdentifier(yieldHandling); 4303 if (!name) { 4304 return errorResult(); 4305 } 4306 4307 NameNodeType binding = MOZ_TRY(newName(name)); 4308 if (!noteDeclaredName(name, kind, pos())) { 4309 return errorResult(); 4310 } 4311 4312 return binding; 4313 } 4314 4315 template <class ParseHandler, typename Unit> 4316 typename ParseHandler::NodeResult 4317 GeneralParser<ParseHandler, Unit>::bindingIdentifierOrPattern( 4318 DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) { 4319 if (tt == TokenKind::LeftBracket) { 4320 return arrayBindingPattern(kind, yieldHandling); 4321 } 4322 4323 if (tt == TokenKind::LeftCurly) { 4324 return objectBindingPattern(kind, yieldHandling); 4325 } 4326 4327 if (!TokenKindIsPossibleIdentifierName(tt)) { 4328 error(JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); 4329 return errorResult(); 4330 } 4331 4332 return bindingIdentifier(kind, yieldHandling); 4333 } 4334 4335 template <class ParseHandler, typename Unit> 4336 typename ParseHandler::ListNodeResult 4337 GeneralParser<ParseHandler, Unit>::objectBindingPattern( 4338 DeclarationKind kind, YieldHandling yieldHandling) { 4339 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); 4340 4341 AutoCheckRecursionLimit recursion(this->fc_); 4342 if (!recursion.check(this->fc_)) { 4343 return errorResult(); 4344 } 4345 4346 uint32_t begin = pos().begin; 4347 ListNodeType literal = MOZ_TRY(handler_.newObjectLiteral(begin)); 4348 4349 Maybe<DeclarationKind> declKind = Some(kind); 4350 TaggedParserAtomIndex propAtom; 4351 for (;;) { 4352 TokenKind tt; 4353 if (!tokenStream.peekToken(&tt)) { 4354 return errorResult(); 4355 } 4356 if (tt == TokenKind::RightCurly) { 4357 break; 4358 } 4359 4360 if (tt == TokenKind::TripleDot) { 4361 tokenStream.consumeKnownToken(TokenKind::TripleDot); 4362 uint32_t begin = pos().begin; 4363 4364 TokenKind tt; 4365 if (!tokenStream.getToken(&tt)) { 4366 return errorResult(); 4367 } 4368 4369 if (!TokenKindIsPossibleIdentifierName(tt)) { 4370 error(JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); 4371 return errorResult(); 4372 } 4373 4374 NameNodeType inner = MOZ_TRY(bindingIdentifier(kind, yieldHandling)); 4375 4376 if (!handler_.addSpreadProperty(literal, begin, inner)) { 4377 return errorResult(); 4378 } 4379 } else { 4380 TokenPos namePos = anyChars.nextToken().pos; 4381 4382 PropertyType propType; 4383 Node propName = MOZ_TRY( 4384 propertyOrMethodName(yieldHandling, PropertyNameInPattern, declKind, 4385 literal, &propType, &propAtom)); 4386 4387 if (propType == PropertyType::Normal) { 4388 // Handle e.g., |var {p: x} = o| and |var {p: x=0} = o|. 4389 4390 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 4391 return errorResult(); 4392 } 4393 4394 Node binding = 4395 MOZ_TRY(bindingIdentifierOrPattern(kind, yieldHandling, tt)); 4396 4397 bool hasInitializer; 4398 if (!tokenStream.matchToken(&hasInitializer, TokenKind::Assign, 4399 TokenStream::SlashIsRegExp)) { 4400 return errorResult(); 4401 } 4402 4403 Node bindingExpr; 4404 if (hasInitializer) { 4405 bindingExpr = 4406 MOZ_TRY(bindingInitializer(binding, kind, yieldHandling)); 4407 } else { 4408 bindingExpr = binding; 4409 } 4410 4411 if (!handler_.addPropertyDefinition(literal, propName, bindingExpr)) { 4412 return errorResult(); 4413 } 4414 } else if (propType == PropertyType::Shorthand) { 4415 // Handle e.g., |var {x, y} = o| as destructuring shorthand 4416 // for |var {x: x, y: y} = o|. 4417 MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt)); 4418 4419 NameNodeType binding = MOZ_TRY(bindingIdentifier(kind, yieldHandling)); 4420 4421 if (!handler_.addShorthand(literal, handler_.asNameNode(propName), 4422 binding)) { 4423 return errorResult(); 4424 } 4425 } else if (propType == PropertyType::CoverInitializedName) { 4426 // Handle e.g., |var {x=1, y=2} = o| as destructuring 4427 // shorthand with default values. 4428 MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt)); 4429 4430 NameNodeType binding = MOZ_TRY(bindingIdentifier(kind, yieldHandling)); 4431 4432 tokenStream.consumeKnownToken(TokenKind::Assign); 4433 4434 BinaryNodeType bindingExpr = 4435 MOZ_TRY(bindingInitializer(binding, kind, yieldHandling)); 4436 4437 if (!handler_.addPropertyDefinition(literal, propName, bindingExpr)) { 4438 return errorResult(); 4439 } 4440 } else { 4441 errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); 4442 return errorResult(); 4443 } 4444 } 4445 4446 bool matched; 4447 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 4448 TokenStream::SlashIsInvalid)) { 4449 return errorResult(); 4450 } 4451 if (!matched) { 4452 break; 4453 } 4454 if (tt == TokenKind::TripleDot) { 4455 error(JSMSG_REST_WITH_COMMA); 4456 return errorResult(); 4457 } 4458 } 4459 4460 if (!mustMatchToken(TokenKind::RightCurly, [this, begin](TokenKind actual) { 4461 this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED, 4462 begin); 4463 })) { 4464 return errorResult(); 4465 } 4466 4467 handler_.setEndPosition(literal, pos().end); 4468 return literal; 4469 } 4470 4471 template <class ParseHandler, typename Unit> 4472 typename ParseHandler::ListNodeResult 4473 GeneralParser<ParseHandler, Unit>::arrayBindingPattern( 4474 DeclarationKind kind, YieldHandling yieldHandling) { 4475 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket)); 4476 4477 AutoCheckRecursionLimit recursion(this->fc_); 4478 if (!recursion.check(this->fc_)) { 4479 return errorResult(); 4480 } 4481 4482 uint32_t begin = pos().begin; 4483 ListNodeType literal = MOZ_TRY(handler_.newArrayLiteral(begin)); 4484 4485 uint32_t index = 0; 4486 for (;; index++) { 4487 if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) { 4488 error(JSMSG_ARRAY_INIT_TOO_BIG); 4489 return errorResult(); 4490 } 4491 4492 TokenKind tt; 4493 if (!tokenStream.getToken(&tt)) { 4494 return errorResult(); 4495 } 4496 4497 if (tt == TokenKind::RightBracket) { 4498 anyChars.ungetToken(); 4499 break; 4500 } 4501 4502 if (tt == TokenKind::Comma) { 4503 if (!handler_.addElision(literal, pos())) { 4504 return errorResult(); 4505 } 4506 } else if (tt == TokenKind::TripleDot) { 4507 uint32_t begin = pos().begin; 4508 4509 TokenKind tt; 4510 if (!tokenStream.getToken(&tt)) { 4511 return errorResult(); 4512 } 4513 4514 Node inner = MOZ_TRY(bindingIdentifierOrPattern(kind, yieldHandling, tt)); 4515 4516 if (!handler_.addSpreadElement(literal, begin, inner)) { 4517 return errorResult(); 4518 } 4519 } else { 4520 Node binding = 4521 MOZ_TRY(bindingIdentifierOrPattern(kind, yieldHandling, tt)); 4522 4523 bool hasInitializer; 4524 if (!tokenStream.matchToken(&hasInitializer, TokenKind::Assign, 4525 TokenStream::SlashIsRegExp)) { 4526 return errorResult(); 4527 } 4528 4529 Node element; 4530 if (hasInitializer) { 4531 element = MOZ_TRY(bindingInitializer(binding, kind, yieldHandling)); 4532 } else { 4533 element = binding; 4534 } 4535 4536 handler_.addArrayElement(literal, element); 4537 } 4538 4539 if (tt != TokenKind::Comma) { 4540 // If we didn't already match TokenKind::Comma in above case. 4541 bool matched; 4542 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 4543 TokenStream::SlashIsRegExp)) { 4544 return errorResult(); 4545 } 4546 if (!matched) { 4547 break; 4548 } 4549 4550 if (tt == TokenKind::TripleDot) { 4551 error(JSMSG_REST_WITH_COMMA); 4552 return errorResult(); 4553 } 4554 } 4555 } 4556 4557 if (!mustMatchToken(TokenKind::RightBracket, [this, begin](TokenKind actual) { 4558 this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST, 4559 JSMSG_BRACKET_OPENED, begin); 4560 })) { 4561 return errorResult(); 4562 } 4563 4564 handler_.setEndPosition(literal, pos().end); 4565 return literal; 4566 } 4567 4568 template <class ParseHandler, typename Unit> 4569 typename ParseHandler::NodeResult 4570 GeneralParser<ParseHandler, Unit>::destructuringDeclaration( 4571 DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) { 4572 MOZ_ASSERT(anyChars.isCurrentTokenType(tt)); 4573 MOZ_ASSERT(tt == TokenKind::LeftBracket || tt == TokenKind::LeftCurly); 4574 4575 if (tt == TokenKind::LeftBracket) { 4576 return arrayBindingPattern(kind, yieldHandling); 4577 } 4578 return objectBindingPattern(kind, yieldHandling); 4579 } 4580 4581 template <class ParseHandler, typename Unit> 4582 typename ParseHandler::NodeResult 4583 GeneralParser<ParseHandler, Unit>::destructuringDeclarationWithoutYieldOrAwait( 4584 DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) { 4585 uint32_t startYieldOffset = pc_->lastYieldOffset; 4586 uint32_t startAwaitOffset = pc_->lastAwaitOffset; 4587 4588 Node res = MOZ_TRY(destructuringDeclaration(kind, yieldHandling, tt)); 4589 4590 if (pc_->lastYieldOffset != startYieldOffset) { 4591 errorAt(pc_->lastYieldOffset, JSMSG_YIELD_IN_PARAMETER); 4592 return errorResult(); 4593 } 4594 if (pc_->lastAwaitOffset != startAwaitOffset) { 4595 errorAt(pc_->lastAwaitOffset, JSMSG_AWAIT_IN_PARAMETER); 4596 return errorResult(); 4597 } 4598 return res; 4599 } 4600 4601 template <class ParseHandler, typename Unit> 4602 typename ParseHandler::LexicalScopeNodeResult 4603 GeneralParser<ParseHandler, Unit>::blockStatement(YieldHandling yieldHandling, 4604 unsigned errorNumber) { 4605 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); 4606 uint32_t openedPos = pos().begin; 4607 4608 ParseContext::Statement stmt(pc_, StatementKind::Block); 4609 ParseContext::Scope scope(this); 4610 if (!scope.init(pc_)) { 4611 return errorResult(); 4612 } 4613 4614 ListNodeType list = MOZ_TRY(statementList(yieldHandling)); 4615 4616 if (!mustMatchToken(TokenKind::RightCurly, [this, errorNumber, 4617 openedPos](TokenKind actual) { 4618 this->reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED, openedPos); 4619 })) { 4620 return errorResult(); 4621 } 4622 4623 return finishLexicalScope(scope, list); 4624 } 4625 4626 template <class ParseHandler, typename Unit> 4627 typename ParseHandler::NodeResult 4628 GeneralParser<ParseHandler, Unit>::expressionAfterForInOrOf( 4629 ParseNodeKind forHeadKind, YieldHandling yieldHandling) { 4630 MOZ_ASSERT(forHeadKind == ParseNodeKind::ForIn || 4631 forHeadKind == ParseNodeKind::ForOf); 4632 if (forHeadKind == ParseNodeKind::ForOf) { 4633 return assignExpr(InAllowed, yieldHandling, TripledotProhibited); 4634 } 4635 4636 return expr(InAllowed, yieldHandling, TripledotProhibited); 4637 } 4638 4639 template <class ParseHandler, typename Unit> 4640 typename ParseHandler::NodeResult 4641 GeneralParser<ParseHandler, Unit>::declarationPattern( 4642 DeclarationKind declKind, TokenKind tt, bool initialDeclaration, 4643 YieldHandling yieldHandling, ParseNodeKind* forHeadKind, 4644 Node* forInOrOfExpression) { 4645 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket) || 4646 anyChars.isCurrentTokenType(TokenKind::LeftCurly)); 4647 4648 Node pattern = MOZ_TRY(destructuringDeclaration(declKind, yieldHandling, tt)); 4649 4650 if (initialDeclaration && forHeadKind) { 4651 bool isForIn, isForOf; 4652 if (!matchInOrOf(&isForIn, &isForOf)) { 4653 return errorResult(); 4654 } 4655 4656 if (isForIn) { 4657 *forHeadKind = ParseNodeKind::ForIn; 4658 } else if (isForOf) { 4659 *forHeadKind = ParseNodeKind::ForOf; 4660 } else { 4661 *forHeadKind = ParseNodeKind::ForHead; 4662 } 4663 4664 if (*forHeadKind != ParseNodeKind::ForHead) { 4665 *forInOrOfExpression = 4666 MOZ_TRY(expressionAfterForInOrOf(*forHeadKind, yieldHandling)); 4667 4668 return pattern; 4669 } 4670 } 4671 4672 if (!mustMatchToken(TokenKind::Assign, JSMSG_BAD_DESTRUCT_DECL)) { 4673 return errorResult(); 4674 } 4675 4676 Node init = MOZ_TRY(assignExpr(forHeadKind ? InProhibited : InAllowed, 4677 yieldHandling, TripledotProhibited)); 4678 4679 return handler_.newAssignment(ParseNodeKind::AssignExpr, pattern, init); 4680 } 4681 4682 template <class ParseHandler, typename Unit> 4683 typename ParseHandler::AssignmentNodeResult 4684 GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration( 4685 NameNodeType binding, DeclarationKind declKind, bool initialDeclaration, 4686 YieldHandling yieldHandling, ParseNodeKind* forHeadKind, 4687 Node* forInOrOfExpression) { 4688 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assign)); 4689 4690 uint32_t initializerOffset; 4691 if (!tokenStream.peekOffset(&initializerOffset, TokenStream::SlashIsRegExp)) { 4692 return errorResult(); 4693 } 4694 4695 Node initializer = MOZ_TRY(assignExpr(forHeadKind ? InProhibited : InAllowed, 4696 yieldHandling, TripledotProhibited)); 4697 4698 if (forHeadKind && initialDeclaration) { 4699 bool isForIn, isForOf; 4700 if (!matchInOrOf(&isForIn, &isForOf)) { 4701 return errorResult(); 4702 } 4703 4704 // An initialized declaration can't appear in a for-of: 4705 // 4706 // for (var/let/const x = ... of ...); // BAD 4707 if (isForOf) { 4708 errorAt(initializerOffset, JSMSG_OF_AFTER_FOR_LOOP_DECL); 4709 return errorResult(); 4710 } 4711 4712 if (isForIn) { 4713 // Lexical declarations in for-in loops can't be initialized: 4714 // 4715 // for (let/const x = ... in ...); // BAD 4716 if (DeclarationKindIsLexical(declKind)) { 4717 errorAt(initializerOffset, JSMSG_IN_AFTER_LEXICAL_FOR_DECL); 4718 return errorResult(); 4719 } 4720 4721 // This leaves only initialized for-in |var| declarations. ES6 4722 // forbids these; later ES un-forbids in non-strict mode code. 4723 *forHeadKind = ParseNodeKind::ForIn; 4724 if (!strictModeErrorAt(initializerOffset, 4725 JSMSG_INVALID_FOR_IN_DECL_WITH_INIT)) { 4726 return errorResult(); 4727 } 4728 4729 *forInOrOfExpression = MOZ_TRY( 4730 expressionAfterForInOrOf(ParseNodeKind::ForIn, yieldHandling)); 4731 } else { 4732 *forHeadKind = ParseNodeKind::ForHead; 4733 } 4734 } 4735 4736 return handler_.finishInitializerAssignment(binding, initializer); 4737 } 4738 4739 template <class ParseHandler, typename Unit> 4740 typename ParseHandler::NodeResult 4741 GeneralParser<ParseHandler, Unit>::declarationName(DeclarationKind declKind, 4742 TokenKind tt, 4743 bool initialDeclaration, 4744 YieldHandling yieldHandling, 4745 ParseNodeKind* forHeadKind, 4746 Node* forInOrOfExpression) { 4747 // Anything other than possible identifier is an error. 4748 if (!TokenKindIsPossibleIdentifier(tt)) { 4749 error(JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); 4750 return errorResult(); 4751 } 4752 4753 TaggedParserAtomIndex name = bindingIdentifier(yieldHandling); 4754 if (!name) { 4755 return errorResult(); 4756 } 4757 4758 NameNodeType binding = MOZ_TRY(newName(name)); 4759 4760 TokenPos namePos = pos(); 4761 4762 // The '=' context after a variable name in a declaration is an opportunity 4763 // for ASI, and thus for the next token to start an ExpressionStatement: 4764 // 4765 // var foo // VariableDeclaration 4766 // /bar/g; // ExpressionStatement 4767 // 4768 // Therefore get the token here with SlashIsRegExp. 4769 bool matched; 4770 if (!tokenStream.matchToken(&matched, TokenKind::Assign, 4771 TokenStream::SlashIsRegExp)) { 4772 return errorResult(); 4773 } 4774 4775 Node declaration; 4776 if (matched) { 4777 declaration = MOZ_TRY(initializerInNameDeclaration( 4778 binding, declKind, initialDeclaration, yieldHandling, forHeadKind, 4779 forInOrOfExpression)); 4780 } else { 4781 declaration = binding; 4782 4783 if (initialDeclaration && forHeadKind) { 4784 bool isForIn, isForOf; 4785 if (!matchInOrOf(&isForIn, &isForOf)) { 4786 return errorResult(); 4787 } 4788 4789 if (isForIn) { 4790 *forHeadKind = ParseNodeKind::ForIn; 4791 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 4792 if (declKind == DeclarationKind::Using || 4793 declKind == DeclarationKind::AwaitUsing) { 4794 errorAt(namePos.begin, JSMSG_NO_IN_WITH_USING); 4795 return errorResult(); 4796 } 4797 #endif 4798 } else if (isForOf) { 4799 *forHeadKind = ParseNodeKind::ForOf; 4800 } else { 4801 *forHeadKind = ParseNodeKind::ForHead; 4802 } 4803 } 4804 4805 if (forHeadKind && *forHeadKind != ParseNodeKind::ForHead) { 4806 *forInOrOfExpression = 4807 MOZ_TRY(expressionAfterForInOrOf(*forHeadKind, yieldHandling)); 4808 } else { 4809 // Normal const declarations, and const declarations in for(;;) 4810 // heads, must be initialized. 4811 if (declKind == DeclarationKind::Const) { 4812 errorAt(namePos.begin, JSMSG_BAD_CONST_DECL); 4813 return errorResult(); 4814 } 4815 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 4816 if (declKind == DeclarationKind::Using || 4817 declKind == DeclarationKind::AwaitUsing) { 4818 errorAt(namePos.begin, JSMSG_BAD_USING_DECL); 4819 return errorResult(); 4820 } 4821 #endif 4822 } 4823 } 4824 4825 // Note the declared name after knowing whether or not we are in a for-of 4826 // loop, due to special early error semantics in Annex B.3.5. 4827 if (!noteDeclaredName(name, declKind, namePos)) { 4828 return errorResult(); 4829 } 4830 4831 return declaration; 4832 } 4833 4834 template <class ParseHandler, typename Unit> 4835 typename ParseHandler::DeclarationListNodeResult 4836 GeneralParser<ParseHandler, Unit>::declarationList( 4837 YieldHandling yieldHandling, ParseNodeKind kind, 4838 ParseNodeKind* forHeadKind /* = nullptr */, 4839 Node* forInOrOfExpression /* = nullptr */) { 4840 MOZ_ASSERT(kind == ParseNodeKind::VarStmt || kind == ParseNodeKind::LetDecl || 4841 kind == ParseNodeKind::ConstDecl 4842 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 4843 || kind == ParseNodeKind::UsingDecl || 4844 kind == ParseNodeKind::AwaitUsingDecl 4845 #endif 4846 ); 4847 4848 DeclarationKind declKind; 4849 switch (kind) { 4850 case ParseNodeKind::VarStmt: 4851 declKind = DeclarationKind::Var; 4852 break; 4853 case ParseNodeKind::ConstDecl: 4854 declKind = DeclarationKind::Const; 4855 break; 4856 case ParseNodeKind::LetDecl: 4857 declKind = DeclarationKind::Let; 4858 break; 4859 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 4860 case ParseNodeKind::UsingDecl: 4861 declKind = DeclarationKind::Using; 4862 break; 4863 case ParseNodeKind::AwaitUsingDecl: 4864 declKind = DeclarationKind::AwaitUsing; 4865 break; 4866 #endif 4867 default: 4868 MOZ_CRASH("Unknown declaration kind"); 4869 } 4870 4871 DeclarationListNodeType decl = 4872 MOZ_TRY(handler_.newDeclarationList(kind, pos())); 4873 4874 bool moreDeclarations; 4875 bool initialDeclaration = true; 4876 do { 4877 MOZ_ASSERT_IF(!initialDeclaration && forHeadKind, 4878 *forHeadKind == ParseNodeKind::ForHead); 4879 4880 TokenKind tt; 4881 if (!tokenStream.getToken(&tt)) { 4882 return errorResult(); 4883 } 4884 4885 Node binding; 4886 if (tt == TokenKind::LeftBracket || tt == TokenKind::LeftCurly) { 4887 if (declKind == DeclarationKind::Using || 4888 declKind == DeclarationKind::AwaitUsing) { 4889 MOZ_ASSERT(!initialDeclaration); 4890 error(JSMSG_NO_DESTRUCT_IN_USING); 4891 return errorResult(); 4892 } 4893 binding = MOZ_TRY(declarationPattern(declKind, tt, initialDeclaration, 4894 yieldHandling, forHeadKind, 4895 forInOrOfExpression)); 4896 } else { 4897 binding = MOZ_TRY(declarationName(declKind, tt, initialDeclaration, 4898 yieldHandling, forHeadKind, 4899 forInOrOfExpression)); 4900 } 4901 4902 handler_.addList(decl, binding); 4903 4904 // If we have a for-in/of loop, the above call matches the entirety 4905 // of the loop head (up to the closing parenthesis). 4906 if (forHeadKind && *forHeadKind != ParseNodeKind::ForHead) { 4907 break; 4908 } 4909 4910 initialDeclaration = false; 4911 4912 if (!tokenStream.matchToken(&moreDeclarations, TokenKind::Comma, 4913 TokenStream::SlashIsRegExp)) { 4914 return errorResult(); 4915 } 4916 } while (moreDeclarations); 4917 4918 return decl; 4919 } 4920 4921 template <class ParseHandler, typename Unit> 4922 typename ParseHandler::DeclarationListNodeResult 4923 GeneralParser<ParseHandler, Unit>::lexicalDeclaration( 4924 YieldHandling yieldHandling, DeclarationKind kind) { 4925 MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let 4926 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 4927 || kind == DeclarationKind::Using || 4928 kind == DeclarationKind::AwaitUsing 4929 #endif 4930 ); 4931 4932 if (options().selfHostingMode) { 4933 error(JSMSG_SELFHOSTED_LEXICAL); 4934 return errorResult(); 4935 } 4936 4937 /* 4938 * Parse body-level lets without a new block object. ES6 specs 4939 * that an execution environment's initial lexical environment 4940 * is the VariableEnvironment, i.e., body-level lets are in 4941 * the same environment record as vars. 4942 * 4943 * However, they cannot be parsed exactly as vars, as ES6 4944 * requires that uninitialized lets throw ReferenceError on use. 4945 * 4946 * See 8.1.1.1.6 and the note in 13.2.1. 4947 */ 4948 ParseNodeKind pnk; 4949 switch (kind) { 4950 case DeclarationKind::Const: 4951 pnk = ParseNodeKind::ConstDecl; 4952 break; 4953 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 4954 case DeclarationKind::Using: 4955 pnk = ParseNodeKind::UsingDecl; 4956 break; 4957 case DeclarationKind::AwaitUsing: 4958 pnk = ParseNodeKind::AwaitUsingDecl; 4959 break; 4960 #endif 4961 case DeclarationKind::Let: 4962 pnk = ParseNodeKind::LetDecl; 4963 break; 4964 default: 4965 MOZ_CRASH("unexpected node kind"); 4966 } 4967 DeclarationListNodeType decl = MOZ_TRY(declarationList(yieldHandling, pnk)); 4968 if (!matchOrInsertSemicolon()) { 4969 return errorResult(); 4970 } 4971 4972 return decl; 4973 } 4974 4975 template <class ParseHandler, typename Unit> 4976 typename ParseHandler::NameNodeResult 4977 GeneralParser<ParseHandler, Unit>::moduleExportName() { 4978 MOZ_ASSERT(anyChars.currentToken().type == TokenKind::String); 4979 TaggedParserAtomIndex name = anyChars.currentToken().atom(); 4980 if (!this->parserAtoms().isModuleExportName(name)) { 4981 error(JSMSG_UNPAIRED_SURROGATE_EXPORT); 4982 return errorResult(); 4983 } 4984 return handler_.newStringLiteral(name, pos()); 4985 } 4986 4987 template <class ParseHandler, typename Unit> 4988 bool GeneralParser<ParseHandler, Unit>::withClause(ListNodeType attributesSet) { 4989 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::With)); 4990 4991 if (!abortIfSyntaxParser()) { 4992 return false; 4993 } 4994 4995 if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_AFTER_WITH)) { 4996 return false; 4997 } 4998 4999 // Handle the form |... with {}| 5000 TokenKind token; 5001 if (!tokenStream.getToken(&token)) { 5002 return false; 5003 } 5004 if (token == TokenKind::RightCurly) { 5005 return true; 5006 } 5007 5008 js::HashSet<TaggedParserAtomIndex, TaggedParserAtomIndexHasher, 5009 js::SystemAllocPolicy> 5010 usedAssertionKeys; 5011 5012 for (;;) { 5013 TaggedParserAtomIndex keyName; 5014 if (TokenKindIsPossibleIdentifierName(token)) { 5015 keyName = anyChars.currentName(); 5016 } else if (token == TokenKind::String) { 5017 keyName = anyChars.currentToken().atom(); 5018 } else { 5019 error(JSMSG_ATTRIBUTE_KEY_EXPECTED); 5020 return false; 5021 } 5022 5023 auto p = usedAssertionKeys.lookupForAdd(keyName); 5024 if (p) { 5025 UniqueChars str = this->parserAtoms().toPrintableString(keyName); 5026 if (!str) { 5027 ReportOutOfMemory(this->fc_); 5028 return false; 5029 } 5030 error(JSMSG_DUPLICATE_ATTRIBUTE_KEY, str.get()); 5031 return false; 5032 } 5033 if (!usedAssertionKeys.add(p, keyName)) { 5034 ReportOutOfMemory(this->fc_); 5035 return false; 5036 } 5037 5038 NameNodeType keyNode; 5039 MOZ_TRY_VAR_OR_RETURN(keyNode, newName(keyName), false); 5040 5041 if (!mustMatchToken(TokenKind::Colon, JSMSG_COLON_AFTER_ATTRIBUTE_KEY)) { 5042 return false; 5043 } 5044 if (!mustMatchToken(TokenKind::String, JSMSG_WITH_CLAUSE_STRING_LITERAL)) { 5045 return false; 5046 } 5047 5048 NameNodeType valueNode; 5049 MOZ_TRY_VAR_OR_RETURN(valueNode, stringLiteral(), false); 5050 5051 BinaryNodeType importAttributeNode; 5052 MOZ_TRY_VAR_OR_RETURN(importAttributeNode, 5053 handler_.newImportAttribute(keyNode, valueNode), 5054 false); 5055 5056 handler_.addList(attributesSet, importAttributeNode); 5057 5058 if (!tokenStream.getToken(&token)) { 5059 return false; 5060 } 5061 if (token == TokenKind::Comma) { 5062 if (!tokenStream.getToken(&token)) { 5063 return false; 5064 } 5065 } 5066 if (token == TokenKind::RightCurly) { 5067 break; 5068 } 5069 } 5070 5071 return true; 5072 } 5073 5074 template <class ParseHandler, typename Unit> 5075 bool GeneralParser<ParseHandler, Unit>::namedImports( 5076 ListNodeType importSpecSet) { 5077 if (!abortIfSyntaxParser()) { 5078 return false; 5079 } 5080 5081 while (true) { 5082 // Handle the forms |import {} from 'a'| and 5083 // |import { ..., } from 'a'| (where ... is non empty), by 5084 // escaping the loop early if the next token is }. 5085 TokenKind tt; 5086 if (!tokenStream.getToken(&tt)) { 5087 return false; 5088 } 5089 5090 if (tt == TokenKind::RightCurly) { 5091 break; 5092 } 5093 5094 TaggedParserAtomIndex importName; 5095 NameNodeType importNameNode = null(); 5096 if (TokenKindIsPossibleIdentifierName(tt)) { 5097 importName = anyChars.currentName(); 5098 MOZ_TRY_VAR_OR_RETURN(importNameNode, newName(importName), false); 5099 } else if (tt == TokenKind::String) { 5100 MOZ_TRY_VAR_OR_RETURN(importNameNode, moduleExportName(), false); 5101 } else { 5102 error(JSMSG_NO_IMPORT_NAME); 5103 return false; 5104 } 5105 5106 bool matched; 5107 if (!tokenStream.matchToken(&matched, TokenKind::As)) { 5108 return false; 5109 } 5110 5111 if (matched) { 5112 TokenKind afterAs; 5113 if (!tokenStream.getToken(&afterAs)) { 5114 return false; 5115 } 5116 5117 if (!TokenKindIsPossibleIdentifierName(afterAs)) { 5118 error(JSMSG_NO_BINDING_NAME); 5119 return false; 5120 } 5121 } else { 5122 // String export names can't refer to local bindings. 5123 if (tt == TokenKind::String) { 5124 error(JSMSG_AS_AFTER_STRING); 5125 return false; 5126 } 5127 5128 // Keywords cannot be bound to themselves, so an import name 5129 // that is a keyword is a syntax error if it is not followed 5130 // by the keyword 'as'. 5131 // See the ImportSpecifier production in ES6 section 15.2.2. 5132 MOZ_ASSERT(importName); 5133 if (IsKeyword(importName)) { 5134 error(JSMSG_AS_AFTER_RESERVED_WORD, ReservedWordToCharZ(importName)); 5135 return false; 5136 } 5137 } 5138 5139 TaggedParserAtomIndex bindingAtom = importedBinding(); 5140 if (!bindingAtom) { 5141 return false; 5142 } 5143 5144 NameNodeType bindingName; 5145 MOZ_TRY_VAR_OR_RETURN(bindingName, newName(bindingAtom), false); 5146 if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos())) { 5147 return false; 5148 } 5149 5150 BinaryNodeType importSpec; 5151 MOZ_TRY_VAR_OR_RETURN( 5152 importSpec, handler_.newImportSpec(importNameNode, bindingName), false); 5153 5154 handler_.addList(importSpecSet, importSpec); 5155 5156 TokenKind next; 5157 if (!tokenStream.getToken(&next)) { 5158 return false; 5159 } 5160 5161 if (next == TokenKind::RightCurly) { 5162 break; 5163 } 5164 5165 if (next != TokenKind::Comma) { 5166 error(JSMSG_RC_AFTER_IMPORT_SPEC_LIST); 5167 return false; 5168 } 5169 } 5170 5171 return true; 5172 } 5173 5174 template <class ParseHandler, typename Unit> 5175 bool GeneralParser<ParseHandler, Unit>::namespaceImport( 5176 ListNodeType importSpecSet) { 5177 if (!abortIfSyntaxParser()) { 5178 return false; 5179 } 5180 5181 if (!mustMatchToken(TokenKind::As, JSMSG_AS_AFTER_IMPORT_STAR)) { 5182 return false; 5183 } 5184 uint32_t begin = pos().begin; 5185 5186 if (!mustMatchToken(TokenKindIsPossibleIdentifierName, 5187 JSMSG_NO_BINDING_NAME)) { 5188 return false; 5189 } 5190 5191 // Namespace imports are not indirect bindings but lexical 5192 // definitions that hold a module namespace object. They are treated 5193 // as const variables which are initialized during the 5194 // ModuleInstantiate step. 5195 TaggedParserAtomIndex bindingName = importedBinding(); 5196 if (!bindingName) { 5197 return false; 5198 } 5199 NameNodeType bindingNameNode; 5200 MOZ_TRY_VAR_OR_RETURN(bindingNameNode, newName(bindingName), false); 5201 if (!noteDeclaredName(bindingName, DeclarationKind::Const, pos())) { 5202 return false; 5203 } 5204 5205 // The namespace import name is currently required to live on the 5206 // environment. 5207 pc_->varScope().lookupDeclaredName(bindingName)->value()->setClosedOver(); 5208 5209 UnaryNodeType importSpec; 5210 MOZ_TRY_VAR_OR_RETURN(importSpec, 5211 handler_.newImportNamespaceSpec(begin, bindingNameNode), 5212 false); 5213 5214 handler_.addList(importSpecSet, importSpec); 5215 5216 return true; 5217 } 5218 5219 template <class ParseHandler, typename Unit> 5220 typename ParseHandler::BinaryNodeResult 5221 GeneralParser<ParseHandler, Unit>::importDeclaration() { 5222 if (!abortIfSyntaxParser()) { 5223 return errorResult(); 5224 } 5225 5226 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import)); 5227 5228 if (!pc_->atModuleLevel()) { 5229 error(JSMSG_IMPORT_DECL_AT_TOP_LEVEL); 5230 return errorResult(); 5231 } 5232 5233 uint32_t begin = pos().begin; 5234 TokenKind tt; 5235 if (!tokenStream.getToken(&tt)) { 5236 return errorResult(); 5237 } 5238 5239 ListNodeType importSpecSet = 5240 MOZ_TRY(handler_.newList(ParseNodeKind::ImportSpecList, pos())); 5241 5242 if (tt == TokenKind::String) { 5243 // Handle the form |import 'a'| by leaving the list empty. This is 5244 // equivalent to |import {} from 'a'|. 5245 handler_.setEndPosition(importSpecSet, pos().begin); 5246 } else { 5247 if (tt == TokenKind::LeftCurly) { 5248 if (!namedImports(importSpecSet)) { 5249 return errorResult(); 5250 } 5251 } else if (tt == TokenKind::Mul) { 5252 if (!namespaceImport(importSpecSet)) { 5253 return errorResult(); 5254 } 5255 } else if (TokenKindIsPossibleIdentifierName(tt)) { 5256 // Handle the form |import a from 'b'|, by adding a single import 5257 // specifier to the list, with 'default' as the import name and 5258 // 'a' as the binding name. This is equivalent to 5259 // |import { default as a } from 'b'|. 5260 NameNodeType importName = 5261 MOZ_TRY(newName(TaggedParserAtomIndex::WellKnown::default_())); 5262 5263 TaggedParserAtomIndex bindingAtom = importedBinding(); 5264 if (!bindingAtom) { 5265 return errorResult(); 5266 } 5267 5268 NameNodeType bindingName = MOZ_TRY(newName(bindingAtom)); 5269 5270 if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos())) { 5271 return errorResult(); 5272 } 5273 5274 BinaryNodeType importSpec = 5275 MOZ_TRY(handler_.newImportSpec(importName, bindingName)); 5276 5277 handler_.addList(importSpecSet, importSpec); 5278 5279 if (!tokenStream.peekToken(&tt)) { 5280 return errorResult(); 5281 } 5282 5283 if (tt == TokenKind::Comma) { 5284 tokenStream.consumeKnownToken(tt); 5285 if (!tokenStream.getToken(&tt)) { 5286 return errorResult(); 5287 } 5288 5289 if (tt == TokenKind::LeftCurly) { 5290 if (!namedImports(importSpecSet)) { 5291 return errorResult(); 5292 } 5293 } else if (tt == TokenKind::Mul) { 5294 if (!namespaceImport(importSpecSet)) { 5295 return errorResult(); 5296 } 5297 } else { 5298 error(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT); 5299 return errorResult(); 5300 } 5301 } 5302 } else { 5303 error(JSMSG_DECLARATION_AFTER_IMPORT); 5304 return errorResult(); 5305 } 5306 5307 if (!mustMatchToken(TokenKind::From, JSMSG_FROM_AFTER_IMPORT_CLAUSE)) { 5308 return errorResult(); 5309 } 5310 5311 if (!mustMatchToken(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM)) { 5312 return errorResult(); 5313 } 5314 } 5315 5316 NameNodeType moduleSpec = MOZ_TRY(stringLiteral()); 5317 5318 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 5319 return errorResult(); 5320 } 5321 5322 ListNodeType importAttributeList = 5323 MOZ_TRY(handler_.newList(ParseNodeKind::ImportAttributeList, pos())); 5324 5325 if (tt == TokenKind::With) { 5326 tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); 5327 5328 if (!withClause(importAttributeList)) { 5329 return errorResult(); 5330 } 5331 } 5332 5333 if (!matchOrInsertSemicolon(TokenStream::SlashIsRegExp)) { 5334 return errorResult(); 5335 } 5336 5337 BinaryNodeType moduleRequest = MOZ_TRY(handler_.newModuleRequest( 5338 moduleSpec, importAttributeList, TokenPos(begin, pos().end))); 5339 5340 BinaryNodeType node = MOZ_TRY(handler_.newImportDeclaration( 5341 importSpecSet, moduleRequest, TokenPos(begin, pos().end))); 5342 if (!processImport(node)) { 5343 return errorResult(); 5344 } 5345 5346 return node; 5347 } 5348 5349 template <class ParseHandler, typename Unit> 5350 inline typename ParseHandler::NodeResult 5351 GeneralParser<ParseHandler, Unit>::importDeclarationOrImportExpr( 5352 YieldHandling yieldHandling) { 5353 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import)); 5354 5355 TokenKind tt; 5356 if (!tokenStream.peekToken(&tt)) { 5357 return errorResult(); 5358 } 5359 5360 if (tt == TokenKind::Dot || tt == TokenKind::LeftParen) { 5361 return expressionStatement(yieldHandling); 5362 } 5363 5364 return importDeclaration(); 5365 } 5366 5367 template <typename Unit> 5368 bool Parser<FullParseHandler, Unit>::checkExportedName( 5369 TaggedParserAtomIndex exportName) { 5370 switch (pc_->sc()->asModuleContext()->builder.noteExportedName(exportName)) { 5371 case ModuleBuilder::NoteExportedNameResult::Success: 5372 return true; 5373 case ModuleBuilder::NoteExportedNameResult::OutOfMemory: 5374 return false; 5375 case ModuleBuilder::NoteExportedNameResult::AlreadyDeclared: 5376 break; 5377 } 5378 5379 UniqueChars str = this->parserAtoms().toPrintableString(exportName); 5380 if (!str) { 5381 ReportOutOfMemory(this->fc_); 5382 return false; 5383 } 5384 5385 error(JSMSG_DUPLICATE_EXPORT_NAME, str.get()); 5386 return false; 5387 } 5388 5389 template <typename Unit> 5390 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedName( 5391 TaggedParserAtomIndex exportName) { 5392 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5393 return false; 5394 } 5395 5396 template <class ParseHandler, typename Unit> 5397 inline bool GeneralParser<ParseHandler, Unit>::checkExportedName( 5398 TaggedParserAtomIndex exportName) { 5399 return asFinalParser()->checkExportedName(exportName); 5400 } 5401 5402 template <typename Unit> 5403 bool Parser<FullParseHandler, Unit>::checkExportedNamesForArrayBinding( 5404 ListNode* array) { 5405 MOZ_ASSERT(array->isKind(ParseNodeKind::ArrayExpr)); 5406 5407 for (ParseNode* node : array->contents()) { 5408 if (node->isKind(ParseNodeKind::Elision)) { 5409 continue; 5410 } 5411 5412 ParseNode* binding; 5413 if (node->isKind(ParseNodeKind::Spread)) { 5414 binding = node->as<UnaryNode>().kid(); 5415 } else if (node->isKind(ParseNodeKind::AssignExpr)) { 5416 binding = node->as<AssignmentNode>().left(); 5417 } else { 5418 binding = node; 5419 } 5420 5421 if (!checkExportedNamesForDeclaration(binding)) { 5422 return false; 5423 } 5424 } 5425 5426 return true; 5427 } 5428 5429 template <typename Unit> 5430 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNamesForArrayBinding( 5431 ListNodeType array) { 5432 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5433 return false; 5434 } 5435 5436 template <class ParseHandler, typename Unit> 5437 inline bool 5438 GeneralParser<ParseHandler, Unit>::checkExportedNamesForArrayBinding( 5439 ListNodeType array) { 5440 return asFinalParser()->checkExportedNamesForArrayBinding(array); 5441 } 5442 5443 template <typename Unit> 5444 bool Parser<FullParseHandler, Unit>::checkExportedNamesForObjectBinding( 5445 ListNode* obj) { 5446 MOZ_ASSERT(obj->isKind(ParseNodeKind::ObjectExpr)); 5447 5448 for (ParseNode* node : obj->contents()) { 5449 MOZ_ASSERT(node->isKind(ParseNodeKind::MutateProto) || 5450 node->isKind(ParseNodeKind::PropertyDefinition) || 5451 node->isKind(ParseNodeKind::Shorthand) || 5452 node->isKind(ParseNodeKind::Spread)); 5453 5454 ParseNode* target; 5455 if (node->isKind(ParseNodeKind::Spread)) { 5456 target = node->as<UnaryNode>().kid(); 5457 } else { 5458 if (node->isKind(ParseNodeKind::MutateProto)) { 5459 target = node->as<UnaryNode>().kid(); 5460 } else { 5461 target = node->as<BinaryNode>().right(); 5462 } 5463 5464 if (target->isKind(ParseNodeKind::AssignExpr)) { 5465 target = target->as<AssignmentNode>().left(); 5466 } 5467 } 5468 5469 if (!checkExportedNamesForDeclaration(target)) { 5470 return false; 5471 } 5472 } 5473 5474 return true; 5475 } 5476 5477 template <typename Unit> 5478 inline bool Parser<SyntaxParseHandler, 5479 Unit>::checkExportedNamesForObjectBinding(ListNodeType obj) { 5480 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5481 return false; 5482 } 5483 5484 template <class ParseHandler, typename Unit> 5485 inline bool 5486 GeneralParser<ParseHandler, Unit>::checkExportedNamesForObjectBinding( 5487 ListNodeType obj) { 5488 return asFinalParser()->checkExportedNamesForObjectBinding(obj); 5489 } 5490 5491 template <typename Unit> 5492 bool Parser<FullParseHandler, Unit>::checkExportedNamesForDeclaration( 5493 ParseNode* node) { 5494 if (node->isKind(ParseNodeKind::Name)) { 5495 if (!checkExportedName(node->as<NameNode>().atom())) { 5496 return false; 5497 } 5498 } else if (node->isKind(ParseNodeKind::ArrayExpr)) { 5499 if (!checkExportedNamesForArrayBinding(&node->as<ListNode>())) { 5500 return false; 5501 } 5502 } else { 5503 MOZ_ASSERT(node->isKind(ParseNodeKind::ObjectExpr)); 5504 if (!checkExportedNamesForObjectBinding(&node->as<ListNode>())) { 5505 return false; 5506 } 5507 } 5508 5509 return true; 5510 } 5511 5512 template <typename Unit> 5513 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNamesForDeclaration( 5514 Node node) { 5515 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5516 return false; 5517 } 5518 5519 template <class ParseHandler, typename Unit> 5520 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNamesForDeclaration( 5521 Node node) { 5522 return asFinalParser()->checkExportedNamesForDeclaration(node); 5523 } 5524 5525 template <typename Unit> 5526 bool Parser<FullParseHandler, Unit>::checkExportedNamesForDeclarationList( 5527 DeclarationListNodeType node) { 5528 for (ParseNode* binding : node->contents()) { 5529 if (binding->isKind(ParseNodeKind::AssignExpr)) { 5530 binding = binding->as<AssignmentNode>().left(); 5531 } else { 5532 MOZ_ASSERT(binding->isKind(ParseNodeKind::Name)); 5533 } 5534 5535 if (!checkExportedNamesForDeclaration(binding)) { 5536 return false; 5537 } 5538 } 5539 5540 return true; 5541 } 5542 5543 template <typename Unit> 5544 inline bool 5545 Parser<SyntaxParseHandler, Unit>::checkExportedNamesForDeclarationList( 5546 DeclarationListNodeType node) { 5547 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5548 return false; 5549 } 5550 5551 template <class ParseHandler, typename Unit> 5552 inline bool 5553 GeneralParser<ParseHandler, Unit>::checkExportedNamesForDeclarationList( 5554 DeclarationListNodeType node) { 5555 return asFinalParser()->checkExportedNamesForDeclarationList(node); 5556 } 5557 5558 template <typename Unit> 5559 inline bool Parser<FullParseHandler, Unit>::checkExportedNameForClause( 5560 NameNode* nameNode) { 5561 return checkExportedName(nameNode->atom()); 5562 } 5563 5564 template <typename Unit> 5565 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNameForClause( 5566 NameNodeType nameNode) { 5567 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5568 return false; 5569 } 5570 5571 template <class ParseHandler, typename Unit> 5572 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNameForClause( 5573 NameNodeType nameNode) { 5574 return asFinalParser()->checkExportedNameForClause(nameNode); 5575 } 5576 5577 template <typename Unit> 5578 bool Parser<FullParseHandler, Unit>::checkExportedNameForFunction( 5579 FunctionNode* funNode) { 5580 return checkExportedName(funNode->funbox()->explicitName()); 5581 } 5582 5583 template <typename Unit> 5584 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNameForFunction( 5585 FunctionNodeType funNode) { 5586 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5587 return false; 5588 } 5589 5590 template <class ParseHandler, typename Unit> 5591 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNameForFunction( 5592 FunctionNodeType funNode) { 5593 return asFinalParser()->checkExportedNameForFunction(funNode); 5594 } 5595 5596 template <typename Unit> 5597 bool Parser<FullParseHandler, Unit>::checkExportedNameForClass( 5598 ClassNode* classNode) { 5599 MOZ_ASSERT(classNode->names()); 5600 return checkExportedName(classNode->names()->innerBinding()->atom()); 5601 } 5602 5603 template <typename Unit> 5604 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNameForClass( 5605 ClassNodeType classNode) { 5606 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5607 return false; 5608 } 5609 5610 template <class ParseHandler, typename Unit> 5611 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNameForClass( 5612 ClassNodeType classNode) { 5613 return asFinalParser()->checkExportedNameForClass(classNode); 5614 } 5615 5616 template <> 5617 inline bool PerHandlerParser<FullParseHandler>::processExport(ParseNode* node) { 5618 return pc_->sc()->asModuleContext()->builder.processExport(node); 5619 } 5620 5621 template <> 5622 inline bool PerHandlerParser<SyntaxParseHandler>::processExport(Node node) { 5623 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5624 return false; 5625 } 5626 5627 template <> 5628 inline bool PerHandlerParser<FullParseHandler>::processExportFrom( 5629 BinaryNodeType node) { 5630 return pc_->sc()->asModuleContext()->builder.processExportFrom(node); 5631 } 5632 5633 template <> 5634 inline bool PerHandlerParser<SyntaxParseHandler>::processExportFrom( 5635 BinaryNodeType node) { 5636 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5637 return false; 5638 } 5639 5640 template <> 5641 inline bool PerHandlerParser<FullParseHandler>::processImport( 5642 BinaryNodeType node) { 5643 return pc_->sc()->asModuleContext()->builder.processImport(node); 5644 } 5645 5646 template <> 5647 inline bool PerHandlerParser<SyntaxParseHandler>::processImport( 5648 BinaryNodeType node) { 5649 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5650 return false; 5651 } 5652 5653 template <class ParseHandler, typename Unit> 5654 typename ParseHandler::BinaryNodeResult 5655 GeneralParser<ParseHandler, Unit>::exportFrom(uint32_t begin, Node specList) { 5656 if (!abortIfSyntaxParser()) { 5657 return errorResult(); 5658 } 5659 5660 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::From)); 5661 5662 if (!mustMatchToken(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM)) { 5663 return errorResult(); 5664 } 5665 5666 NameNodeType moduleSpec = MOZ_TRY(stringLiteral()); 5667 5668 TokenKind tt; 5669 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 5670 return errorResult(); 5671 } 5672 5673 uint32_t moduleSpecPos = pos().begin; 5674 5675 ListNodeType importAttributeList = 5676 MOZ_TRY(handler_.newList(ParseNodeKind::ImportAttributeList, pos())); 5677 if (tt == TokenKind::With) { 5678 tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); 5679 5680 if (!withClause(importAttributeList)) { 5681 return errorResult(); 5682 } 5683 } 5684 5685 if (!matchOrInsertSemicolon(TokenStream::SlashIsRegExp)) { 5686 return errorResult(); 5687 } 5688 5689 BinaryNodeType moduleRequest = MOZ_TRY(handler_.newModuleRequest( 5690 moduleSpec, importAttributeList, TokenPos(moduleSpecPos, pos().end))); 5691 5692 BinaryNodeType node = MOZ_TRY( 5693 handler_.newExportFromDeclaration(begin, specList, moduleRequest)); 5694 5695 if (!processExportFrom(node)) { 5696 return errorResult(); 5697 } 5698 5699 return node; 5700 } 5701 5702 template <class ParseHandler, typename Unit> 5703 typename ParseHandler::BinaryNodeResult 5704 GeneralParser<ParseHandler, Unit>::exportBatch(uint32_t begin) { 5705 if (!abortIfSyntaxParser()) { 5706 return errorResult(); 5707 } 5708 5709 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Mul)); 5710 uint32_t beginExportSpec = pos().begin; 5711 5712 ListNodeType kid = 5713 MOZ_TRY(handler_.newList(ParseNodeKind::ExportSpecList, pos())); 5714 5715 bool foundAs; 5716 if (!tokenStream.matchToken(&foundAs, TokenKind::As)) { 5717 return errorResult(); 5718 } 5719 5720 if (foundAs) { 5721 TokenKind tt; 5722 if (!tokenStream.getToken(&tt)) { 5723 return errorResult(); 5724 } 5725 5726 NameNodeType exportName = null(); 5727 if (TokenKindIsPossibleIdentifierName(tt)) { 5728 exportName = MOZ_TRY(newName(anyChars.currentName())); 5729 } else if (tt == TokenKind::String) { 5730 exportName = MOZ_TRY(moduleExportName()); 5731 } else { 5732 error(JSMSG_NO_EXPORT_NAME); 5733 return errorResult(); 5734 } 5735 5736 if (!checkExportedNameForClause(exportName)) { 5737 return errorResult(); 5738 } 5739 5740 UnaryNodeType exportSpec = 5741 MOZ_TRY(handler_.newExportNamespaceSpec(beginExportSpec, exportName)); 5742 5743 handler_.addList(kid, exportSpec); 5744 } else { 5745 // Handle the form |export *| by adding a special export batch 5746 // specifier to the list. 5747 NullaryNodeType exportSpec = MOZ_TRY(handler_.newExportBatchSpec(pos())); 5748 5749 handler_.addList(kid, exportSpec); 5750 } 5751 5752 if (!mustMatchToken(TokenKind::From, JSMSG_FROM_AFTER_EXPORT_STAR)) { 5753 return errorResult(); 5754 } 5755 5756 return exportFrom(begin, kid); 5757 } 5758 5759 template <typename Unit> 5760 bool Parser<FullParseHandler, Unit>::checkLocalExportNames(ListNode* node) { 5761 // ES 2017 draft 15.2.3.1. 5762 for (ParseNode* next : node->contents()) { 5763 ParseNode* name = next->as<BinaryNode>().left(); 5764 5765 if (name->isKind(ParseNodeKind::StringExpr)) { 5766 errorAt(name->pn_pos.begin, JSMSG_BAD_LOCAL_STRING_EXPORT); 5767 return false; 5768 } 5769 5770 MOZ_ASSERT(name->isKind(ParseNodeKind::Name)); 5771 5772 TaggedParserAtomIndex ident = name->as<NameNode>().atom(); 5773 if (!checkLocalExportName(ident, name->pn_pos.begin)) { 5774 return false; 5775 } 5776 } 5777 5778 return true; 5779 } 5780 5781 template <typename Unit> 5782 bool Parser<SyntaxParseHandler, Unit>::checkLocalExportNames( 5783 ListNodeType node) { 5784 MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); 5785 return false; 5786 } 5787 5788 template <class ParseHandler, typename Unit> 5789 inline bool GeneralParser<ParseHandler, Unit>::checkLocalExportNames( 5790 ListNodeType node) { 5791 return asFinalParser()->checkLocalExportNames(node); 5792 } 5793 5794 template <class ParseHandler, typename Unit> 5795 typename ParseHandler::NodeResult 5796 GeneralParser<ParseHandler, Unit>::exportClause(uint32_t begin) { 5797 if (!abortIfSyntaxParser()) { 5798 return errorResult(); 5799 } 5800 5801 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); 5802 5803 ListNodeType kid = 5804 MOZ_TRY(handler_.newList(ParseNodeKind::ExportSpecList, pos())); 5805 5806 TokenKind tt; 5807 while (true) { 5808 // Handle the forms |export {}| and |export { ..., }| (where ... is non 5809 // empty), by escaping the loop early if the next token is }. 5810 if (!tokenStream.getToken(&tt)) { 5811 return errorResult(); 5812 } 5813 5814 if (tt == TokenKind::RightCurly) { 5815 break; 5816 } 5817 5818 NameNodeType bindingName = null(); 5819 if (TokenKindIsPossibleIdentifierName(tt)) { 5820 bindingName = MOZ_TRY(newName(anyChars.currentName())); 5821 } else if (tt == TokenKind::String) { 5822 bindingName = MOZ_TRY(moduleExportName()); 5823 } else { 5824 error(JSMSG_NO_BINDING_NAME); 5825 return errorResult(); 5826 } 5827 5828 bool foundAs; 5829 if (!tokenStream.matchToken(&foundAs, TokenKind::As)) { 5830 return errorResult(); 5831 } 5832 5833 NameNodeType exportName = null(); 5834 if (foundAs) { 5835 TokenKind tt; 5836 if (!tokenStream.getToken(&tt)) { 5837 return errorResult(); 5838 } 5839 5840 if (TokenKindIsPossibleIdentifierName(tt)) { 5841 exportName = MOZ_TRY(newName(anyChars.currentName())); 5842 } else if (tt == TokenKind::String) { 5843 exportName = MOZ_TRY(moduleExportName()); 5844 } else { 5845 error(JSMSG_NO_EXPORT_NAME); 5846 return errorResult(); 5847 } 5848 } else { 5849 if (tt != TokenKind::String) { 5850 exportName = MOZ_TRY(newName(anyChars.currentName())); 5851 } else { 5852 exportName = MOZ_TRY(moduleExportName()); 5853 } 5854 } 5855 5856 if (!checkExportedNameForClause(exportName)) { 5857 return errorResult(); 5858 } 5859 5860 BinaryNodeType exportSpec = 5861 MOZ_TRY(handler_.newExportSpec(bindingName, exportName)); 5862 5863 handler_.addList(kid, exportSpec); 5864 5865 TokenKind next; 5866 if (!tokenStream.getToken(&next)) { 5867 return errorResult(); 5868 } 5869 5870 if (next == TokenKind::RightCurly) { 5871 break; 5872 } 5873 5874 if (next != TokenKind::Comma) { 5875 error(JSMSG_RC_AFTER_EXPORT_SPEC_LIST); 5876 return errorResult(); 5877 } 5878 } 5879 5880 // Careful! If |from| follows, even on a new line, it must start a 5881 // FromClause: 5882 // 5883 // export { x } 5884 // from "foo"; // a single ExportDeclaration 5885 // 5886 // But if it doesn't, we might have an ASI opportunity in SlashIsRegExp 5887 // context: 5888 // 5889 // export { x } // ExportDeclaration, terminated by ASI 5890 // fro\u006D // ExpressionStatement, the name "from" 5891 // 5892 // In that case let matchOrInsertSemicolon sort out ASI or any necessary 5893 // error. 5894 bool matched; 5895 if (!tokenStream.matchToken(&matched, TokenKind::From, 5896 TokenStream::SlashIsRegExp)) { 5897 return errorResult(); 5898 } 5899 5900 if (matched) { 5901 return exportFrom(begin, kid); 5902 } 5903 5904 if (!matchOrInsertSemicolon()) { 5905 return errorResult(); 5906 } 5907 5908 if (!checkLocalExportNames(kid)) { 5909 return errorResult(); 5910 } 5911 5912 UnaryNodeType node = 5913 MOZ_TRY(handler_.newExportDeclaration(kid, TokenPos(begin, pos().end))); 5914 5915 if (!processExport(node)) { 5916 return errorResult(); 5917 } 5918 5919 return node; 5920 } 5921 5922 template <class ParseHandler, typename Unit> 5923 typename ParseHandler::UnaryNodeResult 5924 GeneralParser<ParseHandler, Unit>::exportVariableStatement(uint32_t begin) { 5925 if (!abortIfSyntaxParser()) { 5926 return errorResult(); 5927 } 5928 5929 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Var)); 5930 5931 DeclarationListNodeType kid = 5932 MOZ_TRY(declarationList(YieldIsName, ParseNodeKind::VarStmt)); 5933 if (!matchOrInsertSemicolon()) { 5934 return errorResult(); 5935 } 5936 if (!checkExportedNamesForDeclarationList(kid)) { 5937 return errorResult(); 5938 } 5939 5940 UnaryNodeType node = 5941 MOZ_TRY(handler_.newExportDeclaration(kid, TokenPos(begin, pos().end))); 5942 5943 if (!processExport(node)) { 5944 return errorResult(); 5945 } 5946 5947 return node; 5948 } 5949 5950 template <class ParseHandler, typename Unit> 5951 typename ParseHandler::UnaryNodeResult 5952 GeneralParser<ParseHandler, Unit>::exportFunctionDeclaration( 5953 uint32_t begin, uint32_t toStringStart, 5954 FunctionAsyncKind asyncKind /* = SyncFunction */) { 5955 if (!abortIfSyntaxParser()) { 5956 return errorResult(); 5957 } 5958 5959 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); 5960 5961 Node kid = MOZ_TRY( 5962 functionStmt(toStringStart, YieldIsName, NameRequired, asyncKind)); 5963 5964 if (!checkExportedNameForFunction(handler_.asFunctionNode(kid))) { 5965 return errorResult(); 5966 } 5967 5968 UnaryNodeType node = 5969 MOZ_TRY(handler_.newExportDeclaration(kid, TokenPos(begin, pos().end))); 5970 5971 if (!processExport(node)) { 5972 return errorResult(); 5973 } 5974 5975 return node; 5976 } 5977 5978 template <class ParseHandler, typename Unit> 5979 typename ParseHandler::UnaryNodeResult 5980 GeneralParser<ParseHandler, Unit>::exportClassDeclaration(uint32_t begin) { 5981 if (!abortIfSyntaxParser()) { 5982 return errorResult(); 5983 } 5984 5985 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class)); 5986 5987 ClassNodeType kid = 5988 MOZ_TRY(classDefinition(YieldIsName, ClassStatement, NameRequired)); 5989 5990 if (!checkExportedNameForClass(kid)) { 5991 return errorResult(); 5992 } 5993 5994 UnaryNodeType node = 5995 MOZ_TRY(handler_.newExportDeclaration(kid, TokenPos(begin, pos().end))); 5996 5997 if (!processExport(node)) { 5998 return errorResult(); 5999 } 6000 6001 return node; 6002 } 6003 6004 template <class ParseHandler, typename Unit> 6005 typename ParseHandler::UnaryNodeResult 6006 GeneralParser<ParseHandler, Unit>::exportLexicalDeclaration( 6007 uint32_t begin, DeclarationKind kind) { 6008 if (!abortIfSyntaxParser()) { 6009 return errorResult(); 6010 } 6011 6012 MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let); 6013 MOZ_ASSERT_IF(kind == DeclarationKind::Const, 6014 anyChars.isCurrentTokenType(TokenKind::Const)); 6015 MOZ_ASSERT_IF(kind == DeclarationKind::Let, 6016 anyChars.isCurrentTokenType(TokenKind::Let)); 6017 6018 DeclarationListNodeType kid = MOZ_TRY(lexicalDeclaration(YieldIsName, kind)); 6019 if (!checkExportedNamesForDeclarationList(kid)) { 6020 return errorResult(); 6021 } 6022 6023 UnaryNodeType node = 6024 MOZ_TRY(handler_.newExportDeclaration(kid, TokenPos(begin, pos().end))); 6025 6026 if (!processExport(node)) { 6027 return errorResult(); 6028 } 6029 6030 return node; 6031 } 6032 6033 template <class ParseHandler, typename Unit> 6034 typename ParseHandler::BinaryNodeResult 6035 GeneralParser<ParseHandler, Unit>::exportDefaultFunctionDeclaration( 6036 uint32_t begin, uint32_t toStringStart, 6037 FunctionAsyncKind asyncKind /* = SyncFunction */) { 6038 if (!abortIfSyntaxParser()) { 6039 return errorResult(); 6040 } 6041 6042 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); 6043 6044 Node kid = MOZ_TRY( 6045 functionStmt(toStringStart, YieldIsName, AllowDefaultName, asyncKind)); 6046 6047 BinaryNodeType node = MOZ_TRY(handler_.newExportDefaultDeclaration( 6048 kid, null(), TokenPos(begin, pos().end))); 6049 6050 if (!processExport(node)) { 6051 return errorResult(); 6052 } 6053 6054 return node; 6055 } 6056 6057 template <class ParseHandler, typename Unit> 6058 typename ParseHandler::BinaryNodeResult 6059 GeneralParser<ParseHandler, Unit>::exportDefaultClassDeclaration( 6060 uint32_t begin) { 6061 if (!abortIfSyntaxParser()) { 6062 return errorResult(); 6063 } 6064 6065 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class)); 6066 6067 ClassNodeType kid = 6068 MOZ_TRY(classDefinition(YieldIsName, ClassStatement, AllowDefaultName)); 6069 6070 BinaryNodeType node = MOZ_TRY(handler_.newExportDefaultDeclaration( 6071 kid, null(), TokenPos(begin, pos().end))); 6072 6073 if (!processExport(node)) { 6074 return errorResult(); 6075 } 6076 6077 return node; 6078 } 6079 6080 template <class ParseHandler, typename Unit> 6081 typename ParseHandler::BinaryNodeResult 6082 GeneralParser<ParseHandler, Unit>::exportDefaultAssignExpr(uint32_t begin) { 6083 if (!abortIfSyntaxParser()) { 6084 return errorResult(); 6085 } 6086 6087 TaggedParserAtomIndex name = TaggedParserAtomIndex::WellKnown::default_(); 6088 NameNodeType nameNode = MOZ_TRY(newName(name)); 6089 if (!noteDeclaredName(name, DeclarationKind::Const, pos())) { 6090 return errorResult(); 6091 } 6092 6093 Node kid = MOZ_TRY(assignExpr(InAllowed, YieldIsName, TripledotProhibited)); 6094 6095 if (!matchOrInsertSemicolon()) { 6096 return errorResult(); 6097 } 6098 6099 BinaryNodeType node = MOZ_TRY(handler_.newExportDefaultDeclaration( 6100 kid, nameNode, TokenPos(begin, pos().end))); 6101 6102 if (!processExport(node)) { 6103 return errorResult(); 6104 } 6105 6106 return node; 6107 } 6108 6109 template <class ParseHandler, typename Unit> 6110 typename ParseHandler::BinaryNodeResult 6111 GeneralParser<ParseHandler, Unit>::exportDefault(uint32_t begin) { 6112 if (!abortIfSyntaxParser()) { 6113 return errorResult(); 6114 } 6115 6116 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Default)); 6117 6118 TokenKind tt; 6119 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 6120 return errorResult(); 6121 } 6122 6123 if (!checkExportedName(TaggedParserAtomIndex::WellKnown::default_())) { 6124 return errorResult(); 6125 } 6126 6127 switch (tt) { 6128 case TokenKind::Function: 6129 return exportDefaultFunctionDeclaration(begin, pos().begin); 6130 6131 case TokenKind::Async: { 6132 TokenKind nextSameLine = TokenKind::Eof; 6133 if (!tokenStream.peekTokenSameLine(&nextSameLine)) { 6134 return errorResult(); 6135 } 6136 6137 if (nextSameLine == TokenKind::Function) { 6138 uint32_t toStringStart = pos().begin; 6139 tokenStream.consumeKnownToken(TokenKind::Function); 6140 return exportDefaultFunctionDeclaration( 6141 begin, toStringStart, FunctionAsyncKind::AsyncFunction); 6142 } 6143 6144 anyChars.ungetToken(); 6145 return exportDefaultAssignExpr(begin); 6146 } 6147 6148 case TokenKind::Class: 6149 return exportDefaultClassDeclaration(begin); 6150 6151 default: 6152 anyChars.ungetToken(); 6153 return exportDefaultAssignExpr(begin); 6154 } 6155 } 6156 6157 template <class ParseHandler, typename Unit> 6158 typename ParseHandler::NodeResult 6159 GeneralParser<ParseHandler, Unit>::exportDeclaration() { 6160 if (!abortIfSyntaxParser()) { 6161 return errorResult(); 6162 } 6163 6164 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Export)); 6165 6166 if (!pc_->atModuleLevel()) { 6167 error(JSMSG_EXPORT_DECL_AT_TOP_LEVEL); 6168 return errorResult(); 6169 } 6170 6171 uint32_t begin = pos().begin; 6172 6173 TokenKind tt; 6174 if (!tokenStream.getToken(&tt)) { 6175 return errorResult(); 6176 } 6177 switch (tt) { 6178 case TokenKind::Mul: 6179 return exportBatch(begin); 6180 6181 case TokenKind::LeftCurly: 6182 return exportClause(begin); 6183 6184 case TokenKind::Var: 6185 return exportVariableStatement(begin); 6186 6187 case TokenKind::Function: 6188 return exportFunctionDeclaration(begin, pos().begin); 6189 6190 case TokenKind::Async: { 6191 TokenKind nextSameLine = TokenKind::Eof; 6192 if (!tokenStream.peekTokenSameLine(&nextSameLine)) { 6193 return errorResult(); 6194 } 6195 6196 if (nextSameLine == TokenKind::Function) { 6197 uint32_t toStringStart = pos().begin; 6198 tokenStream.consumeKnownToken(TokenKind::Function); 6199 return exportFunctionDeclaration(begin, toStringStart, 6200 FunctionAsyncKind::AsyncFunction); 6201 } 6202 6203 error(JSMSG_DECLARATION_AFTER_EXPORT); 6204 return errorResult(); 6205 } 6206 6207 case TokenKind::Class: 6208 return exportClassDeclaration(begin); 6209 6210 case TokenKind::Const: 6211 return exportLexicalDeclaration(begin, DeclarationKind::Const); 6212 6213 case TokenKind::Let: 6214 return exportLexicalDeclaration(begin, DeclarationKind::Let); 6215 6216 case TokenKind::Default: 6217 return exportDefault(begin); 6218 6219 default: 6220 error(JSMSG_DECLARATION_AFTER_EXPORT); 6221 return errorResult(); 6222 } 6223 } 6224 6225 template <class ParseHandler, typename Unit> 6226 typename ParseHandler::UnaryNodeResult 6227 GeneralParser<ParseHandler, Unit>::expressionStatement( 6228 YieldHandling yieldHandling, InvokedPrediction invoked) { 6229 anyChars.ungetToken(); 6230 Node pnexpr = MOZ_TRY(expr(InAllowed, yieldHandling, TripledotProhibited, 6231 /* possibleError = */ nullptr, invoked)); 6232 if (!matchOrInsertSemicolon()) { 6233 return errorResult(); 6234 } 6235 return handler_.newExprStatement(pnexpr, pos().end); 6236 } 6237 6238 template <class ParseHandler, typename Unit> 6239 typename ParseHandler::NodeResult 6240 GeneralParser<ParseHandler, Unit>::consequentOrAlternative( 6241 YieldHandling yieldHandling) { 6242 TokenKind next; 6243 if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) { 6244 return errorResult(); 6245 } 6246 6247 // Annex B.3.4 says that unbraced FunctionDeclarations under if/else in 6248 // non-strict code act as if they were braced: |if (x) function f() {}| 6249 // parses as |if (x) { function f() {} }|. 6250 // 6251 // Careful! FunctionDeclaration doesn't include generators or async 6252 // functions. 6253 if (next == TokenKind::Function) { 6254 tokenStream.consumeKnownToken(next, TokenStream::SlashIsRegExp); 6255 6256 // Parser::statement would handle this, but as this function handles 6257 // every other error case, it seems best to handle this. 6258 if (pc_->sc()->strict()) { 6259 error(JSMSG_FORBIDDEN_AS_STATEMENT, "function declarations"); 6260 return errorResult(); 6261 } 6262 6263 TokenKind maybeStar; 6264 if (!tokenStream.peekToken(&maybeStar)) { 6265 return errorResult(); 6266 } 6267 6268 if (maybeStar == TokenKind::Mul) { 6269 error(JSMSG_FORBIDDEN_AS_STATEMENT, "generator declarations"); 6270 return errorResult(); 6271 } 6272 6273 ParseContext::Statement stmt(pc_, StatementKind::Block); 6274 ParseContext::Scope scope(this); 6275 if (!scope.init(pc_)) { 6276 return errorResult(); 6277 } 6278 6279 TokenPos funcPos = pos(); 6280 Node fun = MOZ_TRY(functionStmt(pos().begin, yieldHandling, NameRequired)); 6281 6282 ListNodeType block = MOZ_TRY(handler_.newStatementList(funcPos)); 6283 6284 handler_.addStatementToList(block, fun); 6285 return finishLexicalScope(scope, block); 6286 } 6287 6288 return statement(yieldHandling); 6289 } 6290 6291 template <class ParseHandler, typename Unit> 6292 typename ParseHandler::TernaryNodeResult 6293 GeneralParser<ParseHandler, Unit>::ifStatement(YieldHandling yieldHandling) { 6294 Vector<Node, 4> condList(fc_), thenList(fc_); 6295 Vector<uint32_t, 4> posList(fc_); 6296 Node elseBranch; 6297 6298 ParseContext::Statement stmt(pc_, StatementKind::If); 6299 6300 while (true) { 6301 uint32_t begin = pos().begin; 6302 6303 /* An IF node has three kids: condition, then, and optional else. */ 6304 Node cond = MOZ_TRY(condition(InAllowed, yieldHandling)); 6305 6306 TokenKind tt; 6307 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 6308 return errorResult(); 6309 } 6310 6311 Node thenBranch = MOZ_TRY(consequentOrAlternative(yieldHandling)); 6312 6313 if (!condList.append(cond) || !thenList.append(thenBranch) || 6314 !posList.append(begin)) { 6315 return errorResult(); 6316 } 6317 6318 bool matched; 6319 if (!tokenStream.matchToken(&matched, TokenKind::Else, 6320 TokenStream::SlashIsRegExp)) { 6321 return errorResult(); 6322 } 6323 if (matched) { 6324 if (!tokenStream.matchToken(&matched, TokenKind::If, 6325 TokenStream::SlashIsRegExp)) { 6326 return errorResult(); 6327 } 6328 if (matched) { 6329 continue; 6330 } 6331 elseBranch = MOZ_TRY(consequentOrAlternative(yieldHandling)); 6332 } else { 6333 elseBranch = null(); 6334 } 6335 break; 6336 } 6337 6338 TernaryNodeType ifNode; 6339 for (int i = condList.length() - 1; i >= 0; i--) { 6340 ifNode = MOZ_TRY(handler_.newIfStatement(posList[i], condList[i], 6341 thenList[i], elseBranch)); 6342 elseBranch = ifNode; 6343 } 6344 6345 return ifNode; 6346 } 6347 6348 template <class ParseHandler, typename Unit> 6349 typename ParseHandler::BinaryNodeResult 6350 GeneralParser<ParseHandler, Unit>::doWhileStatement( 6351 YieldHandling yieldHandling) { 6352 uint32_t begin = pos().begin; 6353 ParseContext::Statement stmt(pc_, StatementKind::DoLoop); 6354 Node body = MOZ_TRY(statement(yieldHandling)); 6355 if (!mustMatchToken(TokenKind::While, JSMSG_WHILE_AFTER_DO)) { 6356 return errorResult(); 6357 } 6358 Node cond = MOZ_TRY(condition(InAllowed, yieldHandling)); 6359 6360 // The semicolon after do-while is even more optional than most 6361 // semicolons in JS. Web compat required this by 2004: 6362 // http://bugzilla.mozilla.org/show_bug.cgi?id=238945 6363 // ES3 and ES5 disagreed, but ES6 conforms to Web reality: 6364 // https://bugs.ecmascript.org/show_bug.cgi?id=157 6365 // To parse |do {} while (true) false| correctly, use SlashIsRegExp. 6366 bool ignored; 6367 if (!tokenStream.matchToken(&ignored, TokenKind::Semi, 6368 TokenStream::SlashIsRegExp)) { 6369 return errorResult(); 6370 } 6371 return handler_.newDoWhileStatement(body, cond, TokenPos(begin, pos().end)); 6372 } 6373 6374 template <class ParseHandler, typename Unit> 6375 typename ParseHandler::BinaryNodeResult 6376 GeneralParser<ParseHandler, Unit>::whileStatement(YieldHandling yieldHandling) { 6377 uint32_t begin = pos().begin; 6378 ParseContext::Statement stmt(pc_, StatementKind::WhileLoop); 6379 Node cond = MOZ_TRY(condition(InAllowed, yieldHandling)); 6380 Node body = MOZ_TRY(statement(yieldHandling)); 6381 return handler_.newWhileStatement(begin, cond, body); 6382 } 6383 6384 template <class ParseHandler, typename Unit> 6385 bool GeneralParser<ParseHandler, Unit>::matchInOrOf(bool* isForInp, 6386 bool* isForOfp) { 6387 TokenKind tt; 6388 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 6389 return false; 6390 } 6391 6392 *isForInp = tt == TokenKind::In; 6393 *isForOfp = tt == TokenKind::Of; 6394 if (!*isForInp && !*isForOfp) { 6395 anyChars.ungetToken(); 6396 } 6397 6398 MOZ_ASSERT_IF(*isForInp || *isForOfp, *isForInp != *isForOfp); 6399 return true; 6400 } 6401 6402 template <class ParseHandler, typename Unit> 6403 bool GeneralParser<ParseHandler, Unit>::forHeadStart( 6404 YieldHandling yieldHandling, IteratorKind iterKind, 6405 ParseNodeKind* forHeadKind, Node* forInitialPart, 6406 Maybe<ParseContext::Scope>& forLoopLexicalScope, 6407 Node* forInOrOfExpression) { 6408 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftParen)); 6409 6410 TokenKind tt; 6411 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 6412 return false; 6413 } 6414 6415 // Super-duper easy case: |for (;| is a C-style for-loop with no init 6416 // component. 6417 if (tt == TokenKind::Semi) { 6418 *forInitialPart = null(); 6419 *forHeadKind = ParseNodeKind::ForHead; 6420 return true; 6421 } 6422 6423 // Parsing after |for (var| is also relatively simple (from this method's 6424 // point of view). No block-related work complicates matters, so delegate 6425 // to Parser::declaration. 6426 if (tt == TokenKind::Var) { 6427 tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); 6428 6429 // Pass null for block object because |var| declarations don't use one. 6430 MOZ_TRY_VAR_OR_RETURN(*forInitialPart, 6431 declarationList(yieldHandling, ParseNodeKind::VarStmt, 6432 forHeadKind, forInOrOfExpression), 6433 false); 6434 return true; 6435 } 6436 6437 // Otherwise we have a lexical declaration or an expression. 6438 6439 // For-in loop backwards compatibility requires that |let| starting a 6440 // for-loop that's not a (new to ES6) for-of loop, in non-strict mode code, 6441 // parse as an identifier. (|let| in for-of is always a declaration.) 6442 // 6443 // For-of loops can't start with the token sequence "async of", because that 6444 // leads to a shift-reduce conflict when parsing |for (async of => {};;)| or 6445 // |for (async of [])|. 6446 bool parsingLexicalDeclaration = false; 6447 bool letIsIdentifier = false; 6448 bool startsWithForOf = false; 6449 6450 if (tt == TokenKind::Const) { 6451 parsingLexicalDeclaration = true; 6452 tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); 6453 } 6454 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 6455 else if (tt == TokenKind::Await && options().explicitResourceManagement()) { 6456 if (!pc_->isAsync()) { 6457 if (pc_->atModuleTopLevel()) { 6458 if (!options().topLevelAwait) { 6459 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED); 6460 return false; 6461 } 6462 pc_->sc()->asModuleContext()->setIsAsync(); 6463 MOZ_ASSERT(pc_->isAsync()); 6464 } 6465 } 6466 if (pc_->isAsync()) { 6467 // Try finding evidence of a AwaitUsingDeclaration the syntax for which 6468 // would be: 6469 // await [no LineTerminator here] using [no LineTerminator here] 6470 // identifier 6471 tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); 6472 6473 TokenKind nextTok = TokenKind::Eof; 6474 if (!tokenStream.peekTokenSameLine(&nextTok, 6475 TokenStream::SlashIsRegExp)) { 6476 return false; 6477 } 6478 6479 if (nextTok == TokenKind::Using) { 6480 tokenStream.consumeKnownToken(nextTok, TokenStream::SlashIsRegExp); 6481 6482 TokenKind nextTokIdent = TokenKind::Eof; 6483 if (!tokenStream.peekTokenSameLine(&nextTokIdent)) { 6484 return false; 6485 } 6486 6487 if (TokenKindIsPossibleIdentifier(nextTokIdent)) { 6488 parsingLexicalDeclaration = true; 6489 } else { 6490 anyChars.ungetToken(); // put back using token 6491 anyChars.ungetToken(); // put back await token 6492 } 6493 } else { 6494 anyChars.ungetToken(); // put back await token 6495 } 6496 } 6497 } else if (tt == TokenKind::Using && options().explicitResourceManagement()) { 6498 tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); 6499 6500 // Look ahead to find either a 'of' token or if not identifier 6501 TokenKind nextTok = TokenKind::Eof; 6502 if (!tokenStream.peekTokenSameLine(&nextTok)) { 6503 return false; 6504 } 6505 6506 if (!TokenKindIsPossibleIdentifier(nextTok)) { 6507 anyChars.ungetToken(); // we didnt find a valid case of using decl put 6508 // back the token 6509 } else if (nextTok == TokenKind::Of) { 6510 // "for (using of" can be a prefix of the following: 6511 // * "for (using of = 0;;) { ... }" 6512 // * "for (using of [1, 2, 3]) { ... }" 6513 // 6514 // If the "of" token is followed by the assignment token, the loop is 6515 // considered a C-style for-statement with a using declaration where 6516 // "of" is an identifier. 6517 // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-for-statement&secAll=true 6518 // 6519 // If the "of" token is followed by anything else, this is a for-of 6520 // statement with the "using" being an identifier", and the token after 6521 // the "of" token being the first token of the iterated expression (thus 6522 // SlashIsRegExp is used as the modifier). 6523 // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-for-in-and-for-of-statements&secAll=true 6524 tokenStream.consumeKnownToken(nextTok); 6525 TokenKind nextTokAssign; 6526 if (!tokenStream.peekToken(&nextTokAssign, TokenStream::SlashIsRegExp)) { 6527 return false; 6528 } 6529 if (nextTokAssign == TokenKind::Assign) { 6530 parsingLexicalDeclaration = true; 6531 anyChars.ungetToken(); // put back the assignment token 6532 } else { 6533 anyChars.ungetToken(); // put back the token after the "of" token 6534 anyChars.ungetToken(); // put back the of token 6535 } 6536 } else { 6537 parsingLexicalDeclaration = true; 6538 } 6539 } 6540 #endif 6541 else if (tt == TokenKind::Let) { 6542 // We could have a {For,Lexical}Declaration, or we could have a 6543 // LeftHandSideExpression with lookahead restrictions so it's not 6544 // ambiguous with the former. Check for a continuation of the former 6545 // to decide which we have. 6546 tokenStream.consumeKnownToken(TokenKind::Let, TokenStream::SlashIsRegExp); 6547 6548 TokenKind next; 6549 if (!tokenStream.peekToken(&next)) { 6550 return false; 6551 } 6552 6553 parsingLexicalDeclaration = nextTokenContinuesLetDeclaration(next); 6554 if (!parsingLexicalDeclaration) { 6555 // If we end up here, we may have `for (let <reserved word> of/in ...`, 6556 // which is not valid. 6557 if (next != TokenKind::In && next != TokenKind::Of && 6558 TokenKindIsReservedWord(next)) { 6559 tokenStream.consumeKnownToken(next); 6560 error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(next)); 6561 return false; 6562 } 6563 6564 anyChars.ungetToken(); 6565 letIsIdentifier = true; 6566 } 6567 } else if (tt == TokenKind::Async && iterKind == IteratorKind::Sync) { 6568 tokenStream.consumeKnownToken(TokenKind::Async, TokenStream::SlashIsRegExp); 6569 6570 TokenKind next; 6571 if (!tokenStream.peekToken(&next)) { 6572 return false; 6573 } 6574 6575 if (next == TokenKind::Of) { 6576 startsWithForOf = true; 6577 } 6578 anyChars.ungetToken(); 6579 } 6580 6581 if (parsingLexicalDeclaration) { 6582 if (options().selfHostingMode) { 6583 error(JSMSG_SELFHOSTED_LEXICAL); 6584 return false; 6585 } 6586 6587 forLoopLexicalScope.emplace(this); 6588 if (!forLoopLexicalScope->init(pc_)) { 6589 return false; 6590 } 6591 6592 // Push a temporary ForLoopLexicalHead Statement that allows for 6593 // lexical declarations, as they are usually allowed only in braced 6594 // statements. 6595 ParseContext::Statement forHeadStmt(pc_, StatementKind::ForLoopLexicalHead); 6596 6597 ParseNodeKind declKind; 6598 switch (tt) { 6599 case TokenKind::Const: 6600 declKind = ParseNodeKind::ConstDecl; 6601 break; 6602 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 6603 case TokenKind::Using: 6604 declKind = ParseNodeKind::UsingDecl; 6605 break; 6606 case TokenKind::Await: 6607 declKind = ParseNodeKind::AwaitUsingDecl; 6608 break; 6609 #endif 6610 case TokenKind::Let: 6611 declKind = ParseNodeKind::LetDecl; 6612 break; 6613 default: 6614 MOZ_CRASH("unexpected node kind"); 6615 } 6616 6617 MOZ_TRY_VAR_OR_RETURN(*forInitialPart, 6618 declarationList(yieldHandling, declKind, forHeadKind, 6619 forInOrOfExpression), 6620 false); 6621 return true; 6622 } 6623 6624 uint32_t exprOffset; 6625 if (!tokenStream.peekOffset(&exprOffset, TokenStream::SlashIsRegExp)) { 6626 return false; 6627 } 6628 6629 // Finally, handle for-loops that start with expressions. Pass 6630 // |InProhibited| so that |in| isn't parsed in a RelationalExpression as a 6631 // binary operator. |in| makes it a for-in loop, *not* an |in| expression. 6632 PossibleError possibleError(*this); 6633 MOZ_TRY_VAR_OR_RETURN( 6634 *forInitialPart, 6635 expr(InProhibited, yieldHandling, TripledotProhibited, &possibleError), 6636 false); 6637 6638 bool isForIn, isForOf; 6639 if (!matchInOrOf(&isForIn, &isForOf)) { 6640 return false; 6641 } 6642 6643 // If we don't encounter 'in'/'of', we have a for(;;) loop. We've handled 6644 // the init expression; the caller handles the rest. 6645 if (!isForIn && !isForOf) { 6646 if (!possibleError.checkForExpressionError()) { 6647 return false; 6648 } 6649 6650 *forHeadKind = ParseNodeKind::ForHead; 6651 return true; 6652 } 6653 6654 MOZ_ASSERT(isForIn != isForOf); 6655 6656 // In a for-of loop, 'let' that starts the loop head is a |let| keyword, 6657 // per the [lookahead ≠let] restriction on the LeftHandSideExpression 6658 // variant of such loops. Expressions that start with |let| can't be used 6659 // here. 6660 // 6661 // var let = {}; 6662 // for (let.prop of [1]) // BAD 6663 // break; 6664 // 6665 // See ES6 13.7. 6666 if (isForOf && letIsIdentifier) { 6667 errorAt(exprOffset, JSMSG_BAD_STARTING_FOROF_LHS, "let"); 6668 return false; 6669 } 6670 6671 // In a for-of loop, the LeftHandSideExpression isn't allowed to be an 6672 // identifier named "async" per the [lookahead ≠async of] restriction. 6673 if (isForOf && startsWithForOf) { 6674 errorAt(exprOffset, JSMSG_BAD_STARTING_FOROF_LHS, "async of"); 6675 return false; 6676 } 6677 6678 *forHeadKind = isForIn ? ParseNodeKind::ForIn : ParseNodeKind::ForOf; 6679 6680 // Verify the left-hand side expression doesn't have a forbidden form. 6681 if (handler_.isUnparenthesizedDestructuringPattern(*forInitialPart)) { 6682 if (!possibleError.checkForDestructuringErrorOrWarning()) { 6683 return false; 6684 } 6685 } else if (handler_.isName(*forInitialPart)) { 6686 if (const char* chars = nameIsArgumentsOrEval(*forInitialPart)) { 6687 // |chars| is "arguments" or "eval" here. 6688 if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars)) { 6689 return false; 6690 } 6691 } 6692 } else if (handler_.isArgumentsLength(*forInitialPart)) { 6693 pc_->sc()->setIneligibleForArgumentsLength(); 6694 } else if (handler_.isPropertyOrPrivateMemberAccess(*forInitialPart)) { 6695 // Permitted: no additional testing/fixup needed. 6696 } else if (handler_.isFunctionCall(*forInitialPart)) { 6697 if (!strictModeErrorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE)) { 6698 return false; 6699 } 6700 } else { 6701 errorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE); 6702 return false; 6703 } 6704 6705 if (!possibleError.checkForExpressionError()) { 6706 return false; 6707 } 6708 6709 // Finally, parse the iterated expression, making the for-loop's closing 6710 // ')' the next token. 6711 MOZ_TRY_VAR_OR_RETURN(*forInOrOfExpression, 6712 expressionAfterForInOrOf(*forHeadKind, yieldHandling), 6713 false); 6714 return true; 6715 } 6716 6717 template <class ParseHandler, typename Unit> 6718 typename ParseHandler::NodeResult 6719 GeneralParser<ParseHandler, Unit>::forStatement(YieldHandling yieldHandling) { 6720 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::For)); 6721 6722 uint32_t begin = pos().begin; 6723 6724 ParseContext::Statement stmt(pc_, StatementKind::ForLoop); 6725 6726 IteratorKind iterKind = IteratorKind::Sync; 6727 unsigned iflags = 0; 6728 6729 if (pc_->isAsync() || pc_->sc()->isModuleContext()) { 6730 bool matched; 6731 if (!tokenStream.matchToken(&matched, TokenKind::Await)) { 6732 return errorResult(); 6733 } 6734 6735 // If we come across a top level await here, mark the module as async. 6736 if (matched && pc_->sc()->isModuleContext() && !pc_->isAsync()) { 6737 if (!options().topLevelAwait) { 6738 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED); 6739 return errorResult(); 6740 } 6741 pc_->sc()->asModuleContext()->setIsAsync(); 6742 MOZ_ASSERT(pc_->isAsync()); 6743 } 6744 6745 if (matched) { 6746 iflags |= JSITER_FORAWAITOF; 6747 iterKind = IteratorKind::Async; 6748 } 6749 } 6750 6751 if (!mustMatchToken(TokenKind::LeftParen, [this](TokenKind actual) { 6752 this->error((actual == TokenKind::Await && !this->pc_->isAsync()) 6753 ? JSMSG_FOR_AWAIT_OUTSIDE_ASYNC 6754 : JSMSG_PAREN_AFTER_FOR); 6755 })) { 6756 return errorResult(); 6757 } 6758 6759 // ParseNodeKind::ForHead, ParseNodeKind::ForIn, or 6760 // ParseNodeKind::ForOf depending on the loop type. 6761 ParseNodeKind headKind; 6762 6763 // |x| in either |for (x; ...; ...)| or |for (x in/of ...)|. 6764 Node startNode; 6765 6766 // The next two variables are used to implement `for (let/const ...)`. 6767 // 6768 // We generate an implicit block, wrapping the whole loop, to store loop 6769 // variables declared this way. Note that if the loop uses `for (var...)` 6770 // instead, those variables go on some existing enclosing scope, so no 6771 // implicit block scope is created. 6772 // 6773 // Both variables remain null/none if the loop is any other form. 6774 6775 // The static block scope for the implicit block scope. 6776 Maybe<ParseContext::Scope> forLoopLexicalScope; 6777 6778 // The expression being iterated over, for for-in/of loops only. Unused 6779 // for for(;;) loops. 6780 Node iteratedExpr; 6781 6782 // Parse the entirety of the loop-head for a for-in/of loop (so the next 6783 // token is the closing ')'): 6784 // 6785 // for (... in/of ...) ... 6786 // ^next token 6787 // 6788 // ...OR, parse up to the first ';' in a C-style for-loop: 6789 // 6790 // for (...; ...; ...) ... 6791 // ^next token 6792 // 6793 // In either case the subsequent token can be consistently accessed using 6794 // TokenStream::SlashIsDiv semantics. 6795 if (!forHeadStart(yieldHandling, iterKind, &headKind, &startNode, 6796 forLoopLexicalScope, &iteratedExpr)) { 6797 return errorResult(); 6798 } 6799 6800 MOZ_ASSERT(headKind == ParseNodeKind::ForIn || 6801 headKind == ParseNodeKind::ForOf || 6802 headKind == ParseNodeKind::ForHead); 6803 6804 if (iterKind == IteratorKind::Async && headKind != ParseNodeKind::ForOf) { 6805 errorAt(begin, JSMSG_FOR_AWAIT_NOT_OF); 6806 return errorResult(); 6807 } 6808 6809 TernaryNodeType forHead; 6810 if (headKind == ParseNodeKind::ForHead) { 6811 Node init = startNode; 6812 6813 // Look for an operand: |for (;| means we might have already examined 6814 // this semicolon with that modifier. 6815 if (!mustMatchToken(TokenKind::Semi, JSMSG_SEMI_AFTER_FOR_INIT)) { 6816 return errorResult(); 6817 } 6818 6819 TokenKind tt; 6820 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 6821 return errorResult(); 6822 } 6823 6824 Node test; 6825 if (tt == TokenKind::Semi) { 6826 test = null(); 6827 } else { 6828 test = MOZ_TRY(expr(InAllowed, yieldHandling, TripledotProhibited)); 6829 } 6830 6831 if (!mustMatchToken(TokenKind::Semi, JSMSG_SEMI_AFTER_FOR_COND)) { 6832 return errorResult(); 6833 } 6834 6835 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 6836 return errorResult(); 6837 } 6838 6839 Node update; 6840 if (tt == TokenKind::RightParen) { 6841 update = null(); 6842 } else { 6843 update = MOZ_TRY(expr(InAllowed, yieldHandling, TripledotProhibited)); 6844 } 6845 6846 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_FOR_CTRL)) { 6847 return errorResult(); 6848 } 6849 6850 TokenPos headPos(begin, pos().end); 6851 forHead = MOZ_TRY(handler_.newForHead(init, test, update, headPos)); 6852 } else { 6853 MOZ_ASSERT(headKind == ParseNodeKind::ForIn || 6854 headKind == ParseNodeKind::ForOf); 6855 6856 // |target| is the LeftHandSideExpression or declaration to which the 6857 // per-iteration value (an arbitrary value exposed by the iteration 6858 // protocol, or a string naming a property) is assigned. 6859 Node target = startNode; 6860 6861 // Parse the rest of the for-in/of head. 6862 if (headKind == ParseNodeKind::ForIn) { 6863 stmt.refineForKind(StatementKind::ForInLoop); 6864 } else { 6865 stmt.refineForKind(StatementKind::ForOfLoop); 6866 } 6867 6868 // Parser::declaration consumed everything up to the closing ')'. That 6869 // token follows an {Assignment,}Expression and so must be interpreted 6870 // as an operand to be consistent with normal expression tokenizing. 6871 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_FOR_CTRL)) { 6872 return errorResult(); 6873 } 6874 6875 TokenPos headPos(begin, pos().end); 6876 forHead = MOZ_TRY( 6877 handler_.newForInOrOfHead(headKind, target, iteratedExpr, headPos)); 6878 } 6879 6880 Node body = MOZ_TRY(statement(yieldHandling)); 6881 6882 ForNodeType forLoop = 6883 MOZ_TRY(handler_.newForStatement(begin, forHead, body, iflags)); 6884 6885 if (forLoopLexicalScope) { 6886 return finishLexicalScope(*forLoopLexicalScope, forLoop); 6887 } 6888 6889 return forLoop; 6890 } 6891 6892 template <class ParseHandler, typename Unit> 6893 typename ParseHandler::SwitchStatementResult 6894 GeneralParser<ParseHandler, Unit>::switchStatement( 6895 YieldHandling yieldHandling) { 6896 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Switch)); 6897 uint32_t begin = pos().begin; 6898 6899 if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_SWITCH)) { 6900 return errorResult(); 6901 } 6902 6903 Node discriminant = 6904 MOZ_TRY(exprInParens(InAllowed, yieldHandling, TripledotProhibited)); 6905 6906 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_SWITCH)) { 6907 return errorResult(); 6908 } 6909 if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_SWITCH)) { 6910 return errorResult(); 6911 } 6912 6913 ParseContext::Statement stmt(pc_, StatementKind::Switch); 6914 ParseContext::Scope scope(this); 6915 if (!scope.init(pc_)) { 6916 return errorResult(); 6917 } 6918 6919 ListNodeType caseList = MOZ_TRY(handler_.newStatementList(pos())); 6920 6921 bool seenDefault = false; 6922 TokenKind tt; 6923 while (true) { 6924 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 6925 return errorResult(); 6926 } 6927 if (tt == TokenKind::RightCurly) { 6928 break; 6929 } 6930 uint32_t caseBegin = pos().begin; 6931 6932 Node caseExpr; 6933 switch (tt) { 6934 case TokenKind::Default: 6935 if (seenDefault) { 6936 error(JSMSG_TOO_MANY_DEFAULTS); 6937 return errorResult(); 6938 } 6939 seenDefault = true; 6940 caseExpr = null(); // The default case has pn_left == nullptr. 6941 break; 6942 6943 case TokenKind::Case: 6944 caseExpr = MOZ_TRY(expr(InAllowed, yieldHandling, TripledotProhibited)); 6945 break; 6946 6947 default: 6948 error(JSMSG_BAD_SWITCH); 6949 return errorResult(); 6950 } 6951 6952 if (!mustMatchToken(TokenKind::Colon, JSMSG_COLON_AFTER_CASE)) { 6953 return errorResult(); 6954 } 6955 6956 ListNodeType body = MOZ_TRY(handler_.newStatementList(pos())); 6957 6958 bool afterReturn = false; 6959 bool warnedAboutStatementsAfterReturn = false; 6960 uint32_t statementBegin = 0; 6961 while (true) { 6962 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 6963 return errorResult(); 6964 } 6965 if (tt == TokenKind::RightCurly || tt == TokenKind::Case || 6966 tt == TokenKind::Default) { 6967 break; 6968 } 6969 if (afterReturn) { 6970 if (!tokenStream.peekOffset(&statementBegin, 6971 TokenStream::SlashIsRegExp)) { 6972 return errorResult(); 6973 } 6974 } 6975 Node stmt = MOZ_TRY(statementListItem(yieldHandling)); 6976 if (!warnedAboutStatementsAfterReturn) { 6977 if (afterReturn) { 6978 if (!handler_.isStatementPermittedAfterReturnStatement(stmt)) { 6979 if (!warningAt(statementBegin, JSMSG_STMT_AFTER_RETURN)) { 6980 return errorResult(); 6981 } 6982 6983 warnedAboutStatementsAfterReturn = true; 6984 } 6985 } else if (handler_.isReturnStatement(stmt)) { 6986 afterReturn = true; 6987 } 6988 } 6989 handler_.addStatementToList(body, stmt); 6990 } 6991 6992 CaseClauseType caseClause = 6993 MOZ_TRY(handler_.newCaseOrDefault(caseBegin, caseExpr, body)); 6994 handler_.addCaseStatementToList(caseList, caseClause); 6995 } 6996 6997 LexicalScopeNodeType lexicalForCaseList = 6998 MOZ_TRY(finishLexicalScope(scope, caseList)); 6999 7000 handler_.setEndPosition(lexicalForCaseList, pos().end); 7001 7002 return handler_.newSwitchStatement(begin, discriminant, lexicalForCaseList, 7003 seenDefault); 7004 } 7005 7006 template <class ParseHandler, typename Unit> 7007 typename ParseHandler::ContinueStatementResult 7008 GeneralParser<ParseHandler, Unit>::continueStatement( 7009 YieldHandling yieldHandling) { 7010 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Continue)); 7011 uint32_t begin = pos().begin; 7012 7013 TaggedParserAtomIndex label; 7014 if (!matchLabel(yieldHandling, &label)) { 7015 return errorResult(); 7016 } 7017 7018 auto validity = pc_->checkContinueStatement(label); 7019 if (validity.isErr()) { 7020 switch (validity.unwrapErr()) { 7021 case ParseContext::ContinueStatementError::NotInALoop: 7022 errorAt(begin, JSMSG_BAD_CONTINUE); 7023 break; 7024 case ParseContext::ContinueStatementError::LabelNotFound: 7025 error(JSMSG_LABEL_NOT_FOUND); 7026 break; 7027 } 7028 return errorResult(); 7029 } 7030 7031 if (!matchOrInsertSemicolon()) { 7032 return errorResult(); 7033 } 7034 7035 return handler_.newContinueStatement(label, TokenPos(begin, pos().end)); 7036 } 7037 7038 template <class ParseHandler, typename Unit> 7039 typename ParseHandler::BreakStatementResult 7040 GeneralParser<ParseHandler, Unit>::breakStatement(YieldHandling yieldHandling) { 7041 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Break)); 7042 uint32_t begin = pos().begin; 7043 7044 TaggedParserAtomIndex label; 7045 if (!matchLabel(yieldHandling, &label)) { 7046 return errorResult(); 7047 } 7048 7049 auto validity = pc_->checkBreakStatement(label); 7050 if (validity.isErr()) { 7051 switch (validity.unwrapErr()) { 7052 case ParseContext::BreakStatementError::ToughBreak: 7053 errorAt(begin, JSMSG_TOUGH_BREAK); 7054 return errorResult(); 7055 case ParseContext::BreakStatementError::LabelNotFound: 7056 error(JSMSG_LABEL_NOT_FOUND); 7057 return errorResult(); 7058 } 7059 } 7060 7061 if (!matchOrInsertSemicolon()) { 7062 return errorResult(); 7063 } 7064 7065 return handler_.newBreakStatement(label, TokenPos(begin, pos().end)); 7066 } 7067 7068 template <class ParseHandler, typename Unit> 7069 typename ParseHandler::UnaryNodeResult 7070 GeneralParser<ParseHandler, Unit>::returnStatement( 7071 YieldHandling yieldHandling) { 7072 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Return)); 7073 uint32_t begin = pos().begin; 7074 7075 MOZ_ASSERT(pc_->isFunctionBox()); 7076 7077 // Parse an optional operand. 7078 // 7079 // This is ugly, but we don't want to require a semicolon. 7080 TokenKind tt = TokenKind::Eof; 7081 if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) { 7082 return errorResult(); 7083 } 7084 7085 Node exprNode; 7086 switch (tt) { 7087 case TokenKind::Eol: 7088 case TokenKind::Eof: 7089 case TokenKind::Semi: 7090 case TokenKind::RightCurly: 7091 exprNode = null(); 7092 break; 7093 default: { 7094 exprNode = MOZ_TRY(expr(InAllowed, yieldHandling, TripledotProhibited)); 7095 } 7096 } 7097 7098 if (!matchOrInsertSemicolon()) { 7099 return errorResult(); 7100 } 7101 7102 return handler_.newReturnStatement(exprNode, TokenPos(begin, pos().end)); 7103 } 7104 7105 template <class ParseHandler, typename Unit> 7106 typename ParseHandler::UnaryNodeResult 7107 GeneralParser<ParseHandler, Unit>::yieldExpression(InHandling inHandling) { 7108 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Yield)); 7109 uint32_t begin = pos().begin; 7110 7111 MOZ_ASSERT(pc_->isGenerator()); 7112 MOZ_ASSERT(pc_->isFunctionBox()); 7113 7114 pc_->lastYieldOffset = begin; 7115 7116 Node exprNode; 7117 ParseNodeKind kind = ParseNodeKind::YieldExpr; 7118 TokenKind tt = TokenKind::Eof; 7119 if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) { 7120 return errorResult(); 7121 } 7122 switch (tt) { 7123 // TokenKind::Eol is special; it implements the [no LineTerminator here] 7124 // quirk in the grammar. 7125 case TokenKind::Eol: 7126 // The rest of these make up the complete set of tokens that can 7127 // appear after any of the places where AssignmentExpression is used 7128 // throughout the grammar. Conveniently, none of them can also be the 7129 // start an expression. 7130 case TokenKind::Eof: 7131 case TokenKind::Semi: 7132 case TokenKind::RightCurly: 7133 case TokenKind::RightBracket: 7134 case TokenKind::RightParen: 7135 case TokenKind::Colon: 7136 case TokenKind::Comma: 7137 case TokenKind::In: // Annex B.3.6 `for (x = yield in y) ;` 7138 // No value. 7139 exprNode = null(); 7140 break; 7141 case TokenKind::Mul: 7142 kind = ParseNodeKind::YieldStarExpr; 7143 tokenStream.consumeKnownToken(TokenKind::Mul, TokenStream::SlashIsRegExp); 7144 [[fallthrough]]; 7145 default: 7146 exprNode = 7147 MOZ_TRY(assignExpr(inHandling, YieldIsKeyword, TripledotProhibited)); 7148 } 7149 if (kind == ParseNodeKind::YieldStarExpr) { 7150 return handler_.newYieldStarExpression(begin, exprNode); 7151 } 7152 return handler_.newYieldExpression(begin, exprNode); 7153 } 7154 7155 template <class ParseHandler, typename Unit> 7156 typename ParseHandler::BinaryNodeResult 7157 GeneralParser<ParseHandler, Unit>::withStatement(YieldHandling yieldHandling) { 7158 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::With)); 7159 uint32_t begin = pos().begin; 7160 7161 if (pc_->sc()->strict()) { 7162 if (!strictModeError(JSMSG_STRICT_CODE_WITH)) { 7163 return errorResult(); 7164 } 7165 } 7166 7167 if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_WITH)) { 7168 return errorResult(); 7169 } 7170 7171 Node objectExpr = 7172 MOZ_TRY(exprInParens(InAllowed, yieldHandling, TripledotProhibited)); 7173 7174 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_WITH)) { 7175 return errorResult(); 7176 } 7177 7178 Node innerBlock; 7179 { 7180 ParseContext::Statement stmt(pc_, StatementKind::With); 7181 innerBlock = MOZ_TRY(statement(yieldHandling)); 7182 } 7183 7184 pc_->sc()->setBindingsAccessedDynamically(); 7185 7186 return handler_.newWithStatement(begin, objectExpr, innerBlock); 7187 } 7188 7189 template <class ParseHandler, typename Unit> 7190 typename ParseHandler::NodeResult 7191 GeneralParser<ParseHandler, Unit>::labeledItem(YieldHandling yieldHandling) { 7192 TokenKind tt; 7193 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 7194 return errorResult(); 7195 } 7196 7197 if (tt == TokenKind::Function) { 7198 TokenKind next; 7199 if (!tokenStream.peekToken(&next)) { 7200 return errorResult(); 7201 } 7202 7203 // GeneratorDeclaration is only matched by HoistableDeclaration in 7204 // StatementListItem, so generators can't be inside labels. 7205 if (next == TokenKind::Mul) { 7206 error(JSMSG_GENERATOR_LABEL); 7207 return errorResult(); 7208 } 7209 7210 // Per 13.13.1 it's a syntax error if LabelledItem: FunctionDeclaration 7211 // is ever matched. Per Annex B.3.2 that modifies this text, this 7212 // applies only to strict mode code. 7213 if (pc_->sc()->strict()) { 7214 error(JSMSG_FUNCTION_LABEL); 7215 return errorResult(); 7216 } 7217 7218 return functionStmt(pos().begin, yieldHandling, NameRequired); 7219 } 7220 7221 anyChars.ungetToken(); 7222 return statement(yieldHandling); 7223 } 7224 7225 template <class ParseHandler, typename Unit> 7226 typename ParseHandler::LabeledStatementResult 7227 GeneralParser<ParseHandler, Unit>::labeledStatement( 7228 YieldHandling yieldHandling) { 7229 TaggedParserAtomIndex label = labelIdentifier(yieldHandling); 7230 if (!label) { 7231 return errorResult(); 7232 } 7233 7234 auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) { 7235 return stmt->label() == label; 7236 }; 7237 7238 uint32_t begin = pos().begin; 7239 7240 if (pc_->template findInnermostStatement<ParseContext::LabelStatement>( 7241 hasSameLabel)) { 7242 errorAt(begin, JSMSG_DUPLICATE_LABEL); 7243 return errorResult(); 7244 } 7245 7246 tokenStream.consumeKnownToken(TokenKind::Colon); 7247 7248 /* Push a label struct and parse the statement. */ 7249 ParseContext::LabelStatement stmt(pc_, label); 7250 Node pn = MOZ_TRY(labeledItem(yieldHandling)); 7251 7252 return handler_.newLabeledStatement(label, pn, begin); 7253 } 7254 7255 template <class ParseHandler, typename Unit> 7256 typename ParseHandler::UnaryNodeResult 7257 GeneralParser<ParseHandler, Unit>::throwStatement(YieldHandling yieldHandling) { 7258 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Throw)); 7259 uint32_t begin = pos().begin; 7260 7261 /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */ 7262 TokenKind tt = TokenKind::Eof; 7263 if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) { 7264 return errorResult(); 7265 } 7266 if (tt == TokenKind::Eof || tt == TokenKind::Semi || 7267 tt == TokenKind::RightCurly) { 7268 error(JSMSG_MISSING_EXPR_AFTER_THROW); 7269 return errorResult(); 7270 } 7271 if (tt == TokenKind::Eol) { 7272 error(JSMSG_LINE_BREAK_AFTER_THROW); 7273 return errorResult(); 7274 } 7275 7276 Node throwExpr = MOZ_TRY(expr(InAllowed, yieldHandling, TripledotProhibited)); 7277 7278 if (!matchOrInsertSemicolon()) { 7279 return errorResult(); 7280 } 7281 7282 return handler_.newThrowStatement(throwExpr, TokenPos(begin, pos().end)); 7283 } 7284 7285 template <class ParseHandler, typename Unit> 7286 typename ParseHandler::TernaryNodeResult 7287 GeneralParser<ParseHandler, Unit>::tryStatement(YieldHandling yieldHandling) { 7288 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Try)); 7289 uint32_t begin = pos().begin; 7290 7291 /* 7292 * try nodes are ternary. 7293 * kid1 is the try statement 7294 * kid2 is the catch node list or null 7295 * kid3 is the finally statement 7296 * 7297 * catch nodes are binary. 7298 * left is the catch-name/pattern or null 7299 * right is the catch block 7300 * 7301 * catch lvalue nodes are either: 7302 * a single identifier 7303 * TokenKind::RightBracket for a destructuring left-hand side 7304 * TokenKind::RightCurly for a destructuring left-hand side 7305 * 7306 * finally nodes are TokenKind::LeftCurly statement lists. 7307 */ 7308 7309 Node innerBlock; 7310 { 7311 if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_TRY)) { 7312 return errorResult(); 7313 } 7314 7315 uint32_t openedPos = pos().begin; 7316 7317 ParseContext::Statement stmt(pc_, StatementKind::Try); 7318 ParseContext::Scope scope(this); 7319 if (!scope.init(pc_)) { 7320 return errorResult(); 7321 } 7322 7323 innerBlock = MOZ_TRY(statementList(yieldHandling)); 7324 7325 innerBlock = MOZ_TRY(finishLexicalScope(scope, innerBlock)); 7326 7327 if (!mustMatchToken( 7328 TokenKind::RightCurly, [this, openedPos](TokenKind actual) { 7329 this->reportMissingClosing(JSMSG_CURLY_AFTER_TRY, 7330 JSMSG_CURLY_OPENED, openedPos); 7331 })) { 7332 return errorResult(); 7333 } 7334 } 7335 7336 LexicalScopeNodeType catchScope = null(); 7337 TokenKind tt; 7338 if (!tokenStream.getToken(&tt)) { 7339 return errorResult(); 7340 } 7341 if (tt == TokenKind::Catch) { 7342 /* 7343 * Create a lexical scope node around the whole catch clause, 7344 * including the head. 7345 */ 7346 ParseContext::Statement stmt(pc_, StatementKind::Catch); 7347 ParseContext::Scope scope(this); 7348 if (!scope.init(pc_)) { 7349 return errorResult(); 7350 } 7351 7352 /* 7353 * Legal catch forms are: 7354 * catch (lhs) { 7355 * catch { 7356 * where lhs is a name or a destructuring left-hand side. 7357 */ 7358 bool omittedBinding; 7359 if (!tokenStream.matchToken(&omittedBinding, TokenKind::LeftCurly)) { 7360 return errorResult(); 7361 } 7362 7363 Node catchName; 7364 if (omittedBinding) { 7365 catchName = null(); 7366 } else { 7367 if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_CATCH)) { 7368 return errorResult(); 7369 } 7370 7371 if (!tokenStream.getToken(&tt)) { 7372 return errorResult(); 7373 } 7374 switch (tt) { 7375 case TokenKind::LeftBracket: 7376 case TokenKind::LeftCurly: 7377 catchName = MOZ_TRY(destructuringDeclaration( 7378 DeclarationKind::CatchParameter, yieldHandling, tt)); 7379 break; 7380 7381 default: { 7382 if (!TokenKindIsPossibleIdentifierName(tt)) { 7383 error(JSMSG_CATCH_IDENTIFIER); 7384 return errorResult(); 7385 } 7386 7387 catchName = MOZ_TRY(bindingIdentifier( 7388 DeclarationKind::SimpleCatchParameter, yieldHandling)); 7389 break; 7390 } 7391 } 7392 7393 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_CATCH)) { 7394 return errorResult(); 7395 } 7396 7397 if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CATCH)) { 7398 return errorResult(); 7399 } 7400 } 7401 7402 LexicalScopeNodeType catchBody = 7403 MOZ_TRY(catchBlockStatement(yieldHandling, scope)); 7404 7405 catchScope = MOZ_TRY(finishLexicalScope(scope, catchBody)); 7406 7407 if (!handler_.setupCatchScope(catchScope, catchName, catchBody)) { 7408 return errorResult(); 7409 } 7410 handler_.setEndPosition(catchScope, pos().end); 7411 7412 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 7413 return errorResult(); 7414 } 7415 } 7416 7417 Node finallyBlock = null(); 7418 7419 if (tt == TokenKind::Finally) { 7420 if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_FINALLY)) { 7421 return errorResult(); 7422 } 7423 7424 uint32_t openedPos = pos().begin; 7425 7426 ParseContext::Statement stmt(pc_, StatementKind::Finally); 7427 ParseContext::Scope scope(this); 7428 if (!scope.init(pc_)) { 7429 return errorResult(); 7430 } 7431 7432 finallyBlock = MOZ_TRY(statementList(yieldHandling)); 7433 7434 finallyBlock = MOZ_TRY(finishLexicalScope(scope, finallyBlock)); 7435 7436 if (!mustMatchToken( 7437 TokenKind::RightCurly, [this, openedPos](TokenKind actual) { 7438 this->reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY, 7439 JSMSG_CURLY_OPENED, openedPos); 7440 })) { 7441 return errorResult(); 7442 } 7443 } else { 7444 anyChars.ungetToken(); 7445 } 7446 if (!catchScope && !finallyBlock) { 7447 error(JSMSG_CATCH_OR_FINALLY); 7448 return errorResult(); 7449 } 7450 7451 return handler_.newTryStatement(begin, innerBlock, catchScope, finallyBlock); 7452 } 7453 7454 template <class ParseHandler, typename Unit> 7455 typename ParseHandler::LexicalScopeNodeResult 7456 GeneralParser<ParseHandler, Unit>::catchBlockStatement( 7457 YieldHandling yieldHandling, ParseContext::Scope& catchParamScope) { 7458 uint32_t openedPos = pos().begin; 7459 7460 ParseContext::Statement stmt(pc_, StatementKind::Block); 7461 7462 // ES 13.15.7 CatchClauseEvaluation 7463 // 7464 // Step 8 means that the body of a catch block always has an additional 7465 // lexical scope. 7466 ParseContext::Scope scope(this); 7467 if (!scope.init(pc_)) { 7468 return errorResult(); 7469 } 7470 7471 // The catch parameter names cannot be redeclared inside the catch 7472 // block, so declare the name in the inner scope. 7473 if (!scope.addCatchParameters(pc_, catchParamScope)) { 7474 return errorResult(); 7475 } 7476 7477 ListNodeType list = MOZ_TRY(statementList(yieldHandling)); 7478 7479 if (!mustMatchToken( 7480 TokenKind::RightCurly, [this, openedPos](TokenKind actual) { 7481 this->reportMissingClosing(JSMSG_CURLY_AFTER_CATCH, 7482 JSMSG_CURLY_OPENED, openedPos); 7483 })) { 7484 return errorResult(); 7485 } 7486 7487 // The catch parameter names are not bound in the body scope, so remove 7488 // them before generating bindings. 7489 scope.removeCatchParameters(pc_, catchParamScope); 7490 return finishLexicalScope(scope, list); 7491 } 7492 7493 template <class ParseHandler, typename Unit> 7494 typename ParseHandler::DebuggerStatementResult 7495 GeneralParser<ParseHandler, Unit>::debuggerStatement() { 7496 TokenPos p; 7497 p.begin = pos().begin; 7498 if (!matchOrInsertSemicolon()) { 7499 return errorResult(); 7500 } 7501 p.end = pos().end; 7502 7503 return handler_.newDebuggerStatement(p); 7504 } 7505 7506 static AccessorType ToAccessorType(PropertyType propType) { 7507 switch (propType) { 7508 case PropertyType::Getter: 7509 return AccessorType::Getter; 7510 case PropertyType::Setter: 7511 return AccessorType::Setter; 7512 case PropertyType::Normal: 7513 case PropertyType::Method: 7514 case PropertyType::GeneratorMethod: 7515 case PropertyType::AsyncMethod: 7516 case PropertyType::AsyncGeneratorMethod: 7517 case PropertyType::Constructor: 7518 case PropertyType::DerivedConstructor: 7519 return AccessorType::None; 7520 default: 7521 MOZ_CRASH("unexpected property type"); 7522 } 7523 } 7524 7525 #ifdef ENABLE_DECORATORS 7526 template <class ParseHandler, typename Unit> 7527 typename ParseHandler::ListNodeResult 7528 GeneralParser<ParseHandler, Unit>::decoratorList(YieldHandling yieldHandling) { 7529 ListNodeType decorators = 7530 MOZ_TRY(handler_.newList(ParseNodeKind::DecoratorList, pos())); 7531 7532 // Build a decorator list element. At each entry point to this loop we have 7533 // already consumed the |@| token 7534 TokenKind tt; 7535 for (;;) { 7536 if (!tokenStream.getToken(&tt, TokenStream::SlashIsInvalid)) { 7537 return errorResult(); 7538 } 7539 7540 Node decorator = MOZ_TRY(decoratorExpr(yieldHandling, tt)); 7541 7542 handler_.addList(decorators, decorator); 7543 7544 if (!tokenStream.getToken(&tt)) { 7545 return errorResult(); 7546 } 7547 if (tt != TokenKind::At) { 7548 anyChars.ungetToken(); 7549 break; 7550 } 7551 } 7552 return decorators; 7553 } 7554 #endif 7555 7556 template <class ParseHandler, typename Unit> 7557 bool GeneralParser<ParseHandler, Unit>::classMember( 7558 YieldHandling yieldHandling, const ParseContext::ClassStatement& classStmt, 7559 TaggedParserAtomIndex className, uint32_t classStartOffset, 7560 HasHeritage hasHeritage, ClassInitializedMembers& classInitializedMembers, 7561 ListNodeType& classMembers, bool* done) { 7562 *done = false; 7563 7564 TokenKind tt; 7565 if (!tokenStream.getToken(&tt, TokenStream::SlashIsInvalid)) { 7566 return false; 7567 } 7568 if (tt == TokenKind::RightCurly) { 7569 *done = true; 7570 return true; 7571 } 7572 7573 if (tt == TokenKind::Semi) { 7574 return true; 7575 } 7576 7577 #ifdef ENABLE_DECORATORS 7578 ListNodeType decorators = null(); 7579 if (tt == TokenKind::At) { 7580 MOZ_TRY_VAR_OR_RETURN(decorators, decoratorList(yieldHandling), false); 7581 7582 if (!tokenStream.getToken(&tt, TokenStream::SlashIsInvalid)) { 7583 return false; 7584 } 7585 } 7586 #endif 7587 7588 bool isStatic = false; 7589 if (tt == TokenKind::Static) { 7590 if (!tokenStream.peekToken(&tt)) { 7591 return false; 7592 } 7593 7594 if (tt == TokenKind::LeftCurly) { 7595 /* Parsing static class block: static { ... } */ 7596 FunctionNodeType staticBlockBody; 7597 MOZ_TRY_VAR_OR_RETURN(staticBlockBody, 7598 staticClassBlock(classInitializedMembers), false); 7599 7600 StaticClassBlockType classBlock; 7601 MOZ_TRY_VAR_OR_RETURN( 7602 classBlock, handler_.newStaticClassBlock(staticBlockBody), false); 7603 7604 return handler_.addClassMemberDefinition(classMembers, classBlock); 7605 } 7606 7607 if (tt != TokenKind::LeftParen && tt != TokenKind::Assign && 7608 tt != TokenKind::Semi && tt != TokenKind::RightCurly) { 7609 isStatic = true; 7610 } else { 7611 anyChars.ungetToken(); 7612 } 7613 } else { 7614 anyChars.ungetToken(); 7615 } 7616 7617 uint32_t propNameOffset; 7618 if (!tokenStream.peekOffset(&propNameOffset, TokenStream::SlashIsInvalid)) { 7619 return false; 7620 } 7621 7622 TaggedParserAtomIndex propAtom; 7623 PropertyType propType; 7624 Node propName; 7625 MOZ_TRY_VAR_OR_RETURN( 7626 propName, 7627 propertyOrMethodName(yieldHandling, PropertyNameInClass, 7628 /* maybeDecl = */ Nothing(), classMembers, &propType, 7629 &propAtom), 7630 false); 7631 7632 if (propType == PropertyType::Field || 7633 propType == PropertyType::FieldWithAccessor) { 7634 if (isStatic) { 7635 if (propAtom == TaggedParserAtomIndex::WellKnown::prototype()) { 7636 errorAt(propNameOffset, JSMSG_CLASS_STATIC_PROTO); 7637 return false; 7638 } 7639 } 7640 7641 if (propAtom == TaggedParserAtomIndex::WellKnown::constructor()) { 7642 errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); 7643 return false; 7644 } 7645 7646 if (handler_.isPrivateName(propName)) { 7647 if (propAtom == TaggedParserAtomIndex::WellKnown::hash_constructor_()) { 7648 errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); 7649 return false; 7650 } 7651 7652 auto privateName = propAtom; 7653 if (!noteDeclaredPrivateName( 7654 propName, privateName, propType, 7655 isStatic ? FieldPlacement::Static : FieldPlacement::Instance, 7656 pos())) { 7657 return false; 7658 } 7659 } 7660 7661 #ifdef ENABLE_DECORATORS 7662 ClassMethodType accessorGetterNode = null(); 7663 ClassMethodType accessorSetterNode = null(); 7664 if (propType == PropertyType::FieldWithAccessor) { 7665 // Decorators Proposal 7666 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-runtime-semantics-classfielddefinitionevaluation 7667 // 7668 // FieldDefinition : accessor ClassElementName Initializeropt 7669 // 7670 // Step 1. Let name be the result of evaluating ClassElementName. 7671 // ... 7672 // Step 3. Let privateStateDesc be the string-concatenation of name 7673 // and " accessor storage". 7674 StringBuilder privateStateDesc(fc_); 7675 if (!privateStateDesc.append(this->parserAtoms(), propAtom)) { 7676 return false; 7677 } 7678 if (!privateStateDesc.append(" accessor storage")) { 7679 return false; 7680 } 7681 // Step 4. Let privateStateName be a new Private Name whose 7682 // [[Description]] value is privateStateDesc. 7683 TokenPos propNamePos(propNameOffset, pos().end); 7684 auto privateStateName = 7685 privateStateDesc.finishParserAtom(this->parserAtoms(), fc_); 7686 if (!noteDeclaredPrivateName( 7687 propName, privateStateName, propType, 7688 isStatic ? FieldPlacement::Static : FieldPlacement::Instance, 7689 propNamePos)) { 7690 return false; 7691 } 7692 7693 // Step 5. Let getter be MakeAutoAccessorGetter(homeObject, name, 7694 // privateStateName). 7695 MOZ_TRY_VAR_OR_RETURN( 7696 accessorGetterNode, 7697 synthesizeAccessor(propName, propNamePos, propAtom, privateStateName, 7698 isStatic, FunctionSyntaxKind::Getter, 7699 classInitializedMembers), 7700 false); 7701 7702 // If the accessor is not decorated or is a non-static private field, 7703 // add it to the class here. Otherwise, we'll handle this when the 7704 // decorators are called. We don't need to keep a reference to the node 7705 // after this except for non-static private accessors. Please see the 7706 // comment in the definition of ClassField for details. 7707 bool addAccessorImmediately = 7708 !decorators || (!isStatic && handler_.isPrivateName(propName)); 7709 if (addAccessorImmediately) { 7710 if (!handler_.addClassMemberDefinition(classMembers, 7711 accessorGetterNode)) { 7712 return false; 7713 } 7714 if (!handler_.isPrivateName(propName)) { 7715 accessorGetterNode = null(); 7716 } 7717 } 7718 7719 // Step 6. Let setter be MakeAutoAccessorSetter(homeObject, name, 7720 // privateStateName). 7721 MOZ_TRY_VAR_OR_RETURN( 7722 accessorSetterNode, 7723 synthesizeAccessor(propName, propNamePos, propAtom, privateStateName, 7724 isStatic, FunctionSyntaxKind::Setter, 7725 classInitializedMembers), 7726 false); 7727 7728 if (addAccessorImmediately) { 7729 if (!handler_.addClassMemberDefinition(classMembers, 7730 accessorSetterNode)) { 7731 return false; 7732 } 7733 if (!handler_.isPrivateName(propName)) { 7734 accessorSetterNode = null(); 7735 } 7736 } 7737 7738 // Step 10. Return ClassElementDefinition Record { [[Key]]: name, 7739 // [[Kind]]: accessor, [[Get]]: getter, [[Set]]: setter, 7740 // [[BackingStorageKey]]: privateStateName, [[Initializers]]: 7741 // initializers, [[Decorators]]: empty }. 7742 MOZ_TRY_VAR_OR_RETURN( 7743 propName, handler_.newPrivateName(privateStateName, pos()), false); 7744 propAtom = privateStateName; 7745 // We maintain `decorators` here to perform this step at the same time: 7746 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-static-semantics-classelementevaluation 7747 // 4. Set fieldDefinition.[[Decorators]] to decorators. 7748 } 7749 #endif 7750 if (isStatic) { 7751 classInitializedMembers.staticFields++; 7752 } else { 7753 classInitializedMembers.instanceFields++; 7754 #ifdef ENABLE_DECORATORS 7755 if (decorators) { 7756 classInitializedMembers.hasInstanceDecorators = true; 7757 } 7758 #endif 7759 } 7760 7761 TokenPos propNamePos(propNameOffset, pos().end); 7762 FunctionNodeType initializer; 7763 MOZ_TRY_VAR_OR_RETURN( 7764 initializer, 7765 fieldInitializerOpt(propNamePos, propName, propAtom, 7766 classInitializedMembers, isStatic, hasHeritage), 7767 false); 7768 7769 if (!matchOrInsertSemicolon(TokenStream::SlashIsInvalid)) { 7770 return false; 7771 } 7772 7773 ClassFieldType field; 7774 MOZ_TRY_VAR_OR_RETURN(field, 7775 handler_.newClassFieldDefinition( 7776 propName, initializer, isStatic 7777 #ifdef ENABLE_DECORATORS 7778 , 7779 decorators, accessorGetterNode, accessorSetterNode 7780 #endif 7781 ), 7782 false); 7783 7784 return handler_.addClassMemberDefinition(classMembers, field); 7785 } 7786 7787 if (propType != PropertyType::Getter && propType != PropertyType::Setter && 7788 propType != PropertyType::Method && 7789 propType != PropertyType::GeneratorMethod && 7790 propType != PropertyType::AsyncMethod && 7791 propType != PropertyType::AsyncGeneratorMethod) { 7792 errorAt(propNameOffset, JSMSG_BAD_CLASS_MEMBER_DEF); 7793 return false; 7794 } 7795 7796 bool isConstructor = 7797 !isStatic && propAtom == TaggedParserAtomIndex::WellKnown::constructor(); 7798 if (isConstructor) { 7799 if (propType != PropertyType::Method) { 7800 errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); 7801 return false; 7802 } 7803 if (classStmt.constructorBox) { 7804 errorAt(propNameOffset, JSMSG_DUPLICATE_CONSTRUCTOR); 7805 return false; 7806 } 7807 propType = hasHeritage == HasHeritage::Yes 7808 ? PropertyType::DerivedConstructor 7809 : PropertyType::Constructor; 7810 } else if (isStatic && 7811 propAtom == TaggedParserAtomIndex::WellKnown::prototype()) { 7812 errorAt(propNameOffset, JSMSG_CLASS_STATIC_PROTO); 7813 return false; 7814 } 7815 7816 TaggedParserAtomIndex funName; 7817 switch (propType) { 7818 case PropertyType::Getter: 7819 case PropertyType::Setter: { 7820 bool hasStaticName = 7821 !anyChars.isCurrentTokenType(TokenKind::RightBracket) && propAtom; 7822 if (hasStaticName) { 7823 funName = prefixAccessorName(propType, propAtom); 7824 if (!funName) { 7825 return false; 7826 } 7827 } 7828 break; 7829 } 7830 case PropertyType::Constructor: 7831 case PropertyType::DerivedConstructor: 7832 funName = className; 7833 break; 7834 default: 7835 if (!anyChars.isCurrentTokenType(TokenKind::RightBracket)) { 7836 funName = propAtom; 7837 } 7838 } 7839 7840 // When |super()| is invoked, we search for the nearest scope containing 7841 // |.initializers| to initialize the class fields. This set-up precludes 7842 // declaring |.initializers| in the class scope, because in some syntactic 7843 // contexts |super()| can appear nested in a class, while actually belonging 7844 // to an outer class definition. 7845 // 7846 // Example: 7847 // class Outer extends Base { 7848 // field = 1; 7849 // constructor() { 7850 // class Inner { 7851 // field = 2; 7852 // 7853 // // The super() call in the computed property name mustn't access 7854 // // Inner's |.initializers| array, but instead Outer's. 7855 // [super()]() {} 7856 // } 7857 // } 7858 // } 7859 Maybe<ParseContext::Scope> dotInitializersScope; 7860 if (isConstructor && !options().selfHostingMode) { 7861 dotInitializersScope.emplace(this); 7862 if (!dotInitializersScope->init(pc_)) { 7863 return false; 7864 } 7865 7866 if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::dot_initializers_(), 7867 DeclarationKind::Let, pos())) { 7868 return false; 7869 } 7870 7871 #ifdef ENABLE_DECORATORS 7872 if (!noteDeclaredName( 7873 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_(), 7874 DeclarationKind::Let, pos())) { 7875 return false; 7876 } 7877 #endif 7878 } 7879 7880 // Calling toString on constructors need to return the source text for 7881 // the entire class. The end offset is unknown at this point in 7882 // parsing and will be amended when class parsing finishes below. 7883 FunctionNodeType funNode; 7884 MOZ_TRY_VAR_OR_RETURN( 7885 funNode, 7886 methodDefinition(isConstructor ? classStartOffset : propNameOffset, 7887 propType, funName), 7888 false); 7889 7890 AccessorType atype = ToAccessorType(propType); 7891 7892 Maybe<FunctionNodeType> initializerIfPrivate = Nothing(); 7893 if (handler_.isPrivateName(propName)) { 7894 if (propAtom == TaggedParserAtomIndex::WellKnown::hash_constructor_()) { 7895 // #constructor is an invalid private name. 7896 errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); 7897 return false; 7898 } 7899 7900 TaggedParserAtomIndex privateName = propAtom; 7901 if (!noteDeclaredPrivateName( 7902 propName, privateName, propType, 7903 isStatic ? FieldPlacement::Static : FieldPlacement::Instance, 7904 pos())) { 7905 return false; 7906 } 7907 7908 // Private non-static methods are stored in the class body environment. 7909 // Private non-static accessors are stamped onto every instance using 7910 // initializers. Private static methods are stamped onto the constructor 7911 // during class evaluation; see BytecodeEmitter::emitPropertyList. 7912 if (!isStatic) { 7913 if (atype == AccessorType::Getter || atype == AccessorType::Setter) { 7914 classInitializedMembers.privateAccessors++; 7915 TokenPos propNamePos(propNameOffset, pos().end); 7916 FunctionNodeType initializerNode; 7917 MOZ_TRY_VAR_OR_RETURN( 7918 initializerNode, 7919 synthesizePrivateMethodInitializer(propAtom, atype, propNamePos), 7920 false); 7921 initializerIfPrivate = Some(initializerNode); 7922 } else { 7923 MOZ_ASSERT(atype == AccessorType::None); 7924 classInitializedMembers.privateMethods++; 7925 } 7926 } 7927 } 7928 7929 #ifdef ENABLE_DECORATORS 7930 if (decorators) { 7931 classInitializedMembers.hasInstanceDecorators = true; 7932 } 7933 #endif 7934 7935 Node method; 7936 MOZ_TRY_VAR_OR_RETURN( 7937 method, 7938 handler_.newClassMethodDefinition(propName, funNode, atype, isStatic, 7939 initializerIfPrivate 7940 #ifdef ENABLE_DECORATORS 7941 , 7942 decorators 7943 #endif 7944 ), 7945 false); 7946 7947 if (dotInitializersScope.isSome()) { 7948 MOZ_TRY_VAR_OR_RETURN( 7949 method, finishLexicalScope(*dotInitializersScope, method), false); 7950 dotInitializersScope.reset(); 7951 } 7952 7953 return handler_.addClassMemberDefinition(classMembers, method); 7954 } 7955 7956 template <class ParseHandler, typename Unit> 7957 bool GeneralParser<ParseHandler, Unit>::finishClassConstructor( 7958 const ParseContext::ClassStatement& classStmt, 7959 TaggedParserAtomIndex className, HasHeritage hasHeritage, 7960 uint32_t classStartOffset, uint32_t classEndOffset, 7961 const ClassInitializedMembers& classInitializedMembers, 7962 ListNodeType& classMembers) { 7963 if (classStmt.constructorBox == nullptr) { 7964 MOZ_ASSERT(!options().selfHostingMode); 7965 // Unconditionally create the scope here, because it's always the 7966 // constructor. 7967 ParseContext::Scope dotInitializersScope(this); 7968 if (!dotInitializersScope.init(pc_)) { 7969 return false; 7970 } 7971 7972 if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::dot_initializers_(), 7973 DeclarationKind::Let, pos())) { 7974 return false; 7975 } 7976 7977 #ifdef ENABLE_DECORATORS 7978 if (!noteDeclaredName( 7979 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_(), 7980 DeclarationKind::Let, pos(), ClosedOver::Yes)) { 7981 return false; 7982 } 7983 #endif 7984 7985 // synthesizeConstructor assigns to classStmt.constructorBox 7986 TokenPos synthesizedBodyPos(classStartOffset, classEndOffset); 7987 FunctionNodeType synthesizedCtor; 7988 MOZ_TRY_VAR_OR_RETURN( 7989 synthesizedCtor, 7990 synthesizeConstructor(className, synthesizedBodyPos, hasHeritage), 7991 false); 7992 7993 // Note: the *function* has the name of the class, but the *property* 7994 // containing the function has the name "constructor" 7995 Node constructorNameNode; 7996 MOZ_TRY_VAR_OR_RETURN( 7997 constructorNameNode, 7998 handler_.newObjectLiteralPropertyName( 7999 TaggedParserAtomIndex::WellKnown::constructor(), pos()), 8000 false); 8001 ClassMethodType method; 8002 MOZ_TRY_VAR_OR_RETURN(method, 8003 handler_.newDefaultClassConstructor( 8004 constructorNameNode, synthesizedCtor), 8005 false); 8006 LexicalScopeNodeType scope; 8007 MOZ_TRY_VAR_OR_RETURN( 8008 scope, finishLexicalScope(dotInitializersScope, method), false); 8009 if (!handler_.addClassMemberDefinition(classMembers, scope)) { 8010 return false; 8011 } 8012 } 8013 8014 MOZ_ASSERT(classStmt.constructorBox); 8015 FunctionBox* ctorbox = classStmt.constructorBox; 8016 8017 // Amend the toStringEnd offset for the constructor now that we've 8018 // finished parsing the class. 8019 ctorbox->setCtorToStringEnd(classEndOffset); 8020 8021 size_t numMemberInitializers = classInitializedMembers.privateAccessors + 8022 classInitializedMembers.instanceFields; 8023 bool hasPrivateBrand = classInitializedMembers.hasPrivateBrand(); 8024 if (hasPrivateBrand || numMemberInitializers > 0) { 8025 // Now that we have full set of initializers, update the constructor. 8026 MemberInitializers initializers( 8027 hasPrivateBrand, 8028 #ifdef ENABLE_DECORATORS 8029 classInitializedMembers.hasInstanceDecorators, 8030 #endif 8031 numMemberInitializers); 8032 ctorbox->setMemberInitializers(initializers); 8033 8034 // Field initialization need access to `this`. 8035 ctorbox->setCtorFunctionHasThisBinding(); 8036 } 8037 8038 return true; 8039 } 8040 8041 template <class ParseHandler, typename Unit> 8042 typename ParseHandler::ClassNodeResult 8043 GeneralParser<ParseHandler, Unit>::classDefinition( 8044 YieldHandling yieldHandling, ClassContext classContext, 8045 DefaultHandling defaultHandling) { 8046 #ifdef ENABLE_DECORATORS 8047 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::At) || 8048 anyChars.isCurrentTokenType(TokenKind::Class)); 8049 8050 ListNodeType decorators = null(); 8051 FunctionNodeType addInitializerFunction = null(); 8052 if (anyChars.isCurrentTokenType(TokenKind::At)) { 8053 decorators = MOZ_TRY(decoratorList(yieldHandling)); 8054 TokenKind next; 8055 if (!tokenStream.getToken(&next)) { 8056 return errorResult(); 8057 } 8058 if (next != TokenKind::Class) { 8059 error(JSMSG_CLASS_EXPECTED); 8060 return errorResult(); 8061 } 8062 } 8063 #else 8064 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class)); 8065 #endif 8066 8067 uint32_t classStartOffset = pos().begin; 8068 bool savedStrictness = setLocalStrictMode(true); 8069 8070 // Classes are quite broken in self-hosted code. 8071 if (options().selfHostingMode) { 8072 error(JSMSG_SELFHOSTED_CLASS); 8073 return errorResult(); 8074 } 8075 8076 TokenKind tt; 8077 if (!tokenStream.getToken(&tt)) { 8078 return errorResult(); 8079 } 8080 8081 TaggedParserAtomIndex className; 8082 if (TokenKindIsPossibleIdentifier(tt)) { 8083 className = bindingIdentifier(yieldHandling); 8084 if (!className) { 8085 return errorResult(); 8086 } 8087 } else if (classContext == ClassStatement) { 8088 if (defaultHandling == AllowDefaultName) { 8089 className = TaggedParserAtomIndex::WellKnown::default_(); 8090 anyChars.ungetToken(); 8091 } else { 8092 // Class statements must have a bound name 8093 error(JSMSG_UNNAMED_CLASS_STMT); 8094 return errorResult(); 8095 } 8096 } else { 8097 // Make sure to put it back, whatever it was 8098 anyChars.ungetToken(); 8099 } 8100 8101 // Because the binding definitions keep track of their blockId, we need to 8102 // create at least the inner binding later. Keep track of the name's 8103 // position in order to provide it for the nodes created later. 8104 TokenPos namePos = pos(); 8105 8106 auto isClass = [](ParseContext::Statement* stmt) { 8107 return stmt->kind() == StatementKind::Class; 8108 }; 8109 8110 bool isInClass = pc_->sc()->inClass() || pc_->findInnermostStatement(isClass); 8111 8112 // Push a ParseContext::ClassStatement to keep track of the constructor 8113 // funbox. 8114 ParseContext::ClassStatement classStmt(pc_); 8115 8116 NameNodeType innerName; 8117 Node nameNode = null(); 8118 Node classHeritage = null(); 8119 LexicalScopeNodeType classBlock = null(); 8120 ClassBodyScopeNodeType classBodyBlock = null(); 8121 uint32_t classEndOffset; 8122 { 8123 // A named class creates a new lexical scope with a const binding of the 8124 // class name for the "inner name". 8125 ParseContext::Statement innerScopeStmt(pc_, StatementKind::Block); 8126 ParseContext::Scope innerScope(this); 8127 if (!innerScope.init(pc_)) { 8128 return errorResult(); 8129 } 8130 8131 bool hasHeritageBool; 8132 if (!tokenStream.matchToken(&hasHeritageBool, TokenKind::Extends)) { 8133 return errorResult(); 8134 } 8135 HasHeritage hasHeritage = 8136 hasHeritageBool ? HasHeritage::Yes : HasHeritage::No; 8137 if (hasHeritage == HasHeritage::Yes) { 8138 if (!tokenStream.getToken(&tt)) { 8139 return errorResult(); 8140 } 8141 classHeritage = 8142 MOZ_TRY(optionalExpr(yieldHandling, TripledotProhibited, tt)); 8143 } 8144 8145 if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CLASS)) { 8146 return errorResult(); 8147 } 8148 8149 { 8150 ParseContext::Statement bodyScopeStmt(pc_, StatementKind::Block); 8151 ParseContext::Scope bodyScope(this); 8152 if (!bodyScope.init(pc_)) { 8153 return errorResult(); 8154 } 8155 8156 ListNodeType classMembers = 8157 MOZ_TRY(handler_.newClassMemberList(pos().begin)); 8158 8159 ClassInitializedMembers classInitializedMembers{}; 8160 for (;;) { 8161 bool done; 8162 if (!classMember(yieldHandling, classStmt, className, classStartOffset, 8163 hasHeritage, classInitializedMembers, classMembers, 8164 &done)) { 8165 return errorResult(); 8166 } 8167 if (done) { 8168 break; 8169 } 8170 } 8171 #ifdef ENABLE_DECORATORS 8172 if (classInitializedMembers.hasInstanceDecorators) { 8173 addInitializerFunction = MOZ_TRY(synthesizeAddInitializerFunction( 8174 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_(), 8175 yieldHandling)); 8176 } 8177 #endif 8178 8179 if (classInitializedMembers.privateMethods + 8180 classInitializedMembers.privateAccessors > 8181 0) { 8182 // We declare `.privateBrand` as ClosedOver because the constructor 8183 // always uses it, even a default constructor. We could equivalently 8184 // `noteUsedName` when parsing the constructor, except that at that 8185 // time, we don't necessarily know if the class has a private brand. 8186 if (!noteDeclaredName( 8187 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(), 8188 DeclarationKind::Synthetic, namePos, ClosedOver::Yes)) { 8189 return errorResult(); 8190 } 8191 } 8192 8193 if (classInitializedMembers.instanceFieldKeys > 0) { 8194 if (!noteDeclaredName( 8195 TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(), 8196 DeclarationKind::Synthetic, namePos)) { 8197 return errorResult(); 8198 } 8199 } 8200 8201 if (classInitializedMembers.staticFields > 0) { 8202 if (!noteDeclaredName( 8203 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_(), 8204 DeclarationKind::Synthetic, namePos)) { 8205 return errorResult(); 8206 } 8207 } 8208 8209 if (classInitializedMembers.staticFieldKeys > 0) { 8210 if (!noteDeclaredName( 8211 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_(), 8212 DeclarationKind::Synthetic, namePos)) { 8213 return errorResult(); 8214 } 8215 } 8216 8217 classEndOffset = pos().end; 8218 if (!finishClassConstructor(classStmt, className, hasHeritage, 8219 classStartOffset, classEndOffset, 8220 classInitializedMembers, classMembers)) { 8221 return errorResult(); 8222 } 8223 8224 classBodyBlock = MOZ_TRY(finishClassBodyScope(bodyScope, classMembers)); 8225 8226 // Pop the class body scope 8227 } 8228 8229 if (className) { 8230 // The inner name is immutable. 8231 if (!noteDeclaredName(className, DeclarationKind::Const, namePos)) { 8232 return errorResult(); 8233 } 8234 8235 innerName = MOZ_TRY(newName(className, namePos)); 8236 } 8237 8238 classBlock = MOZ_TRY(finishLexicalScope(innerScope, classBodyBlock)); 8239 8240 // Pop the inner scope. 8241 } 8242 8243 if (className) { 8244 NameNodeType outerName = null(); 8245 if (classContext == ClassStatement) { 8246 // The outer name is mutable. 8247 if (!noteDeclaredName(className, DeclarationKind::Class, namePos)) { 8248 return errorResult(); 8249 } 8250 8251 outerName = MOZ_TRY(newName(className, namePos)); 8252 } 8253 8254 nameNode = MOZ_TRY(handler_.newClassNames(outerName, innerName, namePos)); 8255 } 8256 MOZ_ALWAYS_TRUE(setLocalStrictMode(savedStrictness)); 8257 // We're leaving a class definition that was not itself nested within a class 8258 if (!isInClass) { 8259 mozilla::Maybe<UnboundPrivateName> maybeUnboundName; 8260 if (!usedNames_.hasUnboundPrivateNames(fc_, maybeUnboundName)) { 8261 return errorResult(); 8262 } 8263 if (maybeUnboundName) { 8264 UniqueChars str = 8265 this->parserAtoms().toPrintableString(maybeUnboundName->atom); 8266 if (!str) { 8267 ReportOutOfMemory(this->fc_); 8268 return errorResult(); 8269 } 8270 8271 errorAt(maybeUnboundName->position.begin, JSMSG_MISSING_PRIVATE_DECL, 8272 str.get()); 8273 return errorResult(); 8274 } 8275 } 8276 8277 return handler_.newClass(nameNode, classHeritage, classBlock, 8278 #ifdef ENABLE_DECORATORS 8279 decorators, addInitializerFunction, 8280 #endif 8281 TokenPos(classStartOffset, classEndOffset)); 8282 } 8283 8284 template <class ParseHandler, typename Unit> 8285 typename ParseHandler::FunctionNodeResult 8286 GeneralParser<ParseHandler, Unit>::synthesizeConstructor( 8287 TaggedParserAtomIndex className, TokenPos synthesizedBodyPos, 8288 HasHeritage hasHeritage) { 8289 FunctionSyntaxKind functionSyntaxKind = 8290 hasHeritage == HasHeritage::Yes 8291 ? FunctionSyntaxKind::DerivedClassConstructor 8292 : FunctionSyntaxKind::ClassConstructor; 8293 8294 bool isSelfHosting = options().selfHostingMode; 8295 FunctionFlags flags = 8296 InitialFunctionFlags(functionSyntaxKind, GeneratorKind::NotGenerator, 8297 FunctionAsyncKind::SyncFunction, isSelfHosting); 8298 8299 // Create the top-level field initializer node. 8300 FunctionNodeType funNode = 8301 MOZ_TRY(handler_.newFunction(functionSyntaxKind, synthesizedBodyPos)); 8302 8303 // If we see any inner function, note it on our current context. The bytecode 8304 // emitter may eliminate the function later, but we use a conservative 8305 // definition for consistency between lazy and full parsing. 8306 pc_->sc()->setHasInnerFunctions(); 8307 8308 // When fully parsing a lazy script, we do not fully reparse its inner 8309 // functions, which are also lazy. Instead, their free variables and source 8310 // extents are recorded and may be skipped. 8311 if (handler_.reuseLazyInnerFunctions()) { 8312 if (!skipLazyInnerFunction(funNode, synthesizedBodyPos.begin, 8313 /* tryAnnexB = */ false)) { 8314 return errorResult(); 8315 } 8316 8317 return funNode; 8318 } 8319 8320 // Create the FunctionBox and link it to the function object. 8321 Directives directives(true); 8322 FunctionBox* funbox = newFunctionBox( 8323 funNode, className, flags, synthesizedBodyPos.begin, directives, 8324 GeneratorKind::NotGenerator, FunctionAsyncKind::SyncFunction); 8325 if (!funbox) { 8326 return errorResult(); 8327 } 8328 funbox->initWithEnclosingParseContext(pc_, functionSyntaxKind); 8329 setFunctionEndFromCurrentToken(funbox); 8330 8331 // Mark this function as being synthesized by the parser. This means special 8332 // handling in delazification will be used since we don't have typical 8333 // function syntax. 8334 funbox->setSyntheticFunction(); 8335 8336 // Push a SourceParseContext on to the stack. 8337 ParseContext* outerpc = pc_; 8338 SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr); 8339 if (!funpc.init()) { 8340 return errorResult(); 8341 } 8342 8343 if (!synthesizeConstructorBody(synthesizedBodyPos, hasHeritage, funNode, 8344 funbox)) { 8345 return errorResult(); 8346 } 8347 8348 if (!leaveInnerFunction(outerpc)) { 8349 return errorResult(); 8350 } 8351 8352 return funNode; 8353 } 8354 8355 template <class ParseHandler, typename Unit> 8356 bool GeneralParser<ParseHandler, Unit>::synthesizeConstructorBody( 8357 TokenPos synthesizedBodyPos, HasHeritage hasHeritage, 8358 FunctionNodeType funNode, FunctionBox* funbox) { 8359 MOZ_ASSERT(funbox->isClassConstructor()); 8360 8361 // Create a ParamsBodyNode for the parameters + body (there are no 8362 // parameters). 8363 ParamsBodyNodeType argsbody; 8364 MOZ_TRY_VAR_OR_RETURN(argsbody, handler_.newParamsBody(synthesizedBodyPos), 8365 false); 8366 handler_.setFunctionFormalParametersAndBody(funNode, argsbody); 8367 setFunctionStartAtPosition(funbox, synthesizedBodyPos); 8368 8369 if (hasHeritage == HasHeritage::Yes) { 8370 // Synthesize the equivalent to `function f(...args)` 8371 funbox->setHasRest(); 8372 if (!notePositionalFormalParameter( 8373 funNode, TaggedParserAtomIndex::WellKnown::dot_args_(), 8374 synthesizedBodyPos.begin, 8375 /* disallowDuplicateParams = */ false, 8376 /* duplicatedParam = */ nullptr)) { 8377 return false; 8378 } 8379 funbox->setArgCount(1); 8380 } else { 8381 funbox->setArgCount(0); 8382 } 8383 8384 pc_->functionScope().useAsVarScope(pc_); 8385 8386 ListNodeType stmtList; 8387 MOZ_TRY_VAR_OR_RETURN(stmtList, handler_.newStatementList(synthesizedBodyPos), 8388 false); 8389 8390 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_this_())) { 8391 return false; 8392 } 8393 8394 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) { 8395 return false; 8396 } 8397 8398 #ifdef ENABLE_DECORATORS 8399 if (!noteUsedName( 8400 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_())) { 8401 return false; 8402 } 8403 #endif 8404 8405 if (hasHeritage == HasHeritage::Yes) { 8406 // |super()| implicitly reads |new.target|. 8407 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) { 8408 return false; 8409 } 8410 8411 NameNodeType thisName; 8412 MOZ_TRY_VAR_OR_RETURN(thisName, newThisName(), false); 8413 8414 UnaryNodeType superBase; 8415 MOZ_TRY_VAR_OR_RETURN( 8416 superBase, handler_.newSuperBase(thisName, synthesizedBodyPos), false); 8417 8418 ListNodeType arguments; 8419 MOZ_TRY_VAR_OR_RETURN(arguments, handler_.newArguments(synthesizedBodyPos), 8420 false); 8421 8422 NameNodeType argsNameNode; 8423 MOZ_TRY_VAR_OR_RETURN(argsNameNode, 8424 newName(TaggedParserAtomIndex::WellKnown::dot_args_(), 8425 synthesizedBodyPos), 8426 false); 8427 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_args_())) { 8428 return false; 8429 } 8430 8431 UnaryNodeType spreadArgs; 8432 MOZ_TRY_VAR_OR_RETURN( 8433 spreadArgs, handler_.newSpread(synthesizedBodyPos.begin, argsNameNode), 8434 false); 8435 handler_.addList(arguments, spreadArgs); 8436 8437 CallNodeType superCall; 8438 MOZ_TRY_VAR_OR_RETURN( 8439 superCall, 8440 handler_.newSuperCall(superBase, arguments, /* isSpread = */ true), 8441 false); 8442 8443 BinaryNodeType setThis; 8444 MOZ_TRY_VAR_OR_RETURN(setThis, handler_.newSetThis(thisName, superCall), 8445 false); 8446 8447 UnaryNodeType exprStatement; 8448 MOZ_TRY_VAR_OR_RETURN( 8449 exprStatement, 8450 handler_.newExprStatement(setThis, synthesizedBodyPos.end), false); 8451 8452 handler_.addStatementToList(stmtList, exprStatement); 8453 } 8454 8455 bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings(); 8456 if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) { 8457 return false; 8458 } 8459 if (!pc_->declareNewTarget(usedNames_, canSkipLazyClosedOverBindings)) { 8460 return false; 8461 } 8462 8463 LexicalScopeNodeType initializerBody; 8464 MOZ_TRY_VAR_OR_RETURN( 8465 initializerBody, 8466 finishLexicalScope(pc_->varScope(), stmtList, ScopeKind::FunctionLexical), 8467 false); 8468 handler_.setBeginPosition(initializerBody, stmtList); 8469 handler_.setEndPosition(initializerBody, stmtList); 8470 8471 handler_.setFunctionBody(funNode, initializerBody); 8472 8473 return finishFunction(); 8474 } 8475 8476 template <class ParseHandler, typename Unit> 8477 typename ParseHandler::FunctionNodeResult 8478 GeneralParser<ParseHandler, Unit>::privateMethodInitializer( 8479 TokenPos propNamePos, TaggedParserAtomIndex propAtom, 8480 TaggedParserAtomIndex storedMethodAtom) { 8481 if (!abortIfSyntaxParser()) { 8482 return errorResult(); 8483 } 8484 8485 // Synthesize an initializer function that the constructor can use to stamp a 8486 // private method onto an instance object. 8487 FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::FieldInitializer; 8488 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction; 8489 GeneratorKind generatorKind = GeneratorKind::NotGenerator; 8490 bool isSelfHosting = options().selfHostingMode; 8491 FunctionFlags flags = 8492 InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting); 8493 8494 FunctionNodeType funNode = 8495 MOZ_TRY(handler_.newFunction(syntaxKind, propNamePos)); 8496 8497 Directives directives(true); 8498 FunctionBox* funbox = 8499 newFunctionBox(funNode, TaggedParserAtomIndex::null(), flags, 8500 propNamePos.begin, directives, generatorKind, asyncKind); 8501 if (!funbox) { 8502 return errorResult(); 8503 } 8504 funbox->initWithEnclosingParseContext(pc_, syntaxKind); 8505 8506 // Push a SourceParseContext on to the stack. 8507 ParseContext* outerpc = pc_; 8508 SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr); 8509 if (!funpc.init()) { 8510 return errorResult(); 8511 } 8512 pc_->functionScope().useAsVarScope(pc_); 8513 8514 // Add empty parameter list. 8515 ParamsBodyNodeType argsbody = MOZ_TRY(handler_.newParamsBody(propNamePos)); 8516 handler_.setFunctionFormalParametersAndBody(funNode, argsbody); 8517 setFunctionStartAtCurrentToken(funbox); 8518 funbox->setArgCount(0); 8519 8520 // Note both the stored private method body and it's private name as being 8521 // used in the initializer. They will be emitted into the method body in the 8522 // BCE. 8523 if (!noteUsedName(storedMethodAtom)) { 8524 return errorResult(); 8525 } 8526 MOZ_TRY(privateNameReference(propAtom)); 8527 8528 // Unlike field initializers, private method initializers are not created with 8529 // a body of synthesized AST nodes. Instead, the body is left empty and the 8530 // initializer is synthesized at the bytecode level. 8531 // See BytecodeEmitter::emitPrivateMethodInitializer. 8532 ListNodeType stmtList = MOZ_TRY(handler_.newStatementList(propNamePos)); 8533 8534 bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings(); 8535 if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) { 8536 return errorResult(); 8537 } 8538 if (!pc_->declareNewTarget(usedNames_, canSkipLazyClosedOverBindings)) { 8539 return errorResult(); 8540 } 8541 8542 LexicalScopeNodeType initializerBody = MOZ_TRY(finishLexicalScope( 8543 pc_->varScope(), stmtList, ScopeKind::FunctionLexical)); 8544 handler_.setBeginPosition(initializerBody, stmtList); 8545 handler_.setEndPosition(initializerBody, stmtList); 8546 handler_.setFunctionBody(funNode, initializerBody); 8547 8548 // Set field-initializer lambda boundary to start at property name and end 8549 // after method body. 8550 setFunctionStartAtPosition(funbox, propNamePos); 8551 setFunctionEndFromCurrentToken(funbox); 8552 8553 if (!finishFunction()) { 8554 return errorResult(); 8555 } 8556 8557 if (!leaveInnerFunction(outerpc)) { 8558 return errorResult(); 8559 } 8560 8561 return funNode; 8562 } 8563 8564 template <class ParseHandler, typename Unit> 8565 typename ParseHandler::FunctionNodeResult 8566 GeneralParser<ParseHandler, Unit>::staticClassBlock( 8567 ClassInitializedMembers& classInitializedMembers) { 8568 // Both for getting-this-done, and because this will invariably be executed, 8569 // syntax parsing should be aborted. 8570 if (!abortIfSyntaxParser()) { 8571 return errorResult(); 8572 } 8573 8574 FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::StaticClassBlock; 8575 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction; 8576 GeneratorKind generatorKind = GeneratorKind::NotGenerator; 8577 bool isSelfHosting = options().selfHostingMode; 8578 FunctionFlags flags = 8579 InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting); 8580 8581 AutoAwaitIsKeyword awaitIsKeyword(this, AwaitHandling::AwaitIsDisallowed); 8582 8583 // Create the function node for the static class body. 8584 FunctionNodeType funNode = MOZ_TRY(handler_.newFunction(syntaxKind, pos())); 8585 8586 // Create the FunctionBox and link it to the function object. 8587 Directives directives(true); 8588 FunctionBox* funbox = 8589 newFunctionBox(funNode, TaggedParserAtomIndex::null(), flags, pos().begin, 8590 directives, generatorKind, asyncKind); 8591 if (!funbox) { 8592 return errorResult(); 8593 } 8594 funbox->initWithEnclosingParseContext(pc_, syntaxKind); 8595 MOZ_ASSERT(funbox->isSyntheticFunction()); 8596 MOZ_ASSERT(!funbox->allowSuperCall()); 8597 MOZ_ASSERT(!funbox->allowArguments()); 8598 MOZ_ASSERT(!funbox->allowReturn()); 8599 8600 // Set start at `static` token. 8601 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Static)); 8602 setFunctionStartAtCurrentToken(funbox); 8603 8604 // Push a SourceParseContext on to the stack. 8605 ParseContext* outerpc = pc_; 8606 SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr); 8607 if (!funpc.init()) { 8608 return errorResult(); 8609 } 8610 8611 pc_->functionScope().useAsVarScope(pc_); 8612 8613 uint32_t start = pos().begin; 8614 8615 tokenStream.consumeKnownToken(TokenKind::LeftCurly); 8616 8617 // Static class blocks are code-generated as if they were static field 8618 // initializers, so we bump the staticFields count here, which ensures 8619 // .staticInitializers is noted as used. 8620 classInitializedMembers.staticFields++; 8621 8622 LexicalScopeNodeType body = 8623 MOZ_TRY(functionBody(InHandling::InAllowed, YieldHandling::YieldIsKeyword, 8624 syntaxKind, FunctionBodyType::StatementListBody)); 8625 8626 if (anyChars.isEOF()) { 8627 error(JSMSG_UNTERMINATED_STATIC_CLASS_BLOCK); 8628 return errorResult(); 8629 } 8630 8631 tokenStream.consumeKnownToken(TokenKind::RightCurly, 8632 TokenStream::Modifier::SlashIsRegExp); 8633 8634 TokenPos wholeBodyPos(start, pos().end); 8635 8636 handler_.setEndPosition(funNode, wholeBodyPos.end); 8637 setFunctionEndFromCurrentToken(funbox); 8638 8639 // Create a ParamsBodyNode for the parameters + body (there are no 8640 // parameters). 8641 ParamsBodyNodeType argsbody = MOZ_TRY(handler_.newParamsBody(wholeBodyPos)); 8642 8643 handler_.setFunctionFormalParametersAndBody(funNode, argsbody); 8644 funbox->setArgCount(0); 8645 8646 if (pc_->superScopeNeedsHomeObject()) { 8647 funbox->setNeedsHomeObject(); 8648 } 8649 8650 handler_.setEndPosition(body, pos().begin); 8651 handler_.setEndPosition(funNode, pos().end); 8652 handler_.setFunctionBody(funNode, body); 8653 8654 if (!finishFunction()) { 8655 return errorResult(); 8656 } 8657 8658 if (!leaveInnerFunction(outerpc)) { 8659 return errorResult(); 8660 } 8661 8662 return funNode; 8663 } 8664 8665 template <class ParseHandler, typename Unit> 8666 typename ParseHandler::FunctionNodeResult 8667 GeneralParser<ParseHandler, Unit>::fieldInitializerOpt( 8668 TokenPos propNamePos, Node propName, TaggedParserAtomIndex propAtom, 8669 ClassInitializedMembers& classInitializedMembers, bool isStatic, 8670 HasHeritage hasHeritage) { 8671 if (!abortIfSyntaxParser()) { 8672 return errorResult(); 8673 } 8674 8675 bool hasInitializer = false; 8676 if (!tokenStream.matchToken(&hasInitializer, TokenKind::Assign, 8677 TokenStream::SlashIsDiv)) { 8678 return errorResult(); 8679 } 8680 8681 FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::FieldInitializer; 8682 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction; 8683 GeneratorKind generatorKind = GeneratorKind::NotGenerator; 8684 bool isSelfHosting = options().selfHostingMode; 8685 FunctionFlags flags = 8686 InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting); 8687 8688 // Create the top-level field initializer node. 8689 FunctionNodeType funNode = 8690 MOZ_TRY(handler_.newFunction(syntaxKind, propNamePos)); 8691 8692 // Create the FunctionBox and link it to the function object. 8693 Directives directives(true); 8694 FunctionBox* funbox = 8695 newFunctionBox(funNode, TaggedParserAtomIndex::null(), flags, 8696 propNamePos.begin, directives, generatorKind, asyncKind); 8697 if (!funbox) { 8698 return errorResult(); 8699 } 8700 funbox->initWithEnclosingParseContext(pc_, syntaxKind); 8701 MOZ_ASSERT(funbox->isSyntheticFunction()); 8702 8703 // We can't use setFunctionStartAtCurrentToken because that uses pos().begin, 8704 // which is incorrect for fields without initializers (pos() points to the 8705 // field identifier) 8706 setFunctionStartAtPosition(funbox, propNamePos); 8707 8708 // Push a SourceParseContext on to the stack. 8709 ParseContext* outerpc = pc_; 8710 SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr); 8711 if (!funpc.init()) { 8712 return errorResult(); 8713 } 8714 8715 pc_->functionScope().useAsVarScope(pc_); 8716 8717 Node initializerExpr; 8718 if (hasInitializer) { 8719 // Parse the expression for the field initializer. 8720 { 8721 AutoAwaitIsKeyword awaitHandling(this, AwaitIsName); 8722 initializerExpr = 8723 MOZ_TRY(assignExpr(InAllowed, YieldIsName, TripledotProhibited)); 8724 } 8725 8726 handler_.checkAndSetIsDirectRHSAnonFunction(initializerExpr); 8727 } else { 8728 initializerExpr = MOZ_TRY(handler_.newRawUndefinedLiteral(propNamePos)); 8729 } 8730 8731 TokenPos wholeInitializerPos(propNamePos.begin, pos().end); 8732 8733 // Update the end position of the parse node. 8734 handler_.setEndPosition(funNode, wholeInitializerPos.end); 8735 setFunctionEndFromCurrentToken(funbox); 8736 8737 // Create a ParamsBodyNode for the parameters + body (there are no 8738 // parameters). 8739 ParamsBodyNodeType argsbody = 8740 MOZ_TRY(handler_.newParamsBody(wholeInitializerPos)); 8741 handler_.setFunctionFormalParametersAndBody(funNode, argsbody); 8742 funbox->setArgCount(0); 8743 8744 NameNodeType thisName = MOZ_TRY(newThisName()); 8745 8746 // Build `this.field` expression. 8747 ThisLiteralType propAssignThis = 8748 MOZ_TRY(handler_.newThisLiteral(wholeInitializerPos, thisName)); 8749 8750 Node propAssignFieldAccess; 8751 uint32_t indexValue; 8752 if (!propAtom) { 8753 // See BytecodeEmitter::emitCreateFieldKeys for an explanation of what 8754 // .fieldKeys means and its purpose. 8755 NameNodeType fieldKeysName; 8756 if (isStatic) { 8757 fieldKeysName = MOZ_TRY(newInternalDotName( 8758 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_())); 8759 } else { 8760 fieldKeysName = MOZ_TRY(newInternalDotName( 8761 TaggedParserAtomIndex::WellKnown::dot_fieldKeys_())); 8762 } 8763 if (!fieldKeysName) { 8764 return errorResult(); 8765 } 8766 8767 double fieldKeyIndex; 8768 if (isStatic) { 8769 fieldKeyIndex = classInitializedMembers.staticFieldKeys++; 8770 } else { 8771 fieldKeyIndex = classInitializedMembers.instanceFieldKeys++; 8772 } 8773 Node fieldKeyIndexNode = MOZ_TRY(handler_.newNumber( 8774 fieldKeyIndex, DecimalPoint::NoDecimal, wholeInitializerPos)); 8775 8776 Node fieldKeyValue = MOZ_TRY(handler_.newPropertyByValue( 8777 fieldKeysName, fieldKeyIndexNode, wholeInitializerPos.end)); 8778 8779 propAssignFieldAccess = MOZ_TRY(handler_.newPropertyByValue( 8780 propAssignThis, fieldKeyValue, wholeInitializerPos.end)); 8781 } else if (handler_.isPrivateName(propName)) { 8782 // It would be nice if we could tweak this here such that only if 8783 // HasHeritage::Yes we end up emitting CheckPrivateField, but otherwise we 8784 // emit InitElem -- this is an optimization to minimize HasOwn checks 8785 // in InitElem for classes without heritage. 8786 // 8787 // Further tweaking would be to ultimately only do CheckPrivateField for the 8788 // -first- field in a derived class, which would suffice to match the 8789 // semantic check. 8790 8791 NameNodeType privateNameNode = MOZ_TRY(privateNameReference(propAtom)); 8792 8793 propAssignFieldAccess = MOZ_TRY(handler_.newPrivateMemberAccess( 8794 propAssignThis, privateNameNode, wholeInitializerPos.end)); 8795 } else if (this->parserAtoms().isIndex(propAtom, &indexValue)) { 8796 propAssignFieldAccess = MOZ_TRY(handler_.newPropertyByValue( 8797 propAssignThis, propName, wholeInitializerPos.end)); 8798 } else { 8799 NameNodeType propAssignName = 8800 MOZ_TRY(handler_.newPropertyName(propAtom, wholeInitializerPos)); 8801 8802 propAssignFieldAccess = 8803 MOZ_TRY(handler_.newPropertyAccess(propAssignThis, propAssignName)); 8804 } 8805 8806 // Synthesize an property init. 8807 BinaryNodeType initializerPropInit = 8808 MOZ_TRY(handler_.newInitExpr(propAssignFieldAccess, initializerExpr)); 8809 8810 UnaryNodeType exprStatement = MOZ_TRY( 8811 handler_.newExprStatement(initializerPropInit, wholeInitializerPos.end)); 8812 8813 ListNodeType statementList = 8814 MOZ_TRY(handler_.newStatementList(wholeInitializerPos)); 8815 handler_.addStatementToList(statementList, exprStatement); 8816 8817 bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings(); 8818 if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) { 8819 return errorResult(); 8820 } 8821 if (!pc_->declareNewTarget(usedNames_, canSkipLazyClosedOverBindings)) { 8822 return errorResult(); 8823 } 8824 8825 // Set the function's body to the field assignment. 8826 LexicalScopeNodeType initializerBody = MOZ_TRY(finishLexicalScope( 8827 pc_->varScope(), statementList, ScopeKind::FunctionLexical)); 8828 8829 handler_.setFunctionBody(funNode, initializerBody); 8830 8831 if (pc_->superScopeNeedsHomeObject()) { 8832 funbox->setNeedsHomeObject(); 8833 } 8834 8835 if (!finishFunction()) { 8836 return errorResult(); 8837 } 8838 8839 if (!leaveInnerFunction(outerpc)) { 8840 return errorResult(); 8841 } 8842 8843 return funNode; 8844 } 8845 8846 template <class ParseHandler, typename Unit> 8847 typename ParseHandler::FunctionNodeResult 8848 GeneralParser<ParseHandler, Unit>::synthesizePrivateMethodInitializer( 8849 TaggedParserAtomIndex propAtom, AccessorType accessorType, 8850 TokenPos propNamePos) { 8851 if (!abortIfSyntaxParser()) { 8852 return errorResult(); 8853 } 8854 8855 // Synthesize a name for the lexical variable that will store the 8856 // accessor body. 8857 StringBuilder storedMethodName(fc_); 8858 if (!storedMethodName.append(this->parserAtoms(), propAtom)) { 8859 return errorResult(); 8860 } 8861 if (!storedMethodName.append( 8862 accessorType == AccessorType::Getter ? ".getter" : ".setter")) { 8863 return errorResult(); 8864 } 8865 auto storedMethodProp = 8866 storedMethodName.finishParserAtom(this->parserAtoms(), fc_); 8867 if (!storedMethodProp) { 8868 return errorResult(); 8869 } 8870 if (!noteDeclaredName(storedMethodProp, DeclarationKind::Synthetic, pos())) { 8871 return errorResult(); 8872 } 8873 8874 return privateMethodInitializer(propNamePos, propAtom, storedMethodProp); 8875 } 8876 8877 #ifdef ENABLE_DECORATORS 8878 template <class ParseHandler, typename Unit> 8879 typename ParseHandler::FunctionNodeResult 8880 GeneralParser<ParseHandler, Unit>::synthesizeAddInitializerFunction( 8881 TaggedParserAtomIndex initializers, YieldHandling yieldHandling) { 8882 if (!abortIfSyntaxParser()) { 8883 return errorResult(); 8884 } 8885 8886 // TODO: Add support for static and class extra initializers, see bug 1868220 8887 // and bug 1868221. 8888 MOZ_ASSERT( 8889 initializers == 8890 TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_()); 8891 8892 TokenPos propNamePos = pos(); 8893 8894 // Synthesize an addInitializer function that can be used to append to 8895 // .initializers 8896 FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Statement; 8897 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction; 8898 GeneratorKind generatorKind = GeneratorKind::NotGenerator; 8899 bool isSelfHosting = options().selfHostingMode; 8900 FunctionFlags flags = 8901 InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting); 8902 8903 FunctionNodeType funNode = 8904 MOZ_TRY(handler_.newFunction(syntaxKind, propNamePos)); 8905 8906 Directives directives(true); 8907 FunctionBox* funbox = 8908 newFunctionBox(funNode, TaggedParserAtomIndex::null(), flags, 8909 propNamePos.begin, directives, generatorKind, asyncKind); 8910 if (!funbox) { 8911 return errorResult(); 8912 } 8913 funbox->initWithEnclosingParseContext(pc_, syntaxKind); 8914 8915 ParseContext* outerpc = pc_; 8916 SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr); 8917 if (!funpc.init()) { 8918 return errorResult(); 8919 } 8920 pc_->functionScope().useAsVarScope(pc_); 8921 8922 // Takes a single parameter, `initializer`. 8923 ParamsBodyNodeType params = MOZ_TRY(handler_.newParamsBody(propNamePos)); 8924 8925 handler_.setFunctionFormalParametersAndBody(funNode, params); 8926 8927 constexpr bool disallowDuplicateParams = true; 8928 bool duplicatedParam = false; 8929 if (!notePositionalFormalParameter( 8930 funNode, TaggedParserAtomIndex::WellKnown::initializer(), pos().begin, 8931 disallowDuplicateParams, &duplicatedParam)) { 8932 return null(); 8933 } 8934 MOZ_ASSERT(!duplicatedParam); 8935 MOZ_ASSERT(pc_->positionalFormalParameterNames().length() == 1); 8936 8937 funbox->setLength(1); 8938 funbox->setArgCount(1); 8939 setFunctionStartAtCurrentToken(funbox); 8940 8941 // Like private method initializers, the addInitializer method is not created 8942 // with a body of synthesized AST nodes. Instead, the body is left empty and 8943 // the initializer is synthesized at the bytecode level. See 8944 // DecoratorEmitter::emitCreateAddInitializerFunction. 8945 ListNodeType stmtList = MOZ_TRY(handler_.newStatementList(propNamePos)); 8946 8947 if (!noteUsedName(initializers)) { 8948 return null(); 8949 } 8950 8951 bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings(); 8952 if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) { 8953 return null(); 8954 } 8955 if (!pc_->declareNewTarget(usedNames_, canSkipLazyClosedOverBindings)) { 8956 return null(); 8957 } 8958 8959 LexicalScopeNodeType addInitializerBody = MOZ_TRY(finishLexicalScope( 8960 pc_->varScope(), stmtList, ScopeKind::FunctionLexical)); 8961 handler_.setBeginPosition(addInitializerBody, stmtList); 8962 handler_.setEndPosition(addInitializerBody, stmtList); 8963 handler_.setFunctionBody(funNode, addInitializerBody); 8964 8965 // Set field-initializer lambda boundary to start at property name and end 8966 // after method body. 8967 setFunctionStartAtPosition(funbox, propNamePos); 8968 setFunctionEndFromCurrentToken(funbox); 8969 8970 if (!finishFunction()) { 8971 return errorResult(); 8972 } 8973 8974 if (!leaveInnerFunction(outerpc)) { 8975 return errorResult(); 8976 } 8977 8978 return funNode; 8979 } 8980 8981 template <class ParseHandler, typename Unit> 8982 typename ParseHandler::ClassMethodResult 8983 GeneralParser<ParseHandler, Unit>::synthesizeAccessor( 8984 Node propName, TokenPos propNamePos, TaggedParserAtomIndex propAtom, 8985 TaggedParserAtomIndex privateStateNameAtom, bool isStatic, 8986 FunctionSyntaxKind syntaxKind, 8987 ClassInitializedMembers& classInitializedMembers) { 8988 // Decorators Proposal 8989 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter 8990 // The abstract operation MakeAutoAccessorGetter takes arguments homeObject 8991 // (an Object), name (a property key or Private Name), and privateStateName (a 8992 // Private Name) and returns a function object. 8993 // 8994 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter 8995 // The abstract operation MakeAutoAccessorSetter takes arguments homeObject 8996 // (an Object), name (a property key or Private Name), and privateStateName (a 8997 // Private Name) and returns a function object. 8998 if (!abortIfSyntaxParser()) { 8999 return errorResult(); 9000 } 9001 9002 AccessorType accessorType = syntaxKind == FunctionSyntaxKind::Getter 9003 ? AccessorType::Getter 9004 : AccessorType::Setter; 9005 9006 mozilla::Maybe<FunctionNodeType> initializerIfPrivate = Nothing(); 9007 if (!isStatic && handler_.isPrivateName(propName)) { 9008 classInitializedMembers.privateAccessors++; 9009 FunctionNodeType initializerNode = 9010 MOZ_TRY(synthesizePrivateMethodInitializer(propAtom, accessorType, 9011 propNamePos)); 9012 initializerIfPrivate = Some(initializerNode); 9013 handler_.setPrivateNameKind(propName, PrivateNameKind::GetterSetter); 9014 } 9015 9016 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter 9017 // 2. Let getter be CreateBuiltinFunction(getterClosure, 0, "get", « »). 9018 // 9019 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter 9020 // 2. Let setter be CreateBuiltinFunction(setterClosure, 1, "set", « »). 9021 StringBuilder storedMethodName(fc_); 9022 if (!storedMethodName.append(accessorType == AccessorType::Getter ? "get" 9023 : "set")) { 9024 return errorResult(); 9025 } 9026 TaggedParserAtomIndex funNameAtom = 9027 storedMethodName.finishParserAtom(this->parserAtoms(), fc_); 9028 9029 FunctionNodeType funNode = MOZ_TRY(synthesizeAccessorBody( 9030 funNameAtom, propNamePos, privateStateNameAtom, syntaxKind)); 9031 9032 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter 9033 // 3. Perform MakeMethod(getter, homeObject). 9034 // 4. Return getter. 9035 // 9036 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter 9037 // 3. Perform MakeMethod(setter, homeObject). 9038 // 4. Return setter. 9039 return handler_.newClassMethodDefinition( 9040 propName, funNode, accessorType, isStatic, initializerIfPrivate, null()); 9041 } 9042 9043 template <class ParseHandler, typename Unit> 9044 typename ParseHandler::FunctionNodeResult 9045 GeneralParser<ParseHandler, Unit>::synthesizeAccessorBody( 9046 TaggedParserAtomIndex funNameAtom, TokenPos propNamePos, 9047 TaggedParserAtomIndex propNameAtom, FunctionSyntaxKind syntaxKind) { 9048 if (!abortIfSyntaxParser()) { 9049 return errorResult(); 9050 } 9051 9052 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction; 9053 GeneratorKind generatorKind = GeneratorKind::NotGenerator; 9054 bool isSelfHosting = options().selfHostingMode; 9055 FunctionFlags flags = 9056 InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting); 9057 9058 // Create the top-level function node. 9059 FunctionNodeType funNode = 9060 MOZ_TRY(handler_.newFunction(syntaxKind, propNamePos)); 9061 9062 // Create the FunctionBox and link it to the function object. 9063 Directives directives(true); 9064 FunctionBox* funbox = 9065 newFunctionBox(funNode, funNameAtom, flags, propNamePos.begin, directives, 9066 generatorKind, asyncKind); 9067 if (!funbox) { 9068 return errorResult(); 9069 } 9070 funbox->initWithEnclosingParseContext(pc_, syntaxKind); 9071 funbox->setSyntheticFunction(); 9072 9073 // Push a SourceParseContext on to the stack. 9074 ParseContext* outerpc = pc_; 9075 SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr); 9076 if (!funpc.init()) { 9077 return errorResult(); 9078 } 9079 9080 pc_->functionScope().useAsVarScope(pc_); 9081 9082 // The function we synthesize is located at the field with the 9083 // accessor. 9084 setFunctionStartAtCurrentToken(funbox); 9085 setFunctionEndFromCurrentToken(funbox); 9086 9087 // Create a ListNode for the parameters + body 9088 ParamsBodyNodeType paramsbody = MOZ_TRY(handler_.newParamsBody(propNamePos)); 9089 handler_.setFunctionFormalParametersAndBody(funNode, paramsbody); 9090 9091 if (syntaxKind == FunctionSyntaxKind::Getter) { 9092 funbox->setArgCount(0); 9093 } else { 9094 funbox->setArgCount(1); 9095 } 9096 9097 // Build `this` expression to access the privateStateName for use in the 9098 // operations to create the getter and setter below. 9099 NameNodeType thisName = MOZ_TRY(newThisName()); 9100 9101 ThisLiteralType propThis = 9102 MOZ_TRY(handler_.newThisLiteral(propNamePos, thisName)); 9103 9104 NameNodeType privateNameNode = MOZ_TRY(privateNameReference(propNameAtom)); 9105 9106 Node propFieldAccess = MOZ_TRY(handler_.newPrivateMemberAccess( 9107 propThis, privateNameNode, propNamePos.end)); 9108 9109 Node accessorBody; 9110 if (syntaxKind == FunctionSyntaxKind::Getter) { 9111 // Decorators Proposal 9112 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter 9113 // 1. Let getterClosure be a new Abstract Closure with no parameters that 9114 // captures privateStateName and performs the following steps when called: 9115 // 1.a. Let o be the this value. 9116 // 1.b. Return ? PrivateGet(privateStateName, o). 9117 accessorBody = 9118 MOZ_TRY(handler_.newReturnStatement(propFieldAccess, propNamePos)); 9119 } else { 9120 // Decorators Proposal 9121 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter 9122 // The abstract operation MakeAutoAccessorSetter takes arguments homeObject 9123 // (an Object), name (a property key or Private Name), and privateStateName 9124 // (a Private Name) and returns a function object. 9125 // 1. Let setterClosure be a new Abstract Closure with parameters (value) 9126 // that captures privateStateName and performs the following steps when 9127 // called: 9128 // 1.a. Let o be the this value. 9129 notePositionalFormalParameter(funNode, 9130 TaggedParserAtomIndex::WellKnown::value(), 9131 /* pos = */ 0, false, 9132 /* duplicatedParam = */ nullptr); 9133 9134 Node initializerExpr = MOZ_TRY(handler_.newName( 9135 TaggedParserAtomIndex::WellKnown::value(), propNamePos)); 9136 9137 // 1.b. Perform ? PrivateSet(privateStateName, o, value). 9138 Node assignment = MOZ_TRY(handler_.newAssignment( 9139 ParseNodeKind::AssignExpr, propFieldAccess, initializerExpr)); 9140 9141 accessorBody = 9142 MOZ_TRY(handler_.newExprStatement(assignment, propNamePos.end)); 9143 9144 // 1.c. Return undefined. 9145 } 9146 9147 ListNodeType statementList = MOZ_TRY(handler_.newStatementList(propNamePos)); 9148 handler_.addStatementToList(statementList, accessorBody); 9149 9150 bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings(); 9151 if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) { 9152 return errorResult(); 9153 } 9154 if (!pc_->declareNewTarget(usedNames_, canSkipLazyClosedOverBindings)) { 9155 return errorResult(); 9156 } 9157 9158 LexicalScopeNodeType initializerBody = MOZ_TRY(finishLexicalScope( 9159 pc_->varScope(), statementList, ScopeKind::FunctionLexical)); 9160 9161 handler_.setFunctionBody(funNode, initializerBody); 9162 9163 if (pc_->superScopeNeedsHomeObject()) { 9164 funbox->setNeedsHomeObject(); 9165 } 9166 9167 if (!finishFunction()) { 9168 return errorResult(); 9169 } 9170 9171 if (!leaveInnerFunction(outerpc)) { 9172 return errorResult(); 9173 } 9174 9175 return funNode; 9176 } 9177 9178 #endif 9179 9180 bool ParserBase::nextTokenContinuesLetDeclaration(TokenKind next) { 9181 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Let)); 9182 MOZ_ASSERT(anyChars.nextToken().type == next); 9183 9184 TokenStreamShared::verifyConsistentModifier(TokenStreamShared::SlashIsDiv, 9185 anyChars.nextToken()); 9186 9187 // Destructuring continues a let declaration. 9188 if (next == TokenKind::LeftBracket || next == TokenKind::LeftCurly) { 9189 return true; 9190 } 9191 9192 // A "let" edge case deserves special comment. Consider this: 9193 // 9194 // let // not an ASI opportunity 9195 // let; 9196 // 9197 // Static semantics in §13.3.1.1 turn a LexicalDeclaration that binds 9198 // "let" into an early error. Does this retroactively permit ASI so 9199 // that we should parse this as two ExpressionStatements? No. ASI 9200 // resolves during parsing. Static semantics only apply to the full 9201 // parse tree with ASI applied. No backsies! 9202 9203 // Otherwise a let declaration must have a name. 9204 return TokenKindIsPossibleIdentifier(next); 9205 } 9206 9207 template <class ParseHandler, typename Unit> 9208 typename ParseHandler::DeclarationListNodeResult 9209 GeneralParser<ParseHandler, Unit>::variableStatement( 9210 YieldHandling yieldHandling) { 9211 DeclarationListNodeType vars = 9212 MOZ_TRY(declarationList(yieldHandling, ParseNodeKind::VarStmt)); 9213 if (!matchOrInsertSemicolon()) { 9214 return errorResult(); 9215 } 9216 return vars; 9217 } 9218 9219 template <class ParseHandler, typename Unit> 9220 typename ParseHandler::NodeResult GeneralParser<ParseHandler, Unit>::statement( 9221 YieldHandling yieldHandling) { 9222 MOZ_ASSERT(checkOptionsCalled_); 9223 9224 AutoCheckRecursionLimit recursion(this->fc_); 9225 if (!recursion.check(this->fc_)) { 9226 return errorResult(); 9227 } 9228 9229 TokenKind tt; 9230 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 9231 return errorResult(); 9232 } 9233 9234 switch (tt) { 9235 // BlockStatement[?Yield, ?Return] 9236 case TokenKind::LeftCurly: 9237 return blockStatement(yieldHandling); 9238 9239 // VariableStatement[?Yield] 9240 case TokenKind::Var: 9241 return variableStatement(yieldHandling); 9242 9243 // EmptyStatement 9244 case TokenKind::Semi: 9245 return handler_.newEmptyStatement(pos()); 9246 9247 // ExpressionStatement[?Yield]. 9248 9249 case TokenKind::Yield: { 9250 // Don't use a ternary operator here due to obscure linker issues 9251 // around using static consts in the arms of a ternary. 9252 Modifier modifier; 9253 if (yieldExpressionsSupported()) { 9254 modifier = TokenStream::SlashIsRegExp; 9255 } else { 9256 modifier = TokenStream::SlashIsDiv; 9257 } 9258 9259 TokenKind next; 9260 if (!tokenStream.peekToken(&next, modifier)) { 9261 return errorResult(); 9262 } 9263 9264 if (next == TokenKind::Colon) { 9265 return labeledStatement(yieldHandling); 9266 } 9267 9268 return expressionStatement(yieldHandling); 9269 } 9270 9271 default: { 9272 // If we encounter an await in a module, and the module is not marked 9273 // as async, mark the module as async. 9274 if (tt == TokenKind::Await && !pc_->isAsync()) { 9275 if (pc_->atModuleTopLevel()) { 9276 if (!options().topLevelAwait) { 9277 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED); 9278 return errorResult(); 9279 } 9280 pc_->sc()->asModuleContext()->setIsAsync(); 9281 MOZ_ASSERT(pc_->isAsync()); 9282 } 9283 } 9284 9285 // Avoid getting next token with SlashIsDiv. 9286 if (tt == TokenKind::Await && pc_->isAsync()) { 9287 return expressionStatement(yieldHandling); 9288 } 9289 9290 if (!TokenKindIsPossibleIdentifier(tt)) { 9291 return expressionStatement(yieldHandling); 9292 } 9293 9294 TokenKind next; 9295 if (!tokenStream.peekToken(&next)) { 9296 return errorResult(); 9297 } 9298 9299 // |let| here can only be an Identifier, not a declaration. Give nicer 9300 // errors for declaration-looking typos. 9301 if (tt == TokenKind::Let) { 9302 bool forbiddenLetDeclaration = false; 9303 9304 if (next == TokenKind::LeftBracket) { 9305 // Enforce ExpressionStatement's 'let [' lookahead restriction. 9306 forbiddenLetDeclaration = true; 9307 } else if (next == TokenKind::LeftCurly || 9308 TokenKindIsPossibleIdentifier(next)) { 9309 // 'let {' and 'let foo' aren't completely forbidden, if ASI 9310 // causes 'let' to be the entire Statement. But if they're 9311 // same-line, we can aggressively give a better error message. 9312 // 9313 // Note that this ignores 'yield' as TokenKind::Yield: we'll handle it 9314 // correctly but with a worse error message. 9315 TokenKind nextSameLine; 9316 if (!tokenStream.peekTokenSameLine(&nextSameLine)) { 9317 return errorResult(); 9318 } 9319 9320 MOZ_ASSERT(TokenKindIsPossibleIdentifier(nextSameLine) || 9321 nextSameLine == TokenKind::LeftCurly || 9322 nextSameLine == TokenKind::Eol); 9323 9324 forbiddenLetDeclaration = nextSameLine != TokenKind::Eol; 9325 } 9326 9327 if (forbiddenLetDeclaration) { 9328 error(JSMSG_FORBIDDEN_AS_STATEMENT, "lexical declarations"); 9329 return errorResult(); 9330 } 9331 } else if (tt == TokenKind::Async) { 9332 // Peek only on the same line: ExpressionStatement's lookahead 9333 // restriction is phrased as 9334 // 9335 // [lookahead ∉ { '{', 9336 // function, 9337 // async [no LineTerminator here] function, 9338 // class, 9339 // let '[' }] 9340 // 9341 // meaning that code like this is valid: 9342 // 9343 // if (true) 9344 // async // ASI opportunity 9345 // function clownshoes() {} 9346 TokenKind maybeFunction; 9347 if (!tokenStream.peekTokenSameLine(&maybeFunction)) { 9348 return errorResult(); 9349 } 9350 9351 if (maybeFunction == TokenKind::Function) { 9352 error(JSMSG_FORBIDDEN_AS_STATEMENT, "async function declarations"); 9353 return errorResult(); 9354 } 9355 9356 // Otherwise this |async| begins an ExpressionStatement or is a 9357 // label name. 9358 } 9359 9360 // NOTE: It's unfortunately allowed to have a label named 'let' in 9361 // non-strict code. 💯 9362 if (next == TokenKind::Colon) { 9363 return labeledStatement(yieldHandling); 9364 } 9365 9366 return expressionStatement(yieldHandling); 9367 } 9368 9369 case TokenKind::New: 9370 return expressionStatement(yieldHandling, PredictInvoked); 9371 9372 // IfStatement[?Yield, ?Return] 9373 case TokenKind::If: 9374 return ifStatement(yieldHandling); 9375 9376 // BreakableStatement[?Yield, ?Return] 9377 // 9378 // BreakableStatement[Yield, Return]: 9379 // IterationStatement[?Yield, ?Return] 9380 // SwitchStatement[?Yield, ?Return] 9381 case TokenKind::Do: 9382 return doWhileStatement(yieldHandling); 9383 9384 case TokenKind::While: 9385 return whileStatement(yieldHandling); 9386 9387 case TokenKind::For: 9388 return forStatement(yieldHandling); 9389 9390 case TokenKind::Switch: 9391 return switchStatement(yieldHandling); 9392 9393 // ContinueStatement[?Yield] 9394 case TokenKind::Continue: 9395 return continueStatement(yieldHandling); 9396 9397 // BreakStatement[?Yield] 9398 case TokenKind::Break: 9399 return breakStatement(yieldHandling); 9400 9401 // [+Return] ReturnStatement[?Yield] 9402 case TokenKind::Return: 9403 // The Return parameter is only used here, and the effect is easily 9404 // detected this way, so don't bother passing around an extra parameter 9405 // everywhere. 9406 if (!pc_->allowReturn()) { 9407 error(JSMSG_BAD_RETURN_OR_YIELD, "return"); 9408 return errorResult(); 9409 } 9410 return returnStatement(yieldHandling); 9411 9412 // WithStatement[?Yield, ?Return] 9413 case TokenKind::With: 9414 return withStatement(yieldHandling); 9415 9416 // LabelledStatement[?Yield, ?Return] 9417 // This is really handled by default and TokenKind::Yield cases above. 9418 9419 // ThrowStatement[?Yield] 9420 case TokenKind::Throw: 9421 return throwStatement(yieldHandling); 9422 9423 // TryStatement[?Yield, ?Return] 9424 case TokenKind::Try: 9425 return tryStatement(yieldHandling); 9426 9427 // DebuggerStatement 9428 case TokenKind::Debugger: 9429 return debuggerStatement(); 9430 9431 // |function| is forbidden by lookahead restriction (unless as child 9432 // statement of |if| or |else|, but Parser::consequentOrAlternative 9433 // handles that). 9434 case TokenKind::Function: 9435 error(JSMSG_FORBIDDEN_AS_STATEMENT, "function declarations"); 9436 return errorResult(); 9437 9438 // |class| is also forbidden by lookahead restriction. 9439 case TokenKind::Class: 9440 error(JSMSG_FORBIDDEN_AS_STATEMENT, "classes"); 9441 return errorResult(); 9442 9443 // ImportDeclaration (only inside modules) 9444 case TokenKind::Import: 9445 return importDeclarationOrImportExpr(yieldHandling); 9446 9447 // ExportDeclaration (only inside modules) 9448 case TokenKind::Export: 9449 return exportDeclaration(); 9450 9451 // Miscellaneous error cases arguably better caught here than elsewhere. 9452 9453 case TokenKind::Catch: 9454 error(JSMSG_CATCH_WITHOUT_TRY); 9455 return errorResult(); 9456 9457 case TokenKind::Finally: 9458 error(JSMSG_FINALLY_WITHOUT_TRY); 9459 return errorResult(); 9460 9461 // NOTE: default case handled in the ExpressionStatement section. 9462 } 9463 } 9464 9465 template <class ParseHandler, typename Unit> 9466 typename ParseHandler::NodeResult 9467 GeneralParser<ParseHandler, Unit>::statementListItem( 9468 YieldHandling yieldHandling, bool canHaveDirectives /* = false */) { 9469 MOZ_ASSERT(checkOptionsCalled_); 9470 9471 AutoCheckRecursionLimit recursion(this->fc_); 9472 if (!recursion.check(this->fc_)) { 9473 return errorResult(); 9474 } 9475 9476 TokenKind tt; 9477 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 9478 return errorResult(); 9479 } 9480 9481 switch (tt) { 9482 // BlockStatement[?Yield, ?Return] 9483 case TokenKind::LeftCurly: 9484 return blockStatement(yieldHandling); 9485 9486 // VariableStatement[?Yield] 9487 case TokenKind::Var: 9488 return variableStatement(yieldHandling); 9489 9490 // EmptyStatement 9491 case TokenKind::Semi: 9492 return handler_.newEmptyStatement(pos()); 9493 9494 // ExpressionStatement[?Yield]. 9495 // 9496 // These should probably be handled by a single ExpressionStatement 9497 // function in a default, not split up this way. 9498 case TokenKind::String: 9499 if (!canHaveDirectives && 9500 anyChars.currentToken().atom() == 9501 TaggedParserAtomIndex::WellKnown::use_asm_()) { 9502 if (!warning(JSMSG_USE_ASM_DIRECTIVE_FAIL)) { 9503 return errorResult(); 9504 } 9505 } 9506 return expressionStatement(yieldHandling); 9507 9508 case TokenKind::Yield: { 9509 // Don't use a ternary operator here due to obscure linker issues 9510 // around using static consts in the arms of a ternary. 9511 Modifier modifier; 9512 if (yieldExpressionsSupported()) { 9513 modifier = TokenStream::SlashIsRegExp; 9514 } else { 9515 modifier = TokenStream::SlashIsDiv; 9516 } 9517 9518 TokenKind next; 9519 if (!tokenStream.peekToken(&next, modifier)) { 9520 return errorResult(); 9521 } 9522 9523 if (next == TokenKind::Colon) { 9524 return labeledStatement(yieldHandling); 9525 } 9526 9527 return expressionStatement(yieldHandling); 9528 } 9529 9530 default: { 9531 // If we encounter an await in a module, and the module is not marked 9532 // as async, mark the module as async. 9533 if (tt == TokenKind::Await && !pc_->isAsync()) { 9534 if (pc_->atModuleTopLevel()) { 9535 if (!options().topLevelAwait) { 9536 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED); 9537 return errorResult(); 9538 } 9539 pc_->sc()->asModuleContext()->setIsAsync(); 9540 MOZ_ASSERT(pc_->isAsync()); 9541 } 9542 } 9543 9544 if (tt == TokenKind::Await && pc_->isAsync()) { 9545 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 9546 if (options().explicitResourceManagement()) { 9547 // Try finding evidence of a AwaitUsingDeclaration the syntax for 9548 // which 9549 // would be: 9550 // await [no LineTerminator here] using [no LineTerminator here] 9551 // identifier 9552 9553 TokenKind nextTokUsing = TokenKind::Eof; 9554 // Scan with regex modifier because when its await expression, `/` 9555 // should be treated as a regexp. 9556 if (!tokenStream.peekTokenSameLine(&nextTokUsing, 9557 TokenStream::SlashIsRegExp)) { 9558 return errorResult(); 9559 } 9560 9561 if (nextTokUsing == TokenKind::Using && 9562 this->pc_->isUsingSyntaxAllowed()) { 9563 tokenStream.consumeKnownToken(nextTokUsing, 9564 TokenStream::SlashIsRegExp); 9565 TokenKind nextTokIdentifier = TokenKind::Eof; 9566 // Here we can use the Div modifier because if the next token is 9567 // using then a `/` as the next token can only be considered a 9568 // division. 9569 if (!tokenStream.peekTokenSameLine(&nextTokIdentifier)) { 9570 return errorResult(); 9571 } 9572 if (TokenKindIsPossibleIdentifier(nextTokIdentifier)) { 9573 return lexicalDeclaration(yieldHandling, 9574 DeclarationKind::AwaitUsing); 9575 } 9576 anyChars.ungetToken(); // put back using. 9577 } 9578 } 9579 #endif 9580 return expressionStatement(yieldHandling); 9581 } 9582 9583 if (!TokenKindIsPossibleIdentifier(tt)) { 9584 return expressionStatement(yieldHandling); 9585 } 9586 9587 TokenKind next; 9588 if (!tokenStream.peekToken(&next)) { 9589 return errorResult(); 9590 } 9591 9592 if (tt == TokenKind::Let && nextTokenContinuesLetDeclaration(next)) { 9593 return lexicalDeclaration(yieldHandling, DeclarationKind::Let); 9594 } 9595 9596 if (tt == TokenKind::Async) { 9597 TokenKind nextSameLine = TokenKind::Eof; 9598 if (!tokenStream.peekTokenSameLine(&nextSameLine)) { 9599 return errorResult(); 9600 } 9601 if (nextSameLine == TokenKind::Function) { 9602 uint32_t toStringStart = pos().begin; 9603 tokenStream.consumeKnownToken(TokenKind::Function); 9604 return functionStmt(toStringStart, yieldHandling, NameRequired, 9605 FunctionAsyncKind::AsyncFunction); 9606 } 9607 } 9608 9609 if (next == TokenKind::Colon) { 9610 return labeledStatement(yieldHandling); 9611 } 9612 9613 return expressionStatement(yieldHandling); 9614 } 9615 9616 case TokenKind::New: 9617 return expressionStatement(yieldHandling, PredictInvoked); 9618 9619 // IfStatement[?Yield, ?Return] 9620 case TokenKind::If: 9621 return ifStatement(yieldHandling); 9622 9623 // BreakableStatement[?Yield, ?Return] 9624 // 9625 // BreakableStatement[Yield, Return]: 9626 // IterationStatement[?Yield, ?Return] 9627 // SwitchStatement[?Yield, ?Return] 9628 case TokenKind::Do: 9629 return doWhileStatement(yieldHandling); 9630 9631 case TokenKind::While: 9632 return whileStatement(yieldHandling); 9633 9634 case TokenKind::For: 9635 return forStatement(yieldHandling); 9636 9637 case TokenKind::Switch: 9638 return switchStatement(yieldHandling); 9639 9640 // ContinueStatement[?Yield] 9641 case TokenKind::Continue: 9642 return continueStatement(yieldHandling); 9643 9644 // BreakStatement[?Yield] 9645 case TokenKind::Break: 9646 return breakStatement(yieldHandling); 9647 9648 // [+Return] ReturnStatement[?Yield] 9649 case TokenKind::Return: 9650 // The Return parameter is only used here, and the effect is easily 9651 // detected this way, so don't bother passing around an extra parameter 9652 // everywhere. 9653 if (!pc_->allowReturn()) { 9654 error(JSMSG_BAD_RETURN_OR_YIELD, "return"); 9655 return errorResult(); 9656 } 9657 return returnStatement(yieldHandling); 9658 9659 // WithStatement[?Yield, ?Return] 9660 case TokenKind::With: 9661 return withStatement(yieldHandling); 9662 9663 // LabelledStatement[?Yield, ?Return] 9664 // This is really handled by default and TokenKind::Yield cases above. 9665 9666 // ThrowStatement[?Yield] 9667 case TokenKind::Throw: 9668 return throwStatement(yieldHandling); 9669 9670 // TryStatement[?Yield, ?Return] 9671 case TokenKind::Try: 9672 return tryStatement(yieldHandling); 9673 9674 // DebuggerStatement 9675 case TokenKind::Debugger: 9676 return debuggerStatement(); 9677 9678 // Declaration[Yield]: 9679 9680 // HoistableDeclaration[?Yield, ~Default] 9681 case TokenKind::Function: 9682 return functionStmt(pos().begin, yieldHandling, NameRequired); 9683 9684 // DecoratorList[?Yield, ?Await] opt ClassDeclaration[?Yield, ~Default] 9685 #ifdef ENABLE_DECORATORS 9686 case TokenKind::At: 9687 return classDefinition(yieldHandling, ClassStatement, NameRequired); 9688 #endif 9689 9690 case TokenKind::Class: 9691 return classDefinition(yieldHandling, ClassStatement, NameRequired); 9692 9693 // LexicalDeclaration[In, ?Yield] 9694 // LetOrConst BindingList[?In, ?Yield] 9695 case TokenKind::Const: 9696 // [In] is the default behavior, because for-loops specially parse 9697 // their heads to handle |in| in this situation. 9698 return lexicalDeclaration(yieldHandling, DeclarationKind::Const); 9699 9700 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 9701 case TokenKind::Using: { 9702 TokenKind nextTok = TokenKind::Eol; 9703 if (!tokenStream.peekTokenSameLine(&nextTok)) { 9704 return errorResult(); 9705 } 9706 if (!options().explicitResourceManagement() || 9707 !TokenKindIsPossibleIdentifier(nextTok) || 9708 !this->pc_->isUsingSyntaxAllowed()) { 9709 if (!tokenStream.peekToken(&nextTok)) { 9710 return errorResult(); 9711 } 9712 // labelled statement could be like using\n:\nexpr 9713 if (nextTok == TokenKind::Colon) { 9714 return labeledStatement(yieldHandling); 9715 } 9716 return expressionStatement(yieldHandling); 9717 } 9718 return lexicalDeclaration(yieldHandling, DeclarationKind::Using); 9719 } 9720 #endif 9721 9722 // ImportDeclaration (only inside modules) 9723 case TokenKind::Import: 9724 return importDeclarationOrImportExpr(yieldHandling); 9725 9726 // ExportDeclaration (only inside modules) 9727 case TokenKind::Export: 9728 return exportDeclaration(); 9729 9730 // Miscellaneous error cases arguably better caught here than elsewhere. 9731 9732 case TokenKind::Catch: 9733 error(JSMSG_CATCH_WITHOUT_TRY); 9734 return errorResult(); 9735 9736 case TokenKind::Finally: 9737 error(JSMSG_FINALLY_WITHOUT_TRY); 9738 return errorResult(); 9739 9740 // NOTE: default case handled in the ExpressionStatement section. 9741 } 9742 } 9743 9744 template <class ParseHandler, typename Unit> 9745 typename ParseHandler::NodeResult GeneralParser<ParseHandler, Unit>::expr( 9746 InHandling inHandling, YieldHandling yieldHandling, 9747 TripledotHandling tripledotHandling, 9748 PossibleError* possibleError /* = nullptr */, 9749 InvokedPrediction invoked /* = PredictUninvoked */) { 9750 Node pn = MOZ_TRY(assignExpr(inHandling, yieldHandling, tripledotHandling, 9751 possibleError, invoked)); 9752 9753 bool matched; 9754 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 9755 TokenStream::SlashIsRegExp)) { 9756 return errorResult(); 9757 } 9758 if (!matched) { 9759 return pn; 9760 } 9761 9762 ListNodeType seq = MOZ_TRY(handler_.newCommaExpressionList(pn)); 9763 while (true) { 9764 // Trailing comma before the closing parenthesis is valid in an arrow 9765 // function parameters list: `(a, b, ) => body`. Check if we are 9766 // directly under CoverParenthesizedExpressionAndArrowParameterList, 9767 // and the next two tokens are closing parenthesis and arrow. If all 9768 // are present allow the trailing comma. 9769 if (tripledotHandling == TripledotAllowed) { 9770 TokenKind tt; 9771 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 9772 return errorResult(); 9773 } 9774 9775 if (tt == TokenKind::RightParen) { 9776 tokenStream.consumeKnownToken(TokenKind::RightParen, 9777 TokenStream::SlashIsRegExp); 9778 9779 if (!tokenStream.peekToken(&tt)) { 9780 return errorResult(); 9781 } 9782 if (tt != TokenKind::Arrow) { 9783 error(JSMSG_UNEXPECTED_TOKEN, "expression", 9784 TokenKindToDesc(TokenKind::RightParen)); 9785 return errorResult(); 9786 } 9787 9788 anyChars.ungetToken(); // put back right paren 9789 break; 9790 } 9791 } 9792 9793 // Additional calls to assignExpr should not reuse the possibleError 9794 // which had been passed into the function. Otherwise we would lose 9795 // information needed to determine whether or not we're dealing with 9796 // a non-recoverable situation. 9797 PossibleError possibleErrorInner(*this); 9798 pn = MOZ_TRY(assignExpr(inHandling, yieldHandling, tripledotHandling, 9799 &possibleErrorInner)); 9800 9801 if (!possibleError) { 9802 // Report any pending expression error. 9803 if (!possibleErrorInner.checkForExpressionError()) { 9804 return errorResult(); 9805 } 9806 } else { 9807 possibleErrorInner.transferErrorsTo(possibleError); 9808 } 9809 9810 handler_.addList(seq, pn); 9811 9812 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 9813 TokenStream::SlashIsRegExp)) { 9814 return errorResult(); 9815 } 9816 if (!matched) { 9817 break; 9818 } 9819 } 9820 return seq; 9821 } 9822 9823 static ParseNodeKind BinaryOpTokenKindToParseNodeKind(TokenKind tok) { 9824 MOZ_ASSERT(TokenKindIsBinaryOp(tok)); 9825 return ParseNodeKind(size_t(ParseNodeKind::BinOpFirst) + 9826 (size_t(tok) - size_t(TokenKind::BinOpFirst))); 9827 } 9828 9829 // This list must be kept in the same order in several places: 9830 // - The binary operators in ParseNode.h , 9831 // - the binary operators in TokenKind.h 9832 // - the JSOp code list in BytecodeEmitter.cpp 9833 static const int PrecedenceTable[] = { 9834 1, /* ParseNodeKind::Coalesce */ 9835 2, /* ParseNodeKind::Or */ 9836 3, /* ParseNodeKind::And */ 9837 4, /* ParseNodeKind::BitOr */ 9838 5, /* ParseNodeKind::BitXor */ 9839 6, /* ParseNodeKind::BitAnd */ 9840 7, /* ParseNodeKind::StrictEq */ 9841 7, /* ParseNodeKind::Eq */ 9842 7, /* ParseNodeKind::StrictNe */ 9843 7, /* ParseNodeKind::Ne */ 9844 8, /* ParseNodeKind::Lt */ 9845 8, /* ParseNodeKind::Le */ 9846 8, /* ParseNodeKind::Gt */ 9847 8, /* ParseNodeKind::Ge */ 9848 8, /* ParseNodeKind::InstanceOf */ 9849 8, /* ParseNodeKind::In */ 9850 8, /* ParseNodeKind::PrivateIn */ 9851 9, /* ParseNodeKind::Lsh */ 9852 9, /* ParseNodeKind::Rsh */ 9853 9, /* ParseNodeKind::Ursh */ 9854 10, /* ParseNodeKind::Add */ 9855 10, /* ParseNodeKind::Sub */ 9856 11, /* ParseNodeKind::Star */ 9857 11, /* ParseNodeKind::Div */ 9858 11, /* ParseNodeKind::Mod */ 9859 12 /* ParseNodeKind::Pow */ 9860 }; 9861 9862 static const int PRECEDENCE_CLASSES = 12; 9863 9864 static int Precedence(ParseNodeKind pnk) { 9865 // Everything binds tighter than ParseNodeKind::Limit, because we want 9866 // to reduce all nodes to a single node when we reach a token that is not 9867 // another binary operator. 9868 if (pnk == ParseNodeKind::Limit) { 9869 return 0; 9870 } 9871 9872 MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst); 9873 MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast); 9874 return PrecedenceTable[size_t(pnk) - size_t(ParseNodeKind::BinOpFirst)]; 9875 } 9876 9877 enum class EnforcedParentheses : uint8_t { CoalesceExpr, AndOrExpr, None }; 9878 9879 template <class ParseHandler, typename Unit> 9880 MOZ_ALWAYS_INLINE typename ParseHandler::NodeResult 9881 GeneralParser<ParseHandler, Unit>::orExpr(InHandling inHandling, 9882 YieldHandling yieldHandling, 9883 TripledotHandling tripledotHandling, 9884 PossibleError* possibleError, 9885 InvokedPrediction invoked) { 9886 // Shift-reduce parser for the binary operator part of the JS expression 9887 // syntax. 9888 9889 // Conceptually there's just one stack, a stack of pairs (lhs, op). 9890 // It's implemented using two separate arrays, though. 9891 Node nodeStack[PRECEDENCE_CLASSES]; 9892 ParseNodeKind kindStack[PRECEDENCE_CLASSES]; 9893 int depth = 0; 9894 Node pn; 9895 EnforcedParentheses unparenthesizedExpression = EnforcedParentheses::None; 9896 for (;;) { 9897 pn = MOZ_TRY(unaryExpr(yieldHandling, tripledotHandling, possibleError, 9898 invoked, PrivateNameHandling::PrivateNameAllowed)); 9899 9900 // If a binary operator follows, consume it and compute the 9901 // corresponding operator. 9902 TokenKind tok; 9903 if (!tokenStream.getToken(&tok)) { 9904 return errorResult(); 9905 } 9906 9907 // Ensure that if we have a private name lhs we are legally constructing a 9908 // `#x in obj` expessions: 9909 if (handler_.isPrivateName(pn)) { 9910 if (tok != TokenKind::In || inHandling != InAllowed) { 9911 error(JSMSG_ILLEGAL_PRIVATE_NAME); 9912 return errorResult(); 9913 } 9914 } 9915 9916 ParseNodeKind pnk; 9917 if (tok == TokenKind::In ? inHandling == InAllowed 9918 : TokenKindIsBinaryOp(tok)) { 9919 // We're definitely not in a destructuring context, so report any 9920 // pending expression error now. 9921 if (possibleError && !possibleError->checkForExpressionError()) { 9922 return errorResult(); 9923 } 9924 9925 bool isErgonomicBrandCheck = false; 9926 switch (tok) { 9927 // Report an error for unary expressions on the LHS of **. 9928 case TokenKind::Pow: 9929 if (handler_.isUnparenthesizedUnaryExpression(pn)) { 9930 error(JSMSG_BAD_POW_LEFTSIDE); 9931 return errorResult(); 9932 } 9933 break; 9934 9935 case TokenKind::Or: 9936 case TokenKind::And: 9937 // In the case that the `??` is on the left hand side of the 9938 // expression: Disallow Mixing of ?? and other logical operators (|| 9939 // and &&) unless one expression is parenthesized 9940 if (unparenthesizedExpression == EnforcedParentheses::CoalesceExpr) { 9941 error(JSMSG_BAD_COALESCE_MIXING); 9942 return errorResult(); 9943 } 9944 // If we have not detected a mixing error at this point, record that 9945 // we have an unparenthesized expression, in case we have one later. 9946 unparenthesizedExpression = EnforcedParentheses::AndOrExpr; 9947 break; 9948 9949 case TokenKind::Coalesce: 9950 if (unparenthesizedExpression == EnforcedParentheses::AndOrExpr) { 9951 error(JSMSG_BAD_COALESCE_MIXING); 9952 return errorResult(); 9953 } 9954 // If we have not detected a mixing error at this point, record that 9955 // we have an unparenthesized expression, in case we have one later. 9956 unparenthesizedExpression = EnforcedParentheses::CoalesceExpr; 9957 break; 9958 9959 case TokenKind::In: 9960 // if the LHS is a private name, and the operator is In, 9961 // ensure we're construcing an ergonomic brand check of 9962 // '#x in y', rather than having a higher precedence operator 9963 // like + cause a different reduction, such as 9964 // 1 + #x in y. 9965 if (handler_.isPrivateName(pn)) { 9966 if (depth > 0 && Precedence(kindStack[depth - 1]) >= 9967 Precedence(ParseNodeKind::InExpr)) { 9968 error(JSMSG_INVALID_PRIVATE_NAME_PRECEDENCE); 9969 return errorResult(); 9970 } 9971 9972 isErgonomicBrandCheck = true; 9973 } 9974 break; 9975 9976 default: 9977 // do nothing in other cases 9978 break; 9979 } 9980 9981 if (isErgonomicBrandCheck) { 9982 pnk = ParseNodeKind::PrivateInExpr; 9983 } else { 9984 pnk = BinaryOpTokenKindToParseNodeKind(tok); 9985 } 9986 9987 } else { 9988 tok = TokenKind::Eof; 9989 pnk = ParseNodeKind::Limit; 9990 } 9991 9992 // From this point on, destructuring defaults are definitely an error. 9993 possibleError = nullptr; 9994 9995 // If pnk has precedence less than or equal to another operator on the 9996 // stack, reduce. This combines nodes on the stack until we form the 9997 // actual lhs of pnk. 9998 // 9999 // The >= in this condition works because it is appendOrCreateList's 10000 // job to decide if the operator in question is left- or 10001 // right-associative, and build the corresponding tree. 10002 while (depth > 0 && Precedence(kindStack[depth - 1]) >= Precedence(pnk)) { 10003 depth--; 10004 ParseNodeKind combiningPnk = kindStack[depth]; 10005 pn = MOZ_TRY( 10006 handler_.appendOrCreateList(combiningPnk, nodeStack[depth], pn, pc_)); 10007 } 10008 10009 if (pnk == ParseNodeKind::Limit) { 10010 break; 10011 } 10012 10013 nodeStack[depth] = pn; 10014 kindStack[depth] = pnk; 10015 depth++; 10016 MOZ_ASSERT(depth <= PRECEDENCE_CLASSES); 10017 } 10018 10019 anyChars.ungetToken(); 10020 10021 // Had the next token been a Div, we would have consumed it. So there's no 10022 // ambiguity if we later (after ASI) re-get this token with SlashIsRegExp. 10023 anyChars.allowGettingNextTokenWithSlashIsRegExp(); 10024 10025 MOZ_ASSERT(depth == 0); 10026 return pn; 10027 } 10028 10029 template <class ParseHandler, typename Unit> 10030 MOZ_ALWAYS_INLINE typename ParseHandler::NodeResult 10031 GeneralParser<ParseHandler, Unit>::condExpr(InHandling inHandling, 10032 YieldHandling yieldHandling, 10033 TripledotHandling tripledotHandling, 10034 PossibleError* possibleError, 10035 InvokedPrediction invoked) { 10036 Node condition = MOZ_TRY(orExpr(inHandling, yieldHandling, tripledotHandling, 10037 possibleError, invoked)); 10038 10039 bool matched; 10040 if (!tokenStream.matchToken(&matched, TokenKind::Hook, 10041 TokenStream::SlashIsInvalid)) { 10042 return errorResult(); 10043 } 10044 if (!matched) { 10045 return condition; 10046 } 10047 10048 Node thenExpr = 10049 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited)); 10050 10051 if (!mustMatchToken(TokenKind::Colon, JSMSG_COLON_IN_COND)) { 10052 return errorResult(); 10053 } 10054 10055 Node elseExpr = 10056 MOZ_TRY(assignExpr(inHandling, yieldHandling, TripledotProhibited)); 10057 10058 return handler_.newConditional(condition, thenExpr, elseExpr); 10059 } 10060 10061 template <class ParseHandler, typename Unit> 10062 typename ParseHandler::NodeResult GeneralParser<ParseHandler, Unit>::assignExpr( 10063 InHandling inHandling, YieldHandling yieldHandling, 10064 TripledotHandling tripledotHandling, 10065 PossibleError* possibleError /* = nullptr */, 10066 InvokedPrediction invoked /* = PredictUninvoked */) { 10067 AutoCheckRecursionLimit recursion(this->fc_); 10068 if (!recursion.check(this->fc_)) { 10069 return errorResult(); 10070 } 10071 10072 // It's very common at this point to have a "detectably simple" expression, 10073 // i.e. a name/number/string token followed by one of the following tokens 10074 // that obviously isn't part of an expression: , ; : ) ] } 10075 // 10076 // (In Parsemark this happens 81.4% of the time; in code with large 10077 // numeric arrays, such as some Kraken benchmarks, it happens more often.) 10078 // 10079 // In such cases, we can avoid the full expression parsing route through 10080 // assignExpr(), condExpr(), orExpr(), unaryExpr(), memberExpr(), and 10081 // primaryExpr(). 10082 10083 TokenKind firstToken; 10084 if (!tokenStream.getToken(&firstToken, TokenStream::SlashIsRegExp)) { 10085 return errorResult(); 10086 } 10087 10088 TokenPos exprPos = pos(); 10089 10090 bool endsExpr; 10091 10092 // This only handles identifiers that *never* have special meaning anywhere 10093 // in the language. Contextual keywords, reserved words in strict mode, 10094 // and other hard cases are handled outside this fast path. 10095 if (firstToken == TokenKind::Name) { 10096 if (!tokenStream.nextTokenEndsExpr(&endsExpr)) { 10097 return errorResult(); 10098 } 10099 if (endsExpr) { 10100 TaggedParserAtomIndex name = identifierReference(yieldHandling); 10101 if (!name) { 10102 return errorResult(); 10103 } 10104 10105 return identifierReference(name); 10106 } 10107 } 10108 10109 if (firstToken == TokenKind::Number) { 10110 if (!tokenStream.nextTokenEndsExpr(&endsExpr)) { 10111 return errorResult(); 10112 } 10113 if (endsExpr) { 10114 return newNumber(anyChars.currentToken()); 10115 } 10116 } 10117 10118 if (firstToken == TokenKind::String) { 10119 if (!tokenStream.nextTokenEndsExpr(&endsExpr)) { 10120 return errorResult(); 10121 } 10122 if (endsExpr) { 10123 return stringLiteral(); 10124 } 10125 } 10126 10127 if (firstToken == TokenKind::Yield && yieldExpressionsSupported()) { 10128 return yieldExpression(inHandling); 10129 } 10130 10131 bool maybeAsyncArrow = false; 10132 if (firstToken == TokenKind::Async) { 10133 TokenKind nextSameLine = TokenKind::Eof; 10134 if (!tokenStream.peekTokenSameLine(&nextSameLine)) { 10135 return errorResult(); 10136 } 10137 10138 if (TokenKindIsPossibleIdentifier(nextSameLine)) { 10139 maybeAsyncArrow = true; 10140 } 10141 } 10142 10143 anyChars.ungetToken(); 10144 10145 // Save the tokenizer state in case we find an arrow function and have to 10146 // rewind. 10147 Position start(tokenStream); 10148 auto ghostToken = this->compilationState_.getPosition(); 10149 10150 PossibleError possibleErrorInner(*this); 10151 Node lhs; 10152 TokenKind tokenAfterLHS; 10153 bool isArrow; 10154 if (maybeAsyncArrow) { 10155 tokenStream.consumeKnownToken(TokenKind::Async, TokenStream::SlashIsRegExp); 10156 10157 TokenKind tokenAfterAsync; 10158 if (!tokenStream.getToken(&tokenAfterAsync)) { 10159 return errorResult(); 10160 } 10161 MOZ_ASSERT(TokenKindIsPossibleIdentifier(tokenAfterAsync)); 10162 10163 // Check yield validity here. 10164 TaggedParserAtomIndex name = bindingIdentifier(yieldHandling); 10165 if (!name) { 10166 return errorResult(); 10167 } 10168 10169 if (!tokenStream.peekToken(&tokenAfterLHS, TokenStream::SlashIsRegExp)) { 10170 return errorResult(); 10171 } 10172 10173 isArrow = tokenAfterLHS == TokenKind::Arrow; 10174 10175 // |async [no LineTerminator] of| without being followed by => is only 10176 // possible in for-await-of loops, e.g. |for await (async of [])|. Pretend 10177 // the |async| token was parsed an identifier reference and then proceed 10178 // with the rest of this function. 10179 if (!isArrow) { 10180 anyChars.ungetToken(); // unget the binding identifier 10181 10182 // The next token is guaranteed to never be a Div (, because it's an 10183 // identifier), so it's okay to re-get the token with SlashIsRegExp. 10184 anyChars.allowGettingNextTokenWithSlashIsRegExp(); 10185 10186 TaggedParserAtomIndex asyncName = identifierReference(yieldHandling); 10187 if (!asyncName) { 10188 return errorResult(); 10189 } 10190 10191 lhs = MOZ_TRY(identifierReference(asyncName)); 10192 } 10193 } else { 10194 lhs = MOZ_TRY(condExpr(inHandling, yieldHandling, tripledotHandling, 10195 &possibleErrorInner, invoked)); 10196 10197 // Use SlashIsRegExp here because the ConditionalExpression parsed above 10198 // could be the entirety of this AssignmentExpression, and then ASI 10199 // permits this token to be a regular expression. 10200 if (!tokenStream.peekToken(&tokenAfterLHS, TokenStream::SlashIsRegExp)) { 10201 return errorResult(); 10202 } 10203 10204 isArrow = tokenAfterLHS == TokenKind::Arrow; 10205 } 10206 10207 if (isArrow) { 10208 // Rewind to reparse as an arrow function. 10209 // 10210 // Note: We do not call CompilationState::rewind here because parsing 10211 // during delazification will see the same rewind and need the same sequence 10212 // of inner functions to skip over. 10213 // Instead, we mark inner functions as "ghost". 10214 // 10215 // See GHOST_FUNCTION in FunctionFlags.h for more details. 10216 tokenStream.rewind(start); 10217 this->compilationState_.markGhost(ghostToken); 10218 10219 TokenKind next; 10220 if (!tokenStream.getToken(&next, TokenStream::SlashIsRegExp)) { 10221 return errorResult(); 10222 } 10223 TokenPos startPos = pos(); 10224 uint32_t toStringStart = startPos.begin; 10225 anyChars.ungetToken(); 10226 10227 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction; 10228 10229 if (next == TokenKind::Async) { 10230 tokenStream.consumeKnownToken(next, TokenStream::SlashIsRegExp); 10231 10232 TokenKind nextSameLine = TokenKind::Eof; 10233 if (!tokenStream.peekTokenSameLine(&nextSameLine)) { 10234 return errorResult(); 10235 } 10236 10237 // The AsyncArrowFunction production are 10238 // async [no LineTerminator here] AsyncArrowBindingIdentifier ... 10239 // async [no LineTerminator here] ArrowFormalParameters ... 10240 if (TokenKindIsPossibleIdentifier(nextSameLine) || 10241 nextSameLine == TokenKind::LeftParen) { 10242 asyncKind = FunctionAsyncKind::AsyncFunction; 10243 } else { 10244 anyChars.ungetToken(); 10245 } 10246 } 10247 10248 FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Arrow; 10249 FunctionNodeType funNode = 10250 MOZ_TRY(handler_.newFunction(syntaxKind, startPos)); 10251 10252 return functionDefinition(funNode, toStringStart, inHandling, yieldHandling, 10253 TaggedParserAtomIndex::null(), syntaxKind, 10254 GeneratorKind::NotGenerator, asyncKind); 10255 } 10256 10257 MOZ_ALWAYS_TRUE( 10258 tokenStream.getToken(&tokenAfterLHS, TokenStream::SlashIsRegExp)); 10259 10260 ParseNodeKind kind; 10261 switch (tokenAfterLHS) { 10262 case TokenKind::Assign: 10263 kind = ParseNodeKind::AssignExpr; 10264 break; 10265 case TokenKind::AddAssign: 10266 kind = ParseNodeKind::AddAssignExpr; 10267 break; 10268 case TokenKind::SubAssign: 10269 kind = ParseNodeKind::SubAssignExpr; 10270 break; 10271 case TokenKind::CoalesceAssign: 10272 kind = ParseNodeKind::CoalesceAssignExpr; 10273 break; 10274 case TokenKind::OrAssign: 10275 kind = ParseNodeKind::OrAssignExpr; 10276 break; 10277 case TokenKind::AndAssign: 10278 kind = ParseNodeKind::AndAssignExpr; 10279 break; 10280 case TokenKind::BitOrAssign: 10281 kind = ParseNodeKind::BitOrAssignExpr; 10282 break; 10283 case TokenKind::BitXorAssign: 10284 kind = ParseNodeKind::BitXorAssignExpr; 10285 break; 10286 case TokenKind::BitAndAssign: 10287 kind = ParseNodeKind::BitAndAssignExpr; 10288 break; 10289 case TokenKind::LshAssign: 10290 kind = ParseNodeKind::LshAssignExpr; 10291 break; 10292 case TokenKind::RshAssign: 10293 kind = ParseNodeKind::RshAssignExpr; 10294 break; 10295 case TokenKind::UrshAssign: 10296 kind = ParseNodeKind::UrshAssignExpr; 10297 break; 10298 case TokenKind::MulAssign: 10299 kind = ParseNodeKind::MulAssignExpr; 10300 break; 10301 case TokenKind::DivAssign: 10302 kind = ParseNodeKind::DivAssignExpr; 10303 break; 10304 case TokenKind::ModAssign: 10305 kind = ParseNodeKind::ModAssignExpr; 10306 break; 10307 case TokenKind::PowAssign: 10308 kind = ParseNodeKind::PowAssignExpr; 10309 break; 10310 10311 default: 10312 MOZ_ASSERT(!anyChars.isCurrentTokenAssignment()); 10313 if (!possibleError) { 10314 if (!possibleErrorInner.checkForExpressionError()) { 10315 return errorResult(); 10316 } 10317 } else { 10318 possibleErrorInner.transferErrorsTo(possibleError); 10319 } 10320 10321 anyChars.ungetToken(); 10322 return lhs; 10323 } 10324 10325 // Verify the left-hand side expression doesn't have a forbidden form. 10326 if (handler_.isUnparenthesizedDestructuringPattern(lhs)) { 10327 if (kind != ParseNodeKind::AssignExpr) { 10328 error(JSMSG_BAD_DESTRUCT_ASS); 10329 return errorResult(); 10330 } 10331 10332 if (!possibleErrorInner.checkForDestructuringErrorOrWarning()) { 10333 return errorResult(); 10334 } 10335 } else if (handler_.isName(lhs)) { 10336 if (const char* chars = nameIsArgumentsOrEval(lhs)) { 10337 // |chars| is "arguments" or "eval" here. 10338 if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_STRICT_ASSIGN, chars)) { 10339 return errorResult(); 10340 } 10341 } 10342 } else if (handler_.isArgumentsLength(lhs)) { 10343 pc_->sc()->setIneligibleForArgumentsLength(); 10344 } else if (handler_.isPropertyOrPrivateMemberAccess(lhs)) { 10345 // Permitted: no additional testing/fixup needed. 10346 } else if (handler_.isFunctionCall(lhs)) { 10347 // We don't have to worry about backward compatibility issues with the new 10348 // compound assignment operators, so we always throw here. Also that way we 10349 // don't have to worry if |f() &&= expr| should always throw an error or 10350 // only if |f()| returns true. 10351 if (kind == ParseNodeKind::CoalesceAssignExpr || 10352 kind == ParseNodeKind::OrAssignExpr || 10353 kind == ParseNodeKind::AndAssignExpr) { 10354 errorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS); 10355 return errorResult(); 10356 } 10357 10358 if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS)) { 10359 return errorResult(); 10360 } 10361 10362 if (possibleError) { 10363 possibleError->setPendingDestructuringErrorAt(exprPos, 10364 JSMSG_BAD_DESTRUCT_TARGET); 10365 } 10366 } else { 10367 errorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS); 10368 return errorResult(); 10369 } 10370 10371 if (!possibleErrorInner.checkForExpressionError()) { 10372 return errorResult(); 10373 } 10374 10375 Node rhs = 10376 MOZ_TRY(assignExpr(inHandling, yieldHandling, TripledotProhibited)); 10377 10378 return handler_.newAssignment(kind, lhs, rhs); 10379 } 10380 10381 template <class ParseHandler> 10382 const char* PerHandlerParser<ParseHandler>::nameIsArgumentsOrEval(Node node) { 10383 MOZ_ASSERT(handler_.isName(node), 10384 "must only call this function on known names"); 10385 10386 if (handler_.isEvalName(node)) { 10387 return "eval"; 10388 } 10389 if (handler_.isArgumentsName(node)) { 10390 return "arguments"; 10391 } 10392 return nullptr; 10393 } 10394 10395 template <class ParseHandler, typename Unit> 10396 bool GeneralParser<ParseHandler, Unit>::checkIncDecOperand( 10397 Node operand, uint32_t operandOffset) { 10398 if (handler_.isName(operand)) { 10399 if (const char* chars = nameIsArgumentsOrEval(operand)) { 10400 if (!strictModeErrorAt(operandOffset, JSMSG_BAD_STRICT_ASSIGN, chars)) { 10401 return false; 10402 } 10403 } 10404 } else if (handler_.isArgumentsLength(operand)) { 10405 pc_->sc()->setIneligibleForArgumentsLength(); 10406 } else if (handler_.isPropertyOrPrivateMemberAccess(operand)) { 10407 // Permitted: no additional testing/fixup needed. 10408 } else if (handler_.isFunctionCall(operand)) { 10409 // Assignment to function calls is forbidden in ES6. We're still 10410 // somewhat concerned about sites using this in dead code, so forbid it 10411 // only in strict mode code. 10412 if (!strictModeErrorAt(operandOffset, JSMSG_BAD_INCOP_OPERAND)) { 10413 return false; 10414 } 10415 } else { 10416 errorAt(operandOffset, JSMSG_BAD_INCOP_OPERAND); 10417 return false; 10418 } 10419 return true; 10420 } 10421 10422 template <class ParseHandler, typename Unit> 10423 typename ParseHandler::UnaryNodeResult 10424 GeneralParser<ParseHandler, Unit>::unaryOpExpr(YieldHandling yieldHandling, 10425 ParseNodeKind kind, 10426 uint32_t begin) { 10427 Node kid = MOZ_TRY(unaryExpr(yieldHandling, TripledotProhibited)); 10428 return handler_.newUnary(kind, begin, kid); 10429 } 10430 10431 template <class ParseHandler, typename Unit> 10432 typename ParseHandler::NodeResult 10433 GeneralParser<ParseHandler, Unit>::optionalExpr( 10434 YieldHandling yieldHandling, TripledotHandling tripledotHandling, 10435 TokenKind tt, PossibleError* possibleError /* = nullptr */, 10436 InvokedPrediction invoked /* = PredictUninvoked */) { 10437 AutoCheckRecursionLimit recursion(this->fc_); 10438 if (!recursion.check(this->fc_)) { 10439 return errorResult(); 10440 } 10441 10442 uint32_t begin = pos().begin; 10443 10444 Node lhs = 10445 MOZ_TRY(memberExpr(yieldHandling, tripledotHandling, tt, 10446 /* allowCallSyntax = */ true, possibleError, invoked)); 10447 10448 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsDiv)) { 10449 return errorResult(); 10450 } 10451 10452 if (tt != TokenKind::OptionalChain) { 10453 return lhs; 10454 } 10455 10456 while (true) { 10457 if (!tokenStream.getToken(&tt)) { 10458 return errorResult(); 10459 } 10460 10461 if (tt == TokenKind::Eof) { 10462 anyChars.ungetToken(); 10463 break; 10464 } 10465 10466 Node nextMember; 10467 if (tt == TokenKind::OptionalChain) { 10468 if (!tokenStream.getToken(&tt)) { 10469 return errorResult(); 10470 } 10471 if (TokenKindIsPossibleIdentifierName(tt)) { 10472 nextMember = MOZ_TRY(memberPropertyAccess(lhs, OptionalKind::Optional)); 10473 } else if (tt == TokenKind::PrivateName) { 10474 nextMember = MOZ_TRY(memberPrivateAccess(lhs, OptionalKind::Optional)); 10475 } else if (tt == TokenKind::LeftBracket) { 10476 nextMember = MOZ_TRY( 10477 memberElemAccess(lhs, yieldHandling, OptionalKind::Optional)); 10478 } else if (tt == TokenKind::LeftParen) { 10479 nextMember = MOZ_TRY(memberCall(tt, lhs, yieldHandling, possibleError, 10480 OptionalKind::Optional)); 10481 } else { 10482 error(JSMSG_NAME_AFTER_DOT); 10483 return errorResult(); 10484 } 10485 } else if (tt == TokenKind::Dot) { 10486 if (!tokenStream.getToken(&tt)) { 10487 return errorResult(); 10488 } 10489 if (TokenKindIsPossibleIdentifierName(tt)) { 10490 nextMember = MOZ_TRY(memberPropertyAccess(lhs)); 10491 } else if (tt == TokenKind::PrivateName) { 10492 nextMember = MOZ_TRY(memberPrivateAccess(lhs)); 10493 } else { 10494 error(JSMSG_NAME_AFTER_DOT); 10495 return errorResult(); 10496 } 10497 } else if (tt == TokenKind::LeftBracket) { 10498 nextMember = MOZ_TRY(memberElemAccess(lhs, yieldHandling)); 10499 } else if (tt == TokenKind::LeftParen) { 10500 nextMember = MOZ_TRY(memberCall(tt, lhs, yieldHandling, possibleError)); 10501 } else if (tt == TokenKind::TemplateHead || 10502 tt == TokenKind::NoSubsTemplate) { 10503 error(JSMSG_BAD_OPTIONAL_TEMPLATE); 10504 return errorResult(); 10505 } else { 10506 anyChars.ungetToken(); 10507 break; 10508 } 10509 10510 MOZ_ASSERT(nextMember); 10511 lhs = nextMember; 10512 } 10513 10514 return handler_.newOptionalChain(begin, lhs); 10515 } 10516 10517 template <class ParseHandler, typename Unit> 10518 typename ParseHandler::NodeResult GeneralParser<ParseHandler, Unit>::unaryExpr( 10519 YieldHandling yieldHandling, TripledotHandling tripledotHandling, 10520 PossibleError* possibleError /* = nullptr */, 10521 InvokedPrediction invoked /* = PredictUninvoked */, 10522 PrivateNameHandling privateNameHandling /* = PrivateNameProhibited */) { 10523 AutoCheckRecursionLimit recursion(this->fc_); 10524 if (!recursion.check(this->fc_)) { 10525 return errorResult(); 10526 } 10527 10528 TokenKind tt; 10529 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 10530 return errorResult(); 10531 } 10532 uint32_t begin = pos().begin; 10533 switch (tt) { 10534 case TokenKind::Void: 10535 return unaryOpExpr(yieldHandling, ParseNodeKind::VoidExpr, begin); 10536 case TokenKind::Not: 10537 return unaryOpExpr(yieldHandling, ParseNodeKind::NotExpr, begin); 10538 case TokenKind::BitNot: 10539 return unaryOpExpr(yieldHandling, ParseNodeKind::BitNotExpr, begin); 10540 case TokenKind::Add: 10541 return unaryOpExpr(yieldHandling, ParseNodeKind::PosExpr, begin); 10542 case TokenKind::Sub: 10543 return unaryOpExpr(yieldHandling, ParseNodeKind::NegExpr, begin); 10544 10545 case TokenKind::TypeOf: { 10546 // The |typeof| operator is specially parsed to distinguish its 10547 // application to a name, from its application to a non-name 10548 // expression: 10549 // 10550 // // Looks up the name, doesn't find it and so evaluates to 10551 // // "undefined". 10552 // assertEq(typeof nonExistentName, "undefined"); 10553 // 10554 // // Evaluates expression, triggering a runtime ReferenceError for 10555 // // the undefined name. 10556 // typeof (1, nonExistentName); 10557 Node kid = MOZ_TRY(unaryExpr(yieldHandling, TripledotProhibited)); 10558 10559 return handler_.newTypeof(begin, kid); 10560 } 10561 10562 case TokenKind::Inc: 10563 case TokenKind::Dec: { 10564 TokenKind tt2; 10565 if (!tokenStream.getToken(&tt2, TokenStream::SlashIsRegExp)) { 10566 return errorResult(); 10567 } 10568 10569 uint32_t operandOffset = pos().begin; 10570 Node operand = 10571 MOZ_TRY(optionalExpr(yieldHandling, TripledotProhibited, tt2)); 10572 if (!checkIncDecOperand(operand, operandOffset)) { 10573 return errorResult(); 10574 } 10575 ParseNodeKind pnk = (tt == TokenKind::Inc) 10576 ? ParseNodeKind::PreIncrementExpr 10577 : ParseNodeKind::PreDecrementExpr; 10578 return handler_.newUpdate(pnk, begin, operand); 10579 } 10580 case TokenKind::PrivateName: { 10581 if (privateNameHandling == PrivateNameHandling::PrivateNameAllowed) { 10582 TaggedParserAtomIndex field = anyChars.currentName(); 10583 return privateNameReference(field); 10584 } 10585 error(JSMSG_INVALID_PRIVATE_NAME_IN_UNARY_EXPR); 10586 return errorResult(); 10587 } 10588 10589 case TokenKind::Delete: { 10590 uint32_t exprOffset; 10591 if (!tokenStream.peekOffset(&exprOffset, TokenStream::SlashIsRegExp)) { 10592 return errorResult(); 10593 } 10594 10595 Node expr = MOZ_TRY(unaryExpr(yieldHandling, TripledotProhibited)); 10596 10597 // Per spec, deleting most unary expressions is valid -- it simply 10598 // returns true -- except for two cases: 10599 // 1. `var x; ...; delete x` is a syntax error in strict mode. 10600 // 2. Private fields cannot be deleted. 10601 if (handler_.isName(expr)) { 10602 if (!strictModeErrorAt(exprOffset, JSMSG_DEPRECATED_DELETE_OPERAND)) { 10603 return errorResult(); 10604 } 10605 10606 pc_->sc()->setBindingsAccessedDynamically(); 10607 } 10608 10609 if (handler_.isPrivateMemberAccess(expr)) { 10610 errorAt(exprOffset, JSMSG_PRIVATE_DELETE); 10611 return errorResult(); 10612 } 10613 10614 return handler_.newDelete(begin, expr); 10615 } 10616 case TokenKind::Await: { 10617 // If we encounter an await in a module, mark it as async. 10618 if (!pc_->isAsync() && pc_->sc()->isModule()) { 10619 if (!options().topLevelAwait) { 10620 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED); 10621 return errorResult(); 10622 } 10623 pc_->sc()->asModuleContext()->setIsAsync(); 10624 MOZ_ASSERT(pc_->isAsync()); 10625 } 10626 10627 if (pc_->isAsync()) { 10628 if (inParametersOfAsyncFunction()) { 10629 error(JSMSG_AWAIT_IN_PARAMETER); 10630 return errorResult(); 10631 } 10632 Node kid = MOZ_TRY(unaryExpr(yieldHandling, tripledotHandling, 10633 possibleError, invoked)); 10634 pc_->lastAwaitOffset = begin; 10635 return handler_.newAwaitExpression(begin, kid); 10636 } 10637 } 10638 10639 [[fallthrough]]; 10640 10641 default: { 10642 Node expr = MOZ_TRY(optionalExpr(yieldHandling, tripledotHandling, tt, 10643 possibleError, invoked)); 10644 10645 /* Don't look across a newline boundary for a postfix incop. */ 10646 if (!tokenStream.peekTokenSameLine(&tt)) { 10647 return errorResult(); 10648 } 10649 10650 if (tt != TokenKind::Inc && tt != TokenKind::Dec) { 10651 return expr; 10652 } 10653 10654 tokenStream.consumeKnownToken(tt); 10655 if (!checkIncDecOperand(expr, begin)) { 10656 return errorResult(); 10657 } 10658 10659 ParseNodeKind pnk = (tt == TokenKind::Inc) 10660 ? ParseNodeKind::PostIncrementExpr 10661 : ParseNodeKind::PostDecrementExpr; 10662 return handler_.newUpdate(pnk, begin, expr); 10663 } 10664 } 10665 } 10666 10667 template <class ParseHandler, typename Unit> 10668 typename ParseHandler::NodeResult 10669 GeneralParser<ParseHandler, Unit>::assignExprWithoutYieldOrAwait( 10670 YieldHandling yieldHandling) { 10671 uint32_t startYieldOffset = pc_->lastYieldOffset; 10672 uint32_t startAwaitOffset = pc_->lastAwaitOffset; 10673 10674 Node res = MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited)); 10675 10676 if (pc_->lastYieldOffset != startYieldOffset) { 10677 errorAt(pc_->lastYieldOffset, JSMSG_YIELD_IN_PARAMETER); 10678 return errorResult(); 10679 } 10680 if (pc_->lastAwaitOffset != startAwaitOffset) { 10681 errorAt(pc_->lastAwaitOffset, JSMSG_AWAIT_IN_PARAMETER); 10682 return errorResult(); 10683 } 10684 return res; 10685 } 10686 10687 template <class ParseHandler, typename Unit> 10688 typename ParseHandler::ListNodeResult 10689 GeneralParser<ParseHandler, Unit>::argumentList( 10690 YieldHandling yieldHandling, bool* isSpread, 10691 PossibleError* possibleError /* = nullptr */) { 10692 ListNodeType argsList = MOZ_TRY(handler_.newArguments(pos())); 10693 10694 bool matched; 10695 if (!tokenStream.matchToken(&matched, TokenKind::RightParen, 10696 TokenStream::SlashIsRegExp)) { 10697 return errorResult(); 10698 } 10699 if (matched) { 10700 handler_.setEndPosition(argsList, pos().end); 10701 return argsList; 10702 } 10703 10704 while (true) { 10705 bool spread = false; 10706 uint32_t begin = 0; 10707 if (!tokenStream.matchToken(&matched, TokenKind::TripleDot, 10708 TokenStream::SlashIsRegExp)) { 10709 return errorResult(); 10710 } 10711 if (matched) { 10712 spread = true; 10713 begin = pos().begin; 10714 *isSpread = true; 10715 } 10716 10717 Node argNode = MOZ_TRY(assignExpr(InAllowed, yieldHandling, 10718 TripledotProhibited, possibleError)); 10719 if (spread) { 10720 argNode = MOZ_TRY(handler_.newSpread(begin, argNode)); 10721 } 10722 10723 handler_.addList(argsList, argNode); 10724 10725 bool matched; 10726 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 10727 TokenStream::SlashIsRegExp)) { 10728 return errorResult(); 10729 } 10730 if (!matched) { 10731 break; 10732 } 10733 10734 TokenKind tt; 10735 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 10736 return errorResult(); 10737 } 10738 if (tt == TokenKind::RightParen) { 10739 break; 10740 } 10741 } 10742 10743 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_ARGS)) { 10744 return errorResult(); 10745 } 10746 10747 handler_.setEndPosition(argsList, pos().end); 10748 return argsList; 10749 } 10750 10751 bool ParserBase::checkAndMarkSuperScope() { 10752 if (!pc_->sc()->allowSuperProperty()) { 10753 return false; 10754 } 10755 10756 pc_->setSuperScopeNeedsHomeObject(); 10757 return true; 10758 } 10759 10760 template <class ParseHandler, typename Unit> 10761 bool GeneralParser<ParseHandler, Unit>::computeErrorMetadata( 10762 ErrorMetadata* err, const ErrorReportMixin::ErrorOffset& offset) const { 10763 if (offset.is<ErrorReportMixin::Current>()) { 10764 return tokenStream.computeErrorMetadata(err, AsVariant(pos().begin)); 10765 } 10766 return tokenStream.computeErrorMetadata(err, offset); 10767 } 10768 10769 template <class ParseHandler, typename Unit> 10770 typename ParseHandler::NodeResult GeneralParser<ParseHandler, Unit>::memberExpr( 10771 YieldHandling yieldHandling, TripledotHandling tripledotHandling, 10772 TokenKind tt, bool allowCallSyntax, PossibleError* possibleError, 10773 InvokedPrediction invoked) { 10774 MOZ_ASSERT(anyChars.isCurrentTokenType(tt)); 10775 10776 Node lhs; 10777 10778 AutoCheckRecursionLimit recursion(this->fc_); 10779 if (!recursion.check(this->fc_)) { 10780 return errorResult(); 10781 } 10782 10783 /* Check for new expression first. */ 10784 if (tt == TokenKind::New) { 10785 uint32_t newBegin = pos().begin; 10786 // Make sure this wasn't a |new.target| in disguise. 10787 NewTargetNodeType newTarget; 10788 if (!tryNewTarget(&newTarget)) { 10789 return errorResult(); 10790 } 10791 if (newTarget) { 10792 lhs = newTarget; 10793 } else { 10794 // Gotten by tryNewTarget 10795 tt = anyChars.currentToken().type; 10796 Node ctorExpr = 10797 MOZ_TRY(memberExpr(yieldHandling, TripledotProhibited, tt, 10798 /* allowCallSyntax = */ false, 10799 /* possibleError = */ nullptr, PredictInvoked)); 10800 10801 // If we have encountered an optional chain, in the form of `new 10802 // ClassName?.()` then we need to throw, as this is disallowed by the 10803 // spec. 10804 bool optionalToken; 10805 if (!tokenStream.matchToken(&optionalToken, TokenKind::OptionalChain)) { 10806 return errorResult(); 10807 } 10808 if (optionalToken) { 10809 errorAt(newBegin, JSMSG_BAD_NEW_OPTIONAL); 10810 return errorResult(); 10811 } 10812 10813 bool matched; 10814 if (!tokenStream.matchToken(&matched, TokenKind::LeftParen)) { 10815 return errorResult(); 10816 } 10817 10818 bool isSpread = false; 10819 ListNodeType args; 10820 if (matched) { 10821 args = MOZ_TRY(argumentList(yieldHandling, &isSpread)); 10822 } else { 10823 args = MOZ_TRY(handler_.newArguments(pos())); 10824 } 10825 10826 if (!args) { 10827 return errorResult(); 10828 } 10829 10830 lhs = MOZ_TRY( 10831 handler_.newNewExpression(newBegin, ctorExpr, args, isSpread)); 10832 } 10833 } else if (tt == TokenKind::Super) { 10834 NameNodeType thisName = MOZ_TRY(newThisName()); 10835 lhs = MOZ_TRY(handler_.newSuperBase(thisName, pos())); 10836 } else if (tt == TokenKind::Import) { 10837 lhs = MOZ_TRY(importExpr(yieldHandling, allowCallSyntax)); 10838 } else { 10839 lhs = MOZ_TRY(primaryExpr(yieldHandling, tripledotHandling, tt, 10840 possibleError, invoked)); 10841 } 10842 10843 MOZ_ASSERT_IF(handler_.isSuperBase(lhs), 10844 anyChars.isCurrentTokenType(TokenKind::Super)); 10845 10846 while (true) { 10847 if (!tokenStream.getToken(&tt)) { 10848 return errorResult(); 10849 } 10850 if (tt == TokenKind::Eof) { 10851 anyChars.ungetToken(); 10852 break; 10853 } 10854 10855 Node nextMember; 10856 if (tt == TokenKind::Dot) { 10857 if (!tokenStream.getToken(&tt)) { 10858 return errorResult(); 10859 } 10860 10861 if (TokenKindIsPossibleIdentifierName(tt)) { 10862 nextMember = MOZ_TRY(memberPropertyAccess(lhs)); 10863 } else if (tt == TokenKind::PrivateName) { 10864 nextMember = MOZ_TRY(memberPrivateAccess(lhs)); 10865 } else { 10866 error(JSMSG_NAME_AFTER_DOT); 10867 return errorResult(); 10868 } 10869 } else if (tt == TokenKind::LeftBracket) { 10870 nextMember = MOZ_TRY(memberElemAccess(lhs, yieldHandling)); 10871 } else if ((allowCallSyntax && tt == TokenKind::LeftParen) || 10872 tt == TokenKind::TemplateHead || 10873 tt == TokenKind::NoSubsTemplate) { 10874 if (handler_.isSuperBase(lhs)) { 10875 if (!pc_->sc()->allowSuperCall()) { 10876 error(JSMSG_BAD_SUPERCALL); 10877 return errorResult(); 10878 } 10879 10880 if (tt != TokenKind::LeftParen) { 10881 error(JSMSG_BAD_SUPER); 10882 return errorResult(); 10883 } 10884 10885 nextMember = MOZ_TRY(memberSuperCall(lhs, yieldHandling)); 10886 10887 if (!noteUsedName( 10888 TaggedParserAtomIndex::WellKnown::dot_initializers_())) { 10889 return errorResult(); 10890 } 10891 #ifdef ENABLE_DECORATORS 10892 if (!noteUsedName(TaggedParserAtomIndex::WellKnown:: 10893 dot_instanceExtraInitializers_())) { 10894 return null(); 10895 } 10896 #endif 10897 } else { 10898 nextMember = MOZ_TRY(memberCall(tt, lhs, yieldHandling, possibleError)); 10899 } 10900 } else { 10901 anyChars.ungetToken(); 10902 if (handler_.isSuperBase(lhs)) { 10903 break; 10904 } 10905 return lhs; 10906 } 10907 10908 lhs = nextMember; 10909 } 10910 10911 if (handler_.isSuperBase(lhs)) { 10912 error(JSMSG_BAD_SUPER); 10913 return errorResult(); 10914 } 10915 10916 return lhs; 10917 } 10918 10919 template <class ParseHandler, typename Unit> 10920 typename ParseHandler::NodeResult 10921 GeneralParser<ParseHandler, Unit>::decoratorExpr(YieldHandling yieldHandling, 10922 TokenKind tt) { 10923 MOZ_ASSERT(anyChars.isCurrentTokenType(tt)); 10924 10925 AutoCheckRecursionLimit recursion(this->fc_); 10926 if (!recursion.check(this->fc_)) { 10927 return errorResult(); 10928 } 10929 10930 if (tt == TokenKind::LeftParen) { 10931 // DecoratorParenthesizedExpression 10932 Node expr = MOZ_TRY(exprInParens(InAllowed, yieldHandling, TripledotAllowed, 10933 /* possibleError*/ nullptr)); 10934 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_DECORATOR)) { 10935 return errorResult(); 10936 } 10937 10938 return handler_.parenthesize(expr); 10939 } 10940 10941 if (!TokenKindIsPossibleIdentifier(tt)) { 10942 error(JSMSG_DECORATOR_NAME_EXPECTED); 10943 return errorResult(); 10944 } 10945 10946 TaggedParserAtomIndex name = identifierReference(yieldHandling); 10947 if (!name) { 10948 return errorResult(); 10949 } 10950 10951 Node lhs = MOZ_TRY(identifierReference(name)); 10952 10953 while (true) { 10954 if (!tokenStream.getToken(&tt)) { 10955 return errorResult(); 10956 } 10957 if (tt == TokenKind::Eof) { 10958 anyChars.ungetToken(); 10959 break; 10960 } 10961 10962 Node nextMember; 10963 if (tt == TokenKind::Dot) { 10964 if (!tokenStream.getToken(&tt)) { 10965 return errorResult(); 10966 } 10967 10968 if (TokenKindIsPossibleIdentifierName(tt)) { 10969 nextMember = MOZ_TRY(memberPropertyAccess(lhs)); 10970 } else if (tt == TokenKind::PrivateName) { 10971 nextMember = MOZ_TRY(memberPrivateAccess(lhs)); 10972 } else { 10973 error(JSMSG_NAME_AFTER_DOT); 10974 return errorResult(); 10975 } 10976 } else if (tt == TokenKind::LeftParen) { 10977 nextMember = MOZ_TRY(memberCall(tt, lhs, yieldHandling, 10978 /* possibleError */ nullptr)); 10979 lhs = nextMember; 10980 // This is a `DecoratorCallExpression` and it's defined at the top level 10981 // of `Decorator`, no other `DecoratorMemberExpression` is allowed to 10982 // follow after the arguments. 10983 break; 10984 } else { 10985 anyChars.ungetToken(); 10986 break; 10987 } 10988 10989 lhs = nextMember; 10990 } 10991 10992 return lhs; 10993 } 10994 10995 template <class ParseHandler> 10996 inline typename ParseHandler::NameNodeResult 10997 PerHandlerParser<ParseHandler>::newName(TaggedParserAtomIndex name) { 10998 return newName(name, pos()); 10999 } 11000 11001 template <class ParseHandler> 11002 inline typename ParseHandler::NameNodeResult 11003 PerHandlerParser<ParseHandler>::newName(TaggedParserAtomIndex name, 11004 TokenPos pos) { 11005 if (name == TaggedParserAtomIndex::WellKnown::arguments()) { 11006 this->pc_->numberOfArgumentsNames++; 11007 } 11008 return handler_.newName(name, pos); 11009 } 11010 11011 template <class ParseHandler> 11012 inline typename ParseHandler::NameNodeResult 11013 PerHandlerParser<ParseHandler>::newPrivateName(TaggedParserAtomIndex name) { 11014 return handler_.newPrivateName(name, pos()); 11015 } 11016 11017 template <class ParseHandler, typename Unit> 11018 typename ParseHandler::NodeResult 11019 GeneralParser<ParseHandler, Unit>::memberPropertyAccess( 11020 Node lhs, OptionalKind optionalKind /* = OptionalKind::NonOptional */) { 11021 MOZ_ASSERT(TokenKindIsPossibleIdentifierName(anyChars.currentToken().type) || 11022 anyChars.currentToken().type == TokenKind::PrivateName); 11023 TaggedParserAtomIndex field = anyChars.currentName(); 11024 if (handler_.isSuperBase(lhs) && !checkAndMarkSuperScope()) { 11025 error(JSMSG_BAD_SUPERPROP, "property"); 11026 return errorResult(); 11027 } 11028 11029 NameNodeType name = MOZ_TRY(handler_.newPropertyName(field, pos())); 11030 11031 if (optionalKind == OptionalKind::Optional) { 11032 MOZ_ASSERT(!handler_.isSuperBase(lhs)); 11033 return handler_.newOptionalPropertyAccess(lhs, name); 11034 } 11035 11036 if (handler_.isArgumentsName(lhs) && handler_.isLengthName(name)) { 11037 MOZ_ASSERT(pc_->numberOfArgumentsNames > 0); 11038 pc_->numberOfArgumentsNames--; 11039 // Currently when resuming Generators don't get their argument length set 11040 // in the interpreter frame (see InterpreterStack::resumeGeneratorCallFrame, 11041 // and its call to initCallFrame). 11042 if (pc_->isGeneratorOrAsync()) { 11043 pc_->sc()->setIneligibleForArgumentsLength(); 11044 } 11045 return handler_.newArgumentsLength(lhs, name); 11046 } 11047 11048 return handler_.newPropertyAccess(lhs, name); 11049 } 11050 11051 template <class ParseHandler, typename Unit> 11052 typename ParseHandler::NodeResult 11053 GeneralParser<ParseHandler, Unit>::memberPrivateAccess( 11054 Node lhs, OptionalKind optionalKind /* = OptionalKind::NonOptional */) { 11055 MOZ_ASSERT(anyChars.currentToken().type == TokenKind::PrivateName); 11056 11057 TaggedParserAtomIndex field = anyChars.currentName(); 11058 // Cannot access private fields on super. 11059 if (handler_.isSuperBase(lhs)) { 11060 error(JSMSG_BAD_SUPERPRIVATE); 11061 return errorResult(); 11062 } 11063 11064 NameNodeType privateName = MOZ_TRY(privateNameReference(field)); 11065 11066 if (optionalKind == OptionalKind::Optional) { 11067 MOZ_ASSERT(!handler_.isSuperBase(lhs)); 11068 return handler_.newOptionalPrivateMemberAccess(lhs, privateName, pos().end); 11069 } 11070 return handler_.newPrivateMemberAccess(lhs, privateName, pos().end); 11071 } 11072 11073 template <class ParseHandler, typename Unit> 11074 typename ParseHandler::NodeResult 11075 GeneralParser<ParseHandler, Unit>::memberElemAccess( 11076 Node lhs, YieldHandling yieldHandling, 11077 OptionalKind optionalKind /* = OptionalKind::NonOptional */) { 11078 MOZ_ASSERT(anyChars.currentToken().type == TokenKind::LeftBracket); 11079 Node propExpr = MOZ_TRY(expr(InAllowed, yieldHandling, TripledotProhibited)); 11080 11081 if (!mustMatchToken(TokenKind::RightBracket, JSMSG_BRACKET_IN_INDEX)) { 11082 return errorResult(); 11083 } 11084 11085 if (handler_.isSuperBase(lhs) && !checkAndMarkSuperScope()) { 11086 error(JSMSG_BAD_SUPERPROP, "member"); 11087 return errorResult(); 11088 } 11089 if (optionalKind == OptionalKind::Optional) { 11090 MOZ_ASSERT(!handler_.isSuperBase(lhs)); 11091 return handler_.newOptionalPropertyByValue(lhs, propExpr, pos().end); 11092 } 11093 return handler_.newPropertyByValue(lhs, propExpr, pos().end); 11094 } 11095 11096 template <class ParseHandler, typename Unit> 11097 typename ParseHandler::NodeResult 11098 GeneralParser<ParseHandler, Unit>::memberSuperCall( 11099 Node lhs, YieldHandling yieldHandling) { 11100 MOZ_ASSERT(anyChars.currentToken().type == TokenKind::LeftParen); 11101 // Despite the fact that it's impossible to have |super()| in a 11102 // generator, we still inherit the yieldHandling of the 11103 // memberExpression, per spec. Curious. 11104 bool isSpread = false; 11105 ListNodeType args = MOZ_TRY(argumentList(yieldHandling, &isSpread)); 11106 11107 CallNodeType superCall = MOZ_TRY(handler_.newSuperCall(lhs, args, isSpread)); 11108 11109 // |super()| implicitly reads |new.target|. 11110 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) { 11111 return errorResult(); 11112 } 11113 11114 NameNodeType thisName = MOZ_TRY(newThisName()); 11115 11116 return handler_.newSetThis(thisName, superCall); 11117 } 11118 11119 template <class ParseHandler, typename Unit> 11120 typename ParseHandler::NodeResult GeneralParser<ParseHandler, Unit>::memberCall( 11121 TokenKind tt, Node lhs, YieldHandling yieldHandling, 11122 PossibleError* possibleError /* = nullptr */, 11123 OptionalKind optionalKind /* = OptionalKind::NonOptional */) { 11124 if (options().selfHostingMode && 11125 (handler_.isPropertyOrPrivateMemberAccess(lhs) || 11126 handler_.isOptionalPropertyOrPrivateMemberAccess(lhs))) { 11127 error(JSMSG_SELFHOSTED_METHOD_CALL); 11128 return errorResult(); 11129 } 11130 11131 MOZ_ASSERT(tt == TokenKind::LeftParen || tt == TokenKind::TemplateHead || 11132 tt == TokenKind::NoSubsTemplate, 11133 "Unexpected token kind for member call"); 11134 11135 JSOp op = JSOp::Call; 11136 bool maybeAsyncArrow = false; 11137 if (tt == TokenKind::LeftParen && optionalKind == OptionalKind::NonOptional) { 11138 if (handler_.isAsyncKeyword(lhs)) { 11139 // |async (| can be the start of an async arrow 11140 // function, so we need to defer reporting possible 11141 // errors from destructuring syntax. To give better 11142 // error messages, we only allow the AsyncArrowHead 11143 // part of the CoverCallExpressionAndAsyncArrowHead 11144 // syntax when the initial name is "async". 11145 maybeAsyncArrow = true; 11146 } else if (handler_.isEvalName(lhs)) { 11147 // Select the right Eval op and flag pc_ as having a 11148 // direct eval. 11149 op = pc_->sc()->strict() ? JSOp::StrictEval : JSOp::Eval; 11150 pc_->sc()->setBindingsAccessedDynamically(); 11151 pc_->sc()->setHasDirectEval(); 11152 11153 // In non-strict mode code, direct calls to eval can 11154 // add variables to the call object. 11155 if (pc_->isFunctionBox() && !pc_->sc()->strict()) { 11156 pc_->functionBox()->setFunHasExtensibleScope(); 11157 } 11158 11159 // If we're in a method, mark the method as requiring 11160 // support for 'super', since direct eval code can use 11161 // it. (If we're not in a method, that's fine, so 11162 // ignore the return value.) 11163 checkAndMarkSuperScope(); 11164 } 11165 } 11166 11167 if (tt == TokenKind::LeftParen) { 11168 bool isSpread = false; 11169 PossibleError* asyncPossibleError = 11170 maybeAsyncArrow ? possibleError : nullptr; 11171 ListNodeType args = 11172 MOZ_TRY(argumentList(yieldHandling, &isSpread, asyncPossibleError)); 11173 if (isSpread) { 11174 if (op == JSOp::Eval) { 11175 op = JSOp::SpreadEval; 11176 } else if (op == JSOp::StrictEval) { 11177 op = JSOp::StrictSpreadEval; 11178 } else { 11179 op = JSOp::SpreadCall; 11180 } 11181 } 11182 11183 if (optionalKind == OptionalKind::Optional) { 11184 return handler_.newOptionalCall(lhs, args, op); 11185 } 11186 return handler_.newCall(lhs, args, op); 11187 } 11188 11189 ListNodeType args = MOZ_TRY(handler_.newArguments(pos())); 11190 11191 if (!taggedTemplate(yieldHandling, args, tt)) { 11192 return errorResult(); 11193 } 11194 11195 if (optionalKind == OptionalKind::Optional) { 11196 error(JSMSG_BAD_OPTIONAL_TEMPLATE); 11197 return errorResult(); 11198 } 11199 11200 return handler_.newTaggedTemplate(lhs, args, op); 11201 } 11202 11203 template <class ParseHandler, typename Unit> 11204 bool GeneralParser<ParseHandler, Unit>::checkLabelOrIdentifierReference( 11205 TaggedParserAtomIndex ident, uint32_t offset, YieldHandling yieldHandling, 11206 TokenKind hint /* = TokenKind::Limit */) { 11207 TokenKind tt; 11208 if (hint == TokenKind::Limit) { 11209 tt = ReservedWordTokenKind(ident); 11210 } else { 11211 // All non-reserved word kinds are folded into TokenKind::Limit in 11212 // ReservedWordTokenKind and the following code. 11213 if (hint == TokenKind::Name || hint == TokenKind::PrivateName) { 11214 hint = TokenKind::Limit; 11215 } 11216 MOZ_ASSERT(hint == ReservedWordTokenKind(ident), 11217 "hint doesn't match actual token kind"); 11218 tt = hint; 11219 } 11220 11221 if (!pc_->sc()->allowArguments() && 11222 ident == TaggedParserAtomIndex::WellKnown::arguments()) { 11223 error(JSMSG_BAD_ARGUMENTS); 11224 return false; 11225 } 11226 11227 if (tt == TokenKind::Limit) { 11228 // Either TokenKind::Name or TokenKind::PrivateName 11229 return true; 11230 } 11231 if (TokenKindIsContextualKeyword(tt)) { 11232 if (tt == TokenKind::Yield) { 11233 if (yieldHandling == YieldIsKeyword) { 11234 errorAt(offset, JSMSG_RESERVED_ID, "yield"); 11235 return false; 11236 } 11237 if (pc_->sc()->strict()) { 11238 if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield")) { 11239 return false; 11240 } 11241 } 11242 return true; 11243 } 11244 if (tt == TokenKind::Await) { 11245 if (awaitIsKeyword() || awaitIsDisallowed()) { 11246 errorAt(offset, JSMSG_RESERVED_ID, "await"); 11247 return false; 11248 } 11249 return true; 11250 } 11251 if (pc_->sc()->strict()) { 11252 if (tt == TokenKind::Let) { 11253 if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let")) { 11254 return false; 11255 } 11256 return true; 11257 } 11258 if (tt == TokenKind::Static) { 11259 if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static")) { 11260 return false; 11261 } 11262 return true; 11263 } 11264 } 11265 return true; 11266 } 11267 if (TokenKindIsStrictReservedWord(tt)) { 11268 if (pc_->sc()->strict()) { 11269 if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, 11270 ReservedWordToCharZ(tt))) { 11271 return false; 11272 } 11273 } 11274 return true; 11275 } 11276 if (TokenKindIsKeyword(tt) || TokenKindIsReservedWordLiteral(tt)) { 11277 errorAt(offset, JSMSG_INVALID_ID, ReservedWordToCharZ(tt)); 11278 return false; 11279 } 11280 if (TokenKindIsFutureReservedWord(tt)) { 11281 errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt)); 11282 return false; 11283 } 11284 MOZ_ASSERT_UNREACHABLE("Unexpected reserved word kind."); 11285 return false; 11286 } 11287 11288 template <class ParseHandler, typename Unit> 11289 bool GeneralParser<ParseHandler, Unit>::checkBindingIdentifier( 11290 TaggedParserAtomIndex ident, uint32_t offset, YieldHandling yieldHandling, 11291 TokenKind hint /* = TokenKind::Limit */) { 11292 if (pc_->sc()->strict()) { 11293 if (ident == TaggedParserAtomIndex::WellKnown::arguments()) { 11294 if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "arguments")) { 11295 return false; 11296 } 11297 return true; 11298 } 11299 11300 if (ident == TaggedParserAtomIndex::WellKnown::eval()) { 11301 if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "eval")) { 11302 return false; 11303 } 11304 return true; 11305 } 11306 } 11307 11308 return checkLabelOrIdentifierReference(ident, offset, yieldHandling, hint); 11309 } 11310 11311 template <class ParseHandler, typename Unit> 11312 TaggedParserAtomIndex 11313 GeneralParser<ParseHandler, Unit>::labelOrIdentifierReference( 11314 YieldHandling yieldHandling) { 11315 // ES 2017 draft 12.1.1. 11316 // StringValue of IdentifierName normalizes any Unicode escape sequences 11317 // in IdentifierName hence such escapes cannot be used to write an 11318 // Identifier whose code point sequence is the same as a ReservedWord. 11319 // 11320 // Use const ParserName* instead of TokenKind to reflect the normalization. 11321 11322 // Unless the name contains escapes, we can reuse the current TokenKind 11323 // to determine if the name is a restricted identifier. 11324 TokenKind hint = !anyChars.currentNameHasEscapes(this->parserAtoms()) 11325 ? anyChars.currentToken().type 11326 : TokenKind::Limit; 11327 TaggedParserAtomIndex ident = anyChars.currentName(); 11328 if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling, 11329 hint)) { 11330 return TaggedParserAtomIndex::null(); 11331 } 11332 return ident; 11333 } 11334 11335 template <class ParseHandler, typename Unit> 11336 TaggedParserAtomIndex GeneralParser<ParseHandler, Unit>::bindingIdentifier( 11337 YieldHandling yieldHandling) { 11338 TokenKind hint = !anyChars.currentNameHasEscapes(this->parserAtoms()) 11339 ? anyChars.currentToken().type 11340 : TokenKind::Limit; 11341 TaggedParserAtomIndex ident = anyChars.currentName(); 11342 if (!checkBindingIdentifier(ident, pos().begin, yieldHandling, hint)) { 11343 return TaggedParserAtomIndex::null(); 11344 } 11345 return ident; 11346 } 11347 11348 template <class ParseHandler> 11349 typename ParseHandler::NameNodeResult 11350 PerHandlerParser<ParseHandler>::identifierReference( 11351 TaggedParserAtomIndex name) { 11352 NameNodeType id = MOZ_TRY(newName(name)); 11353 11354 if (!noteUsedName(name)) { 11355 return errorResult(); 11356 } 11357 11358 return id; 11359 } 11360 11361 template <class ParseHandler> 11362 typename ParseHandler::NameNodeResult 11363 PerHandlerParser<ParseHandler>::privateNameReference( 11364 TaggedParserAtomIndex name) { 11365 NameNodeType id = MOZ_TRY(newPrivateName(name)); 11366 11367 if (!noteUsedName(name, NameVisibility::Private, Some(pos()))) { 11368 return errorResult(); 11369 } 11370 11371 return id; 11372 } 11373 11374 template <class ParseHandler> 11375 typename ParseHandler::NameNodeResult 11376 PerHandlerParser<ParseHandler>::stringLiteral() { 11377 return handler_.newStringLiteral(anyChars.currentToken().atom(), pos()); 11378 } 11379 11380 template <class ParseHandler> 11381 typename ParseHandler::NodeResult 11382 PerHandlerParser<ParseHandler>::noSubstitutionTaggedTemplate() { 11383 if (anyChars.hasInvalidTemplateEscape()) { 11384 anyChars.clearInvalidTemplateEscape(); 11385 return handler_.newRawUndefinedLiteral(pos()); 11386 } 11387 11388 return handler_.newTemplateStringLiteral(anyChars.currentToken().atom(), 11389 pos()); 11390 } 11391 11392 template <class ParseHandler, typename Unit> 11393 typename ParseHandler::NameNodeResult 11394 GeneralParser<ParseHandler, Unit>::noSubstitutionUntaggedTemplate() { 11395 if (!tokenStream.checkForInvalidTemplateEscapeError()) { 11396 return errorResult(); 11397 } 11398 11399 return handler_.newTemplateStringLiteral(anyChars.currentToken().atom(), 11400 pos()); 11401 } 11402 11403 template <typename Unit> 11404 FullParseHandler::RegExpLiteralResult 11405 Parser<FullParseHandler, Unit>::newRegExp() { 11406 MOZ_ASSERT(!options().selfHostingMode); 11407 11408 // Create the regexp and check its syntax. 11409 const auto& chars = tokenStream.getCharBuffer(); 11410 mozilla::Range<const char16_t> range(chars.begin(), chars.length()); 11411 RegExpFlags flags = anyChars.currentToken().regExpFlags(); 11412 11413 uint32_t offset = anyChars.currentToken().pos.begin; 11414 uint32_t line; 11415 JS::LimitedColumnNumberOneOrigin column; 11416 tokenStream.computeLineAndColumn(offset, &line, &column); 11417 11418 if (!handler_.reuseRegexpSyntaxParse()) { 11419 // Verify that the Regexp will syntax parse when the time comes to 11420 // instantiate it. If we have already done a syntax parse, we can 11421 // skip this. 11422 if (!irregexp::CheckPatternSyntax( 11423 this->alloc_, this->fc_->stackLimit(), anyChars, range, flags, 11424 Some(line), Some(JS::ColumnNumberOneOrigin(column)))) { 11425 return errorResult(); 11426 } 11427 } 11428 11429 auto atom = 11430 this->parserAtoms().internChar16(fc_, chars.begin(), chars.length()); 11431 if (!atom) { 11432 return errorResult(); 11433 } 11434 // RegExp patterm must be atomized. 11435 this->parserAtoms().markUsedByStencil(atom, ParserAtom::Atomize::Yes); 11436 11437 RegExpIndex index(this->compilationState_.regExpData.length()); 11438 if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) { 11439 ReportAllocationOverflow(fc_); 11440 return errorResult(); 11441 } 11442 if (!this->compilationState_.regExpData.emplaceBack(atom, flags)) { 11443 js::ReportOutOfMemory(this->fc_); 11444 return errorResult(); 11445 } 11446 11447 return handler_.newRegExp(index, pos()); 11448 } 11449 11450 template <typename Unit> 11451 SyntaxParseHandler::RegExpLiteralResult 11452 Parser<SyntaxParseHandler, Unit>::newRegExp() { 11453 MOZ_ASSERT(!options().selfHostingMode); 11454 11455 // Only check the regexp's syntax, but don't create a regexp object. 11456 const auto& chars = tokenStream.getCharBuffer(); 11457 RegExpFlags flags = anyChars.currentToken().regExpFlags(); 11458 11459 uint32_t offset = anyChars.currentToken().pos.begin; 11460 uint32_t line; 11461 JS::LimitedColumnNumberOneOrigin column; 11462 tokenStream.computeLineAndColumn(offset, &line, &column); 11463 11464 mozilla::Range<const char16_t> source(chars.begin(), chars.length()); 11465 if (!irregexp::CheckPatternSyntax(this->alloc_, this->fc_->stackLimit(), 11466 anyChars, source, flags, Some(line), 11467 Some(JS::ColumnNumberOneOrigin(column)))) { 11468 return errorResult(); 11469 } 11470 11471 return handler_.newRegExp(SyntaxParseHandler::Node::NodeGeneric, pos()); 11472 } 11473 11474 template <class ParseHandler, typename Unit> 11475 typename ParseHandler::RegExpLiteralResult 11476 GeneralParser<ParseHandler, Unit>::newRegExp() { 11477 return asFinalParser()->newRegExp(); 11478 } 11479 11480 template <typename Unit> 11481 FullParseHandler::BigIntLiteralResult 11482 Parser<FullParseHandler, Unit>::newBigInt() { 11483 // The token's charBuffer contains the DecimalIntegerLiteral or 11484 // NonDecimalIntegerLiteral production, and as such does not include the 11485 // BigIntLiteralSuffix (the trailing "n"). Note that NonDecimalIntegerLiteral 11486 // productions start with 0[bBoOxX], indicating binary/octal/hex. 11487 const auto& chars = tokenStream.getCharBuffer(); 11488 if (chars.length() > UINT32_MAX) { 11489 ReportAllocationOverflow(fc_); 11490 return errorResult(); 11491 } 11492 11493 BigIntIndex index(this->bigInts().length()); 11494 if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) { 11495 ReportAllocationOverflow(fc_); 11496 return errorResult(); 11497 } 11498 if (!this->bigInts().emplaceBack()) { 11499 js::ReportOutOfMemory(this->fc_); 11500 return errorResult(); 11501 } 11502 11503 if (!this->bigInts()[index].init(this->fc_, this->stencilAlloc(), chars)) { 11504 return errorResult(); 11505 } 11506 11507 // Should the operations below fail, the buffer held by data will 11508 // be cleaned up by the CompilationState destructor. 11509 return handler_.newBigInt(index, pos()); 11510 } 11511 11512 template <typename Unit> 11513 SyntaxParseHandler::BigIntLiteralResult 11514 Parser<SyntaxParseHandler, Unit>::newBigInt() { 11515 // The tokenizer has already checked the syntax of the bigint. 11516 11517 return handler_.newBigInt(); 11518 } 11519 11520 template <class ParseHandler, typename Unit> 11521 typename ParseHandler::BigIntLiteralResult 11522 GeneralParser<ParseHandler, Unit>::newBigInt() { 11523 return asFinalParser()->newBigInt(); 11524 } 11525 11526 // |exprPossibleError| is the PossibleError state within |expr|, 11527 // |possibleError| is the surrounding PossibleError state. 11528 template <class ParseHandler, typename Unit> 11529 bool GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentTarget( 11530 Node expr, TokenPos exprPos, PossibleError* exprPossibleError, 11531 PossibleError* possibleError, TargetBehavior behavior) { 11532 // Report any pending expression error if we're definitely not in a 11533 // destructuring context or the possible destructuring target is a 11534 // property accessor. 11535 if (!possibleError || handler_.isPropertyOrPrivateMemberAccess(expr)) { 11536 return exprPossibleError->checkForExpressionError(); 11537 } 11538 11539 // |expr| may end up as a destructuring assignment target, so we need to 11540 // validate it's either a name or can be parsed as a nested destructuring 11541 // pattern. Property accessors are also valid assignment targets, but 11542 // those are already handled above. 11543 11544 exprPossibleError->transferErrorsTo(possibleError); 11545 11546 // Return early if a pending destructuring error is already present. 11547 if (possibleError->hasPendingDestructuringError()) { 11548 return true; 11549 } 11550 11551 if (handler_.isName(expr)) { 11552 checkDestructuringAssignmentName(handler_.asNameNode(expr), exprPos, 11553 possibleError); 11554 return true; 11555 } 11556 11557 if (handler_.isUnparenthesizedDestructuringPattern(expr)) { 11558 if (behavior == TargetBehavior::ForbidAssignmentPattern) { 11559 possibleError->setPendingDestructuringErrorAt(exprPos, 11560 JSMSG_BAD_DESTRUCT_TARGET); 11561 } 11562 return true; 11563 } 11564 11565 // Parentheses are forbidden around destructuring *patterns* (but allowed 11566 // around names). Use our nicer error message for parenthesized, nested 11567 // patterns if nested destructuring patterns are allowed. 11568 if (handler_.isParenthesizedDestructuringPattern(expr) && 11569 behavior != TargetBehavior::ForbidAssignmentPattern) { 11570 possibleError->setPendingDestructuringErrorAt(exprPos, 11571 JSMSG_BAD_DESTRUCT_PARENS); 11572 } else { 11573 possibleError->setPendingDestructuringErrorAt(exprPos, 11574 JSMSG_BAD_DESTRUCT_TARGET); 11575 } 11576 11577 return true; 11578 } 11579 11580 template <class ParseHandler, typename Unit> 11581 void GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentName( 11582 NameNodeType name, TokenPos namePos, PossibleError* possibleError) { 11583 #ifdef DEBUG 11584 // GCC 8.0.1 crashes if this is a one-liner. 11585 bool isName = handler_.isName(name); 11586 MOZ_ASSERT(isName); 11587 #endif 11588 11589 // Return early if a pending destructuring error is already present. 11590 if (possibleError->hasPendingDestructuringError()) { 11591 return; 11592 } 11593 11594 if (handler_.isArgumentsLength(name)) { 11595 pc_->sc()->setIneligibleForArgumentsLength(); 11596 } 11597 11598 if (pc_->sc()->strict()) { 11599 if (handler_.isArgumentsName(name)) { 11600 if (pc_->sc()->strict()) { 11601 possibleError->setPendingDestructuringErrorAt( 11602 namePos, JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS); 11603 } else { 11604 possibleError->setPendingDestructuringWarningAt( 11605 namePos, JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS); 11606 } 11607 return; 11608 } 11609 11610 if (handler_.isEvalName(name)) { 11611 if (pc_->sc()->strict()) { 11612 possibleError->setPendingDestructuringErrorAt( 11613 namePos, JSMSG_BAD_STRICT_ASSIGN_EVAL); 11614 } else { 11615 possibleError->setPendingDestructuringWarningAt( 11616 namePos, JSMSG_BAD_STRICT_ASSIGN_EVAL); 11617 } 11618 return; 11619 } 11620 } 11621 } 11622 11623 template <class ParseHandler, typename Unit> 11624 bool GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentElement( 11625 Node expr, TokenPos exprPos, PossibleError* exprPossibleError, 11626 PossibleError* possibleError) { 11627 // ES2018 draft rev 0719f44aab93215ed9a626b2f45bd34f36916834 11628 // 12.15.5 Destructuring Assignment 11629 // 11630 // AssignmentElement[Yield, Await]: 11631 // DestructuringAssignmentTarget[?Yield, ?Await] 11632 // DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, 11633 // ?Yield, 11634 // ?Await] 11635 11636 // If |expr| is an assignment element with an initializer expression, its 11637 // destructuring assignment target was already validated in assignExpr(). 11638 // Otherwise we need to check that |expr| is a valid destructuring target. 11639 if (handler_.isUnparenthesizedAssignment(expr)) { 11640 // Report any pending expression error if we're definitely not in a 11641 // destructuring context. 11642 if (!possibleError) { 11643 return exprPossibleError->checkForExpressionError(); 11644 } 11645 11646 exprPossibleError->transferErrorsTo(possibleError); 11647 return true; 11648 } 11649 return checkDestructuringAssignmentTarget(expr, exprPos, exprPossibleError, 11650 possibleError); 11651 } 11652 11653 template <class ParseHandler, typename Unit> 11654 typename ParseHandler::ListNodeResult 11655 GeneralParser<ParseHandler, Unit>::arrayInitializer( 11656 YieldHandling yieldHandling, PossibleError* possibleError) { 11657 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket)); 11658 11659 uint32_t begin = pos().begin; 11660 ListNodeType literal = MOZ_TRY(handler_.newArrayLiteral(begin)); 11661 11662 TokenKind tt; 11663 if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) { 11664 return errorResult(); 11665 } 11666 11667 if (tt == TokenKind::RightBracket) { 11668 /* 11669 * Mark empty arrays as non-constant, since we cannot easily 11670 * determine their type. 11671 */ 11672 handler_.setListHasNonConstInitializer(literal); 11673 } else { 11674 anyChars.ungetToken(); 11675 11676 for (uint32_t index = 0;; index++) { 11677 if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) { 11678 error(JSMSG_ARRAY_INIT_TOO_BIG); 11679 return errorResult(); 11680 } 11681 11682 TokenKind tt; 11683 if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { 11684 return errorResult(); 11685 } 11686 if (tt == TokenKind::RightBracket) { 11687 break; 11688 } 11689 11690 if (tt == TokenKind::Comma) { 11691 tokenStream.consumeKnownToken(TokenKind::Comma, 11692 TokenStream::SlashIsRegExp); 11693 if (!handler_.addElision(literal, pos())) { 11694 return errorResult(); 11695 } 11696 continue; 11697 } 11698 11699 if (tt == TokenKind::TripleDot) { 11700 tokenStream.consumeKnownToken(TokenKind::TripleDot, 11701 TokenStream::SlashIsRegExp); 11702 uint32_t begin = pos().begin; 11703 11704 TokenPos innerPos; 11705 if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) { 11706 return errorResult(); 11707 } 11708 11709 PossibleError possibleErrorInner(*this); 11710 Node inner = 11711 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited, 11712 &possibleErrorInner)); 11713 if (!checkDestructuringAssignmentTarget( 11714 inner, innerPos, &possibleErrorInner, possibleError)) { 11715 return errorResult(); 11716 } 11717 11718 if (!handler_.addSpreadElement(literal, begin, inner)) { 11719 return errorResult(); 11720 } 11721 } else { 11722 TokenPos elementPos; 11723 if (!tokenStream.peekTokenPos(&elementPos, 11724 TokenStream::SlashIsRegExp)) { 11725 return errorResult(); 11726 } 11727 11728 PossibleError possibleErrorInner(*this); 11729 Node element = 11730 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited, 11731 &possibleErrorInner)); 11732 if (!checkDestructuringAssignmentElement( 11733 element, elementPos, &possibleErrorInner, possibleError)) { 11734 return errorResult(); 11735 } 11736 handler_.addArrayElement(literal, element); 11737 } 11738 11739 bool matched; 11740 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 11741 TokenStream::SlashIsRegExp)) { 11742 return errorResult(); 11743 } 11744 if (!matched) { 11745 break; 11746 } 11747 11748 if (tt == TokenKind::TripleDot && possibleError) { 11749 possibleError->setPendingDestructuringErrorAt(pos(), 11750 JSMSG_REST_WITH_COMMA); 11751 } 11752 } 11753 11754 if (!mustMatchToken( 11755 TokenKind::RightBracket, [this, begin](TokenKind actual) { 11756 this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST, 11757 JSMSG_BRACKET_OPENED, begin); 11758 })) { 11759 return errorResult(); 11760 } 11761 } 11762 11763 handler_.setEndPosition(literal, pos().end); 11764 return literal; 11765 } 11766 11767 template <class ParseHandler, typename Unit> 11768 typename ParseHandler::NodeResult 11769 GeneralParser<ParseHandler, Unit>::propertyName( 11770 YieldHandling yieldHandling, PropertyNameContext propertyNameContext, 11771 const Maybe<DeclarationKind>& maybeDecl, ListNodeType propList, 11772 TaggedParserAtomIndex* propAtomOut) { 11773 // PropertyName[Yield, Await]: 11774 // LiteralPropertyName 11775 // ComputedPropertyName[?Yield, ?Await] 11776 // 11777 // LiteralPropertyName: 11778 // IdentifierName 11779 // StringLiteral 11780 // NumericLiteral 11781 TokenKind ltok = anyChars.currentToken().type; 11782 11783 *propAtomOut = TaggedParserAtomIndex::null(); 11784 switch (ltok) { 11785 case TokenKind::Number: { 11786 auto numAtom = NumberToParserAtom(fc_, this->parserAtoms(), 11787 anyChars.currentToken().number()); 11788 if (!numAtom) { 11789 return errorResult(); 11790 } 11791 *propAtomOut = numAtom; 11792 return newNumber(anyChars.currentToken()); 11793 } 11794 11795 case TokenKind::BigInt: { 11796 Node biNode = MOZ_TRY(newBigInt()); 11797 return handler_.newSyntheticComputedName(biNode, pos().begin, pos().end); 11798 } 11799 case TokenKind::String: { 11800 auto str = anyChars.currentToken().atom(); 11801 *propAtomOut = str; 11802 uint32_t index; 11803 if (this->parserAtoms().isIndex(str, &index)) { 11804 return handler_.newNumber(index, NoDecimal, pos()); 11805 } 11806 return stringLiteral(); 11807 } 11808 11809 case TokenKind::LeftBracket: 11810 return computedPropertyName(yieldHandling, maybeDecl, propertyNameContext, 11811 propList); 11812 11813 case TokenKind::PrivateName: { 11814 if (propertyNameContext != PropertyNameContext::PropertyNameInClass) { 11815 error(JSMSG_ILLEGAL_PRIVATE_FIELD); 11816 return errorResult(); 11817 } 11818 11819 TaggedParserAtomIndex propName = anyChars.currentName(); 11820 *propAtomOut = propName; 11821 return privateNameReference(propName); 11822 } 11823 11824 default: { 11825 if (!TokenKindIsPossibleIdentifierName(ltok)) { 11826 error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(ltok)); 11827 return errorResult(); 11828 } 11829 11830 TaggedParserAtomIndex name = anyChars.currentName(); 11831 *propAtomOut = name; 11832 return handler_.newObjectLiteralPropertyName(name, pos()); 11833 } 11834 } 11835 } 11836 11837 // True if `kind` can be the first token of a PropertyName. 11838 static bool TokenKindCanStartPropertyName(TokenKind tt) { 11839 return TokenKindIsPossibleIdentifierName(tt) || tt == TokenKind::String || 11840 tt == TokenKind::Number || tt == TokenKind::LeftBracket || 11841 tt == TokenKind::BigInt || tt == TokenKind::PrivateName; 11842 } 11843 11844 template <class ParseHandler, typename Unit> 11845 typename ParseHandler::NodeResult 11846 GeneralParser<ParseHandler, Unit>::propertyOrMethodName( 11847 YieldHandling yieldHandling, PropertyNameContext propertyNameContext, 11848 const Maybe<DeclarationKind>& maybeDecl, ListNodeType propList, 11849 PropertyType* propType, TaggedParserAtomIndex* propAtomOut) { 11850 // We're parsing an object literal, class, or destructuring pattern; 11851 // propertyNameContext tells which one. This method parses any of the 11852 // following, storing the corresponding PropertyType in `*propType` to tell 11853 // the caller what we parsed: 11854 // 11855 // async [no LineTerminator here] PropertyName 11856 // ==> PropertyType::AsyncMethod 11857 // async [no LineTerminator here] * PropertyName 11858 // ==> PropertyType::AsyncGeneratorMethod 11859 // * PropertyName ==> PropertyType::GeneratorMethod 11860 // get PropertyName ==> PropertyType::Getter 11861 // set PropertyName ==> PropertyType::Setter 11862 // accessor PropertyName ==> PropertyType::FieldWithAccessor 11863 // PropertyName : ==> PropertyType::Normal 11864 // PropertyName ==> see below 11865 // 11866 // In the last case, where there's not a `:` token to consume, we peek at 11867 // (but don't consume) the next token to decide how to set `*propType`. 11868 // 11869 // `,` or `}` ==> PropertyType::Shorthand 11870 // `(` ==> PropertyType::Method 11871 // `=`, not in a class ==> PropertyType::CoverInitializedName 11872 // '=', in a class ==> PropertyType::Field 11873 // any token, in a class ==> PropertyType::Field (ASI) 11874 // 11875 // The caller must check `*propType` and throw if whatever we parsed isn't 11876 // allowed here (for example, a getter in a destructuring pattern). 11877 // 11878 // This method does *not* match `static` (allowed in classes) or `...` 11879 // (allowed in object literals and patterns). The caller must take care of 11880 // those before calling this method. 11881 11882 TokenKind ltok; 11883 if (!tokenStream.getToken(<ok, TokenStream::SlashIsInvalid)) { 11884 return errorResult(); 11885 } 11886 11887 MOZ_ASSERT(ltok != TokenKind::RightCurly, 11888 "caller should have handled TokenKind::RightCurly"); 11889 11890 // Accept `async` and/or `*`, indicating an async or generator method; 11891 // or `get` or `set` or `accessor`, indicating an accessor. 11892 bool isGenerator = false; 11893 bool isAsync = false; 11894 bool isGetter = false; 11895 bool isSetter = false; 11896 #ifdef ENABLE_DECORATORS 11897 bool hasAccessor = false; 11898 #endif 11899 11900 if (ltok == TokenKind::Async) { 11901 // `async` is also a PropertyName by itself (it's a conditional keyword), 11902 // so peek at the next token to see if we're really looking at a method. 11903 TokenKind tt = TokenKind::Eof; 11904 if (!tokenStream.peekTokenSameLine(&tt)) { 11905 return errorResult(); 11906 } 11907 if (TokenKindCanStartPropertyName(tt) || tt == TokenKind::Mul) { 11908 isAsync = true; 11909 tokenStream.consumeKnownToken(tt); 11910 ltok = tt; 11911 } 11912 } 11913 11914 if (ltok == TokenKind::Mul) { 11915 isGenerator = true; 11916 if (!tokenStream.getToken(<ok)) { 11917 return errorResult(); 11918 } 11919 } 11920 11921 if (!isAsync && !isGenerator && 11922 (ltok == TokenKind::Get || ltok == TokenKind::Set)) { 11923 // We have parsed |get| or |set|. Look for an accessor property 11924 // name next. 11925 TokenKind tt; 11926 if (!tokenStream.peekToken(&tt)) { 11927 return errorResult(); 11928 } 11929 if (TokenKindCanStartPropertyName(tt)) { 11930 tokenStream.consumeKnownToken(tt); 11931 isGetter = (ltok == TokenKind::Get); 11932 isSetter = (ltok == TokenKind::Set); 11933 } 11934 } 11935 11936 #ifdef ENABLE_DECORATORS 11937 if (!isGenerator && !isAsync && propertyNameContext == PropertyNameInClass && 11938 ltok == TokenKind::Accessor) { 11939 MOZ_ASSERT(!isGetter && !isSetter); 11940 TokenKind tt; 11941 if (!tokenStream.peekTokenSameLine(&tt)) { 11942 return errorResult(); 11943 } 11944 11945 // The target rule is `accessor [no LineTerminator here] 11946 // ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt` 11947 if (TokenKindCanStartPropertyName(tt)) { 11948 tokenStream.consumeKnownToken(tt); 11949 hasAccessor = true; 11950 } 11951 } 11952 #endif 11953 11954 Node propName = MOZ_TRY(propertyName(yieldHandling, propertyNameContext, 11955 maybeDecl, propList, propAtomOut)); 11956 11957 // Grab the next token following the property/method name. 11958 // (If this isn't a colon, we're going to either put it back or throw.) 11959 TokenKind tt; 11960 if (!tokenStream.getToken(&tt)) { 11961 return errorResult(); 11962 } 11963 11964 if (tt == TokenKind::Colon) { 11965 if (isGenerator || isAsync || isGetter || isSetter 11966 #ifdef ENABLE_DECORATORS 11967 || hasAccessor 11968 #endif 11969 ) { 11970 error(JSMSG_BAD_PROP_ID); 11971 return errorResult(); 11972 } 11973 *propType = PropertyType::Normal; 11974 return propName; 11975 } 11976 11977 if (propertyNameContext != PropertyNameInClass && 11978 TokenKindIsPossibleIdentifierName(ltok) && 11979 (tt == TokenKind::Comma || tt == TokenKind::RightCurly || 11980 tt == TokenKind::Assign)) { 11981 #ifdef ENABLE_DECORATORS 11982 MOZ_ASSERT(!hasAccessor); 11983 #endif 11984 if (isGenerator || isAsync || isGetter || isSetter) { 11985 error(JSMSG_BAD_PROP_ID); 11986 return errorResult(); 11987 } 11988 11989 anyChars.ungetToken(); 11990 *propType = tt == TokenKind::Assign ? PropertyType::CoverInitializedName 11991 : PropertyType::Shorthand; 11992 return propName; 11993 } 11994 11995 if (tt == TokenKind::LeftParen) { 11996 anyChars.ungetToken(); 11997 11998 #ifdef ENABLE_DECORATORS 11999 if (hasAccessor) { 12000 error(JSMSG_BAD_PROP_ID); 12001 return errorResult(); 12002 } 12003 #endif 12004 12005 if (isGenerator && isAsync) { 12006 *propType = PropertyType::AsyncGeneratorMethod; 12007 } else if (isGenerator) { 12008 *propType = PropertyType::GeneratorMethod; 12009 } else if (isAsync) { 12010 *propType = PropertyType::AsyncMethod; 12011 } else if (isGetter) { 12012 *propType = PropertyType::Getter; 12013 } else if (isSetter) { 12014 *propType = PropertyType::Setter; 12015 } else { 12016 *propType = PropertyType::Method; 12017 } 12018 return propName; 12019 } 12020 12021 if (propertyNameContext == PropertyNameInClass) { 12022 if (isGenerator || isAsync || isGetter || isSetter) { 12023 error(JSMSG_BAD_PROP_ID); 12024 return errorResult(); 12025 } 12026 anyChars.ungetToken(); 12027 #ifdef ENABLE_DECORATORS 12028 if (!hasAccessor) { 12029 *propType = PropertyType::Field; 12030 } else { 12031 *propType = PropertyType::FieldWithAccessor; 12032 } 12033 #else 12034 *propType = PropertyType::Field; 12035 #endif 12036 return propName; 12037 } 12038 12039 error(JSMSG_COLON_AFTER_ID); 12040 return errorResult(); 12041 } 12042 12043 template <class ParseHandler, typename Unit> 12044 typename ParseHandler::UnaryNodeResult 12045 GeneralParser<ParseHandler, Unit>::computedPropertyName( 12046 YieldHandling yieldHandling, const Maybe<DeclarationKind>& maybeDecl, 12047 PropertyNameContext propertyNameContext, ListNodeType literal) { 12048 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket)); 12049 12050 uint32_t begin = pos().begin; 12051 12052 if (maybeDecl) { 12053 if (*maybeDecl == DeclarationKind::FormalParameter) { 12054 pc_->functionBox()->hasParameterExprs = true; 12055 } 12056 } else if (propertyNameContext == 12057 PropertyNameContext::PropertyNameInLiteral) { 12058 handler_.setListHasNonConstInitializer(literal); 12059 } 12060 12061 Node assignNode = 12062 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited)); 12063 12064 if (!mustMatchToken(TokenKind::RightBracket, JSMSG_COMP_PROP_UNTERM_EXPR)) { 12065 return errorResult(); 12066 } 12067 return handler_.newComputedName(assignNode, begin, pos().end); 12068 } 12069 12070 template <class ParseHandler, typename Unit> 12071 typename ParseHandler::ListNodeResult 12072 GeneralParser<ParseHandler, Unit>::objectLiteral(YieldHandling yieldHandling, 12073 PossibleError* possibleError) { 12074 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); 12075 12076 uint32_t openedPos = pos().begin; 12077 12078 ListNodeType literal = MOZ_TRY(handler_.newObjectLiteral(pos().begin)); 12079 12080 bool seenPrototypeMutation = false; 12081 bool seenCoverInitializedName = false; 12082 Maybe<DeclarationKind> declKind = Nothing(); 12083 TaggedParserAtomIndex propAtom; 12084 for (;;) { 12085 TokenKind tt; 12086 if (!tokenStream.peekToken(&tt)) { 12087 return errorResult(); 12088 } 12089 if (tt == TokenKind::RightCurly) { 12090 break; 12091 } 12092 12093 if (tt == TokenKind::TripleDot) { 12094 tokenStream.consumeKnownToken(TokenKind::TripleDot); 12095 uint32_t begin = pos().begin; 12096 12097 TokenPos innerPos; 12098 if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) { 12099 return errorResult(); 12100 } 12101 12102 PossibleError possibleErrorInner(*this); 12103 Node inner = MOZ_TRY(assignExpr( 12104 InAllowed, yieldHandling, TripledotProhibited, &possibleErrorInner)); 12105 if (!checkDestructuringAssignmentTarget( 12106 inner, innerPos, &possibleErrorInner, possibleError, 12107 TargetBehavior::ForbidAssignmentPattern)) { 12108 return errorResult(); 12109 } 12110 if (!handler_.addSpreadProperty(literal, begin, inner)) { 12111 return errorResult(); 12112 } 12113 } else { 12114 TokenPos namePos = anyChars.nextToken().pos; 12115 12116 PropertyType propType; 12117 Node propName = MOZ_TRY( 12118 propertyOrMethodName(yieldHandling, PropertyNameInLiteral, declKind, 12119 literal, &propType, &propAtom)); 12120 12121 if (propType == PropertyType::Normal) { 12122 TokenPos exprPos; 12123 if (!tokenStream.peekTokenPos(&exprPos, TokenStream::SlashIsRegExp)) { 12124 return errorResult(); 12125 } 12126 12127 PossibleError possibleErrorInner(*this); 12128 Node propExpr = 12129 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited, 12130 &possibleErrorInner)); 12131 12132 if (!checkDestructuringAssignmentElement( 12133 propExpr, exprPos, &possibleErrorInner, possibleError)) { 12134 return errorResult(); 12135 } 12136 12137 if (propAtom == TaggedParserAtomIndex::WellKnown::proto_()) { 12138 if (seenPrototypeMutation) { 12139 // Directly report the error when we're definitely not 12140 // in a destructuring context. 12141 if (!possibleError) { 12142 errorAt(namePos.begin, JSMSG_DUPLICATE_PROTO_PROPERTY); 12143 return errorResult(); 12144 } 12145 12146 // Otherwise delay error reporting until we've 12147 // determined whether or not we're destructuring. 12148 possibleError->setPendingExpressionErrorAt( 12149 namePos, JSMSG_DUPLICATE_PROTO_PROPERTY); 12150 } 12151 seenPrototypeMutation = true; 12152 12153 // This occurs *only* if we observe PropertyType::Normal! 12154 // Only |__proto__: v| mutates [[Prototype]]. Getters, 12155 // setters, method/generator definitions, computed 12156 // property name versions of all of these, and shorthands 12157 // do not. 12158 if (!handler_.addPrototypeMutation(literal, namePos.begin, 12159 propExpr)) { 12160 return errorResult(); 12161 } 12162 } else { 12163 BinaryNodeType propDef = 12164 MOZ_TRY(handler_.newPropertyDefinition(propName, propExpr)); 12165 12166 handler_.addPropertyDefinition(literal, propDef); 12167 } 12168 } else if (propType == PropertyType::Shorthand) { 12169 /* 12170 * Support, e.g., |({x, y} = o)| as destructuring shorthand 12171 * for |({x: x, y: y} = o)|, and |var o = {x, y}| as 12172 * initializer shorthand for |var o = {x: x, y: y}|. 12173 */ 12174 TaggedParserAtomIndex name = identifierReference(yieldHandling); 12175 if (!name) { 12176 return errorResult(); 12177 } 12178 12179 NameNodeType nameExpr = MOZ_TRY(identifierReference(name)); 12180 12181 if (possibleError) { 12182 checkDestructuringAssignmentName(nameExpr, namePos, possibleError); 12183 } 12184 12185 if (!handler_.addShorthand(literal, handler_.asNameNode(propName), 12186 nameExpr)) { 12187 return errorResult(); 12188 } 12189 } else if (propType == PropertyType::CoverInitializedName) { 12190 /* 12191 * Support, e.g., |({x=1, y=2} = o)| as destructuring 12192 * shorthand with default values, as per ES6 12.14.5 12193 */ 12194 TaggedParserAtomIndex name = identifierReference(yieldHandling); 12195 if (!name) { 12196 return errorResult(); 12197 } 12198 12199 Node lhs = MOZ_TRY(identifierReference(name)); 12200 12201 tokenStream.consumeKnownToken(TokenKind::Assign); 12202 12203 if (!seenCoverInitializedName) { 12204 // "shorthand default" or "CoverInitializedName" syntax is 12205 // only valid in the case of destructuring. 12206 seenCoverInitializedName = true; 12207 12208 if (!possibleError) { 12209 // Destructuring defaults are definitely not allowed 12210 // in this object literal, because of something the 12211 // caller knows about the preceding code. For example, 12212 // maybe the preceding token is an operator: 12213 // |x + {y=z}|. 12214 error(JSMSG_COLON_AFTER_ID); 12215 return errorResult(); 12216 } 12217 12218 // Here we set a pending error so that later in the parse, 12219 // once we've determined whether or not we're 12220 // destructuring, the error can be reported or ignored 12221 // appropriately. 12222 possibleError->setPendingExpressionErrorAt(pos(), 12223 JSMSG_COLON_AFTER_ID); 12224 } 12225 12226 if (const char* chars = nameIsArgumentsOrEval(lhs)) { 12227 // |chars| is "arguments" or "eval" here. 12228 if (!strictModeErrorAt(namePos.begin, JSMSG_BAD_STRICT_ASSIGN, 12229 chars)) { 12230 return errorResult(); 12231 } 12232 } 12233 12234 if (handler_.isArgumentsLength(lhs)) { 12235 pc_->sc()->setIneligibleForArgumentsLength(); 12236 } 12237 12238 Node rhs = 12239 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited)); 12240 12241 BinaryNodeType propExpr = MOZ_TRY( 12242 handler_.newAssignment(ParseNodeKind::AssignExpr, lhs, rhs)); 12243 12244 if (!handler_.addPropertyDefinition(literal, propName, propExpr)) { 12245 return errorResult(); 12246 } 12247 } else { 12248 TaggedParserAtomIndex funName; 12249 bool hasStaticName = 12250 !anyChars.isCurrentTokenType(TokenKind::RightBracket) && propAtom; 12251 if (hasStaticName) { 12252 funName = propAtom; 12253 12254 if (propType == PropertyType::Getter || 12255 propType == PropertyType::Setter) { 12256 funName = prefixAccessorName(propType, propAtom); 12257 if (!funName) { 12258 return errorResult(); 12259 } 12260 } 12261 } 12262 12263 FunctionNodeType funNode = 12264 MOZ_TRY(methodDefinition(namePos.begin, propType, funName)); 12265 12266 AccessorType atype = ToAccessorType(propType); 12267 if (!handler_.addObjectMethodDefinition(literal, propName, funNode, 12268 atype)) { 12269 return errorResult(); 12270 } 12271 12272 if (possibleError) { 12273 possibleError->setPendingDestructuringErrorAt( 12274 namePos, JSMSG_BAD_DESTRUCT_TARGET); 12275 } 12276 } 12277 } 12278 12279 bool matched; 12280 if (!tokenStream.matchToken(&matched, TokenKind::Comma, 12281 TokenStream::SlashIsInvalid)) { 12282 return errorResult(); 12283 } 12284 if (!matched) { 12285 break; 12286 } 12287 if (tt == TokenKind::TripleDot && possibleError) { 12288 possibleError->setPendingDestructuringErrorAt(pos(), 12289 JSMSG_REST_WITH_COMMA); 12290 } 12291 } 12292 12293 if (!mustMatchToken( 12294 TokenKind::RightCurly, [this, openedPos](TokenKind actual) { 12295 this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST, 12296 JSMSG_CURLY_OPENED, openedPos); 12297 })) { 12298 return errorResult(); 12299 } 12300 12301 handler_.setEndPosition(literal, pos().end); 12302 return literal; 12303 } 12304 12305 template <class ParseHandler, typename Unit> 12306 typename ParseHandler::FunctionNodeResult 12307 GeneralParser<ParseHandler, Unit>::methodDefinition( 12308 uint32_t toStringStart, PropertyType propType, 12309 TaggedParserAtomIndex funName) { 12310 FunctionSyntaxKind syntaxKind; 12311 switch (propType) { 12312 case PropertyType::Getter: 12313 syntaxKind = FunctionSyntaxKind::Getter; 12314 break; 12315 12316 case PropertyType::Setter: 12317 syntaxKind = FunctionSyntaxKind::Setter; 12318 break; 12319 12320 case PropertyType::Method: 12321 case PropertyType::GeneratorMethod: 12322 case PropertyType::AsyncMethod: 12323 case PropertyType::AsyncGeneratorMethod: 12324 syntaxKind = FunctionSyntaxKind::Method; 12325 break; 12326 12327 case PropertyType::Constructor: 12328 syntaxKind = FunctionSyntaxKind::ClassConstructor; 12329 break; 12330 12331 case PropertyType::DerivedConstructor: 12332 syntaxKind = FunctionSyntaxKind::DerivedClassConstructor; 12333 break; 12334 12335 default: 12336 MOZ_CRASH("unexpected property type"); 12337 } 12338 12339 GeneratorKind generatorKind = (propType == PropertyType::GeneratorMethod || 12340 propType == PropertyType::AsyncGeneratorMethod) 12341 ? GeneratorKind::Generator 12342 : GeneratorKind::NotGenerator; 12343 12344 FunctionAsyncKind asyncKind = (propType == PropertyType::AsyncMethod || 12345 propType == PropertyType::AsyncGeneratorMethod) 12346 ? FunctionAsyncKind::AsyncFunction 12347 : FunctionAsyncKind::SyncFunction; 12348 12349 YieldHandling yieldHandling = GetYieldHandling(generatorKind); 12350 12351 FunctionNodeType funNode = MOZ_TRY(handler_.newFunction(syntaxKind, pos())); 12352 12353 return functionDefinition(funNode, toStringStart, InAllowed, yieldHandling, 12354 funName, syntaxKind, generatorKind, asyncKind); 12355 } 12356 12357 template <class ParseHandler, typename Unit> 12358 bool GeneralParser<ParseHandler, Unit>::tryNewTarget( 12359 NewTargetNodeType* newTarget) { 12360 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::New)); 12361 12362 *newTarget = null(); 12363 12364 NullaryNodeType newHolder; 12365 MOZ_TRY_VAR_OR_RETURN(newHolder, handler_.newPosHolder(pos()), false); 12366 12367 uint32_t begin = pos().begin; 12368 12369 // |new| expects to look for an operand, so we will honor that. 12370 TokenKind next; 12371 if (!tokenStream.getToken(&next, TokenStream::SlashIsRegExp)) { 12372 return false; 12373 } 12374 12375 // Don't unget the token, since lookahead cannot handle someone calling 12376 // getToken() with a different modifier. Callers should inspect 12377 // currentToken(). 12378 if (next != TokenKind::Dot) { 12379 return true; 12380 } 12381 12382 if (!tokenStream.getToken(&next)) { 12383 return false; 12384 } 12385 if (next != TokenKind::Target) { 12386 error(JSMSG_UNEXPECTED_TOKEN, "target", TokenKindToDesc(next)); 12387 return false; 12388 } 12389 12390 if (!pc_->sc()->allowNewTarget()) { 12391 errorAt(begin, JSMSG_BAD_NEWTARGET); 12392 return false; 12393 } 12394 12395 NullaryNodeType targetHolder; 12396 MOZ_TRY_VAR_OR_RETURN(targetHolder, handler_.newPosHolder(pos()), false); 12397 12398 NameNodeType newTargetName; 12399 MOZ_TRY_VAR_OR_RETURN(newTargetName, newNewTargetName(), false); 12400 12401 MOZ_TRY_VAR_OR_RETURN( 12402 *newTarget, handler_.newNewTarget(newHolder, targetHolder, newTargetName), 12403 false); 12404 12405 return true; 12406 } 12407 12408 template <class ParseHandler, typename Unit> 12409 typename ParseHandler::BinaryNodeResult 12410 GeneralParser<ParseHandler, Unit>::importExpr(YieldHandling yieldHandling, 12411 bool allowCallSyntax) { 12412 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import)); 12413 12414 NullaryNodeType importHolder = MOZ_TRY(handler_.newPosHolder(pos())); 12415 12416 TokenKind next; 12417 if (!tokenStream.getToken(&next)) { 12418 return errorResult(); 12419 } 12420 12421 if (next == TokenKind::Dot) { 12422 if (!tokenStream.getToken(&next)) { 12423 return errorResult(); 12424 } 12425 if (next != TokenKind::Meta) { 12426 error(JSMSG_UNEXPECTED_TOKEN, "meta", TokenKindToDesc(next)); 12427 return errorResult(); 12428 } 12429 12430 if (parseGoal() != ParseGoal::Module) { 12431 errorAt(pos().begin, JSMSG_IMPORT_META_OUTSIDE_MODULE); 12432 return errorResult(); 12433 } 12434 12435 NullaryNodeType metaHolder = MOZ_TRY(handler_.newPosHolder(pos())); 12436 12437 return handler_.newImportMeta(importHolder, metaHolder); 12438 } 12439 12440 if (next == TokenKind::LeftParen && allowCallSyntax) { 12441 Node arg = 12442 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited)); 12443 12444 if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) { 12445 return errorResult(); 12446 } 12447 12448 Node optionalArg; 12449 if (next == TokenKind::Comma) { 12450 tokenStream.consumeKnownToken(TokenKind::Comma, 12451 TokenStream::SlashIsRegExp); 12452 12453 if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) { 12454 return errorResult(); 12455 } 12456 12457 if (next != TokenKind::RightParen) { 12458 optionalArg = 12459 MOZ_TRY(assignExpr(InAllowed, yieldHandling, TripledotProhibited)); 12460 12461 if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) { 12462 return errorResult(); 12463 } 12464 12465 if (next == TokenKind::Comma) { 12466 tokenStream.consumeKnownToken(TokenKind::Comma, 12467 TokenStream::SlashIsRegExp); 12468 } 12469 } else { 12470 optionalArg = 12471 MOZ_TRY(handler_.newPosHolder(TokenPos(pos().end, pos().end))); 12472 } 12473 } else { 12474 optionalArg = 12475 MOZ_TRY(handler_.newPosHolder(TokenPos(pos().end, pos().end))); 12476 } 12477 12478 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_ARGS)) { 12479 return errorResult(); 12480 } 12481 12482 Node spec = MOZ_TRY(handler_.newCallImportSpec(arg, optionalArg)); 12483 12484 return handler_.newCallImport(importHolder, spec); 12485 } 12486 12487 error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(next)); 12488 return errorResult(); 12489 } 12490 12491 template <class ParseHandler, typename Unit> 12492 typename ParseHandler::NodeResult 12493 GeneralParser<ParseHandler, Unit>::primaryExpr( 12494 YieldHandling yieldHandling, TripledotHandling tripledotHandling, 12495 TokenKind tt, PossibleError* possibleError, InvokedPrediction invoked) { 12496 MOZ_ASSERT(anyChars.isCurrentTokenType(tt)); 12497 AutoCheckRecursionLimit recursion(this->fc_); 12498 if (!recursion.check(this->fc_)) { 12499 return errorResult(); 12500 } 12501 12502 switch (tt) { 12503 case TokenKind::Function: 12504 return functionExpr(pos().begin, invoked, 12505 FunctionAsyncKind::SyncFunction); 12506 12507 case TokenKind::Class: 12508 return classDefinition(yieldHandling, ClassExpression, NameRequired); 12509 12510 case TokenKind::LeftBracket: 12511 return arrayInitializer(yieldHandling, possibleError); 12512 12513 case TokenKind::LeftCurly: 12514 return objectLiteral(yieldHandling, possibleError); 12515 12516 #ifdef ENABLE_DECORATORS 12517 case TokenKind::At: 12518 return classDefinition(yieldHandling, ClassExpression, NameRequired); 12519 #endif 12520 12521 case TokenKind::LeftParen: { 12522 TokenKind next; 12523 if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) { 12524 return errorResult(); 12525 } 12526 12527 if (next == TokenKind::RightParen) { 12528 // Not valid expression syntax, but this is valid in an arrow function 12529 // with no params: `() => body`. 12530 tokenStream.consumeKnownToken(TokenKind::RightParen, 12531 TokenStream::SlashIsRegExp); 12532 12533 if (!tokenStream.peekToken(&next)) { 12534 return errorResult(); 12535 } 12536 if (next != TokenKind::Arrow) { 12537 error(JSMSG_UNEXPECTED_TOKEN, "expression", 12538 TokenKindToDesc(TokenKind::RightParen)); 12539 return errorResult(); 12540 } 12541 12542 // Now just return something that will allow parsing to continue. 12543 // It doesn't matter what; when we reach the =>, we will rewind and 12544 // reparse the whole arrow function. See Parser::assignExpr. 12545 return handler_.newNullLiteral(pos()); 12546 } 12547 12548 // Pass |possibleError| to support destructuring in arrow parameters. 12549 Node expr = MOZ_TRY(exprInParens(InAllowed, yieldHandling, 12550 TripledotAllowed, possibleError)); 12551 if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_IN_PAREN)) { 12552 return errorResult(); 12553 } 12554 return handler_.parenthesize(expr); 12555 } 12556 12557 case TokenKind::TemplateHead: 12558 return templateLiteral(yieldHandling); 12559 12560 case TokenKind::NoSubsTemplate: 12561 return noSubstitutionUntaggedTemplate(); 12562 12563 case TokenKind::String: 12564 return stringLiteral(); 12565 12566 default: { 12567 if (!TokenKindIsPossibleIdentifier(tt)) { 12568 error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt)); 12569 return errorResult(); 12570 } 12571 12572 if (tt == TokenKind::Async) { 12573 TokenKind nextSameLine = TokenKind::Eof; 12574 if (!tokenStream.peekTokenSameLine(&nextSameLine)) { 12575 return errorResult(); 12576 } 12577 12578 if (nextSameLine == TokenKind::Function) { 12579 uint32_t toStringStart = pos().begin; 12580 tokenStream.consumeKnownToken(TokenKind::Function); 12581 return functionExpr(toStringStart, PredictUninvoked, 12582 FunctionAsyncKind::AsyncFunction); 12583 } 12584 } 12585 12586 TaggedParserAtomIndex name = identifierReference(yieldHandling); 12587 if (!name) { 12588 return errorResult(); 12589 } 12590 12591 return identifierReference(name); 12592 } 12593 12594 case TokenKind::RegExp: 12595 return newRegExp(); 12596 12597 case TokenKind::Number: 12598 return newNumber(anyChars.currentToken()); 12599 12600 case TokenKind::BigInt: 12601 return newBigInt(); 12602 12603 case TokenKind::True: 12604 return handler_.newBooleanLiteral(true, pos()); 12605 case TokenKind::False: 12606 return handler_.newBooleanLiteral(false, pos()); 12607 case TokenKind::This: { 12608 NameNodeType thisName = null(); 12609 if (pc_->sc()->hasFunctionThisBinding()) { 12610 thisName = MOZ_TRY(newThisName()); 12611 } 12612 return handler_.newThisLiteral(pos(), thisName); 12613 } 12614 case TokenKind::Null: 12615 return handler_.newNullLiteral(pos()); 12616 12617 case TokenKind::TripleDot: { 12618 // This isn't valid expression syntax, but it's valid in an arrow 12619 // function as a trailing rest param: `(a, b, ...rest) => body`. Check 12620 // if it's directly under 12621 // CoverParenthesizedExpressionAndArrowParameterList, and check for a 12622 // name, closing parenthesis, and arrow, and allow it only if all are 12623 // present. 12624 if (tripledotHandling != TripledotAllowed) { 12625 error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt)); 12626 return errorResult(); 12627 } 12628 12629 TokenKind next; 12630 if (!tokenStream.getToken(&next)) { 12631 return errorResult(); 12632 } 12633 12634 if (next == TokenKind::LeftBracket || next == TokenKind::LeftCurly) { 12635 // Validate, but don't store the pattern right now. The whole arrow 12636 // function is reparsed in functionFormalParametersAndBody(). 12637 MOZ_TRY(destructuringDeclaration(DeclarationKind::CoverArrowParameter, 12638 yieldHandling, next)); 12639 } else { 12640 // This doesn't check that the provided name is allowed, e.g. if 12641 // the enclosing code is strict mode code, any of "let", "yield", 12642 // or "arguments" should be prohibited. Argument-parsing code 12643 // handles that. 12644 if (!TokenKindIsPossibleIdentifier(next)) { 12645 error(JSMSG_UNEXPECTED_TOKEN, "rest argument name", 12646 TokenKindToDesc(next)); 12647 return errorResult(); 12648 } 12649 } 12650 12651 if (!tokenStream.getToken(&next)) { 12652 return errorResult(); 12653 } 12654 if (next != TokenKind::RightParen) { 12655 error(JSMSG_UNEXPECTED_TOKEN, "closing parenthesis", 12656 TokenKindToDesc(next)); 12657 return errorResult(); 12658 } 12659 12660 if (!tokenStream.peekToken(&next)) { 12661 return errorResult(); 12662 } 12663 if (next != TokenKind::Arrow) { 12664 // Advance the scanner for proper error location reporting. 12665 tokenStream.consumeKnownToken(next); 12666 error(JSMSG_UNEXPECTED_TOKEN, "'=>' after argument list", 12667 TokenKindToDesc(next)); 12668 return errorResult(); 12669 } 12670 12671 anyChars.ungetToken(); // put back right paren 12672 12673 // Return an arbitrary expression node. See case TokenKind::RightParen 12674 // above. 12675 return handler_.newNullLiteral(pos()); 12676 } 12677 } 12678 } 12679 12680 template <class ParseHandler, typename Unit> 12681 typename ParseHandler::NodeResult 12682 GeneralParser<ParseHandler, Unit>::exprInParens( 12683 InHandling inHandling, YieldHandling yieldHandling, 12684 TripledotHandling tripledotHandling, 12685 PossibleError* possibleError /* = nullptr */) { 12686 MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftParen)); 12687 return expr(inHandling, yieldHandling, tripledotHandling, possibleError, 12688 PredictInvoked); 12689 } 12690 12691 template class PerHandlerParser<FullParseHandler>; 12692 template class PerHandlerParser<SyntaxParseHandler>; 12693 template class GeneralParser<FullParseHandler, Utf8Unit>; 12694 template class GeneralParser<SyntaxParseHandler, Utf8Unit>; 12695 template class GeneralParser<FullParseHandler, char16_t>; 12696 template class GeneralParser<SyntaxParseHandler, char16_t>; 12697 template class Parser<FullParseHandler, Utf8Unit>; 12698 template class Parser<SyntaxParseHandler, Utf8Unit>; 12699 template class Parser<FullParseHandler, char16_t>; 12700 template class Parser<SyntaxParseHandler, char16_t>; 12701 12702 } // namespace js::frontend