calling function on catch block scope containing an eval result in wrong this value...
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Feb 2012 00:08:00 +0000 (00:08 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Feb 2012 00:08:00 +0000 (00:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=77581

Reviewed by Oliver Hunt.

javascript:function F(){ return 'F' in this; }; try { throw F; } catch (e) { eval(""); alert(e()); }

Source/JavaScriptCore:

* bytecompiler/NodesCodegen.cpp:
(JSC::TryNode::emitBytecode):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createTryStatement):
* parser/NodeConstructors.h:
(JSC::TryNode::TryNode):
* parser/Nodes.h:
(TryNode):
* parser/Parser.cpp:
(JSC::::parseTryStatement):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createTryStatement):
* runtime/JSObject.h:
(JSObject):
(JSC::JSObject::isStaticScopeObject):
(JSC):

LayoutTests:

* fast/js/eval-var-decl-expected.txt:
* fast/js/script-tests/eval-var-decl.js:
(checkThis):
(testEvalInCatch):

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/js/eval-var-decl-expected.txt
LayoutTests/fast/js/script-tests/eval-var-decl.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/NodeConstructors.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/SyntaxChecker.h
Source/JavaScriptCore/runtime/JSObject.h

index 3348b07..dea50cc 100644 (file)
@@ -1,3 +1,17 @@
+2012-02-01  Gavin Barraclough  <barraclough@apple.com>
+
+        calling function on catch block scope containing an eval result in wrong this value being passed
+        https://bugs.webkit.org/show_bug.cgi?id=77581
+
+        Reviewed by Oliver Hunt.
+
+        javascript:function F(){ return 'F' in this; }; try { throw F; } catch (e) { eval(""); alert(e()); }
+
+        * fast/js/eval-var-decl-expected.txt:
+        * fast/js/script-tests/eval-var-decl.js:
+        (checkThis):
+        (testEvalInCatch):
+
 2012-02-01  Florin Malita  <fmalita@google.com>
 
         Backgrounds in HTML inside foreignObject don't draw
index fe983e4..615f467 100644 (file)
@@ -8,6 +8,7 @@ PASS this.hasOwnProperty("bar") is true
 PASS firstEvalResult is true
 PASS secondEvalResult is false
 PASS thirdEvalResult is true
+PASS testEvalInCatch() is true
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 631241f..d1325a3 100644 (file)
@@ -22,3 +22,21 @@ try {
     thirdEvalResult = "Threw exception!";
 }
 shouldBeTrue("thirdEvalResult");
+
+// Check that the correct this value is passed to a function called having been caught from a throw, where the catch block contains an eval (bug#).
+function checkThis()
+{
+    "use strict";
+    return this === undefined;
+}
+function testEvalInCatch()
+{
+    try {
+        throw checkThis;
+    } catch(e) {
+        eval('');
+        return e();
+    }
+    return false;
+}
+shouldBeTrue("testEvalInCatch()");
index 6ee07a0..cd89c2f 100644 (file)
@@ -1,3 +1,31 @@
+2012-02-01  Gavin Barraclough  <barraclough@apple.com>
+
+        calling function on catch block scope containing an eval result in wrong this value being passed
+        https://bugs.webkit.org/show_bug.cgi?id=77581
+
+        Reviewed by Oliver Hunt.
+
+        javascript:function F(){ return 'F' in this; }; try { throw F; } catch (e) { eval(""); alert(e()); }
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::TryNode::emitBytecode):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createTryStatement):
+        * parser/NodeConstructors.h:
+        (JSC::TryNode::TryNode):
+        * parser/Nodes.h:
+        (TryNode):
+        * parser/Parser.cpp:
+        (JSC::::parseTryStatement):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createTryStatement):
+        * runtime/JSObject.h:
+        (JSObject):
+        (JSC::JSObject::isStaticScopeObject):
+        (JSC):
+
 2012-02-01  Oliver Hunt  <oliver@apple.com>
 
         Add support for inferred function names
index 1541909..46ec698 100644 (file)
@@ -1969,13 +1969,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
         // Uncaught exception path: the catch block.
         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
         RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
-        if (m_catchHasEval) {
-            RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
-            generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
-            generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
-            generator.emitPushScope(exceptionRegister.get());
-        } else
-            generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
+        generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
         generator.emitNode(dst, m_catchBlock);
         generator.emitPopScope();
         generator.emitLabel(catchEndLabel.get());
