diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
commit | a4e969f4965059196ca948db781e52f7cfebf19e (patch) | |
tree | 6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/JavaScriptCore/inspector/ScriptDebugServer.cpp | |
parent | 41386e9cb918eed93b3f13648cbef387e371e451 (diff) | |
download | WebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz |
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/JavaScriptCore/inspector/ScriptDebugServer.cpp')
-rw-r--r-- | Source/JavaScriptCore/inspector/ScriptDebugServer.cpp | 169 |
1 files changed, 101 insertions, 68 deletions
diff --git a/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp b/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp index b1151cf7f..98c65de0b 100644 --- a/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp +++ b/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp @@ -12,7 +12,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. * @@ -32,25 +32,22 @@ #include "ScriptDebugServer.h" #include "DebuggerCallFrame.h" +#include "DebuggerScope.h" +#include "Exception.h" #include "JSJavaScriptCallFrame.h" #include "JSLock.h" #include "JavaScriptCallFrame.h" #include "ScriptValue.h" #include "SourceProvider.h" -#include <wtf/MainThread.h> #include <wtf/NeverDestroyed.h> #include <wtf/TemporaryChange.h> -#include <wtf/text/WTFString.h> using namespace JSC; -using namespace Inspector; namespace Inspector { -ScriptDebugServer::ScriptDebugServer(bool isInWorkerThread) - : Debugger(isInWorkerThread) - , m_doneProcessingDebuggerEvents(true) - , m_callingListeners(false) +ScriptDebugServer::ScriptDebugServer(VM& vm) + : Debugger(vm) { } @@ -63,14 +60,14 @@ JSC::BreakpointID ScriptDebugServer::setBreakpoint(JSC::SourceID sourceID, const if (!sourceID) return JSC::noBreakpointID; - JSC::Breakpoint breakpoint(sourceID, scriptBreakpoint.lineNumber, scriptBreakpoint.columnNumber, scriptBreakpoint.condition, scriptBreakpoint.autoContinue); + JSC::Breakpoint breakpoint(sourceID, scriptBreakpoint.lineNumber, scriptBreakpoint.columnNumber, scriptBreakpoint.condition, scriptBreakpoint.autoContinue, scriptBreakpoint.ignoreCount); JSC::BreakpointID id = Debugger::setBreakpoint(breakpoint, *actualLineNumber, *actualColumnNumber); if (id != JSC::noBreakpointID && !scriptBreakpoint.actions.isEmpty()) { #ifndef NDEBUG BreakpointIDToActionsMap::iterator it = m_breakpointIDToActions.find(id); ASSERT(it == m_breakpointIDToActions.end()); #endif - const Vector<ScriptBreakpointAction> &actions = scriptBreakpoint.actions; + const BreakpointActions& actions = scriptBreakpoint.actions; m_breakpointIDToActions.set(id, actions); } return id; @@ -96,24 +93,24 @@ 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); break; } case ScriptBreakpointActionTypeSound: - dispatchBreakpointActionSound(debuggerCallFrame->exec()); + 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); - dispatchDidSampleProbe(state, breakpointAction.identifier, wrappedResult); + Deprecated::ScriptValue wrappedResult = Deprecated::ScriptValue(state->vm(), exception ? exception->value() : result); + dispatchBreakpointActionProbe(state, breakpointAction, wrappedResult); break; } default: @@ -137,7 +134,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 +143,49 @@ void ScriptDebugServer::dispatchBreakpointActionLog(ExecState* exec, const Strin if (m_callingListeners) return; - ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject()); - if (!listeners) + if (m_listeners.isEmpty()) return; - ASSERT(!listeners->isEmpty()); TemporaryChange<bool> change(m_callingListeners, true); Vector<ScriptDebugListener*> listenersCopy; - copyToVector(*listeners, listenersCopy); - for (auto listener : listenersCopy) + copyToVector(m_listeners, listenersCopy); + for (auto* listener : listenersCopy) listener->breakpointActionLog(exec, message); } -void ScriptDebugServer::dispatchBreakpointActionSound(ExecState* exec) +void ScriptDebugServer::dispatchBreakpointActionSound(ExecState*, int breakpointActionIdentifier) { if (m_callingListeners) return; - ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject()); - if (!listeners) + if (m_listeners.isEmpty()) return; - ASSERT(!listeners->isEmpty()); TemporaryChange<bool> change(m_callingListeners, true); Vector<ScriptDebugListener*> listenersCopy; - copyToVector(*listeners, listenersCopy); - for (auto listener : listenersCopy) - listener->breakpointActionSound(); + copyToVector(m_listeners, listenersCopy); + for (auto* listener : listenersCopy) + listener->breakpointActionSound(breakpointActionIdentifier); } -void ScriptDebugServer::dispatchDidSampleProbe(ExecState* exec, int identifier, 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) + if (m_listeners.isEmpty()) return; - ASSERT(!listeners->isEmpty()); TemporaryChange<bool> change(m_callingListeners, true); + unsigned sampleId = m_nextProbeSampleId++; + Vector<ScriptDebugListener*> listenersCopy; - copyToVector(*listeners, listenersCopy); - for (auto listener : listenersCopy) - listener->didSampleProbe(exec, identifier, m_hitCount, sample); + copyToVector(m_listeners, listenersCopy); + for (auto* listener : listenersCopy) + listener->breakpointActionProbe(exec, action, m_currentProbeBatchId, sampleId, sampleValue); } void ScriptDebugServer::dispatchDidContinue(ScriptDebugListener* listener) @@ -205,10 +199,12 @@ void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, Sou ScriptDebugListener::Script script; script.url = sourceProvider->url(); - script.source = sourceProvider->source(); + script.source = sourceProvider->source().toString(); script.startLine = sourceProvider->startPosition().m_line.zeroBasedInt(); script.startColumn = sourceProvider->startPosition().m_column.zeroBasedInt(); script.isContentScript = isContentScript; + script.sourceURL = sourceProvider->sourceURL(); + script.sourceMappingURL = sourceProvider->sourceMappingURL(); int sourceLength = script.source.length(); int lineCount = 1; @@ -235,7 +231,7 @@ void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, Sou void ScriptDebugServer::dispatchFailedToParseSource(const ListenerSet& listeners, SourceProvider* sourceProvider, int errorLine, const String& errorMessage) { String url = sourceProvider->url(); - const String& data = sourceProvider->source(); + String data = sourceProvider->source().toString(); int firstLine = sourceProvider->startPosition().m_line.oneBasedInt(); Vector<ScriptDebugListener*> copy; @@ -249,90 +245,127 @@ void ScriptDebugServer::sourceParsed(ExecState* exec, SourceProvider* sourceProv if (m_callingListeners) return; - ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject()); - if (!listeners) + if (m_listeners.isEmpty()) return; - ASSERT(!listeners->isEmpty()); TemporaryChange<bool> change(m_callingListeners, true); bool isError = errorLine != -1; if (isError) - dispatchFailedToParseSource(*listeners, sourceProvider, errorLine, errorMessage); + dispatchFailedToParseSource(m_listeners, sourceProvider, errorLine, errorMessage); else - 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]); + dispatchDidParseSource(m_listeners, sourceProvider, isContentScript(exec)); } -void ScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, JSGlobalObject* globalObject) +void ScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback) { if (m_callingListeners) return; + if (m_listeners.isEmpty()) + return; + TemporaryChange<bool> change(m_callingListeners, true); - if (ListenerSet* listeners = getListenersForGlobalObject(globalObject)) { - ASSERT(!listeners->isEmpty()); - dispatchFunctionToListeners(*listeners, callback); - } + dispatchFunctionToListeners(m_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 Vector<ScriptBreakpointAction>& ScriptDebugServer::getActionsForBreakpoint(JSC::BreakpointID breakpointID) +const BreakpointActions& ScriptDebugServer::getActionsForBreakpoint(JSC::BreakpointID breakpointID) { ASSERT(breakpointID != JSC::noBreakpointID); if (m_breakpointIDToActions.contains(breakpointID)) return m_breakpointIDToActions.find(breakpointID)->value; - static NeverDestroyed<Vector<ScriptBreakpointAction>> emptyActionVector = Vector<ScriptBreakpointAction>(); + static NeverDestroyed<BreakpointActions> emptyActionVector = BreakpointActions(); return emptyActionVector; } +void ScriptDebugServer::addListener(ScriptDebugListener* listener) +{ + ASSERT(listener); + + bool wasEmpty = m_listeners.isEmpty(); + m_listeners.add(listener); + + // First listener. Attach the debugger. + if (wasEmpty) + attachDebugger(); +} + +void ScriptDebugServer::removeListener(ScriptDebugListener* listener, bool isBeingDestroyed) +{ + ASSERT(listener); + + m_listeners.remove(listener); + + // Last listener. Detach the debugger. + if (m_listeners.isEmpty()) + detachDebugger(isBeingDestroyed); +} + +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(state)); + debuggerCallFrame = debuggerCallFrame->callerFrame(); + } + + return Deprecated::ScriptValue(); +} + } // namespace Inspector |