]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - debugger/DebuggerCallFrame.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / debugger / DebuggerCallFrame.cpp
index 83fb67f3afcdde3875ad5c08fd8073f88b8f80d2..663fc03cdf93ff10421a8ab4b7b5683d635016cc 100644 (file)
 #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 {
 
@@ -55,13 +58,36 @@ private:
     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())
@@ -70,9 +96,12 @@ PassRefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
     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;
@@ -99,27 +128,33 @@ String DebuggerCallFrame::functionName() const
     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
@@ -128,7 +163,7 @@ DebuggerCallFrame::Type DebuggerCallFrame::type() const
     if (!isValid())
         return ProgramType;
 
-    if (m_callFrame->callee())
+    if (jsDynamicCast<JSFunction*>(m_callFrame->callee()))
         return FunctionType;
 
     return ProgramType;
@@ -141,7 +176,7 @@ JSValue DebuggerCallFrame::thisValue() const
 }
 
 // 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;
@@ -153,8 +188,11 @@ JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception)
     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();
@@ -162,7 +200,7 @@ JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception)
     }
 
     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();
@@ -173,10 +211,13 @@ JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception)
 
 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();
     }
 }