diff options
-rw-r--r-- | js/src/frontend/Parser.cpp | 44 | ||||
-rw-r--r-- | js/src/jit-test/tests/parser/missing-closing-brace.js | 46 |
2 files changed, 75 insertions, 15 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 9aed88ce9..ef352ec35 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -66,29 +66,32 @@ using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr; // Read a token. Report an error and return null() if that token doesn't match // to the condition. Do not use MUST_MATCH_TOKEN_INTERNAL directly. -#define MUST_MATCH_TOKEN_INTERNAL(cond, modifier, errorNumber) \ +#define MUST_MATCH_TOKEN_INTERNAL(cond, modifier, errorReport) \ JS_BEGIN_MACRO \ TokenKind token; \ if (!tokenStream.getToken(&token, modifier)) \ return null(); \ if (!(cond)) { \ - error(errorNumber); \ + errorReport; \ return null(); \ } \ JS_END_MACRO #define MUST_MATCH_TOKEN_MOD(tt, modifier, errorNumber) \ - MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, errorNumber) + MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, error(errorNumber)) #define MUST_MATCH_TOKEN(tt, errorNumber) \ MUST_MATCH_TOKEN_MOD(tt, TokenStream::None, errorNumber) #define MUST_MATCH_TOKEN_FUNC_MOD(func, modifier, errorNumber) \ - MUST_MATCH_TOKEN_INTERNAL((func)(token), modifier, errorNumber) + MUST_MATCH_TOKEN_INTERNAL((func)(token), modifier, error(errorNumber)) #define MUST_MATCH_TOKEN_FUNC(func, errorNumber) \ MUST_MATCH_TOKEN_FUNC_MOD(func, TokenStream::None, errorNumber) +#define MUST_MATCH_TOKEN_MOD_WITH_REPORT(tt, modifier, errorReport) \ + MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, errorReport) + template <class T, class U> static inline void PropagateTransitiveParseFlags(const T* inner, U* outer) @@ -3703,13 +3706,9 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling, } if (bodyType == StatementListBody) { - bool matched; - if (!tokenStream.matchToken(&matched, TOK_RC, TokenStream::Operand)) - return false; - if (!matched) { - reportMissingClosing(JSMSG_CURLY_AFTER_BODY, JSMSG_CURLY_OPENED, openedPos); - return false; - } + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand, + reportMissingClosing(JSMSG_CURLY_AFTER_BODY, + JSMSG_CURLY_OPENED, openedPos)); funbox->setEnd(pos().end); } else { #if !JS_HAS_EXPR_CLOSURES @@ -4481,6 +4480,7 @@ typename ParseHandler::Node Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned errorNumber) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC)); + uint32_t openedPos = pos().begin; ParseContext::Statement stmt(pc, StatementKind::Block); ParseContext::Scope scope(this); @@ -4491,7 +4491,9 @@ Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned error if (!list) return null(); - MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, errorNumber); + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand, + reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED, + openedPos)); return finishLexicalScope(scope, list); } @@ -6743,6 +6745,8 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling) { MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY); + uint32_t openedPos = pos().begin; + ParseContext::Statement stmt(pc, StatementKind::Try); ParseContext::Scope scope(this); if (!scope.init(pc)) @@ -6756,7 +6760,9 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling) if (!innerBlock) return null(); - MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_TRY); + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand, + reportMissingClosing(JSMSG_CURLY_AFTER_TRY, + JSMSG_CURLY_OPENED, openedPos)); } bool hasUnconditionalCatch = false; @@ -6872,6 +6878,8 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling) if (tt == TOK_FINALLY) { MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY); + uint32_t openedPos = pos().begin; + ParseContext::Statement stmt(pc, StatementKind::Finally); ParseContext::Scope scope(this); if (!scope.init(pc)) @@ -6885,7 +6893,9 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling) if (!finallyBlock) return null(); - MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_FINALLY); + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand, + reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY, + JSMSG_CURLY_OPENED, openedPos)); } else { tokenStream.ungetToken(); } @@ -6902,6 +6912,8 @@ typename ParseHandler::Node Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope) { + uint32_t openedPos = pos().begin; + ParseContext::Statement stmt(pc, StatementKind::Block); // ES 13.15.7 CatchClauseEvaluation @@ -6921,7 +6933,9 @@ Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling, if (!list) return null(); - MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_CATCH); + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand, + reportMissingClosing(JSMSG_CURLY_AFTER_CATCH, + JSMSG_CURLY_OPENED, openedPos)); // The catch parameter names are not bound in the body scope, so remove // them before generating bindings. diff --git a/js/src/jit-test/tests/parser/missing-closing-brace.js b/js/src/jit-test/tests/parser/missing-closing-brace.js index 4512ad133..2bb96b11b 100644 --- a/js/src/jit-test/tests/parser/missing-closing-brace.js +++ b/js/src/jit-test/tests/parser/missing-closing-brace.js @@ -28,3 +28,49 @@ function test2() { function test3() { } `, [4, 17]); + +// Block statement. +test(` +{ + if (true) { +} +`, [2, 0]); +test(` +if (true) { + if (true) { +} +`, [2, 10]); +test(` +for (;;) { + if (true) { +} +`, [2, 9]); +test(` +while (true) { + if (true) { +} +`, [2, 13]); +test(` +do { + do { +} while(true); +`, [2, 3]); + +// try-catch-finally. +test(` +try { + if (true) { +} +`, [2, 4]); +test(` +try { +} catch (e) { + if (true) { +} +`, [3, 12]); +test(` +try { +} finally { + if (true) { +} +`, [3, 10]); |