Diff
Modified: trunk/Source/WebCore/ChangeLog (108343 => 108344)
--- trunk/Source/WebCore/ChangeLog 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/ChangeLog 2012-02-21 13:10:35 UTC (rev 108344)
@@ -1,3 +1,51 @@
+2012-02-21 Yury Semikhatsky <[email protected]>
+
+ [V8] Web Inspector: set breakpoint/pause doesn't work when worker is in a tight loop
+ https://bugs.webkit.org/show_bug.cgi?id=79097
+
+ Worker script will be interrupted to dispatch all arriving inspector commands.
+ This way debugger will be operable even if worker is in a tight loop.
+
+ Reviewed by Pavel Feldman.
+
+ * bindings/js/ScriptDebugServer.h:
+ (Task):
+ (WebCore::ScriptDebugServer::Task::~Task):
+ (ScriptDebugServer):
+ * bindings/js/WorkerScriptDebugServer.cpp:
+ (WebCore::WorkerScriptDebugServer::interruptAndRunTask):
+ (WebCore):
+ * bindings/js/WorkerScriptDebugServer.h:
+ (WorkerScriptDebugServer):
+ * bindings/v8/ScriptDebugServer.cpp:
+ (WebCore::ScriptDebugServer::interruptAndRun):
+ * bindings/v8/ScriptDebugServer.h:
+ (ScriptDebugServer):
+ * bindings/v8/WorkerScriptDebugServer.cpp:
+ (WebCore::WorkerScriptDebugServer::WorkerScriptDebugServer):
+ (WebCore::WorkerScriptDebugServer::interruptAndRunTask):
+ (WebCore):
+ * bindings/v8/WorkerScriptDebugServer.h:
+ (v8):
+ (WebCore):
+ (WorkerScriptDebugServer):
+ * inspector/WorkerDebuggerAgent.cpp:
+ (WebCore::WorkerDebuggerAgent::WorkerDebuggerAgent):
+ (WebCore::WorkerDebuggerAgent::~WorkerDebuggerAgent):
+ (WebCore):
+ (WebCore::WorkerDebuggerAgent::interruptAndDispatchInspectorCommands):
+ * inspector/WorkerDebuggerAgent.h:
+ (WebCore):
+ (WorkerDebuggerAgent):
+ * workers/WorkerMessagingProxy.cpp:
+ (WebCore):
+ (WebCore::WorkerMessagingProxy::sendMessageToInspector):
+ * workers/WorkerRunLoop.cpp:
+ (WebCore::WorkerRunLoop::run):
+ (WebCore::WorkerRunLoop::runInMode):
+ * workers/WorkerRunLoop.h:
+ (WorkerRunLoop):
+
2012-02-21 'Pavel Feldman' <[email protected]>
Not reviewed: fixing Mac build (take 2).
Modified: trunk/Source/WebCore/bindings/js/ScriptDebugServer.h (108343 => 108344)
--- trunk/Source/WebCore/bindings/js/ScriptDebugServer.h 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/js/ScriptDebugServer.h 2012-02-21 13:10:35 UTC (rev 108344)
@@ -92,6 +92,12 @@
bool isPaused() { return m_paused; }
+ class Task {
+ public:
+ virtual ~Task() { }
+ virtual void run() = 0;
+ };
+
protected:
typedef HashSet<ScriptDebugListener*> ListenerSet;
typedef void (ScriptDebugServer::*_javascript_ExecutionCallback)(ScriptDebugListener*);
Modified: trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp (108343 => 108344)
--- trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp 2012-02-21 13:10:35 UTC (rev 108344)
@@ -33,6 +33,7 @@
#if ENABLE(_javascript__DEBUGGER) && ENABLE(WORKERS)
#include "WorkerScriptDebugServer.h"
+#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -51,6 +52,10 @@
{
}
+void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>)
+{
+}
+
} // namespace WebCore
#endif // ENABLE(_javascript__DEBUGGER) && ENABLE(WORKERS)
Modified: trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.h (108343 => 108344)
--- trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.h 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.h 2012-02-21 13:10:35 UTC (rev 108344)
@@ -50,6 +50,8 @@
static const char* debuggerTaskMode;
+ void interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>);
+
private:
virtual void recompileAllJSFunctions(Timer<ScriptDebugServer>*) { }
virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) { return 0; }
Modified: trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp (108343 => 108344)
--- trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp 2012-02-21 13:10:35 UTC (rev 108344)
@@ -268,9 +268,9 @@
return ScriptValue(toV8(currentCallFrame.release()));
}
-void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task)
+void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task, v8::Isolate* isolate)
{
- v8::Debug::DebugBreakForCommand(new ClientDataImpl(task));
+ v8::Debug::DebugBreakForCommand(new ClientDataImpl(task), isolate);
}
void ScriptDebugServer::runPendingTasks()
Modified: trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h (108343 => 108344)
--- trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h 2012-02-21 13:10:35 UTC (rev 108344)
@@ -89,7 +89,7 @@
virtual ~Task() { }
virtual void run() = 0;
};
- static void interruptAndRun(PassOwnPtr<Task>);
+ static void interruptAndRun(PassOwnPtr<Task>, v8::Isolate* = 0);
void runPendingTasks();
bool isPaused();
Modified: trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp (108343 => 108344)
--- trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp 2012-02-21 13:10:35 UTC (rev 108344)
@@ -41,13 +41,16 @@
#include <v8.h>
#include <wtf/MessageQueue.h>
+
namespace WebCore {
WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerContext* workerContext)
: ScriptDebugServer()
, m_listener(0)
, m_workerContext(workerContext)
+ , m_isolate(v8::Isolate::GetCurrent())
{
+ ASSERT(m_isolate);
}
void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener)
@@ -87,6 +90,11 @@
v8::Debug::SetDebugEventListener2(0);
}
+void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<Task> task)
+{
+ interruptAndRun(task, m_isolate);
+}
+
ScriptDebugListener* WorkerScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context>)
{
// There is only one worker context in isolate.
Modified: trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h (108343 => 108344)
--- trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h 2012-02-21 13:10:35 UTC (rev 108344)
@@ -35,9 +35,14 @@
#include "ScriptDebugServer.h"
+namespace v8 {
+class Isolate;
+}
+
namespace WebCore {
class WorkerContext;
+class WorkerThread;
class WorkerScriptDebugServer : public ScriptDebugServer {
WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer);
@@ -48,6 +53,8 @@
void addListener(ScriptDebugListener*);
void removeListener(ScriptDebugListener*);
+ void interruptAndRunTask(PassOwnPtr<Task>);
+
private:
virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>);
virtual void runMessageLoopOnPause(v8::Handle<v8::Context>);
@@ -56,6 +63,7 @@
typedef HashMap<WorkerContext*, ScriptDebugListener*> ListenersMap;
ScriptDebugListener* m_listener;
WorkerContext* m_workerContext;
+ v8::Isolate* m_isolate;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/inspector/WorkerDebuggerAgent.cpp (108343 => 108344)
--- trunk/Source/WebCore/inspector/WorkerDebuggerAgent.cpp 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/inspector/WorkerDebuggerAgent.cpp 2012-02-21 13:10:35 UTC (rev 108344)
@@ -34,9 +34,49 @@
#if ENABLE(_javascript__DEBUGGER) && ENABLE(INSPECTOR) && ENABLE(WORKERS)
#include "ScriptDebugServer.h"
#include "WorkerContext.h"
+#include "WorkerThread.h"
+#include <wtf/MessageQueue.h>
namespace WebCore {
+namespace {
+
+Mutex& workerDebuggerAgentsMutex()
+{
+ AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
+ return mutex;
+}
+
+typedef HashMap<WorkerThread*, WorkerDebuggerAgent*> WorkerDebuggerAgents;
+
+WorkerDebuggerAgents& workerDebuggerAgents()
+{
+ DEFINE_STATIC_LOCAL(WorkerDebuggerAgents, agents, ());
+ return agents;
+}
+
+
+class RunInspectorCommandsTask : public ScriptDebugServer::Task {
+public:
+ RunInspectorCommandsTask(WorkerThread* thread, WorkerContext* workerContext)
+ : m_thread(thread)
+ , m_workerContext(workerContext) { }
+ virtual ~RunInspectorCommandsTask() { }
+ virtual void run()
+ {
+ // Process all queued debugger commands. It is safe to use m_workerContext here
+ // because it is alive if RunWorkerLoop is not terminated, otherwise it will
+ // just be ignored.
+ while (MessageQueueMessageReceived == m_thread->runLoop().runInMode(m_workerContext, WorkerDebuggerAgent::debuggerTaskMode, WorkerRunLoop::DontWaitForMessage)) { }
+ }
+
+private:
+ RefPtr<WorkerThread> m_thread;
+ WorkerContext* m_workerContext;
+};
+
+} // namespace
+
const char* WorkerDebuggerAgent::debuggerTaskMode = "debugger";
PassOwnPtr<WorkerDebuggerAgent> WorkerDebuggerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, WorkerContext* inspectedWorkerContext, InjectedScriptManager* injectedScriptManager)
@@ -49,12 +89,25 @@
, m_scriptDebugServer(inspectedWorkerContext)
, m_inspectedWorkerContext(inspectedWorkerContext)
{
+ MutexLocker lock(workerDebuggerAgentsMutex());
+ workerDebuggerAgents().set(inspectedWorkerContext->thread(), this);
}
WorkerDebuggerAgent::~WorkerDebuggerAgent()
{
+ MutexLocker lock(workerDebuggerAgentsMutex());
+ ASSERT(workerDebuggerAgents().contains(m_inspectedWorkerContext->thread()));
+ workerDebuggerAgents().remove(m_inspectedWorkerContext->thread());
}
+void WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(WorkerThread* thread)
+{
+ MutexLocker lock(workerDebuggerAgentsMutex());
+ WorkerDebuggerAgent* agent = workerDebuggerAgents().get(thread);
+ if (agent)
+ agent->m_scriptDebugServer.interruptAndRunTask(adoptPtr(new RunInspectorCommandsTask(thread, agent->m_inspectedWorkerContext)));
+}
+
void WorkerDebuggerAgent::startListeningScriptDebugServer()
{
scriptDebugServer().addListener(this);
Modified: trunk/Source/WebCore/inspector/WorkerDebuggerAgent.h (108343 => 108344)
--- trunk/Source/WebCore/inspector/WorkerDebuggerAgent.h 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/inspector/WorkerDebuggerAgent.h 2012-02-21 13:10:35 UTC (rev 108344)
@@ -38,6 +38,7 @@
namespace WebCore {
class WorkerContext;
+class WorkerThread;
class WorkerDebuggerAgent : public InspectorDebuggerAgent {
WTF_MAKE_NONCOPYABLE(WorkerDebuggerAgent);
@@ -47,6 +48,7 @@
virtual ~WorkerDebuggerAgent();
static const char* debuggerTaskMode;
+ static void interruptAndDispatchInspectorCommands(WorkerThread*);
private:
WorkerDebuggerAgent(InstrumentingAgents*, InspectorState*, WorkerContext*, InjectedScriptManager*);
Modified: trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp (108343 => 108344)
--- trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp 2012-02-21 13:10:35 UTC (rev 108344)
@@ -21,7 +21,7 @@
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
@@ -316,7 +316,7 @@
{
m_scriptExecutionContext->postTask(WorkerExceptionTask::create(errorMessage, lineNumber, sourceURL, this));
}
-
+
static void postConsoleMessageTask(ScriptExecutionContext* context, WorkerMessagingProxy* messagingProxy, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
{
if (messagingProxy->askedToTerminate())
@@ -411,6 +411,7 @@
return;
#if ENABLE(_javascript__DEBUGGER)
m_workerThread->runLoop().postTaskForMode(createCallbackTask(dispatchOnInspectorBackendTask, String(message)), WorkerDebuggerAgent::debuggerTaskMode);
+ WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(m_workerThread.get());
#endif
}
#endif
Modified: trunk/Source/WebCore/workers/WorkerRunLoop.cpp (108343 => 108344)
--- trunk/Source/WebCore/workers/WorkerRunLoop.cpp 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.cpp 2012-02-21 13:10:35 UTC (rev 108344)
@@ -132,26 +132,28 @@
ModePredicate modePredicate(defaultMode());
MessageQueueWaitResult result;
do {
- result = runInMode(context, modePredicate);
+ result = runInMode(context, modePredicate, WaitForMessage);
} while (result != MessageQueueTerminated);
runCleanupTasks(context);
}
-MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const String& mode)
+MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const String& mode, WaitMode waitMode)
{
RunLoopSetup setup(*this);
ModePredicate modePredicate(mode);
- MessageQueueWaitResult result = runInMode(context, modePredicate);
+ MessageQueueWaitResult result = runInMode(context, modePredicate, waitMode);
return result;
}
-MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const ModePredicate& predicate)
+MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const ModePredicate& predicate, WaitMode waitMode)
{
ASSERT(context);
ASSERT(context->thread());
ASSERT(context->thread()->threadID() == currentThread());
- double absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<Task>::infiniteTime();
+ double absoluteTime = 0.0;
+ if (waitMode == WaitForMessage)
+ absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<Task>::infiniteTime();
MessageQueueWaitResult result;
OwnPtr<WorkerRunLoop::Task> task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime);
Modified: trunk/Source/WebCore/workers/WorkerRunLoop.h (108343 => 108344)
--- trunk/Source/WebCore/workers/WorkerRunLoop.h 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.h 2012-02-21 13:10:35 UTC (rev 108344)
@@ -52,8 +52,10 @@
// Blocking call. Waits for tasks and timers, invokes the callbacks.
void run(WorkerContext*);
+ enum WaitMode { WaitForMessage, DontWaitForMessage };
+
// Waits for a single task and returns.
- MessageQueueWaitResult runInMode(WorkerContext*, const String& mode);
+ MessageQueueWaitResult runInMode(WorkerContext*, const String& mode, WaitMode = WaitForMessage);
void terminate();
bool terminated() const { return m_messageQueue.killed(); }
@@ -82,7 +84,7 @@
private:
friend class RunLoopSetup;
- MessageQueueWaitResult runInMode(WorkerContext*, const ModePredicate&);
+ MessageQueueWaitResult runInMode(WorkerContext*, const ModePredicate&, WaitMode);
// Runs any clean up tasks that are currently in the queue and returns.
// This should only be called when the context is closed or loop has been terminated.
Modified: trunk/Source/WebKit/chromium/ChangeLog (108343 => 108344)
--- trunk/Source/WebKit/chromium/ChangeLog 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebKit/chromium/ChangeLog 2012-02-21 13:10:35 UTC (rev 108344)
@@ -1,3 +1,15 @@
+2012-02-21 Yury Semikhatsky <[email protected]>
+
+ [V8] Web Inspector: set breakpoint/pause doesn't work when worker is in a tight loop
+ https://bugs.webkit.org/show_bug.cgi?id=79097
+
+ Worker script execution will be interrupted for dispatching inspector commands.
+
+ Reviewed by Pavel Feldman.
+
+ * src/WebSharedWorkerImpl.cpp:
+ (WebKit::WebSharedWorkerImpl::dispatchDevToolsMessage):
+
2012-02-20 Peter Beverloo <[email protected]>
Unreviewed. Rolled DEPS.
Modified: trunk/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp (108343 => 108344)
--- trunk/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp 2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp 2012-02-21 13:10:35 UTC (rev 108344)
@@ -443,6 +443,7 @@
void WebSharedWorkerImpl::dispatchDevToolsMessage(const WebString& message)
{
workerThread()->runLoop().postTaskForMode(createCallbackTask(dispatchOnInspectorBackendTask, String(message)), WorkerDebuggerAgent::debuggerTaskMode);
+ WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(workerThread());
}
WebSharedWorker* WebSharedWorker::create(WebSharedWorkerClient* client)