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
+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
PASS firstEvalResult is true
PASS secondEvalResult is false
PASS thirdEvalResult is true
+PASS testEvalInCatch() is true
PASS successfullyParsed is true
TEST COMPLETE
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()");
+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
// 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());
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;
}
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);
{
}
- 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)
{
}
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);
const Identifier& m_exceptionIdent;
StatementNode* m_catchBlock;
StatementNode* m_finallyBlock;
- bool m_catchHasEval;
};
class ParameterNode : public ParserArenaFreeable {
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();
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));
}
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>
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; }
bool isGlobalObject() const;
bool isVariableObject() const;
+ bool isStaticScopeObject() const;
bool isActivationObject() const;
bool isErrorInstance() const;
bool isGlobalThis() 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;