#include "DebuggerCallFrame.h"
#include "CodeBlock.h"
+#include "DebuggerEvalEnabler.h"
+#include "DebuggerScope.h"
#include "Interpreter.h"
-#include "JSActivation.h"
#include "JSFunction.h"
+#include "JSLexicalEnvironment.h"
#include "JSCInlines.h"
#include "Parser.h"
#include "StackVisitor.h"
+#include "StrongInlines.h"
namespace JSC {
unsigned m_column;
};
+class FindCallerMidStackFunctor {
+public:
+ FindCallerMidStackFunctor(CallFrame* callFrame)
+ : m_callFrame(callFrame)
+ , m_callerFrame(nullptr)
+ { }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ if (visitor->callFrame() == m_callFrame) {
+ m_callerFrame = visitor->callerFrame();
+ return StackVisitor::Done;
+ }
+ return StackVisitor::Continue;
+ }
+
+ CallFrame* getCallerFrame() const { return m_callerFrame; }
+
+private:
+ CallFrame* m_callFrame;
+ CallFrame* m_callerFrame;
+};
+
DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame)
: m_callFrame(callFrame)
{
m_position = positionForCallFrame(m_callFrame);
}
-PassRefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
+RefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
{
ASSERT(isValid());
if (!isValid())
if (m_caller)
return m_caller;
- CallFrame* callerFrame = m_callFrame->callerFrameSkippingVMEntrySentinel();
+ FindCallerMidStackFunctor functor(m_callFrame);
+ m_callFrame->vm().topCallFrame->iterate(functor);
+
+ CallFrame* callerFrame = functor.getCallerFrame();
if (!callerFrame)
- return 0;
+ return nullptr;
m_caller = DebuggerCallFrame::create(callerFrame);
return m_caller;
ASSERT(isValid());
if (!isValid())
return String();
- JSObject* function = m_callFrame->callee();
+ JSFunction* function = jsDynamicCast<JSFunction*>(m_callFrame->callee());
if (!function)
return String();
return getCalculatedDisplayName(m_callFrame, function);
}
-JSScope* DebuggerCallFrame::scope() const
+DebuggerScope* DebuggerCallFrame::scope()
{
ASSERT(isValid());
if (!isValid())
return 0;
- CodeBlock* codeBlock = m_callFrame->codeBlock();
- if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
- JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock);
- m_callFrame->setActivation(activation);
- m_callFrame->setScope(activation);
+ if (!m_scope) {
+ VM& vm = m_callFrame->vm();
+ JSScope* scope;
+ CodeBlock* codeBlock = m_callFrame->codeBlock();
+ if (codeBlock && codeBlock->scopeRegister().isValid())
+ scope = m_callFrame->scope(codeBlock->scopeRegister().offset());
+ else if (JSCallee* callee = jsDynamicCast<JSCallee*>(m_callFrame->callee()))
+ scope = callee->scope();
+ else
+ scope = m_callFrame->lexicalGlobalObject();
+
+ m_scope.set(vm, DebuggerScope::create(vm, scope));
}
-
- return m_callFrame->scope();
+ return m_scope.get();
}
DebuggerCallFrame::Type DebuggerCallFrame::type() const
if (!isValid())
return ProgramType;
- if (m_callFrame->callee())
+ if (jsDynamicCast<JSFunction*>(m_callFrame->callee()))
return FunctionType;
return ProgramType;
}
// Evaluate some JavaScript code in the scope of this frame.
-JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception)
+JSValue DebuggerCallFrame::evaluate(const String& script, NakedPtr<Exception>& exception)
{
ASSERT(isValid());
CallFrame* callFrame = m_callFrame;
if (!callFrame->codeBlock())
return JSValue();
+ DebuggerEvalEnabler evalEnabler(callFrame);
VM& vm = callFrame->vm();
- EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), callFrame->codeBlock()->isStrictMode());
+ auto& codeBlock = *callFrame->codeBlock();
+ ThisTDZMode thisTDZMode = codeBlock.unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded;
+ EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode);
if (vm.exception()) {
exception = vm.exception();
vm.clearException();
}
JSValue thisValue = thisValueForCallFrame(callFrame);
- JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope());
+ JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
if (vm.exception()) {
exception = vm.exception();
vm.clearException();
void DebuggerCallFrame::invalidate()
{
- m_callFrame = nullptr;
- RefPtr<DebuggerCallFrame> frame = m_caller.release();
+ RefPtr<DebuggerCallFrame> frame = this;
while (frame) {
frame->m_callFrame = nullptr;
+ if (frame->m_scope) {
+ frame->m_scope->invalidateChain();
+ frame->m_scope.clear();
+ }
frame = frame->m_caller.release();
}
}