Generate WebScriptCallFrame instances dynamically
authoraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Mar 2008 17:00:04 +0000 (17:00 +0000)
committeraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Mar 2008 17:00:04 +0000 (17:00 +0000)
        WebScriptDebugger no longer holds a reference to the topmost call
        frame, and WebScriptCallFrame no longer holds a reference to its
        caller. We now generate WebScriptCallFrame instances as needed by
        walking the callingExecState chain.

        By making WebKit no longer responsible for keeping track of the call
        stack, we get one step closer to moving most JS debugging code out of
        WebKit entirely.

        This incidentally fixes a bug in Drosera where we'd never show the
        global scope in the call stack.

        Reviewed by Sam and Kevin M.

        * WebScriptCallFrame.cpp:
        (callingFunctionOrGlobalExecState): Finds the nearest calling
        ExecState that is a FunctionExecState or GlobalExecState, if any, and
        returns it.
        (WebScriptCallFrame::WebScriptCallFrame):
          - No longer takes a caller parameter.
          - Sets m_state to the callingFunctionOrGlobalExecState of the
            ExecState passed in.
        (WebScriptCallFrame::createInstance): Removed the caller parameter.
        (WebScriptCallFrame::caller): Generate a new WebScriptCallFrame on the
        fly from our ExecState.
        * WebScriptCallFrame.h: No longer holds a reference to the caller.
        * WebScriptDebugger.cpp:
        (WebScriptDebugger::WebScriptDebugger): Removed the call to callEvent
        that was supposed to set up the global scope call frame, but never
        worked because m_callingServer was set to true, which would cause
        callEvent to return early without doing anything. Also removed the
        m_callingServer guards since we're not calling callEvent anymore.
        (WebScriptDebugger::callEvent): Create a WebScriptCallFrame on the
        fly from the passed-in ExecState.
        (WebScriptDebugger::atStatement): Ditto.
        (WebScriptDebugger::returnEvent): Ditto, but use the callingExecState.
        This is equivalent to what calling leaveFrame() did before.
        (WebScriptDebugger::exception): Ditto, using the passed-in ExecState.
        * WebScriptDebugger.h: Removed m_topStackFrame member and
        enterFrame/leaveFrame methods.

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

WebKit/win/ChangeLog
WebKit/win/WebScriptCallFrame.cpp
WebKit/win/WebScriptCallFrame.h
WebKit/win/WebScriptDebugger.cpp
WebKit/win/WebScriptDebugger.h

index 87a338f2a6714bced109c01171ef26ae9d808571..e37d68268fe184315e2cd6b24d7b0c7ff5a7fc30 100644 (file)
@@ -1,3 +1,48 @@
+2008-03-03  Adam Roben  <aroben@apple.com>
+
+        Generate WebScriptCallFrame instances dynamically
+
+        WebScriptDebugger no longer holds a reference to the topmost call
+        frame, and WebScriptCallFrame no longer holds a reference to its
+        caller. We now generate WebScriptCallFrame instances as needed by
+        walking the callingExecState chain.
+
+        By making WebKit no longer responsible for keeping track of the call
+        stack, we get one step closer to moving most JS debugging code out of
+        WebKit entirely.
+
+        This incidentally fixes a bug in Drosera where we'd never show the
+        global scope in the call stack.
+
+        Reviewed by Sam and Kevin M.
+
+        * WebScriptCallFrame.cpp:
+        (callingFunctionOrGlobalExecState): Finds the nearest calling
+        ExecState that is a FunctionExecState or GlobalExecState, if any, and
+        returns it.
+        (WebScriptCallFrame::WebScriptCallFrame):
+          - No longer takes a caller parameter.
+          - Sets m_state to the callingFunctionOrGlobalExecState of the
+            ExecState passed in.
+        (WebScriptCallFrame::createInstance): Removed the caller parameter.
+        (WebScriptCallFrame::caller): Generate a new WebScriptCallFrame on the
+        fly from our ExecState.
+        * WebScriptCallFrame.h: No longer holds a reference to the caller.
+        * WebScriptDebugger.cpp:
+        (WebScriptDebugger::WebScriptDebugger): Removed the call to callEvent
+        that was supposed to set up the global scope call frame, but never
+        worked because m_callingServer was set to true, which would cause
+        callEvent to return early without doing anything. Also removed the
+        m_callingServer guards since we're not calling callEvent anymore.
+        (WebScriptDebugger::callEvent): Create a WebScriptCallFrame on the
+        fly from the passed-in ExecState.
+        (WebScriptDebugger::atStatement): Ditto.
+        (WebScriptDebugger::returnEvent): Ditto, but use the callingExecState.
+        This is equivalent to what calling leaveFrame() did before.
+        (WebScriptDebugger::exception): Ditto, using the passed-in ExecState.
+        * WebScriptDebugger.h: Removed m_topStackFrame member and
+        enterFrame/leaveFrame methods.
+
 2008-03-03  Sam Weinig  <sam@webkit.org>
 
         Windows build fix.
