diff options
-rw-r--r-- | js/src/frontend/Parser.cpp | 44 | ||||
-rw-r--r-- | js/src/frontend/Parser.h | 2 | ||||
-rw-r--r-- | js/src/jit-test/tests/parser/missing-closing-brace.js | 30 | ||||
-rw-r--r-- | js/src/js.msg | 1 |
4 files changed, 71 insertions, 6 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 01ab3f64c..9aed88ce9 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1014,6 +1014,35 @@ Parser<ParseHandler>::hasValidSimpleStrictParameterNames() template <typename ParseHandler> void +Parser<ParseHandler>::reportMissingClosing(unsigned errorNumber, unsigned noteNumber, + uint32_t openedPos) +{ + auto notes = MakeUnique<JSErrorNotes>(); + if (!notes) + return; + + uint32_t line, column; + tokenStream.srcCoords.lineNumAndColumnIndex(openedPos, &line, &column); + + const size_t MaxWidth = sizeof("4294967295"); + char columnNumber[MaxWidth]; + SprintfLiteral(columnNumber, "%" PRIu32, column); + char lineNumber[MaxWidth]; + SprintfLiteral(lineNumber, "%" PRIu32, line); + + if (!notes->addNoteASCII(pc->sc()->context, + getFilename(), line, column, + GetErrorMessage, nullptr, + noteNumber, lineNumber, columnNumber)) + { + return; + } + + errorWithNotes(Move(notes), errorNumber); +} + +template <typename ParseHandler> +void Parser<ParseHandler>::reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind, TokenPos pos, uint32_t prevPos) { @@ -1039,11 +1068,11 @@ Parser<ParseHandler>::reportRedeclaration(HandlePropertyName name, DeclarationKi char lineNumber[MaxWidth]; SprintfLiteral(lineNumber, "%" PRIu32, line); - if (!notes->addNoteLatin1(pc->sc()->context, - getFilename(), line, column, - GetErrorMessage, nullptr, - JSMSG_REDECLARED_PREV, - lineNumber, columnNumber)) + if (!notes->addNoteASCII(pc->sc()->context, + getFilename(), line, column, + GetErrorMessage, nullptr, + JSMSG_REDECLARED_PREV, + lineNumber, columnNumber)) { return; } @@ -3613,6 +3642,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling, TokenKind tt; if (!tokenStream.getToken(&tt, TokenStream::Operand)) return false; + uint32_t openedPos = 0; if (tt != TOK_LC) { if ((funbox->isStarGenerator() && !funbox->isAsync()) || kind == Method || kind == GetterNoExpressionClosure || kind == SetterNoExpressionClosure || @@ -3634,6 +3664,8 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling, tokenStream.ungetToken(); bodyType = ExpressionBody; funbox->setIsExprBody(); + } else { + openedPos = pos().begin; } // Arrow function parameters inherit yieldHandling from the enclosing @@ -3675,7 +3707,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling, if (!tokenStream.matchToken(&matched, TOK_RC, TokenStream::Operand)) return false; if (!matched) { - error(JSMSG_CURLY_AFTER_BODY); + reportMissingClosing(JSMSG_CURLY_AFTER_BODY, JSMSG_CURLY_OPENED, openedPos); return false; } funbox->setEnd(pos().end); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 7866bc4fd..b1d3bdee0 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1459,6 +1459,8 @@ class Parser final : public ParserBase, private JS::AutoGCRooter bool hasValidSimpleStrictParameterNames(); + void reportMissingClosing(unsigned errorNumber, unsigned noteNumber, uint32_t openedPos); + void reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind, TokenPos pos, uint32_t prevPos); bool notePositionalFormalParameter(Node fn, HandlePropertyName name, uint32_t beginPos, diff --git a/js/src/jit-test/tests/parser/missing-closing-brace.js b/js/src/jit-test/tests/parser/missing-closing-brace.js new file mode 100644 index 000000000..4512ad133 --- /dev/null +++ b/js/src/jit-test/tests/parser/missing-closing-brace.js @@ -0,0 +1,30 @@ +function test(source, [lineNumber, columnNumber]) { + let caught = false; + try { + Reflect.parse(source, { source: "foo.js" }); + } catch (e) { + assertEq(e.message.includes("missing } "), true); + let notes = getErrorNotes(e); + assertEq(notes.length, 1); + let note = notes[0]; + assertEq(note.message, "{ opened at line " + lineNumber + ", column " + columnNumber); + assertEq(note.fileName, "foo.js"); + assertEq(note.lineNumber, lineNumber); + assertEq(note.columnNumber, columnNumber); + caught = true; + } + assertEq(caught, true); +} + +// Function + +test(` +function test1() { +} +function test2() { + if (true) { + //} +} +function test3() { +} +`, [4, 17]); diff --git a/js/src/js.msg b/js/src/js.msg index 569928be8..a51d99933 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -228,6 +228,7 @@ MSG_DEF(JSMSG_COLON_IN_COND, 0, JSEXN_SYNTAXERR, "missing : in conditi MSG_DEF(JSMSG_COMP_PROP_UNTERM_EXPR, 0, JSEXN_SYNTAXERR, "missing ] in computed property name") MSG_DEF(JSMSG_CONTRARY_NONDIRECTIVE, 1, JSEXN_SYNTAXERR, "'{0}' statement won't be enforced as a directive because it isn't in directive prologue position") MSG_DEF(JSMSG_CURLY_AFTER_BODY, 0, JSEXN_SYNTAXERR, "missing } after function body") +MSG_DEF(JSMSG_CURLY_OPENED, 2, JSEXN_NOTE, "{ opened at line {0}, column {1}") MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 0, JSEXN_SYNTAXERR, "missing } after catch block") MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 0, JSEXN_SYNTAXERR, "missing } after finally block") MSG_DEF(JSMSG_CURLY_AFTER_LIST, 0, JSEXN_SYNTAXERR, "missing } after property list") |