Assertion failure for destructuring assignment with new.target and unary operator
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Apr 2016 20:05:13 +0000 (20:05 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Apr 2016 20:05:13 +0000 (20:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157149

Reviewed by Saam Barati.

The caller of parseDefaultValueForDestructuringPattern() should propagate errors.
And this patch also cleans up createSavePoint and createSavePointForError; introducing SavePointWithError.

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseSourceElements):
(JSC::Parser<LexerType>::parseDestructuringPattern):
Add propagateErorr() for parseDefaultValueForDestructuringPattern.

(JSC::Parser<LexerType>::parseAssignmentExpression):
* parser/Parser.h:
(JSC::Parser::restoreLexerState):
(JSC::Parser::internalSaveState):
(JSC::Parser::createSavePointForError):
(JSC::Parser::createSavePoint):
(JSC::Parser::internalRestoreState):
(JSC::Parser::restoreSavePointWithError):
(JSC::Parser::restoreSavePoint):
* tests/stress/default-value-parsing-should-propagate-error.js: Added.
(testSyntaxError):
(testSyntaxError.f):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200293 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/tests/stress/default-value-parsing-should-propagate-error.js [new file with mode: 0644]

index 3983949..5702e52 100644 (file)
@@ -1,3 +1,31 @@
+2016-04-30  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Assertion failure for destructuring assignment with new.target and unary operator
+        https://bugs.webkit.org/show_bug.cgi?id=157149
+
+        Reviewed by Saam Barati.
+
+        The caller of parseDefaultValueForDestructuringPattern() should propagate errors.
+        And this patch also cleans up createSavePoint and createSavePointForError; introducing SavePointWithError.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseSourceElements):
+        (JSC::Parser<LexerType>::parseDestructuringPattern):
+        Add propagateErorr() for parseDefaultValueForDestructuringPattern.
+
+        (JSC::Parser<LexerType>::parseAssignmentExpression):
+        * parser/Parser.h:
+        (JSC::Parser::restoreLexerState):
+        (JSC::Parser::internalSaveState):
+        (JSC::Parser::createSavePointForError):
+        (JSC::Parser::createSavePoint):
+        (JSC::Parser::internalRestoreState):
+        (JSC::Parser::restoreSavePointWithError):
+        (JSC::Parser::restoreSavePoint):
+        * tests/stress/default-value-parsing-should-propagate-error.js: Added.
+        (testSyntaxError):
+        (testSyntaxError.f):
+
 2016-04-28  Darin Adler  <darin@apple.com>
 
         First step in using "enum class" instead of "String" for enumerations in DOM
index e7790c8..e46b303 100644 (file)
@@ -421,6 +421,7 @@ template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceEl
                             semanticFail("Cannot declare a variable named 'eval' in strict mode");
                         semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
                     }
+                    // Since strict mode is changed, restoring lexer state by calling next() may cause errors.
                     restoreSavePoint(savePoint);
                     propagateError();
                     continue;
@@ -954,6 +955,7 @@ template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDe
                 return 0;
             failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
             TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
+            propagateError();
             context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
         } while (consume(COMMA));
 
@@ -1037,6 +1039,7 @@ template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDe
                 return 0;
             failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
             TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