index 48c79c1ab560bfa476c4b7fe7929a68e76ca8972..356086195a9edd370e1da88116ea7571f51691ca 100644 (file)
  */
 
 #include "config.h"
-#include "WebKitDLL.h"
 #include "WebScriptCallFrame.h"
 
 #include "COMEnumVariant.h"
 #include "Function.h"
+#include "WebKitDLL.h"
 
 #include <JavaScriptCore/Interpreter.h>
 #include <JavaScriptCore/JSGlobalObject.h>
@@ -79,12 +79,20 @@ UString WebScriptCallFrame::jsValueToString(KJS::ExecState* state, JSValue* jsva
 
 // WebScriptCallFrame -----------------------------------------------------------
 
-WebScriptCallFrame::WebScriptCallFrame(ExecState* state, IWebScriptCallFrame* caller)
-    : m_refCount(0)
+static ExecState* callingFunctionOrGlobalExecState(ExecState* exec)
 {
-    m_state = state;
-    m_caller = caller;
+    for (ExecState* current = exec; current; current = current->callingExecState())
+        if (current->codeType() == FunctionCode || current->codeType() == GlobalCode)
+            return current;
+    return 0;
+}
 
+WebScriptCallFrame::WebScriptCallFrame(ExecState* state)
+    : m_refCount(0)
+    , m_state(callingFunctionOrGlobalExecState(state))
+{
+    ASSERT_ARG(state, state);
+    ASSERT(m_state);
     gClassCount++;
 }
 
@@ -93,9 +101,9 @@ WebScriptCallFrame::~WebScriptCallFrame()
     gClassCount--;
 }
 
-WebScriptCallFrame* WebScriptCallFrame::createInstance(ExecState* state, IWebScriptCallFrame* caller)
+WebScriptCallFrame* WebScriptCallFrame::createInstance(ExecState* state)
 {
-    WebScriptCallFrame* instance = new WebScriptCallFrame(state, caller);
+    WebScriptCallFrame* instance = new WebScriptCallFrame(state);
     instance->AddRef();
     return instance;
 }
