]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - debugger/DebuggerCallFrame.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / debugger / DebuggerCallFrame.cpp
index a3299d432a0afc79949c82f122be221802b7ef1f..83fb67f3afcdde3875ad5c08fd8073f88b8f80d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
  * 2.  Redistributions in binary form must reproduce the above copyright
  *     notice, this list of conditions and the following disclaimer in the
  *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
  *     its contributors may be used to endorse or promote products derived
  *     from this software without specific prior written permission.
  *
 #include "config.h"
 #include "DebuggerCallFrame.h"
 
-#include "JSFunction.h"
 #include "CodeBlock.h"
 #include "Interpreter.h"
+#include "JSActivation.h"
+#include "JSFunction.h"
+#include "JSCInlines.h"
 #include "Parser.h"
+#include "StackVisitor.h"
 
 namespace JSC {
 
-const UString* DebuggerCallFrame::functionName() const
+class LineAndColumnFunctor {
+public:
+    StackVisitor::Status operator()(StackVisitor& visitor)
+    {
+        visitor->computeLineAndColumn(m_line, m_column);
+        return StackVisitor::Done;
+    }
+
+    unsigned line() const { return m_line; }
+    unsigned column() const { return m_column; }
+
+private:
+    unsigned m_line;
+    unsigned m_column;
+};
+
+DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame)
+    : m_callFrame(callFrame)
 {
-    if (!m_callFrame->codeBlock())
-        return 0;
+    m_position = positionForCallFrame(m_callFrame);
+}
 
-    if (!m_callFrame->callee())
+PassRefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
+{
+    ASSERT(isValid());
+    if (!isValid())
         return 0;
 
-    JSFunction* function = asFunction(m_callFrame->callee());
-    if (!function)
+    if (m_caller)
+        return m_caller;
+
+    CallFrame* callerFrame = m_callFrame->callerFrameSkippingVMEntrySentinel();
+    if (!callerFrame)
         return 0;
-    return &function->name(m_callFrame);
+
+    m_caller = DebuggerCallFrame::create(callerFrame);
+    return m_caller;
 }
-    
-UString DebuggerCallFrame::calculatedFunctionName() const
+
+JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const
 {
-    if (!m_callFrame->codeBlock())
+    ASSERT(isValid());
+    if (!isValid())
         return 0;
+    return m_callFrame->vmEntryGlobalObject();
+}
 
-    if (!m_callFrame->callee())
-        return UString();
+SourceID DebuggerCallFrame::sourceID() const
+{
+    ASSERT(isValid());
+    if (!isValid())
+        return noSourceID;
+    return sourceIDForCallFrame(m_callFrame);
+}
 
-    JSFunction* function = asFunction(m_callFrame->callee());
+String DebuggerCallFrame::functionName() const
+{
+    ASSERT(isValid());
+    if (!isValid())
+        return String();
+    JSObject* function = m_callFrame->callee();
     if (!function)
+        return String();
+
+    return getCalculatedDisplayName(m_callFrame, function);
+}
+
+JSScope* DebuggerCallFrame::scope() const
+{
+    ASSERT(isValid());
+    if (!isValid())
         return 0;
-    return function->calculatedDisplayName(m_callFrame);
+
+    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);
+    }
+
+    return m_callFrame->scope();
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
 {
+    ASSERT(isValid());
+    if (!isValid())
+        return ProgramType;
+
     if (m_callFrame->callee())
         return FunctionType;
 
     return ProgramType;
 }
 
-JSObject* DebuggerCallFrame::thisObject() const
+JSValue DebuggerCallFrame::thisValue() const
 {
-    if (!m_callFrame->codeBlock())
-        return 0;
-
-    return asObject(m_callFrame->thisValue());
+    ASSERT(isValid());
+    return thisValueForCallFrame(m_callFrame);
 }
 
-JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) const
+// Evaluate some JavaScript code in the scope of this frame.
+JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception)
 {
-    if (!m_callFrame->codeBlock())
+    ASSERT(isValid());
+    CallFrame* callFrame = m_callFrame;
+    if (!callFrame)
+        return jsNull();
+
+    JSLockHolder lock(callFrame);
+
+    if (!callFrame->codeBlock())
         return JSValue();
+    
+    VM& vm = callFrame->vm();
+    EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), callFrame->codeBlock()->isStrictMode());
+    if (vm.exception()) {
+        exception = vm.exception();
+        vm.clearException();
+        return jsUndefined();
+    }
+
+    JSValue thisValue = thisValueForCallFrame(callFrame);
+    JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope());
+    if (vm.exception()) {
+        exception = vm.exception();
+        vm.clearException();
+    }
+    ASSERT(result);
+    return result;
+}
 
-    RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script));
-    JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain());
-    if (error)
-        return error;
+void DebuggerCallFrame::invalidate()
+{
+    m_callFrame = nullptr;
+    RefPtr<DebuggerCallFrame> frame = m_caller.release();
+    while (frame) {
+        frame->m_callFrame = nullptr;
+        frame = frame->m_caller.release();
+    }
+}
+
+TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
+{
+    if (!callFrame)
+        return TextPosition();
+
+    LineAndColumnFunctor functor;
+    callFrame->iterate(functor);
+    return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column()));
+}
 
-    return m_callFrame->scopeChain()->globalData->interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
+SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame)
+{
+    ASSERT(callFrame);
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    if (!codeBlock)
+        return noSourceID;
+    return codeBlock->ownerExecutable()->sourceID();
+}
+
+JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame)
+{
+    if (!callFrame)
+        return jsNull();
+
+    ECMAMode ecmaMode = NotStrictMode;
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    if (codeBlock && codeBlock->isStrictMode())
+        ecmaMode = StrictMode;
+    JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode);
+    return thisValue;
 }
 
 } // namespace JSC