+            propagateError();
             if (propertyExpression)
                 context.appendObjectPatternEntry(objectPattern, location, propertyExpression, innerPattern, defaultValue);
             else {
@@ -3078,19 +3081,14 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen
     if (isValidArrowFunctionStart && !match(EOFTOK)) {
         bool isArrowFunctionToken = match(ARROWFUNCTION);
         if (!lhs || isArrowFunctionToken) {
-            SavePoint errorRestorationSavePoint = createSavePointForError();
-            String oldErrorMessage = m_errorMessage;
-            String oldLexerErrorMessage = m_lexer->getErrorMessage();
-            bool hasLexerError = m_lexer->sawError();
+            SavePointWithError errorRestorationSavePoint = createSavePointForError();
             restoreSavePoint(savePoint);
             if (isArrowFunctionParameters()) {
                 if (wasOpenParen)
                     currentScope()->revertToPreviousUsedVariables(usedVariablesSize);
                 return parseArrowFunctionExpression(context);
             }
-            restoreSavePointWithError(errorRestorationSavePoint, oldErrorMessage);
-            m_lexer->setErrorMessage(oldLexerErrorMessage);
-            m_lexer->setSawError(hasLexerError);
+            restoreSavePointWithError(errorRestorationSavePoint);
             if (isArrowFunctionToken)
                 failDueToUnexpectedToken();
         }
@@ -3102,16 +3100,11 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen
         propagateError();
 
     if (maybeAssignmentPattern && (!lhs || (context.isObjectOrArrayLiteral(lhs) && match(EQUAL)))) {
-        String expressionError = m_errorMessage;
-        String oldLexerErrorMessage = m_lexer->getErrorMessage();
-        bool hasLexerError = m_lexer->sawError();
-        SavePoint expressionErrorLocation = createSavePointForError();
+        SavePointWithError expressionErrorLocation = createSavePointForError();
         restoreSavePoint(savePoint);
         auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
         if (classifier.indicatesPossiblePattern() && (!pattern || !match(EQUAL))) {
-            restoreSavePointWithError(expressionErrorLocation, expressionError);
-            m_lexer->setErrorMessage(oldLexerErrorMessage);
-            m_lexer->setSawError(hasLexerError);
+            restoreSavePointWithError(expressionErrorLocation);
             return 0;
         }
         failIfFalse(pattern, "Cannot parse assignment pattern");
index f032057..144545b 100644 (file)
@@ -1518,6 +1518,7 @@ private:
 
     ALWAYS_INLINE void restoreLexerState(const LexerState& lexerState)
     {
+        // setOffset clears lexer errors.
         m_lexer->setOffset(lexerState.startOffset, lexerState.oldLineStartOffset);
         next();
         m_lexer->setLastLineNumber(lexerState.oldLastLineNumber);
@@ -1528,31 +1529,55 @@ private:
         ParserState parserState;
         LexerState lexerState;
     };
+
+    struct SavePointWithError : public SavePoint {
+        bool lexerError;
+        String lexerErrorMessage;
+        String parserErrorMessage;
+    };
+
+    ALWAYS_INLINE void internalSaveState(SavePoint& savePoint)
+    {
+        savePoint.parserState = internalSaveParserState();
+        savePoint.lexerState = internalSaveLexerState();
+    }
     
-    ALWAYS_INLINE SavePoint createSavePointForError()
+    ALWAYS_INLINE SavePointWithError createSavePointForError()
     {
-        SavePoint result;
-        result.parserState = internalSaveParserState();
-        result.lexerState = internalSaveLexerState();
-        return result;
+        SavePointWithError savePoint;
+        internalSaveState(savePoint);
+        savePoint.lexerError = m_lexer->sawError();
+        savePoint.lexerErrorMessage = m_lexer->getErrorMessage();
+        savePoint.parserErrorMessage = m_errorMessage;
+        return savePoint;
     }
     
     ALWAYS_INLINE SavePoint createSavePoint()
     {
         ASSERT(!hasError());
-        return createSavePointForError();
+        SavePoint savePoint;
+        internalSaveState(savePoint);
+        return savePoint;
     }
 
-    ALWAYS_INLINE void restoreSavePointWithError(const SavePoint& savePoint, const String& message)
+    ALWAYS_INLINE void internalRestoreState(const SavePoint& savePoint)
     {
-        m_errorMessage = message;
         restoreLexerState(savePoint.lexerState);
         restoreParserState(savePoint.parserState);
     }
 
+    ALWAYS_INLINE void restoreSavePointWithError(const SavePointWithError& savePoint)
+    {
+        internalRestoreState(savePoint);
+        m_lexer->setSawError(savePoint.lexerError);
+        m_lexer->setErrorMessage(savePoint.lexerErrorMessage);
+        m_errorMessage = savePoint.parserErrorMessage;
+    }
+
     ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint)
     {
-        restoreSavePointWithError(savePoint, String());
+        internalRestoreState(savePoint);
+        m_errorMessage = String();
     }
 
     VM* m_vm;
diff --git a/Source/JavaScriptCore/tests/stress/default-value-parsing-should-propagate-error.js b/Source/JavaScriptCore/tests/stress/default-value-parsing-should-propagate-error.js
new file mode 100644 (file)
index 0000000..4bb7968
--- /dev/null
@@ -0,0 +1,21 @@
+function testSyntaxError(script, message) {
+    var error = null;
+    try {
+        eval(script);
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error("Expected syntax error not thrown");
+
+    if (String(error) !== message)
+        throw new Error("Bad error: " + String(error));
+}
+
+
+testSyntaxError(`
+function f()
+{
+    ({v = (typeof new.target)} = {})
+}
+`, `SyntaxError: Unexpected token '='. Expected a ':' following the property name 'v'.`);