Title: [258861] trunk
Revision
258861
Author
[email protected]
Date
2020-03-23 11:23:50 -0700 (Mon, 23 Mar 2020)

Log Message

Catch parameters must not be lexically redeclared
https://bugs.webkit.org/show_bug.cgi?id=208976

Reviewed by Keith Miller.

JSTests:

* test262/expectations.yaml:
Mark four test cases as passing.

Source/_javascript_Core:

>From https://tc39.es/ecma262/#sec-try-statement-static-semantics-early-errors:
  Catch : catch ( CatchParameter ) Block
    It is a Syntax Error if any element of the BoundNames of CatchParameter
    also occurs in the LexicallyDeclaredNames of Block.

In other words, let/const/class/function declarations in the immediate catch block scope
must not shadow catch parameters.

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseTryStatement):
(JSC::Parser<LexerType>::parseBlockStatement):
* parser/Parser.h:
(JSC::Scope::Scope):
(JSC::Scope::setIsCatchBlockScope): Added.
(JSC::Scope::isCatchBlockScope): Added.
(JSC::Parser::declareVariable):
(JSC::Parser::declareFunction):

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (258860 => 258861)


--- trunk/JSTests/ChangeLog	2020-03-23 18:10:48 UTC (rev 258860)
+++ trunk/JSTests/ChangeLog	2020-03-23 18:23:50 UTC (rev 258861)
@@ -1,3 +1,13 @@
+2020-03-23  Ross Kirsling  <[email protected]>
+
+        Catch parameters must not be lexically redeclared
+        https://bugs.webkit.org/show_bug.cgi?id=208976
+
+        Reviewed by Keith Miller.
+
+        * test262/expectations.yaml:
+        Mark four test cases as passing.
+
 2020-03-20  Ross Kirsling  <[email protected]>
 
         hasObservableSideEffectsForRegExpSplit doesn't check for @@match override

Modified: trunk/JSTests/test262/expectations.yaml (258860 => 258861)


--- trunk/JSTests/test262/expectations.yaml	2020-03-23 18:10:48 UTC (rev 258860)
+++ trunk/JSTests/test262/expectations.yaml	2020-03-23 18:23:50 UTC (rev 258861)
@@ -3679,12 +3679,6 @@
 test/language/statements/switch/syntax/redeclaration/var-name-redeclaration-attempt-with-generator.js:
   default: 'Test262: This statement should not be evaluated.'
   strict mode: 'Test262: This statement should not be evaluated.'
-test/language/statements/try/early-catch-function.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
-test/language/statements/try/early-catch-lex.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
 test/language/statements/while/let-array-with-newline.js:
   default: 'Test262: This statement should not be evaluated.'
 test/language/statements/with/let-array-with-newline.js:

Modified: trunk/Source/_javascript_Core/ChangeLog (258860 => 258861)


--- trunk/Source/_javascript_Core/ChangeLog	2020-03-23 18:10:48 UTC (rev 258860)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-03-23 18:23:50 UTC (rev 258861)
@@ -1,3 +1,28 @@
+2020-03-23  Ross Kirsling  <[email protected]>
+
+        Catch parameters must not be lexically redeclared
+        https://bugs.webkit.org/show_bug.cgi?id=208976
+
+        Reviewed by Keith Miller.
+
+        From https://tc39.es/ecma262/#sec-try-statement-static-semantics-early-errors:
+          Catch : catch ( CatchParameter ) Block
+            It is a Syntax Error if any element of the BoundNames of CatchParameter
+            also occurs in the LexicallyDeclaredNames of Block.
+
+        In other words, let/const/class/function declarations in the immediate catch block scope
+        must not shadow catch parameters.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseTryStatement):
+        (JSC::Parser<LexerType>::parseBlockStatement):
+        * parser/Parser.h:
+        (JSC::Scope::Scope):
+        (JSC::Scope::setIsCatchBlockScope): Added.
+        (JSC::Scope::isCatchBlockScope): Added.
+        (JSC::Parser::declareVariable):
+        (JSC::Parser::declareFunction):
+
 2020-03-23  Michael Catanzaro  <[email protected]>
 
         REGRESSION(r249808): [GTK] Crash in JSC Config::permanentlyFreeze() on architecture ppc64el

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (258860 => 258861)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2020-03-23 18:10:48 UTC (rev 258860)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2020-03-23 18:23:50 UTC (rev 258861)
@@ -1779,7 +1779,8 @@
             }
             handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
             matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
-            catchBlock = parseBlockStatement(context);
+            constexpr bool isCatchBlock = true;
+            catchBlock = parseBlockStatement(context, isCatchBlock);
             failIfFalse(catchBlock, "Unable to parse 'catch' block");
             catchEnvironment = catchScope->finalizeLexicalEnvironment();
             RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