@@ -135,7 +143,11 @@ ULONG STDMETHODCALLTYPE WebScriptCallFrame::Release()
 HRESULT STDMETHODCALLTYPE WebScriptCallFrame::caller(
     /* [out, retval] */ IWebScriptCallFrame** callFrame)
 {
-    return m_caller.copyRefTo(callFrame);
+    if (!callFrame)
+        return E_POINTER;
+
+    *callFrame = m_state->callingExecState() ? WebScriptCallFrame::createInstance(m_state->callingExecState()) : 0;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE WebScriptCallFrame::functionName(
index 311227aa6b4a92dc592197096d4644e76c24095c..a7cd93ac2f708b939c03f882c202f3d3a5167fbb 100644 (file)
 
 #include "WebKit.h"
 
-#include <JavaScriptCore/ExecState.h>
-#pragma warning(push, 0)
-#include <WebCore/COMPtr.h>
-#pragma warning(pop)
-
 namespace KJS {
     class ExecState;
     class JSValue;
@@ -44,10 +39,10 @@ namespace KJS {
 
 class WebScriptCallFrame : public IWebScriptCallFrame {
 public:
-    static WebScriptCallFrame* createInstance(KJS::ExecState*, IWebScriptCallFrame* caller);
+    static WebScriptCallFrame* createInstance(KJS::ExecState*);
 
 private:
-    WebScriptCallFrame(KJS::ExecState*, IWebScriptCallFrame* caller);
+    WebScriptCallFrame(KJS::ExecState*);
     virtual ~WebScriptCallFrame();
 
 public:
@@ -88,7 +83,6 @@ private:
     ULONG m_refCount;
 
     KJS::ExecState* m_state;
-    COMPtr<IWebScriptCallFrame> m_caller;
 };
 
 #endif
index abb22033a6f31d5bc26c48805913cd8d45e99c74..180e325f075c2e96d0f661a3f4e5fa5f991c7f6a 100644 (file)
@@ -47,11 +47,10 @@ using namespace KJS;
 
 WebScriptDebugger::WebScriptDebugger(WebFrame* frame)
     : m_frame(frame)
+    , m_callingServer(false)
 {
     ASSERT(m_frame);
 
-    m_callingServer = true;
-
     KJSProxy* proxy = core(m_frame)->scriptProxy();
     if (!proxy)
         return;
@@ -61,9 +60,6 @@ WebScriptDebugger::WebScriptDebugger(WebFrame* frame)
 
     m_frame->webView(&m_webView);
     ASSERT(m_webView);
-
-    callEvent(globalObject->globalExec(), -1, -1, 0, List());
-    m_callingServer = false;
 }
 
 bool WebScriptDebugger::sourceParsed(ExecState*, int sourceId, const UString& sourceURL,
@@ -103,77 +99,62 @@ bool WebScriptDebugger::sourceParsed(ExecState*, int sourceId, const UString& so
     return true;
 }
 
-bool WebScriptDebugger::callEvent(ExecState* state, int sourceId, int lineno, JSObject* /*function*/, const List &/*args*/)
+bool WebScriptDebugger::callEvent(ExecState* exec, int sourceId, int lineno, JSObject* /*function*/, const List &/*args*/)
 {
     if (m_callingServer)
         return true;
 
     m_callingServer = true;
 
-    enterFrame(state);
-    WebScriptDebugServer::sharedWebScriptDebugServer()->didEnterCallFrame(m_webView.get(), m_topStackFrame.get(), sourceId, lineno, m_frame);
+    COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec));
+    WebScriptDebugServer::sharedWebScriptDebugServer()->didEnterCallFrame(m_webView.get(), callFrame.get(), sourceId, lineno, m_frame);
 
     m_callingServer = false;
 
     return true;
 }
 
-bool WebScriptDebugger::atStatement(ExecState*, int sourceId, int firstLine, int /*lastLine*/)
+bool WebScriptDebugger::atStatement(ExecState* exec, int sourceId, int firstLine, int /*lastLine*/)
 {
     if (m_callingServer)
         return true;
 
     m_callingServer = true;
 
-    WebScriptDebugServer::sharedWebScriptDebugServer()->willExecuteStatement(m_webView.get(), m_topStackFrame.get(), sourceId, firstLine, m_frame);
+    COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec));
+    WebScriptDebugServer::sharedWebScriptDebugServer()->willExecuteStatement(m_webView.get(), callFrame.get(), sourceId, firstLine, m_frame);
 
     m_callingServer = false;
 
     return true;
 }
 
-bool WebScriptDebugger::returnEvent(ExecState*, int sourceId, int lineno, JSObject* /*function*/)
+bool WebScriptDebugger::returnEvent(ExecState* exec, int sourceId, int lineno, JSObject* /*function*/)
 {
     if (m_callingServer)
         return true;
 
     m_callingServer = true;
 
-    leaveFrame();
-    WebScriptDebugServer::sharedWebScriptDebugServer()->willLeaveCallFrame(m_webView.get(), m_topStackFrame.get(), sourceId, lineno, m_frame);
+    COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec->callingExecState()));
+    WebScriptDebugServer::sharedWebScriptDebugServer()->willLeaveCallFrame(m_webView.get(), callFrame.get(), sourceId, lineno, m_frame);
 
     m_callingServer = false;
 
     return true;
 }
 
-bool WebScriptDebugger::exception(ExecState*, int sourceId, int lineno, JSValue* /*exception */)
+bool WebScriptDebugger::exception(ExecState* exec, int sourceId, int lineno, JSValue* /*exception */)
 {
     if (m_callingServer)
         return true;
 
     m_callingServer = true;
 
-    WebScriptDebugServer::sharedWebScriptDebugServer()->exceptionWasRaised(m_webView.get(), m_topStackFrame.get(), sourceId, lineno, m_frame);
+    COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec));
+    WebScriptDebugServer::sharedWebScriptDebugServer()->exceptionWasRaised(m_webView.get(), callFrame.get(), sourceId, lineno, m_frame);
 
     m_callingServer = false;
 
     return true;
 }
-
-void WebScriptDebugger::enterFrame(ExecState* state)
-{
-    m_topStackFrame = WebScriptCallFrame::createInstance(state, m_topStackFrame.get()); // Set the top as the caller
-}
-
-void WebScriptDebugger::leaveFrame()
-{
-    if (!m_topStackFrame)
-        return;
-
-    COMPtr<IWebScriptCallFrame> caller;
-    if (FAILED(m_topStackFrame->caller(&caller)))
-        return;
-
-    m_topStackFrame = caller;
-}
index bb91c25d42d20e0c9ab7661066010fc4832243ee..98ed8f599ac240a1d4b6bc6df614b35616626a4a 100644 (file)
@@ -59,13 +59,9 @@ public:
     bool exception(KJS::ExecState*, int sourceId, int lineno, KJS::JSValue* exception);
 
 private:
-    void enterFrame(KJS::ExecState*);
-    void leaveFrame();
     bool m_callingServer;
-
     WebFrame* m_frame;
     COMPtr<IWebView> m_webView;
-    COMPtr<IWebScriptCallFrame> m_topStackFrame; 
 };
 
 #endif