]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - inspector/ScriptDebugServer.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / inspector / ScriptDebugServer.cpp
index d2798933f93b4d355623e4089d15c2c11ccd5a76..74602c521886707c79fc9a14311664d6efa0b603 100644 (file)
@@ -31,9 +31,9 @@
 #include "config.h"
 #include "ScriptDebugServer.h"
 
-#if ENABLE(INSPECTOR)
-
 #include "DebuggerCallFrame.h"
+#include "DebuggerScope.h"
+#include "Exception.h"
 #include "JSJavaScriptCallFrame.h"
 #include "JSLock.h"
 #include "JavaScriptCallFrame.h"
@@ -49,8 +49,6 @@ namespace Inspector {
 
 ScriptDebugServer::ScriptDebugServer(bool isInWorkerThread)
     : Debugger(isInWorkerThread)
-    , m_doneProcessingDebuggerEvents(true)
-    , m_callingListeners(false)
 {
 }
 
@@ -96,7 +94,7 @@ bool ScriptDebugServer::evaluateBreakpointAction(const ScriptBreakpointAction& b
         break;
     }
     case ScriptBreakpointActionTypeEvaluate: {
-        JSValue exception;
+        NakedPtr<Exception> exception;
         debuggerCallFrame->evaluate(breakpointAction.data, exception);
         if (exception)
             reportException(debuggerCallFrame->exec(), exception);
@@ -106,13 +104,13 @@ bool ScriptDebugServer::evaluateBreakpointAction(const ScriptBreakpointAction& b
         dispatchBreakpointActionSound(debuggerCallFrame->exec(), breakpointAction.identifier);
         break;
     case ScriptBreakpointActionTypeProbe: {
-        JSValue exception;
+        NakedPtr<Exception> exception;
         JSValue result = debuggerCallFrame->evaluate(breakpointAction.data, exception);
         if (exception)
             reportException(debuggerCallFrame->exec(), exception);
         
         JSC::ExecState* state = debuggerCallFrame->scope()->globalObject()->globalExec();
-        Deprecated::ScriptValue wrappedResult = Deprecated::ScriptValue(state->vm(), exception ? exception : result);
+        Deprecated::ScriptValue wrappedResult = Deprecated::ScriptValue(state->vm(), exception ? exception->value() : result);
         dispatchBreakpointActionProbe(state, breakpointAction, wrappedResult);
         break;
     }
@@ -137,7 +135,8 @@ void ScriptDebugServer::dispatchDidPause(ScriptDebugListener* listener)
     JSC::ExecState* state = globalObject->globalExec();
     RefPtr<JavaScriptCallFrame> javaScriptCallFrame = JavaScriptCallFrame::create(debuggerCallFrame);
     JSValue jsCallFrame = toJS(state, globalObject, javaScriptCallFrame.get());
-    listener->didPause(state, Deprecated::ScriptValue(state->vm(), jsCallFrame), Deprecated::ScriptValue());
+
+    listener->didPause(state, Deprecated::ScriptValue(state->vm(), jsCallFrame), exceptionOrCaughtValue(state));
 }
 
 void ScriptDebugServer::dispatchBreakpointActionLog(ExecState* exec, const String& message)
@@ -145,53 +144,52 @@ void ScriptDebugServer::dispatchBreakpointActionLog(ExecState* exec, const Strin
     if (m_callingListeners)
         return;
 
-    ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject());
-    if (!listeners)
+    ListenerSet& listeners = getListeners();
+    if (listeners.isEmpty())
         return;
-    ASSERT(!listeners->isEmpty());
 
     TemporaryChange<bool> change(m_callingListeners, true);
 
     Vector<ScriptDebugListener*> listenersCopy;
-    copyToVector(*listeners, listenersCopy);
+    copyToVector(listeners, listenersCopy);
     for (auto* listener : listenersCopy)
         listener->breakpointActionLog(exec, message);
 }
 
-void ScriptDebugServer::dispatchBreakpointActionSound(ExecState* exec, int breakpointActionIdentifier)
+void ScriptDebugServer::dispatchBreakpointActionSound(ExecState*, int breakpointActionIdentifier)
 {
     if (m_callingListeners)
         return;
 
-    ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject());
-    if (!listeners)
+    ListenerSet& listeners = getListeners();
+    if (listeners.isEmpty())
         return;
-    ASSERT(!listeners->isEmpty());
 
     TemporaryChange<bool> change(m_callingListeners, true);
 
     Vector<ScriptDebugListener*> listenersCopy;
-    copyToVector(*listeners, listenersCopy);
+    copyToVector(listeners, listenersCopy);
     for (auto* listener : listenersCopy)
         listener->breakpointActionSound(breakpointActionIdentifier);
 }
 
-void ScriptDebugServer::dispatchBreakpointActionProbe(ExecState* exec, const ScriptBreakpointAction& action, const Deprecated::ScriptValue& sample)
+void ScriptDebugServer::dispatchBreakpointActionProbe(ExecState* exec, const ScriptBreakpointAction& action, const Deprecated::ScriptValue& sampleValue)
 {
     if (m_callingListeners)
         return;
 
-    ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject());
-    if (!listeners)
+    ListenerSet& listeners = getListeners();
+    if (listeners.isEmpty())
         return;
-    ASSERT(!listeners->isEmpty());
 
     TemporaryChange<bool> change(m_callingListeners, true);
 
+    unsigned sampleId = m_nextProbeSampleId++;
+
     Vector<ScriptDebugListener*> listenersCopy;
-    copyToVector(*listeners, listenersCopy);
+    copyToVector(listeners, listenersCopy);
     for (auto* listener : listenersCopy)