@@ -1812,7 +1813,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context, bool isCatchBlock)
 {
     ASSERT(match(OPENBRACE));
 
@@ -1824,6 +1825,8 @@
         ScopeRef newScope = pushScope();
         newScope->setIsLexicalScope();
         newScope->preventVarDeclarations();
+        if (isCatchBlock)
+            newScope->setIsCatchBlockScope();
         lexicalScope.setIsValid(newScope, this);
     }
     JSTokenLocation location(tokenLocation());

Modified: trunk/Source/_javascript_Core/parser/Parser.h (258860 => 258861)


--- trunk/Source/_javascript_Core/parser/Parser.h	2020-03-23 18:10:48 UTC (rev 258860)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2020-03-23 18:23:50 UTC (rev 258861)
@@ -176,6 +176,7 @@
         , m_isLexicalScope(false)
         , m_isGlobalCodeScope(false)
         , m_isSimpleCatchParameterScope(false)
+        , m_isCatchBlockScope(false)
         , m_isFunctionBoundary(false)
         , m_isValidStrictMode(true)
         , m_hasArguments(false)
@@ -299,6 +300,9 @@
     void setIsSimpleCatchParameterScope() { m_isSimpleCatchParameterScope = true; }
     bool isSimpleCatchParameterScope() { return m_isSimpleCatchParameterScope; }
 
+    void setIsCatchBlockScope() { m_isCatchBlockScope = true; }
+    bool isCatchBlockScope() { return m_isCatchBlockScope; }
+
     void setIsLexicalScope() 
     { 
         m_isLexicalScope = true;
@@ -829,6 +833,7 @@
     bool m_isLexicalScope;
     bool m_isGlobalCodeScope;
     bool m_isSimpleCatchParameterScope;
+    bool m_isCatchBlockScope;
     bool m_isFunctionBoundary;
     bool m_isValidStrictMode;
     bool m_hasArguments;
@@ -1280,7 +1285,11 @@
         if (!m_lexer->isReparsingFunction() && m_statementDepth == 1 && (hasDeclaredParameter(*ident) || hasDeclaredVariable(*ident)))
             return DeclarationResult::InvalidDuplicateDeclaration;
 
-        return currentLexicalDeclarationScope()->declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration, importType);
+        ScopeRef scope = currentLexicalDeclarationScope();
+        if (scope->isCatchBlockScope() && scope.containingScope()->hasLexicallyDeclaredVariable(*ident))
+            return DeclarationResult::InvalidDuplicateDeclaration;
+
+        return scope->declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration, importType);
     }
 
     std::pair<DeclarationResultMask, ScopeRef> declareFunction(const Identifier* ident)
@@ -1295,6 +1304,11 @@
             return std::make_pair(variableScope->declareFunction(ident, declareAsVar, isSloppyModeHoistingCandidate), variableScope);
         }
 
+        bool declareAsVar = false;
+        ScopeRef lexicalVariableScope = currentLexicalDeclarationScope();
+        if (lexicalVariableScope->isCatchBlockScope() && lexicalVariableScope.containingScope()->hasLexicallyDeclaredVariable(*ident))
+            return std::make_pair(DeclarationResult::InvalidDuplicateDeclaration, lexicalVariableScope);
+
         if (!strictMode()) {
             ASSERT(currentScope()->isFunction() || closestParentOrdinaryFunctionNonLexicalScope()->isEvalContext());
 
@@ -1306,9 +1320,7 @@
             // there are is a let/class/const with the same name). Note that this mean we only do the "var" hoisting 
             // binding if the block evaluates. For example, this means we wont won't perform the binding if it's inside
             // the untaken branch of an if statement.
-            bool declareAsVar = false;
             bool isSloppyModeHoistingCandidate = true;
-            ScopeRef lexicalVariableScope = currentLexicalDeclarationScope();
             ScopeRef varScope = currentVariableScope();
             varScope->addSloppyModeHoistableFunctionCandidate(ident);
             ASSERT(varScope != lexicalVariableScope);
@@ -1315,9 +1327,7 @@
             return std::make_pair(lexicalVariableScope->declareFunction(ident, declareAsVar, isSloppyModeHoistingCandidate), lexicalVariableScope);
         }
 
-        bool declareAsVar = false;
         bool isSloppyModeHoistingCandidate = false;
-        ScopeRef lexicalVariableScope = currentLexicalDeclarationScope();
         return std::make_pair(lexicalVariableScope->declareFunction(ident, declareAsVar, isSloppyModeHoistingCandidate), lexicalVariableScope);
     }
 
@@ -1635,7 +1645,7 @@
     template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
     template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&, bool allowFunctionDeclarationAsStatement);
     template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
-    template <class TreeBuilder> TreeStatement parseBlockStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseBlockStatement(TreeBuilder&, bool isCatchBlock = false);
     template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
     template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&, ExpressionErrorClassifier&);
     template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to