diff options
Diffstat (limited to 'js/src/frontend/Parser.cpp')
-rw-r--r-- | js/src/frontend/Parser.cpp | 85 |
1 files changed, 62 insertions, 23 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index d62a26f76..299b8b93a 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -141,7 +141,8 @@ StatementKindIsBraced(StatementKind kind) kind == StatementKind::Switch || kind == StatementKind::Try || kind == StatementKind::Catch || - kind == StatementKind::Finally; + kind == StatementKind::Finally || + kind == StatementKind::Class; } void @@ -472,6 +473,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* trac startLine(1), startColumn(0), preludeStart(preludeStart), + postludeEnd(0), length(0), generatorKindBits_(GeneratorKindAsBits(generatorKind)), asyncKindBits_(AsyncKindAsBits(asyncKind)), @@ -542,10 +544,16 @@ FunctionBox::initWithEnclosingParseContext(ParseContext* enclosing, FunctionSynt allowNewTarget_ = true; allowSuperProperty_ = fun->allowSuperProperty(); - if (kind == DerivedClassConstructor) { - setDerivedClassConstructor(); - allowSuperCall_ = true; - needsThisTDZChecks_ = true; + if (kind == ClassConstructor || kind == DerivedClassConstructor) { + auto stmt = enclosing->findInnermostStatement<ParseContext::ClassStatement>(); + MOZ_ASSERT(stmt); + stmt->setConstructorBox(this); + + if (kind == DerivedClassConstructor) { + setDerivedClassConstructor(); + allowSuperCall_ = true; + needsThisTDZChecks_ = true; + } } if (isGenexpLambda) @@ -566,6 +574,16 @@ FunctionBox::initWithEnclosingParseContext(ParseContext* enclosing, FunctionSynt } void +FunctionBox::resetForAbortedSyntaxParse(ParseContext* enclosing, FunctionSyntaxKind kind) +{ + if (kind == ClassConstructor || kind == DerivedClassConstructor) { + auto stmt = enclosing->findInnermostStatement<ParseContext::ClassStatement>(); + MOZ_ASSERT(stmt); + stmt->clearConstructorBoxForAbortedSyntaxParse(this); + } +} + +void FunctionBox::initWithEnclosingScope(Scope* enclosingScope) { if (!function()->isArrow()) { @@ -3389,6 +3407,7 @@ Parser<FullParseHandler>::trySyntaxParseInnerFunction(ParseNode* pn, HandleFunct // correctness. parser->clearAbortedSyntaxParse(); usedNames.rewind(token); + funbox->resetForAbortedSyntaxParse(pc, kind); MOZ_ASSERT_IF(parser->context->isJSContext(), !parser->context->asJSContext()->isExceptionPending()); break; @@ -3670,14 +3689,14 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling, error(JSMSG_CURLY_AFTER_BODY); return false; } - funbox->bufEnd = pos().end; + funbox->setEnd(pos().end); } else { #if !JS_HAS_EXPR_CLOSURES MOZ_ASSERT(kind == Arrow); #endif if (tokenStream.hadError()) return false; - funbox->bufEnd = pos().end; + funbox->setEnd(pos().end); if (kind == Statement && !matchOrInsertSemicolonAfterExpression()) return false; } @@ -6935,6 +6954,7 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS)); + uint32_t classStartOffset = pos().begin; bool savedStrictness = setLocalStrictMode(true); TokenKind tt; @@ -6960,16 +6980,20 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, tokenStream.ungetToken(); } + // Push a ParseContext::ClassStatement to keep track of the constructor + // funbox. + ParseContext::ClassStatement classStmt(pc); + RootedAtom propAtom(context); // A named class creates a new lexical scope with a const binding of the - // class name. - Maybe<ParseContext::Statement> classStmt; - Maybe<ParseContext::Scope> classScope; + // class name for the "inner name". + Maybe<ParseContext::Statement> innerScopeStmt; + Maybe<ParseContext::Scope> innerScope; if (name) { - classStmt.emplace(pc, StatementKind::Block); - classScope.emplace(this); - if (!classScope->init(pc)) + innerScopeStmt.emplace(pc, StatementKind::Block); + innerScope.emplace(this); + if (!innerScope->init(pc)) return null(); } @@ -6996,7 +7020,6 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, if (!classMethods) return null(); - bool seenConstructor = false; for (;;) { TokenKind tt; if (!tokenStream.getToken(&tt)) @@ -7048,16 +7071,17 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, propType = PropertyType::GetterNoExpressionClosure; if (propType == PropertyType::Setter) propType = PropertyType::SetterNoExpressionClosure; - if (!isStatic && propAtom == context->names().constructor) { + + bool isConstructor = !isStatic && propAtom == context->names().constructor; + if (isConstructor) { if (propType != PropertyType::Method) { errorAt(nameOffset, JSMSG_BAD_METHOD_DEF); return null(); } - if (seenConstructor) { + if (classStmt.constructorBox()) { errorAt(nameOffset, JSMSG_DUPLICATE_PROPERTY, "constructor"); return null(); } - seenConstructor = true; propType = hasHeritage ? PropertyType::DerivedConstructor : PropertyType::Constructor; } else if (isStatic && propAtom == context->names().prototype) { errorAt(nameOffset, JSMSG_BAD_METHOD_DEF); @@ -7082,7 +7106,12 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, if (!tokenStream.isCurrentTokenType(TOK_RB)) funName = propAtom; } - Node fn = methodDefinition(nameOffset, propType, funName); + + // Calling toString on constructors need to return the source text for + // the entire class. The end offset is unknown at this point in + // parsing and will be amended when class parsing finishes below. + Node fn = methodDefinition(isConstructor ? classStartOffset : nameOffset, + propType, funName); if (!fn) return null(); @@ -7093,6 +7122,15 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, return null(); } + // Amend the postlude offset for the constructor now that we've finished + // parsing the class. + uint32_t classEndOffset = pos().end; + if (FunctionBox* ctorbox = classStmt.constructorBox()) { + if (ctorbox->function()->isInterpretedLazy()) + ctorbox->function()->lazyScript()->setPostludeEnd(classEndOffset); + ctorbox->postludeEnd = classEndOffset; + } + Node nameNode = null(); Node methodsOrBlock = classMethods; if (name) { @@ -7104,15 +7142,15 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, if (!innerName) return null(); - Node classBlock = finishLexicalScope(*classScope, classMethods); + Node classBlock = finishLexicalScope(*innerScope, classMethods); if (!classBlock) return null(); methodsOrBlock = classBlock; // Pop the inner scope. - classScope.reset(); - classStmt.reset(); + innerScope.reset(); + innerScopeStmt.reset(); Node outerName = null(); if (classContext == ClassStatement) { @@ -7132,7 +7170,8 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, MOZ_ALWAYS_TRUE(setLocalStrictMode(savedStrictness)); - return handler.newClass(nameNode, classHeritage, methodsOrBlock); + return handler.newClass(nameNode, classHeritage, methodsOrBlock, + TokenPos(classStartOffset, classEndOffset)); } template <class ParseHandler> @@ -8388,7 +8427,7 @@ Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin) uint32_t end = pos().end; handler.setBeginPosition(comp, begin); handler.setEndPosition(comp, end); - genFunbox->bufEnd = end; + genFunbox->setEnd(end); handler.addStatementToList(body, comp); handler.setEndPosition(body, end); handler.setBeginPosition(genfn, begin); |