-        listener->breakpointActionProbe(exec, action, m_hitCount, sample);
+        listener->breakpointActionProbe(exec, action, m_currentProbeBatchId, sampleId, sampleValue);
 }
 
 void ScriptDebugServer::dispatchDidContinue(ScriptDebugListener* listener)
@@ -249,79 +247,77 @@ void ScriptDebugServer::sourceParsed(ExecState* exec, SourceProvider* sourceProv
     if (m_callingListeners)
         return;
 
-    ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject());
-    if (!listeners)
+    ListenerSet& listeners = getListeners();
+    if (listeners.isEmpty())
         return;
-    ASSERT(!listeners->isEmpty());
 
     TemporaryChange<bool> change(m_callingListeners, true);
 
     bool isError = errorLine != -1;
     if (isError)
-        dispatchFailedToParseSource(*listeners, sourceProvider, errorLine, errorMessage);
+        dispatchFailedToParseSource(listeners, sourceProvider, errorLine, errorMessage);
     else
-        dispatchDidParseSource(*listeners, sourceProvider, isContentScript(exec));
+        dispatchDidParseSource(listeners, sourceProvider, isContentScript(exec));
 }
 
-void ScriptDebugServer::dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback)
-{
-    Vector<ScriptDebugListener*> copy;
-    copyToVector(listeners, copy);
-    for (size_t i = 0; i < copy.size(); ++i)
-        (this->*callback)(copy[i]);
-}
-
-void ScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, JSGlobalObject* globalObject)
+void ScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback)
 {
     if (m_callingListeners)
         return;
 
     TemporaryChange<bool> change(m_callingListeners, true);
 
-    if (ListenerSet* listeners = getListenersForGlobalObject(globalObject)) {
-        if (!listeners->isEmpty())
-            dispatchFunctionToListeners(*listeners, callback);
-    }
+    ListenerSet& listeners = getListeners();
+    if (!listeners.isEmpty())
+        dispatchFunctionToListeners(listeners, callback);
 }
 
-void ScriptDebugServer::notifyDoneProcessingDebuggerEvents()
+void ScriptDebugServer::dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback)
 {
-    m_doneProcessingDebuggerEvents = true;
+    Vector<ScriptDebugListener*> copy;
+    copyToVector(listeners, copy);
+    for (size_t i = 0; i < copy.size(); ++i)
+        (this->*callback)(copy[i]);
 }
 
-bool ScriptDebugServer::needPauseHandling(JSGlobalObject* globalObject)
+void ScriptDebugServer::notifyDoneProcessingDebuggerEvents()
 {
-    return !!getListenersForGlobalObject(globalObject);
+    m_doneProcessingDebuggerEvents = true;
 }
 
-void ScriptDebugServer::handleBreakpointHit(const JSC::Breakpoint& breakpoint)
+void ScriptDebugServer::handleBreakpointHit(JSC::JSGlobalObject* globalObject, const JSC::Breakpoint& breakpoint)
 {
-    m_hitCount++;
+    ASSERT(isAttached(globalObject));
+
+    m_currentProbeBatchId++;
+
     BreakpointIDToActionsMap::iterator it = m_breakpointIDToActions.find(breakpoint.id);
     if (it != m_breakpointIDToActions.end()) {
-        BreakpointActions& actions = it->value;
+        BreakpointActions actions = it->value;
         for (size_t i = 0; i < actions.size(); ++i) {
             if (!evaluateBreakpointAction(actions[i]))
                 return;
+            if (!isAttached(globalObject))
+                return;
         }
     }
 }
 
-void ScriptDebugServer::handleExceptionInBreakpointCondition(JSC::ExecState* exec, JSC::JSValue exception) const
+void ScriptDebugServer::handleExceptionInBreakpointCondition(JSC::ExecState* exec, JSC::Exception* exception) const
 {
     reportException(exec, exception);
 }
 
-void ScriptDebugServer::handlePause(Debugger::ReasonForPause, JSGlobalObject* vmEntryGlobalObject)
+void ScriptDebugServer::handlePause(JSGlobalObject* vmEntryGlobalObject, Debugger::ReasonForPause)
 {
-    dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidPause, vmEntryGlobalObject);
+    dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidPause);
     didPause(vmEntryGlobalObject);
 
     m_doneProcessingDebuggerEvents = false;
     runEventLoopWhilePaused();
 
     didContinue(vmEntryGlobalObject);
-    dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidContinue, vmEntryGlobalObject);
+    dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidContinue);
 }
 
 const BreakpointActions& ScriptDebugServer::getActionsForBreakpoint(JSC::BreakpointID breakpointID)
@@ -335,6 +331,20 @@ const BreakpointActions& ScriptDebugServer::getActionsForBreakpoint(JSC::Breakpo
     return emptyActionVector;
 }
 
-} // namespace Inspector
+Deprecated::ScriptValue ScriptDebugServer::exceptionOrCaughtValue(JSC::ExecState* state)
+{
+    if (reasonForPause() == PausedForException)
+        return Deprecated::ScriptValue(state->vm(), currentException());
+
+    RefPtr<DebuggerCallFrame> debuggerCallFrame = currentDebuggerCallFrame();
+    while (debuggerCallFrame) {
+        DebuggerScope* scope = debuggerCallFrame->scope();
+        if (scope->isCatchScope())
+            return Deprecated::ScriptValue(state->vm(), scope->caughtValue());
+        debuggerCallFrame = debuggerCallFrame->callerFrame();
+    }
 
-#endif // ENABLE(INSPECTOR)
+    return Deprecated::ScriptValue();
+}
+
+} // namespace Inspector