index 445e286..51843f2 100644 (file)
@@ -1324,7 +1324,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
     JSObject* variableObject;
     for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
         ASSERT(node);
-        if (node->object->isVariableObject()) {
+        if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) {
             variableObject = static_cast<JSVariableObject*>(node->object.get());
             break;
         }
index 67432d4..b6ea004 100644 (file)
@@ -419,9 +419,9 @@ public:
         return result;
     }
 
-    StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
+    StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
     {
-        TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchHasEval, catchBlock, finallyBlock);
+        TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchBlock, finallyBlock);
         if (catchBlock)
             usesCatch();
         result->setLoc(startLine, endLine);
index 6c06949..eea3f57 100644 (file)
@@ -781,13 +781,12 @@ namespace JSC {
     {
     }
 
-    inline TryNode::TryNode(int lineNumber, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock)
+    inline TryNode::TryNode(int lineNumber, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock)
         : StatementNode(lineNumber)
         , m_tryBlock(tryBlock)
         , m_exceptionIdent(exceptionIdent)
         , m_catchBlock(catchBlock)
         , m_finallyBlock(finallyBlock)
-        , m_catchHasEval(catchHasEval)
     {
     }
 
index 54eccde..278d17e 100644 (file)
@@ -1348,7 +1348,7 @@ namespace JSC {
 
     class TryNode : public StatementNode {
     public:
-        TryNode(int, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock);
+        TryNode(int, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1357,7 +1357,6 @@ namespace JSC {
         const Identifier& m_exceptionIdent;
         StatementNode* m_catchBlock;
         StatementNode* m_finallyBlock;
-        bool m_catchHasEval;
     };
 
     class ParameterNode : public ParserArenaFreeable {
index 2865093..ce65198 100644 (file)
@@ -603,7 +603,6 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(
     ASSERT(match(TRY));
     TreeStatement tryBlock = 0;
     const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
-    bool catchHasEval = false;
     TreeStatement catchBlock = 0;
     TreeStatement finallyBlock = 0;
     int firstLine = tokenLine();
@@ -626,10 +625,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(
         catchScope->preventNewDecls();
         consumeOrFail(CLOSEPAREN);
         matchOrFail(OPENBRACE);
-        int initialEvalCount = context.evalCount();
         catchBlock = parseBlockStatement(context);
         failIfFalseWithMessage(catchBlock, "'try' must have a catch or finally block");
-        catchHasEval = initialEvalCount != context.evalCount();
         failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
     }
     
@@ -640,7 +637,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(
         failIfFalse(finallyBlock);
     }
     failIfFalse(catchBlock || finallyBlock);
-    return context.createTryStatement(m_lexer->lastLineNumber(), tryBlock, ident, catchHasEval, catchBlock, finallyBlock, firstLine, lastLine);
+    return context.createTryStatement(m_lexer->lastLineNumber(), tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
 }
 
 template <typename LexerType>
index 270c823..32cbf7d 100644 (file)
@@ -193,7 +193,7 @@ public:
     int createBreakStatement(int, const Identifier*, int, int, int, int) { return 1; }
     int createContinueStatement(int, int, int, int, int) { return 1; }
     int createContinueStatement(int, const Identifier*, int, int, int, int) { return 1; }
-    int createTryStatement(int, int, const Identifier*, bool, int, int, int, int) { return 1; }
+    int createTryStatement(int, int, const Identifier*, int, int, int, int) { return 1; }
     int createSwitchStatement(int, int, int, int, int, int, int) { return 1; }
     int createWhileStatement(int, int, int, int, int) { return 1; }
     int createWithStatement(int, int, int, int, int, int, int) { return 1; }
index d9700b7..433249c 100644 (file)
@@ -203,6 +203,7 @@ namespace JSC {
 
         bool isGlobalObject() const;
         bool isVariableObject() const;
+        bool isStaticScopeObject() const;
         bool isActivationObject() const;
         bool isErrorInstance() const;
         bool isGlobalThis() const;
@@ -428,6 +429,11 @@ inline bool JSObject::isVariableObject() const
     return structure()->typeInfo().type() >= VariableObjectType;
 }
 
+inline bool JSObject::isStaticScopeObject() const
+{
+    return structure()->typeInfo().type() == StaticScopeObjectType;
+}
+
 inline bool JSObject::isActivationObject() const
 {
     return structure()->typeInfo().type() == ActivationObjectType;