From ccb322db6d1f14c3013bacb01dcb064a3f7fa28f Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 14 Jul 2019 10:15:10 -0400 Subject: 420857 - Part 1: Report the position of opening brace for missing brace error in function body. --- js/src/frontend/Parser.cpp | 44 +++++++++++++++++++--- js/src/frontend/Parser.h | 2 + .../jit-test/tests/parser/missing-closing-brace.js | 30 +++++++++++++++ js/src/js.msg | 1 + 4 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 js/src/jit-test/tests/parser/missing-closing-brace.js (limited to 'js') 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 @@ -1012,6 +1012,35 @@ Parser::hasValidSimpleStrictParameterNames() return true; } +template +void +Parser::reportMissingClosing(unsigned errorNumber, unsigned noteNumber, + uint32_t openedPos) +{ + auto notes = MakeUnique(); + 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 void Parser::reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind, @@ -1039,11 +1068,11 @@ Parser::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::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::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::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") -- cgit v1.2.3