<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[208725] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/208725">208725</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2016-11-14 20:02:59 -0800 (Mon, 14 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Worker debugging should pause all targets and view call frames in all targets
https://bugs.webkit.org/show_bug.cgi?id=164305
&lt;rdar://problem/29056192&gt;

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

* inspector/InjectedScriptSource.js:
(InjectedScript.prototype._propertyDescriptors):
Accessing __proto__ does a ToThis(...) conversion on the receiver.
In the case of GlobalObjects (such as WorkerGlobalScope when paused)
this would return undefined and throw an exception. We can use
Object.getPrototypeOf to avoid that conversion and possible error.

* inspector/protocol/Debugger.json:
Provide a new way to effectively `resume` + `pause` immediately.
This must be implemented on the backend to correctly synchronize
the resuming and pausing.

* inspector/agents/InspectorDebuggerAgent.h:
* inspector/agents/InspectorDebuggerAgent.cpp:
(Inspector::InspectorDebuggerAgent::continueUntilNextRunLoop):
Treat this as `resume` and `pause`. Resume now, and trigger
a pause if the VM becomes idle and we didn't pause before then
(such as hitting a breakpoint after we resumed).

(Inspector::InspectorDebuggerAgent::pause):
(Inspector::InspectorDebuggerAgent::resume):
(Inspector::InspectorDebuggerAgent::schedulePauseOnNextStatement):
(Inspector::InspectorDebuggerAgent::cancelPauseOnNextStatement):
Clean up and correct pause on next statement logic.

(Inspector::InspectorDebuggerAgent::registerIdleHandler):
(Inspector::InspectorDebuggerAgent::willStepAndMayBecomeIdle):
(Inspector::InspectorDebuggerAgent::didBecomeIdle):
(Inspector::InspectorDebuggerAgent::didBecomeIdleAfterStepping): Deleted.
The idle handler may now also trigger a pause in the case
where continueUntilNextRunLoop resumed and wants to pause.

(Inspector::InspectorDebuggerAgent::didPause):
Eliminate the useless didPause. The DOMDebugger was keeping track
of its own state that was worse then the state in DebuggerAgent.

Source/WebCore:

Tests: inspector/debugger/continueUntilNextRunLoop
       inspector/worker/debugger-multiple-targets-pause

* workers/WorkerMessagingProxy.cpp:
(WebCore::WorkerMessagingProxy::postMessageToPageInspector):
Switch from postTask (callOnMainThread) to RunLoop::main().dispatch so
that a paused Worker can send Inspector protocol messages responses
back through the Main Page's InspectorWorkerAgent even if the Page
itself is paused and MainThread callbacks are paused.

* workers/WorkerRunLoop.h:
(WebCore::WorkerRunLoop::isNested):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
When running a nested WorkerRunLoop, running inspector debugger
commands, we should not fire timers on the Worker. Timers would
then be happening out of order and would not be debuggable.

* dom/EventTarget.cpp:
(WebCore::EventTarget::fireEventListeners):
* inspector/InspectorDOMDebuggerAgent.cpp:
(WebCore::InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded):
(WebCore::InspectorDOMDebuggerAgent::clear):
(WebCore::InspectorDOMDebuggerAgent::didPause): Deleted.
* inspector/InspectorDOMDebuggerAgent.h:
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::willHandleEventImpl):
(WebCore::InspectorInstrumentation::didFireTimerImpl):
(WebCore::InspectorInstrumentation::didHandleEventImpl): Deleted.
(WebCore::InspectorInstrumentation::cancelPauseOnNativeEvent): Deleted.
* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::willHandleEvent):
(WebCore::InspectorInstrumentation::didHandleEvent): Deleted.
Remove unnecessary code where WebCore is trying to keep track
of pause on next statement but that state is already more
accurately provided by InspectorDebuggerAgent.

Source/WebInspectorUI:

This implements a policy where, when one Target (&quot;Thread&quot;) pauses
the frontend triggers a pause in all other Targets. The intended
user experience is &quot;all threads pause&quot; whenever the frontend shows
the debugger paused UI.

DebuggerManager has a few straight forward changes:

    - The paused state reflects if any target is paused.
    - The Paused Event is fired when going from !paused -&gt; paused.
      This means when the first target pauses.
    - The Resumed Event is fired when going from paused -&gt; !paused.
      This means only after all targets have resumed.
    - The CallFrameDidChange Event now includes the Target that updated.

When a Target first pauses the frontend then immediately pauses all
other Targets. This puts them into a &quot;pausing&quot; state (we display as
Idle) and they will pause as soon as they start executing JavaScript.

When a Target steps the &quot;paused&quot; state isn't changing. So this is
just a CallFramesDidChange update.

When clicking Resume we resume all targets. This is will be the normal,
expected way users resume execution. Note that one of the threads may
then hit a breakpoint and re-pause all threads.

Sometimes when multiple threads are paused you may want to run an
individual thread to completion but keep other threads paused. There
is a context menu on the ThreadTreeElement to resume just that
single thread. It will continue and pause for its next run loop.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Images/Thread.svg: Added.
* UserInterface/Images/gtk/Thread.svg: Added.
* UserInterface/Main.html:
New strings and files.

* UserInterface/Base/Main.js:
(WebInspector.loaded):
* UserInterface/Test/Test.js:
(WebInspector.loaded):
Place the TargetManager first since other managers may want to listen
for TargetAdded / TargetRemoved events.

* UserInterface/Controllers/DebuggerManager.js:
(WebInspector.DebuggerManager.prototype.get paused):
This is now a computed state.

(WebInspector.DebuggerManager.prototype.pause):
(WebInspector.DebuggerManager.prototype.resume):
Affect all targets.

(WebInspector.DebuggerManager.prototype.stepOver):
(WebInspector.DebuggerManager.prototype.stepInto):
(WebInspector.DebuggerManager.prototype.stepOut):
(WebInspector.DebuggerManager.prototype.reset):
Update to use the paused computed property.

(WebInspector.DebuggerManager.prototype.continueUntilNextRunLoop):
Issue the new Debugger.continueUntilNextRunLoop command
on a given target.

(WebInspector.DebuggerManager.prototype.initializeTarget):
When a new Target is created and we were already paused,
then start that Worker in a paused state.

(WebInspector.DebuggerManager.prototype.debuggerDidPause):
Recover from bad cases where the backend informs the frontend about
internal JavaScript that it shouldn't know about. Legacy backend do
this but also there are corner cases we need to handle.
Dispatch events appropriately now that multiple targets may be paused.

(WebInspector.DebuggerManager.prototype._didResumeInternal):
Dispatch events appropriately now that multiple targets may be paused.

(WebInspector.DebuggerManager.prototype._targetRemoved):
Remove debugger data for targets that go away to avoid leaks.

* UserInterface/Models/DebuggerData.js:
(WebInspector.DebuggerData):
(WebInspector.DebuggerData.prototype.get paused):
(WebInspector.DebuggerData.prototype.get pausing):
Move some more per-Target state into DebuggerData.

(WebInspector.DebuggerData.prototype.pauseIfNeeded):
(WebInspector.DebuggerData.prototype.resumeIfNeeded):
(WebInspector.DebuggerData.prototype.continueUntilNextRunLoop):
These should only be called by DebuggerManager. They correctly
update the state of the DebuggerData for this Target, and also
issue the underlying command to the target.

(WebInspector.DebuggerData.prototype.updateForPause):
(WebInspector.DebuggerData.prototype.updateForResume):
Handle a special case where continueUntilNextRunLoop triggers
an invisible &quot;pause&quot; on the backend that we should mirror.

* UserInterface/Protocol/Target.js:
(WebInspector.MainTarget):
(WebInspector.MainTarget.prototype.get displayName):
(WebInspector.MainTarget.prototype.initialize):
Better display names.

* UserInterface/Views/DebuggerSidebarPanel.js:
(WebInspector.DebuggerSidebarPanel):
(WebInspector.DebuggerSidebarPanel.prototype._debuggerDidPause):
(WebInspector.DebuggerSidebarPanel.prototype._debuggerDidResume):
(WebInspector.DebuggerSidebarPanel.prototype._updateSingleThreadCallStacks):
(WebInspector.DebuggerSidebarPanel.prototype._selectActiveCallFrameTreeElement):
(WebInspector.DebuggerSidebarPanel.prototype._showSingleThreadCallStacks):
(WebInspector.DebuggerSidebarPanel.prototype._showMultipleThreadCallStacks):
(WebInspector.DebuggerSidebarPanel.prototype._findThreadTreeElementForTarget):
(WebInspector.DebuggerSidebarPanel.prototype._targetAdded):
(WebInspector.DebuggerSidebarPanel.prototype._targetRemoved):
(WebInspector.DebuggerSidebarPanel.prototype._debuggerCallFramesDidChange):
(WebInspector.DebuggerSidebarPanel.prototype._debuggerActiveCallFrameDidChange):
The DebuggerSidebar still has a single &quot;Call Stacks&quot; section, but maintains
two TreeOutlines and only shows one at a time. The Single Thread view shows
a flat list of the call frames for the Main Target when it is the only target.
The Multiple Threads view shows a list of Threads and their call frames.
We always keep both up to date, because we may need to swap between them
purely as Targets are added / removed. There is a bit of extra logic to
ensure we select elements properly based only on the visible tree outline.

* UserInterface/Views/LogContentView.js:
(WebInspector.LogContentView.prototype.didAppendConsoleMessageView):
When evaluating in a particular target, &quot;runAfterPendingDispatches&quot;
must wait for all other commands in that particular target to have
completed. So use the target specific version.

* UserInterface/Views/NavigationSidebarPanel.js:
(WebInspector.NavigationSidebarPanel.prototype._isTreeElementWithoutRepresentedObject):
Gracefully handle a few more TreeElements without a represented object.

* UserInterface/Views/IdleTreeElement.css: Added.
(.details-section.call-stack .idle .icon):
* UserInterface/Views/IdleTreeElement.js: Added.
(WebInspector.IdleTreeElement):
Very basic tree element to encapsulate an Idle call frame with an
empty represented object.

* UserInterface/Views/ThreadTreeElement.css: Added.
(.details-section.call-stack .thread .icon):
* UserInterface/Views/ThreadTreeElement.js: Added.
(WebInspector.ThreadTreeElement):
(WebInspector.ThreadTreeElement.prototype.get target):
(WebInspector.ThreadTreeElement.prototype.refresh):
(WebInspector.ThreadTreeElement.prototype.onattach):
(WebInspector.ThreadTreeElement.prototype.oncontextmenu):
ThreadTreeElement has no represented object, but makes it easy
to refresh a list of CallFrameTreeElements for a given target.

LayoutTests:

* inspector/debugger/continueUntilNextRunLoop-expected.txt: Added.
* inspector/debugger/continueUntilNextRunLoop.html: Added.
New test for new Debugger.continueUntilNextRunLoop protocol method.

* inspector/worker/debugger-multiple-targets-pause-expected.txt: Added.
* inspector/worker/debugger-multiple-targets-pause.html: Added.
* inspector/worker/resources/worker-debugger-thread-1.js: Added.
* inspector/worker/resources/worker-debugger-thread-2.js: Added.
This tests uses a 250ms timeout because we have to have the worker thread
evaluate some work and trigger a pause on other threads before their work
starts. On debug builds, shorter times, like 100ms, would not be enough.

* inspector/worker/debugger-pause-expected.txt:
* inspector/worker/debugger-pause.html:
Now that all threads pause, the first InspectorTest.log evaluates JavaScript on
the page and causes a pause. So make the first log empty to keep the test unchanged.

* inspector/worker/runtime-basic-expected.txt:
* inspector/unit-tests/target-manager-expected.txt:
Updated display name of the mainTarget.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsinspectorunitteststargetmanagerexpectedtxt">trunk/LayoutTests/inspector/unit-tests/target-manager-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerdebuggerpauseexpectedtxt">trunk/LayoutTests/inspector/worker/debugger-pause-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerdebuggerpausehtml">trunk/LayoutTests/inspector/worker/debugger-pause.html</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerresourcesinworkerhtml">trunk/LayoutTests/inspector/worker/resources-in-worker.html</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerruntimebasicexpectedtxt">trunk/LayoutTests/inspector/worker/runtime-basic-expected.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs">trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgenth">trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson">trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomEventTargetcpp">trunk/Source/WebCore/dom/EventTarget.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorDOMDebuggerAgentcpp">trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorDOMDebuggerAgenth">trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorInstrumentationcpp">trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorInstrumentationh">trunk/Source/WebCore/inspector/InspectorInstrumentation.h</a></li>
<li><a href="#trunkSourceWebCoreworkersWorkerMessagingProxycpp">trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp</a></li>
<li><a href="#trunkSourceWebCoreworkersWorkerRunLoopcpp">trunk/Source/WebCore/workers/WorkerRunLoop.cpp</a></li>
<li><a href="#trunkSourceWebCoreworkersWorkerRunLooph">trunk/Source/WebCore/workers/WorkerRunLoop.h</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseMainjs">trunk/Source/WebInspectorUI/UserInterface/Base/Main.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsDebuggerDatajs">trunk/Source/WebInspectorUI/UserInterface/Models/DebuggerData.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceProtocolTargetjs">trunk/Source/WebInspectorUI/UserInterface/Protocol/Target.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestTestjs">trunk/Source/WebInspectorUI/UserInterface/Test/Test.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDebuggerSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsLogContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNavigationSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectordebuggercontinueUntilNextRunLoopexpectedtxt">trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggercontinueUntilNextRunLoophtml">trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop.html</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerdebuggermultipletargetspauseexpectedtxt">trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerdebuggermultipletargetspausehtml">trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause.html</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerresourcesworkerdebuggerthread1js">trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-1.js</a></li>
<li><a href="#trunkLayoutTestsinspectorworkerresourcesworkerdebuggerthread2js">trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-2.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesThreadsvg">trunk/Source/WebInspectorUI/UserInterface/Images/Thread.svg</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesgtkThreadsvg">trunk/Source/WebInspectorUI/UserInterface/Images/gtk/Thread.svg</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsIdleTreeElementcss">trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsIdleTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsThreadTreeElementcss">trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsThreadTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/LayoutTests/ChangeLog        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2016-11-14  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Worker debugging should pause all targets and view call frames in all targets
+        https://bugs.webkit.org/show_bug.cgi?id=164305
+        &lt;rdar://problem/29056192&gt;
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/debugger/continueUntilNextRunLoop-expected.txt: Added.
+        * inspector/debugger/continueUntilNextRunLoop.html: Added.
+        New test for new Debugger.continueUntilNextRunLoop protocol method.
+
+        * inspector/worker/debugger-multiple-targets-pause-expected.txt: Added.
+        * inspector/worker/debugger-multiple-targets-pause.html: Added.
+        * inspector/worker/resources/worker-debugger-thread-1.js: Added.
+        * inspector/worker/resources/worker-debugger-thread-2.js: Added.
+        This tests uses a 250ms timeout because we have to have the worker thread
+        evaluate some work and trigger a pause on other threads before their work
+        starts. On debug builds, shorter times, like 100ms, would not be enough.
+
+        * inspector/worker/debugger-pause-expected.txt:
+        * inspector/worker/debugger-pause.html:
+        Now that all threads pause, the first InspectorTest.log evaluates JavaScript on
+        the page and causes a pause. So make the first log empty to keep the test unchanged.
+
+        * inspector/worker/runtime-basic-expected.txt:
+        * inspector/unit-tests/target-manager-expected.txt:
+        Updated display name of the mainTarget.
+
</ins><span class="cx"> 2016-11-14  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebGL2] Teach WebGLRenderingContextBase about new texture internal formats
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggercontinueUntilNextRunLoopexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop-expected.txt (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop-expected.txt        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+Debugger.continueUntilNextRunLoop
+
+
+== Running test suite: Debugger.continueUntilNextRunLoop
+-- Running test case: Debugger.Unpaused.continueUntilNextRunLoop
+PASS: Should produce an error if not paused.
+Can only perform operation while paused.
+
+-- Running test case: Debugger.Unpaused.continueUntilNextRunLoop
+PASS: Received First Pause Event.
+PASS: Should be paused in pause1.
+PASS: Received Second Pause Event.
+PASS: Should be paused in pause2.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggercontinueUntilNextRunLoophtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop.html (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop.html                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/continueUntilNextRunLoop.html        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function triggerMultiplePauses() {
+    setTimeout(pause1, 0);
+    setTimeout(pause2, 0);
+}
+
+function pause1() {
+    debugger;
+}
+
+function pause2() {
+    debugger;
+}
+
+function test()
+{
+    InspectorTest.debug();
+
+    function topCallFrameName() {
+        let targetData = WebInspector.debuggerManager.dataForTarget(WebInspector.mainTarget);
+        return targetData.callFrames[0].functionName;
+    }
+
+    let suite = InspectorTest.createAsyncSuite(&quot;Debugger.continueUntilNextRunLoop&quot;);
+
+    suite.addTestCase({
+        name: &quot;Debugger.Unpaused.continueUntilNextRunLoop&quot;,
+        description: &quot;Debugger.continueUntilNextRunLoop should only work when paused.&quot;,
+        test(resolve, reject) {
+            DebuggerAgent.continueUntilNextRunLoop((error) =&gt; {
+                InspectorTest.expectThat(error, &quot;Should produce an error if not paused.&quot;);
+                InspectorTest.log(error);
+                resolve();
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;Debugger.Unpaused.continueUntilNextRunLoop&quot;,
+        description: &quot;Debugger.continueUntilNextRunLoop should only work when paused.&quot;,
+        test(resolve, reject) {
+            InspectorTest.evaluateInPage(&quot;triggerMultiplePauses()&quot;);
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Paused, (event) =&gt; {
+                InspectorTest.pass(&quot;Received First Pause Event.&quot;);
+                InspectorTest.expectEqual(topCallFrameName(), &quot;pause1&quot;, &quot;Should be paused in pause1.&quot;);
+                WebInspector.debuggerManager.continueUntilNextRunLoop(WebInspector.mainTarget);
+                WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Paused, (event) =&gt; {
+                    InspectorTest.pass(&quot;Received Second Pause Event.&quot;);
+                    InspectorTest.expectEqual(topCallFrameName(), &quot;pause2&quot;, &quot;Should be paused in pause2.&quot;);
+                    WebInspector.debuggerManager.resume().then(resolve, reject);
+                });
+            });
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+&lt;p&gt;Debugger.continueUntilNextRunLoop&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorunitteststargetmanagerexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/unit-tests/target-manager-expected.txt (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/unit-tests/target-manager-expected.txt        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/LayoutTests/inspector/unit-tests/target-manager-expected.txt        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -7,7 +7,7 @@
</span><span class="cx"> PASS: Target list should always contain the main target.
</span><span class="cx"> PASS: Main target should have an ExecutionContext.
</span><span class="cx"> PASS: Main target should have the global RuntimeAgent.
</span><del>-Target - Main - Main Frame
</del><ins>+Target - Main - Page
</ins><span class="cx"> 
</span><span class="cx"> -- Running test case: TargetManager.WorkerTarget.Create
</span><span class="cx"> PASS: Added Target should have Worker type.
</span><span class="lines">@@ -14,10 +14,10 @@
</span><span class="cx"> PASS: Added Target should have an ExecutionContext.
</span><span class="cx"> PASS: Added Target should have a RuntimeAgent.
</span><span class="cx"> PASS: Added Target RuntimeAgent should not be the global RuntimeAgent.
</span><del>-Target - Main - Main Frame
</del><ins>+Target - Main - Page
</ins><span class="cx"> Target - Worker - worker-1.js
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: TargetManager.WorkerTarget.Remove
</span><span class="cx"> PASS: Removed Target should have Worker type.
</span><del>-Target - Main - Main Frame
</del><ins>+Target - Main - Page
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerdebuggermultipletargetspauseexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause-expected.txt (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause-expected.txt        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+Ensure we can pause in multiple targets and evaluate in each.
+
+
+== Running test suite: Worker.Debugger.Threads
+-- Running test case: Worker.Debugger.Threads.CreateThreads
+PASS: Created Worker 1
+PASS: Created Worker 2
+
+-- Running test case: Worker.Debugger.Threads.Pause
+PASS: Paused event should happen before CallFramesDidChange event.
+PASS: In Paused event all other Targets should be pausing.
+PASS: Worker 1 should be the first to pause.
+PASS: All Targets should eventually pause.
+
+TARGET: Page
+   CALL FRAME #1: workOnMainThread
+TARGET: worker-debugger-thread-1.js
+ * CALL FRAME #1: foo
+   CALL FRAME #2: workInThread1
+TARGET: worker-debugger-thread-2.js
+   CALL FRAME #1: workInThread2
+
+-- Running test case: Worker.Debugger.Threads.Paused.Worker1Evaluate
+PASS: Evaluated result in worker-debugger-thread-1.js should be &quot;worker thread 1&quot;.
+
+-- Running test case: Worker.Debugger.Threads.Paused.Worker2Evaluate
+PASS: Evaluated result in worker-debugger-thread-2.js should be &quot;worker thread 2&quot;.
+
+-- Running test case: Worker.Debugger.Threads.Paused.MainEvaluate
+PASS: Evaluated result in Page should be &quot;main thread&quot;.
+
+-- Running test case: Worker.Debugger.Threads.Paused.Worker1.StepOut
+PASS: Should receive CallFramesDidChange for Worker 1.
+
+TARGET: Page
+   CALL FRAME #1: workOnMainThread
+TARGET: worker-debugger-thread-1.js
+ * CALL FRAME #1: workInThread1
+TARGET: worker-debugger-thread-2.js
+   CALL FRAME #1: workInThread2
+
+-- Running test case: Worker.Debugger.Threads.Paused.Worker2.ResumeThread
+PASS: Should Receive CallFramesDidChange for Worker 2.
+PASS: Worker 2 should be pausing.
+PASS: Should Receive CallFramesDidChange for Worker 2.
+PASS: Worker 2 should be paused.
+
+TARGET: Page
+   CALL FRAME #1: workOnMainThread
+TARGET: worker-debugger-thread-1.js
+ * CALL FRAME #1: workInThread1
+TARGET: worker-debugger-thread-2.js
+   CALL FRAME #1: laterWorkInThread2
+
+-- Running test case: Worker.Debugger.Threads.Complete
+PASS: Received Resume event.
+PASS: All Targets should be unpaused.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerdebuggermultipletargetspausehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause.html (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause.html                                (rev 0)
+++ trunk/LayoutTests/inspector/worker/debugger-multiple-targets-pause.html        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,214 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../debugger/resources/log-pause-location.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+let worker1, worker2;
+let testVariable = &quot;main thread&quot;;
+
+function triggerStartWorkers() {
+    worker1 = new Worker(&quot;resources/worker-debugger-thread-1.js&quot;);
+    worker2 = new Worker(&quot;resources/worker-debugger-thread-2.js&quot;);
+}
+
+function triggerWork() {
+    worker1.postMessage(&quot;doWork&quot;);
+    worker2.postMessage(&quot;doWork&quot;);
+    setTimeout(workOnMainThread, 250);
+}
+
+function workOnMainThread() {
+    TestPage.dispatchEventToFrontend(&quot;MainThreadDidWork&quot;);
+    Date.now();
+}
+
+function test()
+{
+    let mainTarget = WebInspector.mainTarget;
+    let workerTarget1;
+    let workerTarget2;
+
+    function areAllTargetsPaused() {
+        for (let target of WebInspector.targets) {
+            let targetData = WebInspector.debuggerManager.dataForTarget(target);
+            if (!targetData.paused)
+                return false;
+        }
+        return true;
+    }
+
+    function areAllTargetsUnpaused() {
+        for (let target of WebInspector.targets) {
+            let targetData = WebInspector.debuggerManager.dataForTarget(target);
+            if (targetData.paused)
+                return false;
+        }
+        return true;
+    }
+
+    function dumpCallFrames() {
+        InspectorTest.log(&quot;&quot;);
+        for (let target of WebInspector.targets) {
+            InspectorTest.log(`TARGET: ${target.displayName}`);
+            let targetData = WebInspector.debuggerManager.dataForTarget(target);
+            let callFrames = targetData.callFrames;
+            for (let i = 0; i &lt; callFrames.length; ++i) {
+                let callFrame = callFrames[i];
+                let active = callFrame === WebInspector.debuggerManager.activeCallFrame;
+                InspectorTest.log(` ${active ? &quot;*&quot; : &quot; &quot;} CALL FRAME #${i + 1}: ${callFrame.functionName}`);
+            }
+        }
+    }
+
+    let okayToReceiveMainThreadEvent = false;
+    InspectorTest.singleFireEventListener(&quot;MainThreadDidWork&quot;, (event) =&gt; {
+        if (!okayToReceiveMainThreadEvent) {
+            InspectorTest.fail(&quot;Main Thread's work fired before it could pause. Failing early.&quot;);
+            InspectorTest.completeTest();
+        }
+    });
+
+    let suite = InspectorTest.createAsyncSuite(&quot;Worker.Debugger.Threads&quot;);
+
+    suite.addTestCase({
+        name: &quot;Worker.Debugger.Threads.CreateThreads&quot;,
+        description: &quot;Spawn multiple targets.&quot;,
+        test(resolve, reject) {
+            InspectorTest.evaluateInPage(`triggerStartWorkers()`);
+            WebInspector.targetManager.singleFireEventListener(WebInspector.TargetManager.Event.TargetAdded, (event) =&gt; {
+                InspectorTest.pass(&quot;Created Worker 1&quot;);
+                workerTarget1 = event.data.target;
+                WebInspector.targetManager.singleFireEventListener(WebInspector.TargetManager.Event.TargetAdded, (event) =&gt; {
+                    InspectorTest.pass(&quot;Created Worker 2&quot;);
+                    workerTarget2 = event.data.target;
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;Worker.Debugger.Threads.Pause&quot;,
+        description: &quot;Should be able to pause in multiple targets.&quot;,
+        test(resolve, reject) {
+            InspectorTest.evaluateInPage(`triggerWork()`);
+
+            let receivedCallFramesDidChange = false;
+            let receivedPauseBeforeCallFramesDidChange = false;
+            let otherTargetsPausing = false;
+
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Paused, (event) =&gt; {
+                receivedPauseBeforeCallFramesDidChange = !receivedCallFramesDidChange;
+                otherTargetsPausing = WebInspector.debuggerManager.dataForTarget(mainTarget).pausing &amp;&amp; WebInspector.debuggerManager.dataForTarget(workerTarget2).pausing;
+            });
+
+            let listener = WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) =&gt; {
+                receivedCallFramesDidChange = true;
+                if (!areAllTargetsPaused())
+                    return;
+
+                WebInspector.debuggerManager.removeEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, listener);
+
+                let activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
+                InspectorTest.assert(activeCallFrame.target === workerTarget1);
+
+                InspectorTest.expectThat(receivedPauseBeforeCallFramesDidChange, &quot;Paused event should happen before CallFramesDidChange event.&quot;);
+                InspectorTest.expectThat(otherTargetsPausing, &quot;In Paused event all other Targets should be pausing.&quot;);
+                InspectorTest.expectEqual(activeCallFrame.target.displayName, &quot;worker-debugger-thread-1.js&quot;, &quot;Worker 1 should be the first to pause.&quot;);
+                InspectorTest.pass(&quot;All Targets should eventually pause.&quot;);
+                dumpCallFrames();
+                resolve();
+            });
+        }
+    });
+
+    function addEvaluateTestCase({name, targetResolver, expected}) {
+        suite.addTestCase({
+            name, description: &quot;Should be able to evaluate in different threads while paused.&quot;,
+            test(resolve, reject) {
+                let target = targetResolver();
+                let targetData = WebInspector.debuggerManager.dataForTarget(target);
+                WebInspector.debuggerManager.activeCallFrame = targetData.callFrames[0];
+                WebInspector.runtimeManager.evaluateInInspectedWindow(&quot;testVariable&quot;, {objectGroup: &quot;test&quot;, includeCommandLineAPI: true}, (remoteObject) =&gt; {
+                    InspectorTest.expectEqual(remoteObject.description, expected, `Evaluated result in ${target.displayName} should be ${JSON.stringify(expected)}.`)
+                    resolve();
+                });
+            }
+        });
+    }
+
+    addEvaluateTestCase({
+        name: &quot;Worker.Debugger.Threads.Paused.Worker1Evaluate&quot;,
+        targetResolver: () =&gt; workerTarget1,
+        expected: &quot;worker thread 1&quot;,
+    });
+
+    addEvaluateTestCase({
+        name: &quot;Worker.Debugger.Threads.Paused.Worker2Evaluate&quot;,
+        targetResolver: () =&gt; workerTarget2,
+        expected: &quot;worker thread 2&quot;,
+    });
+
+    addEvaluateTestCase({
+        name: &quot;Worker.Debugger.Threads.Paused.MainEvaluate&quot;,
+        targetResolver: () =&gt; mainTarget,
+        expected: &quot;main thread&quot;,
+    });
+
+    suite.addTestCase({
+        name: &quot;Worker.Debugger.Threads.Paused.Worker1.StepOut&quot;,
+        description: &quot;Should be able to step in individual threads and not affect the others.&quot;,
+        test(resolve, reject) {
+            let targetData = WebInspector.debuggerManager.dataForTarget(workerTarget1);
+            WebInspector.debuggerManager.activeCallFrame = targetData.callFrames[0];
+            WebInspector.debuggerManager.stepOut();
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) =&gt; {
+                InspectorTest.expectEqual(event.data.target, workerTarget1, &quot;Should receive CallFramesDidChange for Worker 1.&quot;);
+                dumpCallFrames();
+                resolve();
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;Worker.Debugger.Threads.Paused.Worker2.ResumeThread&quot;,
+        description: &quot;Should be able to resume an individual thread and not affect the others.&quot;,
+        test(resolve, reject) {
+            let targetData = WebInspector.debuggerManager.dataForTarget(workerTarget2);
+            WebInspector.debuggerManager.continueUntilNextRunLoop(workerTarget2);
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) =&gt; {
+                InspectorTest.expectEqual(event.data.target, workerTarget2, &quot;Should Receive CallFramesDidChange for Worker 2.&quot;);
+                InspectorTest.expectThat(targetData.pausing, &quot;Worker 2 should be pausing.&quot;);
+                WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) =&gt; {
+                    InspectorTest.expectEqual(event.data.target, workerTarget2, &quot;Should Receive CallFramesDidChange for Worker 2.&quot;);
+                    InspectorTest.expectThat(targetData.paused, &quot;Worker 2 should be paused.&quot;);
+                    dumpCallFrames();
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;Worker.Debugger.Threads.Complete&quot;,
+        description: &quot;Resume all threads for the test to complete.&quot;,
+        test(resolve, reject) {
+            okayToReceiveMainThreadEvent = true;
+            WebInspector.debuggerManager.resume();
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Resumed, () =&gt; {
+                InspectorTest.pass(&quot;Received Resume event.&quot;);
+                InspectorTest.expectThat(areAllTargetsUnpaused(), &quot;All Targets should be unpaused.&quot;);
+                resolve();
+            });
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+&lt;p&gt;Ensure we can pause in multiple targets and evaluate in each.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerdebuggerpauseexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/worker/debugger-pause-expected.txt (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/debugger-pause-expected.txt        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/LayoutTests/inspector/worker/debugger-pause-expected.txt        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -16,6 +16,7 @@
</span><span class="cx">       5    
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> -- Running test case: Worker.Debugger.Pause.Breakpoint
</span><span class="cx"> PASS: Paused
</span><span class="cx"> PASS: Should be paused in a Worker CallFrame.
</span><span class="lines">@@ -30,6 +31,7 @@
</span><span class="cx">      11    
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> -- Running test case: Worker.Debugger.Pause.Exception
</span><span class="cx"> PASS: Paused
</span><span class="cx"> PASS: Should be paused in a Worker CallFrame.
</span><span class="lines">@@ -43,6 +45,7 @@
</span><span class="cx">      15    
</span><span class="cx">      16    function triggerAssertion() {
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> Uncaught exception in test page: TypeError: undefined is not an object (evaluating '[].x.x') [worker-debugger-pause.js:14]
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Worker.Debugger.Pause.Assert
</span><span class="lines">@@ -59,3 +62,4 @@
</span><span class="cx">      20    onmessage = function(event) {
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerdebuggerpausehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/worker/debugger-pause.html (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/debugger-pause.html        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/LayoutTests/inspector/worker/debugger-pause.html        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx">         test(resolve, reject) {
</span><span class="cx">             InspectorTest.evaluateInPage(`worker.postMessage(&quot;triggerDebuggerStatement&quot;)`);
</span><span class="cx">             WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Paused, (event) =&gt; {
</span><ins>+                InspectorTest.log(&quot;&quot;); // This evaluation will pause the MainThread.
</ins><span class="cx">                 InspectorTest.pass(&quot;Paused&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(WebInspector.debuggerManager.activeCallFrame.target, workerTarget, &quot;Should be paused in a Worker CallFrame.&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(workerDebuggerData.pauseReason, WebInspector.DebuggerManager.PauseReason.DebuggerStatement, &quot;Pause reason should be a debugger statement.&quot;);
</span><span class="lines">@@ -49,6 +50,7 @@
</span><span class="cx">             WebInspector.debuggerManager.addBreakpoint(breakpoint);
</span><span class="cx">             InspectorTest.evaluateInPage(`worker.postMessage(&quot;triggerBreakpoint&quot;)`);
</span><span class="cx">             WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Paused, (event) =&gt; {
</span><ins>+                InspectorTest.log(&quot;&quot;); // This evaluation will pause the MainThread.
</ins><span class="cx">                 InspectorTest.pass(&quot;Paused&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(WebInspector.debuggerManager.activeCallFrame.target, workerTarget, &quot;Should be paused in a Worker CallFrame.&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(workerDebuggerData.pauseReason, WebInspector.DebuggerManager.PauseReason.Breakpoint, &quot;Pause reason should be a breakpoint.&quot;);
</span><span class="lines">@@ -64,6 +66,7 @@
</span><span class="cx">         test(resolve, reject) {
</span><span class="cx">             InspectorTest.evaluateInPage(`worker.postMessage(&quot;triggerException&quot;)`);
</span><span class="cx">             WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Paused, (event) =&gt; {
</span><ins>+                InspectorTest.log(&quot;&quot;); // This evaluation will pause the MainThread.
</ins><span class="cx">                 InspectorTest.pass(&quot;Paused&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(WebInspector.debuggerManager.activeCallFrame.target, workerTarget, &quot;Should be paused in a Worker CallFrame.&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(workerDebuggerData.pauseReason, WebInspector.DebuggerManager.PauseReason.Exception, &quot;Pause reason should be an exception.&quot;);
</span><span class="lines">@@ -79,6 +82,7 @@
</span><span class="cx">         test(resolve, reject) {
</span><span class="cx">             InspectorTest.evaluateInPage(`worker.postMessage(&quot;triggerAssertion&quot;)`);
</span><span class="cx">             WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.Paused, (event) =&gt; {
</span><ins>+                InspectorTest.log(&quot;&quot;); // This evaluation will pause the MainThread.
</ins><span class="cx">                 InspectorTest.pass(&quot;Paused&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(WebInspector.debuggerManager.activeCallFrame.target, workerTarget, &quot;Should be paused in a Worker CallFrame.&quot;);
</span><span class="cx">                 InspectorTest.expectEqual(workerDebuggerData.pauseReason, WebInspector.DebuggerManager.PauseReason.Assertion, &quot;Pause reason should be an exception.&quot;);
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerresourcesworkerdebuggerthread1js"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-1.js (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-1.js                                (rev 0)
+++ trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-1.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+let testVariable = &quot;worker thread 1&quot;;
+
+onmessage = function(event) {
+    if (event.data === &quot;doWork&quot;)
+        setTimeout(workInThread1, 0)
+}
+
+function workInThread1() {
+    foo();
+}
+
+function foo() {
+    debugger;
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerresourcesworkerdebuggerthread2js"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-2.js (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-2.js                                (rev 0)
+++ trunk/LayoutTests/inspector/worker/resources/worker-debugger-thread-2.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+let testVariable = &quot;worker thread 2&quot;;
+
+onmessage = function(event) {
+    if (event.data === &quot;doWork&quot;) {
+        setTimeout(workInThread2, 250);
+        setTimeout(laterWorkInThread2, 250);
+    }
+}
+
+function workInThread2() {
+    Date.now();
+}
+
+function laterWorkInThread2() {
+    Date.now();
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerresourcesinworkerhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/worker/resources-in-worker.html (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/resources-in-worker.html        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/LayoutTests/inspector/worker/resources-in-worker.html        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -36,8 +36,6 @@
</span><span class="cx"> 
</span><span class="cx"> function test()
</span><span class="cx"> {
</span><del>-    InspectorTest.debug();
-
</del><span class="cx">     let workerTarget = null;
</span><span class="cx">     let mainTarget = WebInspector.mainTarget;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorworkerruntimebasicexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/worker/runtime-basic-expected.txt (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/worker/runtime-basic-expected.txt        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/LayoutTests/inspector/worker/runtime-basic-expected.txt        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -3,13 +3,13 @@
</span><span class="cx"> 
</span><span class="cx"> == Running test suite: Worker.Runtime.basic
</span><span class="cx"> -- Running test case: Main.Runtime.evaluate
</span><del>-Target - Main Frame - passphrase - page-passphrase
</del><ins>+Target - Page - passphrase - page-passphrase
</ins><span class="cx"> 
</span><span class="cx"> -- Running test case: Worker.Runtime.evaluate
</span><span class="cx"> Target - worker-1.js - passphrase - worker-passphrase
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Main.Runtime.RemoteObjectAndPropertyDescriptor.
</span><del>-Target - Main Frame - location and href - Location: inspector/worker/runtime-basic.html
</del><ins>+Target - Page - location and href - Location: inspector/worker/runtime-basic.html
</ins><span class="cx"> 
</span><span class="cx"> -- Running test case: Worker.Runtime.RemoteObjectAndPropertyDescriptor.
</span><span class="cx"> Target - worker-1.js - location and href - WorkerLocation: inspector/worker/resources/worker-1.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2016-11-14  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Worker debugging should pause all targets and view call frames in all targets
+        https://bugs.webkit.org/show_bug.cgi?id=164305
+        &lt;rdar://problem/29056192&gt;
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/InjectedScriptSource.js:
+        (InjectedScript.prototype._propertyDescriptors):
+        Accessing __proto__ does a ToThis(...) conversion on the receiver.
+        In the case of GlobalObjects (such as WorkerGlobalScope when paused)
+        this would return undefined and throw an exception. We can use
+        Object.getPrototypeOf to avoid that conversion and possible error.
+
+        * inspector/protocol/Debugger.json:
+        Provide a new way to effectively `resume` + `pause` immediately.
+        This must be implemented on the backend to correctly synchronize
+        the resuming and pausing.
+
+        * inspector/agents/InspectorDebuggerAgent.h:
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        (Inspector::InspectorDebuggerAgent::continueUntilNextRunLoop):
+        Treat this as `resume` and `pause`. Resume now, and trigger
+        a pause if the VM becomes idle and we didn't pause before then
+        (such as hitting a breakpoint after we resumed).
+
+        (Inspector::InspectorDebuggerAgent::pause):
+        (Inspector::InspectorDebuggerAgent::resume):
+        (Inspector::InspectorDebuggerAgent::schedulePauseOnNextStatement):
+        (Inspector::InspectorDebuggerAgent::cancelPauseOnNextStatement):
+        Clean up and correct pause on next statement logic.
+
+        (Inspector::InspectorDebuggerAgent::registerIdleHandler):
+        (Inspector::InspectorDebuggerAgent::willStepAndMayBecomeIdle):
+        (Inspector::InspectorDebuggerAgent::didBecomeIdle):
+        (Inspector::InspectorDebuggerAgent::didBecomeIdleAfterStepping): Deleted.
+        The idle handler may now also trigger a pause in the case
+        where continueUntilNextRunLoop resumed and wants to pause.
+
+        (Inspector::InspectorDebuggerAgent::didPause):
+        Eliminate the useless didPause. The DOMDebugger was keeping track
+        of its own state that was worse then the state in DebuggerAgent.
+
</ins><span class="cx"> 2016-11-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, fix cloop.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -688,7 +688,7 @@
</span><span class="cx">             isArrayLike = injectedScript._subtype(object) === &quot;array&quot; &amp;&amp; isFinite(object.length) &amp;&amp; object.length &gt; 0;
</span><span class="cx">         } catch(e) {}
</span><span class="cx"> 
</span><del>-        for (var o = object; this._isDefined(o); o = o.__proto__) {
</del><ins>+        for (var o = object; this._isDefined(o); o = Object.getPrototypeOf(o)) {
</ins><span class="cx">             var isOwnProperty = o === object;
</span><span class="cx"> 
</span><span class="cx">             if (isArrayLike &amp;&amp; isOwnProperty)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -476,6 +476,18 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InspectorDebuggerAgent::continueUntilNextRunLoop(ErrorString&amp; errorString)
+{
+    if (!assertPaused(errorString))
+        return;
+
+    resume(errorString);
+
+    m_enablePauseWhenIdle = true;
+
+    registerIdleHandler();
+}
+
</ins><span class="cx"> void InspectorDebuggerAgent::continueToLocation(ErrorString&amp; errorString, const InspectorObject&amp; location)
</span><span class="cx"> {
</span><span class="cx">     if (!assertPaused(errorString))
</span><span class="lines">@@ -572,8 +584,11 @@
</span><span class="cx">     if (m_javaScriptPauseScheduled)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    m_javaScriptPauseScheduled = true;
+
</ins><span class="cx">     m_breakReason = breakReason;
</span><span class="cx">     m_breakAuxData = WTFMove(data);
</span><ins>+
</ins><span class="cx">     JSC::JSLockHolder locker(m_scriptDebugServer.vm());
</span><span class="cx">     m_scriptDebugServer.setPauseOnNextStatement(true);
</span><span class="cx"> }
</span><span class="lines">@@ -580,25 +595,27 @@
</span><span class="cx"> 
</span><span class="cx"> void InspectorDebuggerAgent::cancelPauseOnNextStatement()
</span><span class="cx"> {
</span><del>-    if (m_javaScriptPauseScheduled)
</del><ins>+    if (!m_javaScriptPauseScheduled)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     clearBreakDetails();
</span><span class="cx">     m_scriptDebugServer.setPauseOnNextStatement(false);
</span><ins>+    m_enablePauseWhenIdle = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InspectorDebuggerAgent::pause(ErrorString&amp;)
</span><span class="cx"> {
</span><span class="cx">     schedulePauseOnNextStatement(DebuggerFrontendDispatcher::Reason::PauseOnNextStatement, nullptr);
</span><del>-
-    m_javaScriptPauseScheduled = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InspectorDebuggerAgent::resume(ErrorString&amp; errorString)
</span><span class="cx"> {
</span><del>-    if (!assertPaused(errorString))
</del><ins>+    if (!m_pausedScriptState &amp;&amp; !m_javaScriptPauseScheduled) {
+        errorString = ASCIILiteral(&quot;Was not paused or waiting to pause&quot;);
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx"> 
</span><ins>+    cancelPauseOnNextStatement();
</ins><span class="cx">     m_scriptDebugServer.continueProgram();
</span><span class="cx">     m_conditionToDispatchResumed = ShouldDispatchResumed::WhenContinued;
</span><span class="cx"> }
</span><span class="lines">@@ -630,23 +647,28 @@
</span><span class="cx">     m_scriptDebugServer.stepOutOfFunction();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InspectorDebuggerAgent::willStepAndMayBecomeIdle()
</del><ins>+void InspectorDebuggerAgent::registerIdleHandler()
</ins><span class="cx"> {
</span><del>-    // When stepping the backend must eventually trigger a &quot;paused&quot; or &quot;resumed&quot; event.
-    // If the step causes us to exit the VM, then we should issue &quot;resumed&quot;.
-    m_conditionToDispatchResumed = ShouldDispatchResumed::WhenIdle;
-
</del><span class="cx">     if (!m_registeredIdleCallback) {
</span><span class="cx">         m_registeredIdleCallback = true;
</span><span class="cx">         JSC::VM&amp; vm = m_scriptDebugServer.vm();
</span><span class="cx">         vm.whenIdle([this]() {
</span><del>-            didBecomeIdleAfterStepping();
</del><ins>+            didBecomeIdle();
</ins><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InspectorDebuggerAgent::didBecomeIdleAfterStepping()
</del><ins>+void InspectorDebuggerAgent::willStepAndMayBecomeIdle()
</ins><span class="cx"> {
</span><ins>+    // When stepping the backend must eventually trigger a &quot;paused&quot; or &quot;resumed&quot; event.
+    // If the step causes us to exit the VM, then we should issue &quot;resumed&quot;.
+    m_conditionToDispatchResumed = ShouldDispatchResumed::WhenIdle;
+
+    registerIdleHandler();
+}
+
+void InspectorDebuggerAgent::didBecomeIdle()
+{
</ins><span class="cx">     m_registeredIdleCallback = false;
</span><span class="cx"> 
</span><span class="cx">     if (m_conditionToDispatchResumed == ShouldDispatchResumed::WhenIdle)
</span><span class="lines">@@ -653,6 +675,11 @@
</span><span class="cx">         m_frontendDispatcher-&gt;resumed();
</span><span class="cx"> 
</span><span class="cx">     m_conditionToDispatchResumed = ShouldDispatchResumed::No;
</span><ins>+
+    if (m_enablePauseWhenIdle) {
+        ErrorString ignored;
+        pause(ignored);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InspectorDebuggerAgent::setPauseOnExceptions(ErrorString&amp; errorString, const String&amp; stringPauseState)
</span><span class="lines">@@ -851,6 +878,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_conditionToDispatchResumed = ShouldDispatchResumed::No;
</span><ins>+    m_enablePauseWhenIdle = false;
</ins><span class="cx"> 
</span><span class="cx">     m_frontendDispatcher-&gt;paused(currentCallFrames(injectedScript), m_breakReason, m_breakAuxData);
</span><span class="cx"> 
</span><span class="lines">@@ -861,9 +889,6 @@
</span><span class="cx">         m_continueToLocationBreakpointID = JSC::noBreakpointID;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_listener)
-        m_listener-&gt;didPause();
-
</del><span class="cx">     RefPtr&lt;Stopwatch&gt; stopwatch = m_injectedScriptManager.inspectorEnvironment().executionStopwatch();
</span><span class="cx">     if (stopwatch &amp;&amp; stopwatch-&gt;isActive()) {
</span><span class="cx">         stopwatch-&gt;stop();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -67,6 +67,7 @@
</span><span class="cx">     void setBreakpointByUrl(ErrorString&amp;, int lineNumber, const String* optionalURL, const String* optionalURLRegex, const int* optionalColumnNumber, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::Debugger::Location&gt;&gt;&amp; locations) final;
</span><span class="cx">     void setBreakpoint(ErrorString&amp;, const Inspector::InspectorObject&amp; location, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr&lt;Inspector::Protocol::Debugger::Location&gt;&amp; actualLocation) final;
</span><span class="cx">     void removeBreakpoint(ErrorString&amp;, const String&amp; breakpointIdentifier) final;
</span><ins>+    void continueUntilNextRunLoop(ErrorString&amp;) final;
</ins><span class="cx">     void continueToLocation(ErrorString&amp;, const InspectorObject&amp; location) final;
</span><span class="cx">     void searchInContent(ErrorString&amp;, const String&amp; scriptID, const String&amp; query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::GenericTypes::SearchMatch&gt;&gt;&amp;) final;
</span><span class="cx">     void getScriptSource(ErrorString&amp;, const String&amp; scriptID, String* scriptSource) final;
</span><span class="lines">@@ -90,6 +91,8 @@
</span><span class="cx"> 
</span><span class="cx">     void schedulePauseOnNextStatement(DebuggerFrontendDispatcher::Reason breakReason, RefPtr&lt;InspectorObject&gt;&amp;&amp; data);
</span><span class="cx">     void cancelPauseOnNextStatement();
</span><ins>+    bool pauseOnNextStatementEnabled() const { return m_javaScriptPauseScheduled; }
+
</ins><span class="cx">     void breakProgram(DebuggerFrontendDispatcher::Reason breakReason, RefPtr&lt;InspectorObject&gt;&amp;&amp; data);
</span><span class="cx">     void scriptExecutionBlockedByCSP(const String&amp; directiveText);
</span><span class="cx"> 
</span><span class="lines">@@ -98,7 +101,6 @@
</span><span class="cx">         virtual ~Listener() { }
</span><span class="cx">         virtual void debuggerWasEnabled() = 0;
</span><span class="cx">         virtual void debuggerWasDisabled() = 0;
</span><del>-        virtual void didPause() = 0;
</del><span class="cx">     };
</span><span class="cx">     void setListener(Listener* listener) { m_listener = listener; }
</span><span class="cx"> 
</span><span class="lines">@@ -142,8 +144,9 @@
</span><span class="cx">     void clearExceptionValue();
</span><span class="cx"> 
</span><span class="cx">     enum class ShouldDispatchResumed { No, WhenIdle, WhenContinued };
</span><ins>+    void registerIdleHandler();
</ins><span class="cx">     void willStepAndMayBecomeIdle();
</span><del>-    void didBecomeIdleAfterStepping();
</del><ins>+    void didBecomeIdle();
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;InspectorObject&gt; buildBreakpointPauseReason(JSC::BreakpointID);
</span><span class="cx">     RefPtr&lt;InspectorObject&gt; buildExceptionPauseReason(JSC::JSValue exception, const InjectedScript&amp;);
</span><span class="lines">@@ -170,6 +173,7 @@
</span><span class="cx">     DebuggerFrontendDispatcher::Reason m_breakReason;
</span><span class="cx">     RefPtr&lt;InspectorObject&gt; m_breakAuxData;
</span><span class="cx">     ShouldDispatchResumed m_conditionToDispatchResumed { ShouldDispatchResumed::No };
</span><ins>+    bool m_enablePauseWhenIdle { false };
</ins><span class="cx">     bool m_enabled { false };
</span><span class="cx">     bool m_javaScriptPauseScheduled { false };
</span><span class="cx">     bool m_hasExceptionValue { false };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -177,11 +177,15 @@
</span><span class="cx">             &quot;description&quot;: &quot;Removes JavaScript breakpoint.&quot;
</span><span class="cx">         },
</span><span class="cx">         {
</span><ins>+            &quot;name&quot;: &quot;continueUntilNextRunLoop&quot;,
+            &quot;description&quot;: &quot;Continues execution until the current evaluation completes. This will trigger either a Debugger.paused or Debugger.resumed event.&quot;
+        },
+        {
</ins><span class="cx">             &quot;name&quot;: &quot;continueToLocation&quot;,
</span><ins>+            &quot;description&quot;: &quot;Continues execution until specific location is reached. This will trigger either a Debugger.paused or Debugger.resumed event.&quot;,
</ins><span class="cx">             &quot;parameters&quot;: [
</span><span class="cx">                 { &quot;name&quot;: &quot;location&quot;, &quot;$ref&quot;: &quot;Location&quot;, &quot;description&quot;: &quot;Location to continue to.&quot; }
</span><del>-            ],
-            &quot;description&quot;: &quot;Continues execution until specific location is reached. This will trigger either a Debugger.paused or Debugger.resumed event.&quot;
</del><ins>+            ]
</ins><span class="cx">         },
</span><span class="cx">         {
</span><span class="cx">             &quot;name&quot;: &quot;stepOver&quot;,
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/ChangeLog        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -1,3 +1,48 @@
</span><ins>+2016-11-14  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Worker debugging should pause all targets and view call frames in all targets
+        https://bugs.webkit.org/show_bug.cgi?id=164305
+        &lt;rdar://problem/29056192&gt;
+
+        Reviewed by Timothy Hatcher.
+
+        Tests: inspector/debugger/continueUntilNextRunLoop
+               inspector/worker/debugger-multiple-targets-pause
+
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore::WorkerMessagingProxy::postMessageToPageInspector):
+        Switch from postTask (callOnMainThread) to RunLoop::main().dispatch so
+        that a paused Worker can send Inspector protocol messages responses
+        back through the Main Page's InspectorWorkerAgent even if the Page
+        itself is paused and MainThread callbacks are paused.
+
+        * workers/WorkerRunLoop.h:
+        (WebCore::WorkerRunLoop::isNested):
+        * workers/WorkerRunLoop.cpp:
+        (WebCore::WorkerRunLoop::runInMode):
+        When running a nested WorkerRunLoop, running inspector debugger
+        commands, we should not fire timers on the Worker. Timers would
+        then be happening out of order and would not be debuggable.
+
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::fireEventListeners):
+        * inspector/InspectorDOMDebuggerAgent.cpp:
+        (WebCore::InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded):
+        (WebCore::InspectorDOMDebuggerAgent::clear):
+        (WebCore::InspectorDOMDebuggerAgent::didPause): Deleted.
+        * inspector/InspectorDOMDebuggerAgent.h:
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::willHandleEventImpl):
+        (WebCore::InspectorInstrumentation::didFireTimerImpl):
+        (WebCore::InspectorInstrumentation::didHandleEventImpl): Deleted.
+        (WebCore::InspectorInstrumentation::cancelPauseOnNativeEvent): Deleted.
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::willHandleEvent):
+        (WebCore::InspectorInstrumentation::didHandleEvent): Deleted.
+        Remove unnecessary code where WebCore is trying to keep track
+        of pause on next statement but that state is already more
+        accurately provided by InspectorDebuggerAgent.
+
</ins><span class="cx"> 2016-11-14  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebGL2] Teach WebGLRenderingContextBase about new texture internal formats
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventTargetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventTarget.cpp (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventTarget.cpp        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/dom/EventTarget.cpp        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -247,9 +247,8 @@
</span><span class="cx">         if (registeredListener-&gt;isPassive())
</span><span class="cx">             event.setInPassiveListener(true);
</span><span class="cx"> 
</span><del>-        auto cookie = InspectorInstrumentation::willHandleEvent(context, event);
</del><ins>+        InspectorInstrumentation::willHandleEvent(context, event);
</ins><span class="cx">         registeredListener-&gt;callback().handleEvent(context, &amp;event);
</span><del>-        InspectorInstrumentation::didHandleEvent(cookie);
</del><span class="cx"> 
</span><span class="cx">         if (registeredListener-&gt;isPassive())
</span><span class="cx">             event.setInPassiveListener(false);
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorDOMDebuggerAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -85,11 +85,6 @@
</span><span class="cx">     disable();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InspectorDOMDebuggerAgent::didPause()
-{
-    m_pauseInNextEventListener = false;
-}
-
</del><span class="cx"> void InspectorDOMDebuggerAgent::disable()
</span><span class="cx"> {
</span><span class="cx">     m_instrumentingAgents.setInspectorDOMDebuggerAgent(nullptr);
</span><span class="lines">@@ -348,15 +343,14 @@
</span><span class="cx"> void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(bool isDOMEvent, const String&amp; eventName, bool synchronous)
</span><span class="cx"> {
</span><span class="cx">     String fullEventName = (isDOMEvent ? listenerEventCategoryType : instrumentationEventCategoryType) + eventName;
</span><del>-    if (m_pauseInNextEventListener)
-        m_pauseInNextEventListener = false;
-    else {
-        if (!m_eventListenerBreakpoints.contains(fullEventName))
-            return;
-    }
</del><span class="cx"> 
</span><ins>+    bool shouldPause = m_debuggerAgent-&gt;pauseOnNextStatementEnabled() || m_eventListenerBreakpoints.contains(fullEventName);
+    if (!shouldPause)
+        return;
+
</ins><span class="cx">     Ref&lt;InspectorObject&gt; eventData = InspectorObject::create();
</span><del>-    eventData-&gt;setString(&quot;eventName&quot;, fullEventName);
</del><ins>+    eventData-&gt;setString(ASCIILiteral(&quot;eventName&quot;), fullEventName);
+
</ins><span class="cx">     if (synchronous)
</span><span class="cx">         m_debuggerAgent-&gt;breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));
</span><span class="cx">     else
</span><span class="lines">@@ -409,7 +403,6 @@
</span><span class="cx"> void InspectorDOMDebuggerAgent::clear()
</span><span class="cx"> {
</span><span class="cx">     m_domBreakpoints.clear();
</span><del>-    m_pauseInNextEventListener = false;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorDOMDebuggerAgenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -84,7 +84,6 @@
</span><span class="cx">     // Inspector::InspectorDebuggerAgent::Listener implementation.
</span><span class="cx">     void debuggerWasEnabled() override;
</span><span class="cx">     void debuggerWasDisabled() override;
</span><del>-    void didPause() override;
</del><span class="cx">     void disable();
</span><span class="cx"> 
</span><span class="cx">     void descriptionForDOMEvent(Node&amp; target, int breakpointType, bool insertion, Inspector::InspectorObject&amp; description);
</span><span class="lines">@@ -103,7 +102,6 @@
</span><span class="cx">     HashMap&lt;Node*, uint32_t&gt; m_domBreakpoints;
</span><span class="cx">     HashSet&lt;String&gt; m_eventListenerBreakpoints;
</span><span class="cx">     HashSet&lt;String&gt; m_xhrBreakpoints;
</span><del>-    bool m_pauseInNextEventListener { false };
</del><span class="cx">     bool m_pauseOnAllXHRsEnabled { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorInstrumentationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -365,18 +365,11 @@
</span><span class="cx">     return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-InspectorInstrumentationCookie InspectorInstrumentation::willHandleEventImpl(InstrumentingAgents&amp; instrumentingAgents, const Event&amp; event)
</del><ins>+void InspectorInstrumentation::willHandleEventImpl(InstrumentingAgents&amp; instrumentingAgents, const Event&amp; event)
</ins><span class="cx"> {
</span><span class="cx">     pauseOnNativeEventIfNeeded(instrumentingAgents, true, event.type(), false);
</span><del>-    return InspectorInstrumentationCookie(instrumentingAgents, 0);
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InspectorInstrumentation::didHandleEventImpl(const InspectorInstrumentationCookie&amp; cookie)
-{
-    if (cookie.isValid())
-        cancelPauseOnNativeEvent(*cookie.instrumentingAgents());
-}
-
</del><span class="cx"> void InspectorInstrumentation::didDispatchEventImpl(const InspectorInstrumentationCookie&amp; cookie)
</span><span class="cx"> {
</span><span class="cx">     if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
</span><span class="lines">@@ -440,9 +433,6 @@
</span><span class="cx"> 
</span><span class="cx"> void InspectorInstrumentation::didFireTimerImpl(const InspectorInstrumentationCookie&amp; cookie)
</span><span class="cx"> {
</span><del>-    if (cookie.isValid())
-        cancelPauseOnNativeEvent(*cookie.instrumentingAgents());
-
</del><span class="cx">     if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
</span><span class="cx">         timelineAgent-&gt;didFireTimer();
</span><span class="cx"> }
</span><span class="lines">@@ -1146,12 +1136,6 @@
</span><span class="cx">         domDebuggerAgent-&gt;pauseOnNativeEventIfNeeded(isDOMEvent, eventName, synchronous);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InspectorInstrumentation::cancelPauseOnNativeEvent(InstrumentingAgents&amp; instrumentingAgents)
-{
-    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
-        debuggerAgent-&gt;cancelPauseOnNextStatement();
-}
-
</del><span class="cx"> void InspectorInstrumentation::didRequestAnimationFrameImpl(InstrumentingAgents&amp; instrumentingAgents, int callbackId, Frame* frame)
</span><span class="cx"> {
</span><span class="cx">     pauseOnNativeEventIfNeeded(instrumentingAgents, false, requestAnimationFrameEventName, true);
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorInstrumentationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.h (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorInstrumentation.h        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.h        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -130,8 +130,7 @@
</span><span class="cx">     static void didCallFunction(const InspectorInstrumentationCookie&amp;, ScriptExecutionContext*);
</span><span class="cx">     static InspectorInstrumentationCookie willDispatchEvent(Document&amp;, const Event&amp;, bool hasEventListeners);
</span><span class="cx">     static void didDispatchEvent(const InspectorInstrumentationCookie&amp;);
</span><del>-    static InspectorInstrumentationCookie willHandleEvent(ScriptExecutionContext*, const Event&amp;);
-    static void didHandleEvent(const InspectorInstrumentationCookie&amp;);
</del><ins>+    static void willHandleEvent(ScriptExecutionContext*, const Event&amp;);
</ins><span class="cx">     static InspectorInstrumentationCookie willDispatchEventOnWindow(Frame*, const Event&amp;, DOMWindow&amp;);
</span><span class="cx">     static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&amp;);
</span><span class="cx">     static InspectorInstrumentationCookie willEvaluateScript(Frame&amp;, const String&amp; url, int lineNumber);
</span><span class="lines">@@ -303,8 +302,7 @@
</span><span class="cx">     static InspectorInstrumentationCookie willCallFunctionImpl(InstrumentingAgents&amp;, const String&amp; scriptName, int scriptLine, ScriptExecutionContext*);
</span><span class="cx">     static void didCallFunctionImpl(const InspectorInstrumentationCookie&amp;, ScriptExecutionContext*);
</span><span class="cx">     static InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents&amp;, Document&amp;, const Event&amp;, bool hasEventListeners);
</span><del>-    static InspectorInstrumentationCookie willHandleEventImpl(InstrumentingAgents&amp;, const Event&amp;);
-    static void didHandleEventImpl(const InspectorInstrumentationCookie&amp;);
</del><ins>+    static void willHandleEventImpl(InstrumentingAgents&amp;, const Event&amp;);
</ins><span class="cx">     static void didDispatchEventImpl(const InspectorInstrumentationCookie&amp;);
</span><span class="cx">     static InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InstrumentingAgents&amp;, const Event&amp;, DOMWindow&amp;);
</span><span class="cx">     static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&amp;);
</span><span class="lines">@@ -442,7 +440,6 @@
</span><span class="cx">     static InspectorTimelineAgent* retrieveTimelineAgent(const InspectorInstrumentationCookie&amp;);
</span><span class="cx"> 
</span><span class="cx">     static void pauseOnNativeEventIfNeeded(InstrumentingAgents&amp;, bool isDOMEvent, const String&amp; eventName, bool synchronous);
</span><del>-    static void cancelPauseOnNativeEvent(InstrumentingAgents&amp;);
</del><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT static int s_frontendCounter;
</span><span class="cx"> };
</span><span class="lines">@@ -702,21 +699,13 @@
</span><span class="cx">         didDispatchEventImpl(cookie);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline InspectorInstrumentationCookie InspectorInstrumentation::willHandleEvent(ScriptExecutionContext* context, const Event&amp; event)
</del><ins>+inline void InspectorInstrumentation::willHandleEvent(ScriptExecutionContext* context, const Event&amp; event)
</ins><span class="cx"> {
</span><del>-    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
</del><ins>+    FAST_RETURN_IF_NO_FRONTENDS(void());
</ins><span class="cx">     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
</span><span class="cx">         return willHandleEventImpl(*instrumentingAgents, event);
</span><del>-    return InspectorInstrumentationCookie();
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void InspectorInstrumentation::didHandleEvent(const InspectorInstrumentationCookie&amp; cookie)
-{
-    FAST_RETURN_IF_NO_FRONTENDS(void());
-    if (cookie.isValid())
-        didHandleEventImpl(cookie);
-}
-
</del><span class="cx"> inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventOnWindow(Frame* frame, const Event&amp; event, DOMWindow&amp; window)
</span><span class="cx"> {
</span><span class="cx">     FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
</span></span></pre></div>
<a id="trunkSourceWebCoreworkersWorkerMessagingProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &lt;inspector/ScriptCallStack.h&gt;
</span><span class="cx"> #include &lt;runtime/ConsoleTypes.h&gt;
</span><span class="cx"> #include &lt;wtf/MainThread.h&gt;
</span><ins>+#include &lt;wtf/RunLoop.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -168,7 +169,7 @@
</span><span class="cx"> 
</span><span class="cx"> void WorkerMessagingProxy::postMessageToPageInspector(const String&amp; message)
</span><span class="cx"> {
</span><del>-    m_scriptExecutionContext-&gt;postTask([this, message = message.isolatedCopy()] (ScriptExecutionContext&amp;) {
</del><ins>+    RunLoop::main().dispatch([this, message = message.isolatedCopy()] {
</ins><span class="cx">         m_inspectorProxy-&gt;sendMessageFromWorkerToFrontend(message);
</span><span class="cx">     });
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreworkersWorkerRunLoopcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/workers/WorkerRunLoop.cpp (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/workers/WorkerRunLoop.cpp        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.cpp        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case MessageQueueTimeout:
</span><del>-        if (!context-&gt;isClosing())
</del><ins>+        if (!context-&gt;isClosing() &amp;&amp; !isNested())
</ins><span class="cx">             m_sharedTimer-&gt;fire();
</span><span class="cx"> #if USE(CF)
</span><span class="cx">         if (nextCFRunLoopTimerFireDate &lt;= CFAbsoluteTimeGetCurrent())
</span></span></pre></div>
<a id="trunkSourceWebCoreworkersWorkerRunLooph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/workers/WorkerRunLoop.h (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/workers/WorkerRunLoop.h        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.h        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -85,6 +85,8 @@
</span><span class="cx">         // This should only be called when the context is closed or loop has been terminated.
</span><span class="cx">         void runCleanupTasks(WorkerGlobalScope*);
</span><span class="cx"> 
</span><ins>+        bool isNested() const { return m_nestedCount &gt; 1; }
+
</ins><span class="cx">         MessageQueue&lt;Task&gt; m_messageQueue;
</span><span class="cx">         std::unique_ptr&lt;WorkerSharedTimer&gt; m_sharedTimer;
</span><span class="cx">         int m_nestedCount;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -1,3 +1,161 @@
</span><ins>+2016-11-14  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Worker debugging should pause all targets and view call frames in all targets
+        https://bugs.webkit.org/show_bug.cgi?id=164305
+        &lt;rdar://problem/29056192&gt;
+
+        Reviewed by Timothy Hatcher.
+
+        This implements a policy where, when one Target (&quot;Thread&quot;) pauses
+        the frontend triggers a pause in all other Targets. The intended
+        user experience is &quot;all threads pause&quot; whenever the frontend shows
+        the debugger paused UI.
+
+        DebuggerManager has a few straight forward changes:
+
+            - The paused state reflects if any target is paused.
+            - The Paused Event is fired when going from !paused -&gt; paused.
+              This means when the first target pauses.
+            - The Resumed Event is fired when going from paused -&gt; !paused.
+              This means only after all targets have resumed.
+            - The CallFrameDidChange Event now includes the Target that updated.
+
+        When a Target first pauses the frontend then immediately pauses all
+        other Targets. This puts them into a &quot;pausing&quot; state (we display as
+        Idle) and they will pause as soon as they start executing JavaScript.
+
+        When a Target steps the &quot;paused&quot; state isn't changing. So this is
+        just a CallFramesDidChange update.
+
+        When clicking Resume we resume all targets. This is will be the normal,
+        expected way users resume execution. Note that one of the threads may
+        then hit a breakpoint and re-pause all threads.
+
+        Sometimes when multiple threads are paused you may want to run an
+        individual thread to completion but keep other threads paused. There
+        is a context menu on the ThreadTreeElement to resume just that
+        single thread. It will continue and pause for its next run loop.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Images/Thread.svg: Added.
+        * UserInterface/Images/gtk/Thread.svg: Added.
+        * UserInterface/Main.html:
+        New strings and files.
+
+        * UserInterface/Base/Main.js:
+        (WebInspector.loaded):
+        * UserInterface/Test/Test.js:
+        (WebInspector.loaded):
+        Place the TargetManager first since other managers may want to listen
+        for TargetAdded / TargetRemoved events.
+
+        * UserInterface/Controllers/DebuggerManager.js:
+        (WebInspector.DebuggerManager.prototype.get paused):
+        This is now a computed state.
+
+        (WebInspector.DebuggerManager.prototype.pause):
+        (WebInspector.DebuggerManager.prototype.resume):
+        Affect all targets.
+
+        (WebInspector.DebuggerManager.prototype.stepOver):
+        (WebInspector.DebuggerManager.prototype.stepInto):
+        (WebInspector.DebuggerManager.prototype.stepOut):
+        (WebInspector.DebuggerManager.prototype.reset):
+        Update to use the paused computed property.
+
+        (WebInspector.DebuggerManager.prototype.continueUntilNextRunLoop):
+        Issue the new Debugger.continueUntilNextRunLoop command
+        on a given target.
+
+        (WebInspector.DebuggerManager.prototype.initializeTarget):
+        When a new Target is created and we were already paused,
+        then start that Worker in a paused state.
+
+        (WebInspector.DebuggerManager.prototype.debuggerDidPause):
+        Recover from bad cases where the backend informs the frontend about
+        internal JavaScript that it shouldn't know about. Legacy backend do
+        this but also there are corner cases we need to handle.
+        Dispatch events appropriately now that multiple targets may be paused.
+
+        (WebInspector.DebuggerManager.prototype._didResumeInternal):
+        Dispatch events appropriately now that multiple targets may be paused.
+
+        (WebInspector.DebuggerManager.prototype._targetRemoved):
+        Remove debugger data for targets that go away to avoid leaks.
+
+        * UserInterface/Models/DebuggerData.js:
+        (WebInspector.DebuggerData):
+        (WebInspector.DebuggerData.prototype.get paused):
+        (WebInspector.DebuggerData.prototype.get pausing):
+        Move some more per-Target state into DebuggerData.
+
+        (WebInspector.DebuggerData.prototype.pauseIfNeeded):
+        (WebInspector.DebuggerData.prototype.resumeIfNeeded):
+        (WebInspector.DebuggerData.prototype.continueUntilNextRunLoop):
+        These should only be called by DebuggerManager. They correctly
+        update the state of the DebuggerData for this Target, and also
+        issue the underlying command to the target.
+
+        (WebInspector.DebuggerData.prototype.updateForPause):
+        (WebInspector.DebuggerData.prototype.updateForResume):
+        Handle a special case where continueUntilNextRunLoop triggers
+        an invisible &quot;pause&quot; on the backend that we should mirror.
+
+        * UserInterface/Protocol/Target.js:
+        (WebInspector.MainTarget):
+        (WebInspector.MainTarget.prototype.get displayName):
+        (WebInspector.MainTarget.prototype.initialize):
+        Better display names.
+
+        * UserInterface/Views/DebuggerSidebarPanel.js:
+        (WebInspector.DebuggerSidebarPanel):
+        (WebInspector.DebuggerSidebarPanel.prototype._debuggerDidPause):
+        (WebInspector.DebuggerSidebarPanel.prototype._debuggerDidResume):
+        (WebInspector.DebuggerSidebarPanel.prototype._updateSingleThreadCallStacks):
+        (WebInspector.DebuggerSidebarPanel.prototype._selectActiveCallFrameTreeElement):
+        (WebInspector.DebuggerSidebarPanel.prototype._showSingleThreadCallStacks):
+        (WebInspector.DebuggerSidebarPanel.prototype._showMultipleThreadCallStacks):
+        (WebInspector.DebuggerSidebarPanel.prototype._findThreadTreeElementForTarget):
+        (WebInspector.DebuggerSidebarPanel.prototype._targetAdded):
+        (WebInspector.DebuggerSidebarPanel.prototype._targetRemoved):
+        (WebInspector.DebuggerSidebarPanel.prototype._debuggerCallFramesDidChange):
+        (WebInspector.DebuggerSidebarPanel.prototype._debuggerActiveCallFrameDidChange):
+        The DebuggerSidebar still has a single &quot;Call Stacks&quot; section, but maintains
+        two TreeOutlines and only shows one at a time. The Single Thread view shows
+        a flat list of the call frames for the Main Target when it is the only target.
+        The Multiple Threads view shows a list of Threads and their call frames.
+        We always keep both up to date, because we may need to swap between them
+        purely as Targets are added / removed. There is a bit of extra logic to
+        ensure we select elements properly based only on the visible tree outline.
+
+        * UserInterface/Views/LogContentView.js:
+        (WebInspector.LogContentView.prototype.didAppendConsoleMessageView):
+        When evaluating in a particular target, &quot;runAfterPendingDispatches&quot;
+        must wait for all other commands in that particular target to have
+        completed. So use the target specific version.
+
+        * UserInterface/Views/NavigationSidebarPanel.js:
+        (WebInspector.NavigationSidebarPanel.prototype._isTreeElementWithoutRepresentedObject):
+        Gracefully handle a few more TreeElements without a represented object.
+
+        * UserInterface/Views/IdleTreeElement.css: Added.
+        (.details-section.call-stack .idle .icon):
+        * UserInterface/Views/IdleTreeElement.js: Added.
+        (WebInspector.IdleTreeElement):
+        Very basic tree element to encapsulate an Idle call frame with an
+        empty represented object.
+
+        * UserInterface/Views/ThreadTreeElement.css: Added.
+        (.details-section.call-stack .thread .icon):
+        * UserInterface/Views/ThreadTreeElement.js: Added.
+        (WebInspector.ThreadTreeElement):
+        (WebInspector.ThreadTreeElement.prototype.get target):
+        (WebInspector.ThreadTreeElement.prototype.refresh):
+        (WebInspector.ThreadTreeElement.prototype.onattach):
+        (WebInspector.ThreadTreeElement.prototype.oncontextmenu):
+        ThreadTreeElement has no represented object, but makes it easy
+        to refresh a list of CallFrameTreeElements for a given target.
+
</ins><span class="cx"> 2016-11-14  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Disable Warning Filter in Debugger Tab By Default
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> localizedStrings[&quot;%dpx²&quot;] = &quot;%dpx²&quot;;
</span><span class="cx"> localizedStrings[&quot;%s (%s)&quot;] = &quot;%s (%s)&quot;;
</span><span class="cx"> localizedStrings[&quot;%s (%s, %s)&quot;] = &quot;%s (%s, %s)&quot;;
</span><ins>+localizedStrings[&quot;%s (default)&quot;] = &quot;%s (default)&quot;;
</ins><span class="cx"> localizedStrings[&quot;%s (hidden)&quot;] = &quot;%s (hidden)&quot;;
</span><span class="cx"> localizedStrings[&quot;%s Event Dispatched&quot;] = &quot;%s Event Dispatched&quot;;
</span><span class="cx"> localizedStrings[&quot;%s Prototype&quot;] = &quot;%s Prototype&quot;;
</span><span class="lines">@@ -183,7 +184,6 @@
</span><span class="cx"> localizedStrings[&quot;Composite&quot;] = &quot;Composite&quot;;
</span><span class="cx"> localizedStrings[&quot;Compressed&quot;] = &quot;Compressed&quot;;
</span><span class="cx"> localizedStrings[&quot;Compression&quot;] = &quot;Compression&quot;;
</span><del>-localizedStrings[&quot;computed&quot;] = &quot;computed&quot;;
</del><span class="cx"> localizedStrings[&quot;Condition&quot;] = &quot;Condition&quot;;
</span><span class="cx"> localizedStrings[&quot;Conditional expression&quot;] = &quot;Conditional expression&quot;;
</span><span class="cx"> localizedStrings[&quot;Connection&quot;] = &quot;Connection&quot;;
</span><span class="lines">@@ -239,7 +239,6 @@
</span><span class="cx"> localizedStrings[&quot;Decoded&quot;] = &quot;Decoded&quot;;
</span><span class="cx"> localizedStrings[&quot;Decoration&quot;] = &quot;Decoration&quot;;
</span><span class="cx"> localizedStrings[&quot;Default&quot;] = &quot;Default&quot;;
</span><del>-localizedStrings[&quot;default&quot;] = &quot;default&quot;;
</del><span class="cx"> localizedStrings[&quot;Delay&quot;] = &quot;Delay&quot;;
</span><span class="cx"> localizedStrings[&quot;Delete&quot;] = &quot;Delete&quot;;
</span><span class="cx"> localizedStrings[&quot;Delete Breakpoint&quot;] = &quot;Delete Breakpoint&quot;;
</span><span class="lines">@@ -411,6 +410,7 @@
</span><span class="cx"> localizedStrings[&quot;Icon and Text (Horizontal)&quot;] = &quot;Icon and Text (Horizontal)&quot;;
</span><span class="cx"> localizedStrings[&quot;Icon and Text (Vertical)&quot;] = &quot;Icon and Text (Vertical)&quot;;
</span><span class="cx"> localizedStrings[&quot;Identity&quot;] = &quot;Identity&quot;;
</span><ins>+localizedStrings[&quot;Idle&quot;] = &quot;Idle&quot;;
</ins><span class="cx"> localizedStrings[&quot;Ignore&quot;] = &quot;Ignore&quot;;
</span><span class="cx"> localizedStrings[&quot;Ignored&quot;] = &quot;Ignored&quot;;
</span><span class="cx"> localizedStrings[&quot;Image&quot;] = &quot;Image&quot;;
</span><span class="lines">@@ -439,6 +439,7 @@
</span><span class="cx"> localizedStrings[&quot;JavaScript&quot;] = &quot;JavaScript&quot;;
</span><span class="cx"> localizedStrings[&quot;JavaScript &amp; Events&quot;] = &quot;JavaScript &amp; Events&quot;;
</span><span class="cx"> localizedStrings[&quot;JavaScript Allocations&quot;] = &quot;JavaScript Allocations&quot;;
</span><ins>+localizedStrings[&quot;JavaScript Context&quot;] = &quot;JavaScript Context&quot;;
</ins><span class="cx"> localizedStrings[&quot;Join&quot;] = &quot;Join&quot;;
</span><span class="cx"> localizedStrings[&quot;Jump to Definition&quot;] = &quot;Jump to Definition&quot;;
</span><span class="cx"> localizedStrings[&quot;Keep Log on Navigation&quot;] = &quot;Keep Log on Navigation&quot;;
</span><span class="lines">@@ -478,7 +479,7 @@
</span><span class="cx"> localizedStrings[&quot;Logs&quot;] = &quot;Logs&quot;;
</span><span class="cx"> localizedStrings[&quot;Lowest: %s&quot;] = &quot;Lowest: %s&quot;;
</span><span class="cx"> localizedStrings[&quot;MIME Type&quot;] = &quot;MIME Type&quot;;
</span><del>-localizedStrings[&quot;Main Context&quot;] = &quot;Main Context&quot;;
</del><ins>+localizedStrings[&quot;Main&quot;] = &quot;Main&quot;;
</ins><span class="cx"> localizedStrings[&quot;Main Frame&quot;] = &quot;Main Frame&quot;;
</span><span class="cx"> localizedStrings[&quot;Manifest URL&quot;] = &quot;Manifest URL&quot;;
</span><span class="cx"> localizedStrings[&quot;Margin&quot;] = &quot;Margin&quot;;
</span><span class="lines">@@ -511,7 +512,6 @@
</span><span class="cx"> localizedStrings[&quot;No Application Cache information available&quot;] = &quot;No Application Cache information available&quot;;
</span><span class="cx"> localizedStrings[&quot;No Attributes&quot;] = &quot;No Attributes&quot;;
</span><span class="cx"> localizedStrings[&quot;No Box Model Information&quot;] = &quot;No Box Model Information&quot;;
</span><del>-localizedStrings[&quot;No Call Frames&quot;] = &quot;No Call Frames&quot;;
</del><span class="cx"> localizedStrings[&quot;No Chart Available&quot;] = &quot;No Chart Available&quot;;
</span><span class="cx"> localizedStrings[&quot;No Child Layers&quot;] = &quot;No Child Layers&quot;;
</span><span class="cx"> localizedStrings[&quot;No Entries.&quot;] = &quot;No Entries.&quot;;
</span><span class="lines">@@ -579,8 +579,6 @@
</span><span class="cx"> localizedStrings[&quot;Pause script execution (%s or %s)&quot;] = &quot;Pause script execution (%s or %s)&quot;;
</span><span class="cx"> localizedStrings[&quot;Play Sound&quot;] = &quot;Play Sound&quot;;
</span><span class="cx"> localizedStrings[&quot;Polite&quot;] = &quot;Polite&quot;;
</span><del>-localizedStrings[&quot;popup&quot;] = &quot;popup&quot;;
-localizedStrings[&quot;popup, toggle&quot;] = &quot;popup, toggle&quot;;
</del><span class="cx"> localizedStrings[&quot;Port&quot;] = &quot;Port&quot;;
</span><span class="cx"> localizedStrings[&quot;Position&quot;] = &quot;Position&quot;;
</span><span class="cx"> localizedStrings[&quot;Position X&quot;] = &quot;Position X&quot;;
</span><span class="lines">@@ -637,6 +635,7 @@
</span><span class="cx"> localizedStrings[&quot;Response&quot;] = &quot;Response&quot;;
</span><span class="cx"> localizedStrings[&quot;Response Headers&quot;] = &quot;Response Headers&quot;;
</span><span class="cx"> localizedStrings[&quot;Restart (%s)&quot;] = &quot;Restart (%s)&quot;;
</span><ins>+localizedStrings[&quot;Resume Thread&quot;] = &quot;Resume Thread&quot;;
</ins><span class="cx"> localizedStrings[&quot;Retained Size&quot;] = &quot;Retained Size&quot;;
</span><span class="cx"> localizedStrings[&quot;Return type for anonymous function&quot;] = &quot;Return type for anonymous function&quot;;
</span><span class="cx"> localizedStrings[&quot;Return type for function: %s&quot;] = &quot;Return type for function: %s&quot;;
</span><span class="lines">@@ -782,7 +781,6 @@
</span><span class="cx"> localizedStrings[&quot;Timer Removed&quot;] = &quot;Timer Removed&quot;;
</span><span class="cx"> localizedStrings[&quot;Timestamp \u2014 %s&quot;] = &quot;Timestamp \u2014 %s&quot;;
</span><span class="cx"> localizedStrings[&quot;Timing&quot;] = &quot;Timing&quot;;
</span><del>-localizedStrings[&quot;toggle&quot;] = &quot;toggle&quot;;
</del><span class="cx"> localizedStrings[&quot;Toggle Classes&quot;] = &quot;Toggle Classes&quot;;
</span><span class="cx"> localizedStrings[&quot;Top&quot;] = &quot;Top&quot;;
</span><span class="cx"> localizedStrings[&quot;Top Functions&quot;] = &quot;Top Functions&quot;;
</span><span class="lines">@@ -845,11 +843,16 @@
</span><span class="cx"> localizedStrings[&quot;Y2&quot;] = &quot;Y2&quot;;
</span><span class="cx"> localizedStrings[&quot;Yes&quot;] = &quot;Yes&quot;;
</span><span class="cx"> localizedStrings[&quot;Z-Index&quot;] = &quot;Z-Index&quot;;
</span><ins>+localizedStrings[&quot;computed&quot;] = &quot;computed&quot;;
+localizedStrings[&quot;default&quot;] = &quot;default&quot;;
</ins><span class="cx"> localizedStrings[&quot;key&quot;] = &quot;key&quot;;
</span><span class="cx"> localizedStrings[&quot;line &quot;] = &quot;line &quot;;
</span><span class="cx"> localizedStrings[&quot;originally %s&quot;] = &quot;originally %s&quot;;
</span><ins>+localizedStrings[&quot;popup&quot;] = &quot;popup&quot;;
+localizedStrings[&quot;popup, toggle&quot;] = &quot;popup, toggle&quot;;
</ins><span class="cx"> localizedStrings[&quot;spaces&quot;] = &quot;spaces&quot;;
</span><span class="cx"> localizedStrings[&quot;time before stopping&quot;] = &quot;time before stopping&quot;;
</span><span class="cx"> localizedStrings[&quot;times before stopping&quot;] = &quot;times before stopping&quot;;
</span><ins>+localizedStrings[&quot;toggle&quot;] = &quot;toggle&quot;;
</ins><span class="cx"> localizedStrings[&quot;value&quot;] = &quot;value&quot;;
</span><span class="cx"> localizedStrings[&quot;“%s” Profile Recorded&quot;] = &quot;“%s” Profile Recorded&quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseMainjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -108,6 +108,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Create the singleton managers next, before the user interface elements, so the user interface can register
</span><span class="cx">     // as event listeners on these managers.
</span><ins>+    this.targetManager = new WebInspector.TargetManager;
</ins><span class="cx">     this.branchManager = new WebInspector.BranchManager;
</span><span class="cx">     this.frameResourceManager = new WebInspector.FrameResourceManager;
</span><span class="cx">     this.storageManager = new WebInspector.StorageManager;
</span><span class="lines">@@ -126,7 +127,6 @@
</span><span class="cx">     this.layerTreeManager = new WebInspector.LayerTreeManager;
</span><span class="cx">     this.dashboardManager = new WebInspector.DashboardManager;
</span><span class="cx">     this.probeManager = new WebInspector.ProbeManager;
</span><del>-    this.targetManager = new WebInspector.TargetManager;
</del><span class="cx">     this.workerManager = new WebInspector.WorkerManager;
</span><span class="cx">     this.replayManager = new WebInspector.ReplayManager;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -43,6 +43,8 @@
</span><span class="cx">         WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingWillStart, this._timelineCapturingWillStart, this);
</span><span class="cx">         WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingStopped, this._timelineCapturingStopped, this);
</span><span class="cx"> 
</span><ins>+        WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event.TargetRemoved, this._targetRemoved, this);
+
</ins><span class="cx">         WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
</span><span class="cx"> 
</span><span class="cx">         this._breakpointsSetting = new WebInspector.Setting(&quot;breakpoints&quot;, []);
</span><span class="lines">@@ -71,11 +73,11 @@
</span><span class="cx"> 
</span><span class="cx">         this._nextBreakpointActionIdentifier = 1;
</span><span class="cx"> 
</span><del>-        this._paused = false;
</del><span class="cx">         this._activeCallFrame = null;
</span><span class="cx"> 
</span><span class="cx">         this._internalWebKitScripts = [];
</span><span class="cx">         this._targetDebuggerDataMap = new Map;
</span><ins>+        this._targetDebuggerDataMap.set(WebInspector.mainTarget, new WebInspector.DebuggerData(WebInspector.mainTarget));
</ins><span class="cx"> 
</span><span class="cx">         // Restore the correct breakpoints enabled setting if Web Inspector had
</span><span class="cx">         // previously been left in a state where breakpoints were temporarily disabled.
</span><span class="lines">@@ -110,7 +112,12 @@
</span><span class="cx"> 
</span><span class="cx">     get paused()
</span><span class="cx">     {
</span><del>-        return this._paused;
</del><ins>+        for (let [target, targetData] of this._targetDebuggerDataMap) {
+            if (targetData.paused)
+                return true;
+        }
+
+        return false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     get activeCallFrame()
</span><span class="lines">@@ -272,7 +279,7 @@
</span><span class="cx"> 
</span><span class="cx">     pause()
</span><span class="cx">     {
</span><del>-        if (this._paused)
</del><ins>+        if (this.paused)
</ins><span class="cx">             return Promise.resolve();
</span><span class="cx"> 
</span><span class="cx">         this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.WaitingToPause);
</span><span class="lines">@@ -283,22 +290,16 @@
</span><span class="cx">             listener.connect(WebInspector.debuggerManager, WebInspector.DebuggerManager.Event.Paused, resolve);
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        // FIXME: &lt;https://webkit.org/b/164305&gt; Web Inspector: Worker debugging should pause all targets and view call frames in all targets
-        // We should pause all targets.
</del><ins>+        let promises = [];
+        for (let [target, targetData] of this._targetDebuggerDataMap)
+            promises.push(targetData.pauseIfNeeded());
</ins><span class="cx"> 
</span><del>-        let protocolResult = DebuggerAgent.pause()
-            .catch(function(error) {
-                listener.disconnect();
-                console.error(&quot;DebuggerManager.pause failed: &quot;, error);
-                throw error;
-            });
-
-        return Promise.all([managerResult, protocolResult]);
</del><ins>+        return Promise.all([managerResult, ...promises]);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     resume()
</span><span class="cx">     {
</span><del>-        if (!this._paused)
</del><ins>+        if (!this.paused)
</ins><span class="cx">             return Promise.resolve();
</span><span class="cx"> 
</span><span class="cx">         let listener = new WebInspector.EventListener(this, true);
</span><span class="lines">@@ -307,22 +308,16 @@
</span><span class="cx">             listener.connect(WebInspector.debuggerManager, WebInspector.DebuggerManager.Event.Resumed, resolve);
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        // FIXME: &lt;https://webkit.org/b/164305&gt; Web Inspector: Worker debugging should pause all targets and view call frames in all targets
-        // We should resume all targets.
</del><ins>+        let promises = [];
+        for (let [target, targetData] of this._targetDebuggerDataMap)
+            promises.push(targetData.resumeIfNeeded());
</ins><span class="cx"> 
</span><del>-        let protocolResult = this._activeCallFrame.target.DebuggerAgent.resume()
-            .catch(function(error) {
-                listener.disconnect();
-                console.error(&quot;DebuggerManager.resume failed: &quot;, error);
-                throw error;
-            });
-
-        return Promise.all([managerResult, protocolResult]);
</del><ins>+        return Promise.all([managerResult, ...promises]);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     stepOver()
</span><span class="cx">     {
</span><del>-        if (!this._paused)
</del><ins>+        if (!this.paused)
</ins><span class="cx">             return Promise.reject(new Error(&quot;Cannot step over because debugger is not paused.&quot;));
</span><span class="cx"> 
</span><span class="cx">         let listener = new WebInspector.EventListener(this, true);
</span><span class="lines">@@ -343,7 +338,7 @@
</span><span class="cx"> 
</span><span class="cx">     stepInto()
</span><span class="cx">     {
</span><del>-        if (!this._paused)
</del><ins>+        if (!this.paused)
</ins><span class="cx">             return Promise.reject(new Error(&quot;Cannot step into because debugger is not paused.&quot;));
</span><span class="cx"> 
</span><span class="cx">         let listener = new WebInspector.EventListener(this, true);
</span><span class="lines">@@ -364,7 +359,7 @@
</span><span class="cx"> 
</span><span class="cx">     stepOut()
</span><span class="cx">     {
</span><del>-        if (!this._paused)
</del><ins>+        if (!this.paused)
</ins><span class="cx">             return Promise.reject(new Error(&quot;Cannot step out because debugger is not paused.&quot;));
</span><span class="cx"> 
</span><span class="cx">         let listener = new WebInspector.EventListener(this, true);
</span><span class="lines">@@ -383,6 +378,11 @@
</span><span class="cx">         return Promise.all([managerResult, protocolResult]);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    continueUntilNextRunLoop(target)
+    {
+        return this.dataForTarget(target).continueUntilNextRunLoop();
+    }
+
</ins><span class="cx">     continueToLocation(script, lineNumber, columnNumber)
</span><span class="cx">     {
</span><span class="cx">         return script.target.DebuggerAgent.continueToLocation({scriptId: script.id, lineNumber, columnNumber});
</span><span class="lines">@@ -477,6 +477,7 @@
</span><span class="cx">     initializeTarget(target)
</span><span class="cx">     {
</span><span class="cx">         let DebuggerAgent = target.DebuggerAgent;
</span><ins>+        let targetData = this.dataForTarget(target);
</ins><span class="cx"> 
</span><span class="cx">         // Initialize global state.
</span><span class="cx">         DebuggerAgent.enable();
</span><span class="lines">@@ -484,8 +485,8 @@
</span><span class="cx">         DebuggerAgent.setPauseOnAssertions(this._assertionsBreakpointEnabledSetting.value);
</span><span class="cx">         DebuggerAgent.setPauseOnExceptions(this._breakOnExceptionsState);
</span><span class="cx"> 
</span><del>-        // FIXME: &lt;https://webkit.org/b/164305&gt; Web Inspector: Worker debugging should pause all targets and view call frames in all targets
-        // Pause this Target if we are currently paused.
</del><ins>+        if (this.paused)
+            targetData.pauseIfNeeded();
</ins><span class="cx"> 
</span><span class="cx">         // Initialize breakpoints.
</span><span class="cx">         this._restoringBreakpoints = true;
</span><span class="lines">@@ -524,12 +525,10 @@
</span><span class="cx">     {
</span><span class="cx">         // Called from WebInspector.DebuggerObserver.
</span><span class="cx"> 
</span><del>-        let wasPaused = this._paused;
</del><ins>+        let wasPaused = this.paused;
</ins><span class="cx"> 
</span><span class="cx">         WebInspector.Script.resetUniqueDisplayNameNumbers();
</span><span class="cx"> 
</span><del>-        this._paused = false;
-
</del><span class="cx">         this._internalWebKitScripts = [];
</span><span class="cx">         this._targetDebuggerDataMap.clear();
</span><span class="cx"> 
</span><span class="lines">@@ -560,10 +559,9 @@
</span><span class="cx">             this._delayedResumeTimeout = undefined;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        let wasPaused = this._paused;
</del><ins>+        let wasPaused = this.paused;
+        let targetData = this._targetDebuggerDataMap.get(target);
</ins><span class="cx"> 
</span><del>-        this._paused = true;
-
</del><span class="cx">         let callFrames = [];
</span><span class="cx">         let pauseReason = this._pauseReasonFromPayload(reason);
</span><span class="cx">         let pauseData = data || null;
</span><span class="lines">@@ -589,22 +587,40 @@
</span><span class="cx">         let activeCallFrame = callFrames[0];
</span><span class="cx"> 
</span><span class="cx">         if (!activeCallFrame) {
</span><del>-            // This indicates we were pausing in internal scripts only (Injected Scripts, built-ins).
-            // Just resume and skip past this pause.
-            target.DebuggerAgent.resume();
</del><ins>+            // FIXME: This may not be safe for multiple threads/targets.
+            // This indicates we were pausing in internal scripts only (Injected Scripts).
+            // Just resume and skip past this pause. We should be fixing the backend to
+            // not send such pauses.
+            if (wasPaused)
+                target.DebuggerAgent.continueUntilNextRunLoop();
+            else
+                target.DebuggerAgent.resume();
</ins><span class="cx">             this._didResumeInternal(target);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        let targetData = this._targetDebuggerDataMap.get(target);
</del><span class="cx">         targetData.updateForPause(callFrames, pauseReason, pauseData);
</span><span class="cx"> 
</span><del>-        this._activeCallFrame = activeCallFrame;
</del><ins>+        // Pause other targets because at least one target has paused.
+        // FIXME: Should this be done on the backend?
+        for (let [otherTarget, otherTargetData] of this._targetDebuggerDataMap)
+            otherTargetData.pauseIfNeeded();
</ins><span class="cx"> 
</span><ins>+        let activeCallFrameDidChange = this._activeCallFrame &amp;&amp; this._activeCallFrame.target === target;
+        if (activeCallFrameDidChange)
+            this._activeCallFrame = activeCallFrame;
+        else if (!wasPaused) {
+            this._activeCallFrame = activeCallFrame;
+            activeCallFrameDidChange = true;
+        }
+
</ins><span class="cx">         if (!wasPaused)
</span><span class="cx">             this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.Paused);
</span><del>-        this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.CallFramesDidChange);
-        this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange);
</del><ins>+
+        this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.CallFramesDidChange, {target});
+
+        if (activeCallFrameDidChange)
+            this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     debuggerDidResume(target)
</span><span class="lines">@@ -1005,6 +1021,16 @@
</span><span class="cx">         this._stopDisablingBreakpointsTemporarily();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _targetRemoved(event)
+    {
+        let wasPaused = this.paused;
+
+        this._targetDebuggerDataMap.delete(event.data.target);
+
+        if (!this.paused &amp;&amp; wasPaused)
+            this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.Resumed);
+    }
+
</ins><span class="cx">     _mainResourceDidChange(event)
</span><span class="cx">     {
</span><span class="cx">         if (!event.target.isMainFrame())
</span><span class="lines">@@ -1015,7 +1041,7 @@
</span><span class="cx"> 
</span><span class="cx">     _didResumeInternal(target)
</span><span class="cx">     {
</span><del>-        if (!this._paused)
</del><ins>+        if (!this.paused)
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         if (this._delayedResumeTimeout) {
</span><span class="lines">@@ -1023,14 +1049,21 @@
</span><span class="cx">             this._delayedResumeTimeout = undefined;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        this._paused = false;
-        this._activeCallFrame = null;
</del><ins>+        let activeCallFrameDidChange = false;
+        if (this._activeCallFrame &amp;&amp; this._activeCallFrame.target === target) {
+            this._activeCallFrame = null;
+            activeCallFrameDidChange = true;
+        }
</ins><span class="cx"> 
</span><span class="cx">         this.dataForTarget(target).updateForResume();
</span><span class="cx"> 
</span><del>-        this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.Resumed);
-        this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.CallFramesDidChange);
-        this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange);
</del><ins>+        if (!this.paused)
+            this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.Resumed);
+
+        this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.CallFramesDidChange, {target});
+
+        if (activeCallFrameDidChange)
+            this.dispatchEventToListeners(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _updateBreakOnExceptionsState()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesThreadsvg"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/Thread.svg (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Images/Thread.svg                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/Thread.svg        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;!-- Copyright © 2016 Apple Inc. All rights reserved. --&gt;
+&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; id=&quot;root&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot;&gt;
+    &lt;circle fill=&quot;rgb(148, 183, 219)&quot; stroke=&quot;rgb(106, 136, 170)&quot; cx=&quot;8&quot; cy=&quot;8&quot; r=&quot;7.5&quot;/&gt;
+    &lt;line stroke=&quot;rgb(106, 136, 170)&quot; x1=&quot;8&quot; y1=&quot;3&quot; x2=&quot;8&quot; y2=&quot;13&quot; stroke-width=&quot;3.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+    &lt;line stroke=&quot;rgb(106, 136, 170)&quot; x1=&quot;5&quot; y1=&quot;5&quot; x2=&quot;5&quot; y2=&quot;11&quot; stroke-width=&quot;3.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+    &lt;line stroke=&quot;rgb(106, 136, 170)&quot; x1=&quot;11&quot; y1=&quot;5&quot; x2=&quot;11&quot; y2=&quot;11&quot; stroke-width=&quot;3.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+    &lt;line stroke=&quot;white&quot; x1=&quot;8&quot; y1=&quot;3&quot; x2=&quot;8&quot; y2=&quot;13&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+    &lt;line stroke=&quot;white&quot; x1=&quot;5&quot; y1=&quot;5&quot; x2=&quot;5&quot; y2=&quot;11&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+    &lt;line stroke=&quot;white&quot; x1=&quot;11&quot; y1=&quot;5&quot; x2=&quot;11&quot; y2=&quot;11&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesgtkThreadsvg"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/gtk/Thread.svg (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Images/gtk/Thread.svg                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/gtk/Thread.svg        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;!-- Licensed under the Creative Commons Attribution-Share Alike 3.0 United States License (http://creativecommons.org/licenses/by-sa/3.0/) --&gt;
+&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; id=&quot;root&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot;&gt;
+ &lt;defs&gt;
+  &lt;radialGradient id=&quot;a&quot; cx=&quot;24.446&quot; cy=&quot;35.878&quot; r=&quot;20.531&quot; gradientUnits=&quot;userSpaceOnUse&quot; gradientTransform=&quot;matrix(.85696 3.2529e-7 -1.253e-7 .33010 -12.949 .77181)&quot;&gt;
+   &lt;stop stop-color=&quot;#fff&quot; offset=&quot;0&quot;/&gt;
+   &lt;stop stop-color=&quot;#cbdbed&quot; offset=&quot;1&quot;/&gt;
+  &lt;/radialGradient&gt;
+  &lt;linearGradient id=&quot;c&quot; x1=&quot;321.57&quot; x2=&quot;311.65&quot; y1=&quot;145.52&quot; y2=&quot;118.5&quot; gradientUnits=&quot;userSpaceOnUse&quot; gradientTransform=&quot;matrix(.55569 0 0 .55568 -169.27 -70.906)&quot;&gt;
+   &lt;stop stop-color=&quot;#204a87&quot; offset=&quot;0&quot;/&gt;
+   &lt;stop stop-color=&quot;#bdd2e9&quot; offset=&quot;1&quot;/&gt;
+  &lt;/linearGradient&gt;
+ &lt;/defs&gt;
+ &lt;circle fill=&quot;url(#a)&quot; fill-rule=&quot;evenodd&quot; stroke=&quot;url(#c)&quot; stroke-miterlimit=&quot;10&quot; cx=&quot;8&quot; cy=&quot;8&quot; r=&quot;7.5&quot;/&gt;
+ &lt;circle fill=&quot;transparent&quot; fill-rule=&quot;evenodd&quot; stroke=&quot;white&quot; stroke-miterlimit=&quot;10&quot; cx=&quot;8&quot; cy=&quot;8&quot; r=&quot;6.5&quot;/&gt;
+ &lt;line stroke=&quot;url(#c)&quot; x1=&quot;8&quot; y1=&quot;4&quot; x2=&quot;8&quot; y2=&quot;12&quot; stroke-width=&quot;3.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+ &lt;line stroke=&quot;url(#c)&quot; x1=&quot;5&quot; y1=&quot;6&quot; x2=&quot;5&quot; y2=&quot;10&quot; stroke-width=&quot;3.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+ &lt;line stroke=&quot;url(#c)&quot; x1=&quot;11&quot; y1=&quot;6&quot; x2=&quot;11&quot; y2=&quot;10&quot; stroke-width=&quot;3.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+ &lt;line stroke=&quot;white&quot; x1=&quot;8&quot; y1=&quot;4&quot; x2=&quot;8&quot; y2=&quot;12&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+ &lt;line stroke=&quot;white&quot; x1=&quot;5&quot; y1=&quot;6&quot; x2=&quot;5&quot; y2=&quot;10&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+ &lt;line stroke=&quot;white&quot; x1=&quot;11&quot; y1=&quot;6&quot; x2=&quot;11&quot; y2=&quot;10&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot;/&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -97,6 +97,7 @@
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/HeapSnapshotInstancesContentView.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/HierarchicalPathComponent.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/HoverMenu.css&quot;&gt;
</span><ins>+    &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/IdleTreeElement.css&quot;&gt;
</ins><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/ImageResourceContentView.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/IndeterminateProgressSpinner.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/IndexedDatabaseObjectStoreContentView.css&quot;&gt;
</span><span class="lines">@@ -167,6 +168,7 @@
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TextNavigationItem.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TextResourceContentView.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TextToggleButtonNavigationItem.css&quot;&gt;
</span><ins>+    &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/ThreadTreeElement.css&quot;&gt;
</ins><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineDataGrid.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineIcons.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineOverview.css&quot;&gt;
</span><span class="lines">@@ -558,6 +560,7 @@
</span><span class="cx">     &lt;script src=&quot;Views/HeapSnapshotInstanceFetchMoreDataGridNode.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/HierarchicalPathNavigationItem.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/HoverMenu.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Views/IdleTreeElement.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Views/ImageResourceContentView.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/IndeterminateProgressSpinner.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/IndexedDatabaseDetailsSidebarPanel.js&quot;&gt;&lt;/script&gt;
</span><span class="lines">@@ -650,6 +653,7 @@
</span><span class="cx">     &lt;script src=&quot;Views/TextNavigationItem.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TextResourceContentView.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TextToggleButtonNavigationItem.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Views/ThreadTreeElement.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Views/TimelineRecordBar.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TimelineRecordFrame.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TimelineRecordingContentView.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsDebuggerDatajs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DebuggerData.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/DebuggerData.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DebuggerData.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -33,20 +33,26 @@
</span><span class="cx"> 
</span><span class="cx">         this._target = target;
</span><span class="cx"> 
</span><del>-        this._callFrames = [];
</del><ins>+        this._paused = false;
+        this._pausing = false;
</ins><span class="cx">         this._pauseReason = null;
</span><span class="cx">         this._pauseData = null;
</span><ins>+        this._callFrames = [];
</ins><span class="cx"> 
</span><span class="cx">         this._scriptIdMap = new Map;
</span><span class="cx">         this._scriptContentIdentifierMap = new Map;
</span><ins>+
+        this._makePausingAfterNextResume = false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get target() { return this._target; }
</span><del>-    get callFrames() { return this._callFrames; }
</del><ins>+    get paused() { return this._paused; }
+    get pausing() { return this._pausing; }
</ins><span class="cx">     get pauseReason() { return this._pauseReason; }
</span><span class="cx">     get pauseData() { return this._pauseData; }
</span><ins>+    get callFrames() { return this._callFrames; }
</ins><span class="cx"> 
</span><span class="cx">     get scripts()
</span><span class="cx">     {
</span><span class="lines">@@ -84,17 +90,62 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    pauseIfNeeded()
+    {
+        if (this._paused || this._pausing)
+            return Promise.resolve();
+
+        this._pausing = true;
+
+        return this._target.DebuggerAgent.pause();
+    }
+
+    resumeIfNeeded()
+    {
+        if (!this._paused &amp;&amp; !this._pausing)
+            return Promise.resolve();
+
+        this._pausing = false;
+
+        return this._target.DebuggerAgent.resume();
+    }
+
+    continueUntilNextRunLoop()
+    {
+        if (!this._paused || this._pausing)
+            return Promise.resolve();
+
+        // The backend will automatically start pausing
+        // after resuming, so we need to match that here.
+        this._makePausingAfterNextResume = true;
+
+        return this._target.DebuggerAgent.continueUntilNextRunLoop();
+    }
+
</ins><span class="cx">     updateForPause(callFrames, pauseReason, pauseData)
</span><span class="cx">     {
</span><del>-        this._callFrames = callFrames;
</del><ins>+        this._paused = true;
+        this._pausing = false;
</ins><span class="cx">         this._pauseReason = pauseReason;
</span><span class="cx">         this._pauseData = pauseData;
</span><ins>+        this._callFrames = callFrames;
+
+        // We paused, no need for auto-pausing.
+        this._makePausingAfterNextResume = false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     updateForResume()
</span><span class="cx">     {
</span><del>-        this._callFrames = [];
</del><ins>+        this._paused = false;
+        this._pausing = false;
</ins><span class="cx">         this._pauseReason = null;
</span><span class="cx">         this._pauseData = null;
</span><ins>+        this._callFrames = [];
+
+        // We resumed, but may be auto-pausing.
+        if (this._makePausingAfterNextResume) {
+            this._makePausingAfterNextResume = false;
+            this._pausing = true;
+        }
</ins><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceProtocolTargetjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/Target.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Protocol/Target.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/Target.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(connection)
</span><span class="cx">     {
</span><del>-        super(&quot;&quot;, &quot;&quot;, WebInspector.Target.Type.Main, InspectorBackend.mainConnection);
</del><ins>+        super(&quot;main&quot;, &quot;&quot;, WebInspector.Target.Type.Main, InspectorBackend.mainConnection);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Protected (Target)
</span><span class="lines">@@ -106,9 +106,15 @@
</span><span class="cx"> 
</span><span class="cx">     get displayName()
</span><span class="cx">     {
</span><del>-        if (WebInspector.debuggableType === WebInspector.DebuggableType.Web)
-            return WebInspector.UIString(&quot;Main Frame&quot;);
-        return WebInspector.UIString(&quot;Main Context&quot;);
</del><ins>+        switch (WebInspector.debuggableType) {
+        case WebInspector.DebuggableType.Web:
+            return WebInspector.UIString(&quot;Page&quot;);
+        case WebInspector.DebuggableType.JavaScript:
+            return WebInspector.UIString(&quot;JavaScript Context&quot;);
+        default:
+            console.error(&quot;Unexpected debuggable type: &quot;, WebInspector.debuggableType);
+            return WebInspector.UIString(&quot;Main&quot;);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     get mainResource()
</span><span class="lines">@@ -119,7 +125,8 @@
</span><span class="cx"> 
</span><span class="cx">     initialize()
</span><span class="cx">     {
</span><del>-        this._executionContext = new WebInspector.ExecutionContext(this, WebInspector.RuntimeManager.TopLevelContextExecutionIdentifier, this.displayName, true, null);
</del><ins>+        let displayName = WebInspector.debuggableType === WebInspector.DebuggableType.Web ? WebInspector.UIString(&quot;Main Frame&quot;) : this.displayName;
+        this._executionContext = new WebInspector.ExecutionContext(this, WebInspector.RuntimeManager.TopLevelContextExecutionIdentifier, displayName, true, null);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestTestjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Test/Test.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test/Test.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/Test.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     WebInspector.mainTarget = new WebInspector.MainTarget;
</span><span class="cx"> 
</span><span class="cx">     // Instantiate controllers used by tests.
</span><ins>+    this.targetManager = new WebInspector.TargetManager;
</ins><span class="cx">     this.frameResourceManager = new WebInspector.FrameResourceManager;
</span><span class="cx">     this.storageManager = new WebInspector.StorageManager;
</span><span class="cx">     this.domTreeManager = new WebInspector.DOMTreeManager;
</span><span class="lines">@@ -65,7 +66,6 @@
</span><span class="cx">     this.timelineManager = new WebInspector.TimelineManager;
</span><span class="cx">     this.debuggerManager = new WebInspector.DebuggerManager;
</span><span class="cx">     this.probeManager = new WebInspector.ProbeManager;
</span><del>-    this.targetManager = new WebInspector.TargetManager;
</del><span class="cx">     this.workerManager = new WebInspector.WorkerManager;
</span><span class="cx">     this.replayManager = new WebInspector.ReplayManager;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDebuggerSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -36,7 +36,6 @@
</span><span class="cx">         WebInspector.Target.addEventListener(WebInspector.Target.Event.ResourceAdded, this._resourceAdded, this);
</span><span class="cx"> 
</span><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
</span><del>-        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, this._debuggerCallFramesDidChange, this);
</del><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
</span><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
</span><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptAdded, this._scriptAdded, this);
</span><span class="lines">@@ -44,6 +43,7 @@
</span><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptsCleared, this._scriptsCleared, this);
</span><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Paused, this._debuggerDidPause, this);
</span><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, this._debuggerDidResume, this);
</span><ins>+        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, this._debuggerCallFramesDidChange, this);
</ins><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._debuggerActiveCallFrameDidChange, this);
</span><span class="cx">         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.WaitingToPause, this._debuggerWaitingToPause, this);
</span><span class="cx"> 
</span><span class="lines">@@ -50,6 +50,9 @@
</span><span class="cx">         WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingWillStart, this._timelineCapturingWillStart, this);
</span><span class="cx">         WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingStopped, this._timelineCapturingStopped, this);
</span><span class="cx"> 
</span><ins>+        WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event.TargetAdded, this._targetAdded, this);
+        WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event.TargetRemoved, this._targetRemoved, this);
+
</ins><span class="cx">         this._timelineRecordingWarningElement = document.createElement(&quot;div&quot;);
</span><span class="cx">         this._timelineRecordingWarningElement.classList.add(&quot;warning-banner&quot;);
</span><span class="cx">         this._timelineRecordingWarningElement.append(WebInspector.UIString(&quot;Debugger is disabled during a Timeline recording.&quot;), &quot; &quot;);
</span><span class="lines">@@ -146,6 +149,8 @@
</span><span class="cx">         let breakpointsSection = new WebInspector.DetailsSection(&quot;breakpoints&quot;, WebInspector.UIString(&quot;Breakpoints&quot;), [breakpointsGroup]);
</span><span class="cx">         this.contentView.element.appendChild(breakpointsSection.element);
</span><span class="cx"> 
</span><ins>+        this._breakpointSectionElement = breakpointsSection.element;
+
</ins><span class="cx">         this._breakpointsContentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
</span><span class="cx">         this._breakpointsContentTreeOutline.ondelete = this._breakpointTreeOutlineDeleteTreeElement.bind(this);
</span><span class="cx">         this._breakpointsContentTreeOutline.oncontextmenu = this._breakpointTreeOutlineContextMenuTreeElement.bind(this);
</span><span class="lines">@@ -167,16 +172,31 @@
</span><span class="cx">         this._scriptsSection = new WebInspector.DetailsSection(&quot;scripts&quot;, WebInspector.UIString(&quot;Sources&quot;), [scriptsGroup]);
</span><span class="cx">         this.contentView.element.appendChild(this._scriptsSection.element);
</span><span class="cx"> 
</span><del>-        this._callStackContentTreeOutline = this.createContentTreeOutline(true, true);
-        this._callStackContentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
-        this._activeCallFrameTreeElement = null;
</del><ins>+        const dontHideByDefault = true;
+        const suppressFiltering = true;
+        this._callStackTreeOutline = this.createContentTreeOutline(dontHideByDefault, suppressFiltering);
+        this._callStackTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
</ins><span class="cx"> 
</span><del>-        this._callStackRow = new WebInspector.DetailsSectionRow(WebInspector.UIString(&quot;No Call Frames&quot;));
-        this._callStackRow.showEmptyMessage();
</del><ins>+        this._singleThreadCallStackTreeOutline = this.createContentTreeOutline(dontHideByDefault, suppressFiltering);
+        this._singleThreadCallStackTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
</ins><span class="cx"> 
</span><del>-        let callStackGroup = new WebInspector.DetailsSectionGroup([this._callStackRow]);
-        this._callStackSection = new WebInspector.DetailsSection(&quot;call-stack&quot;, WebInspector.UIString(&quot;Call Stack&quot;), [callStackGroup]);
</del><ins>+        let mainTargetTreeElement = new WebInspector.ThreadTreeElement(WebInspector.mainTarget);
+        this._callStackTreeOutline.appendChild(mainTargetTreeElement);
</ins><span class="cx"> 
</span><ins>+        this._multipleThreadsCallStackRow = new WebInspector.DetailsSectionRow;
+        this._multipleThreadsCallStackRow.element.appendChild(this._callStackTreeOutline.element);
+
+        this._singleThreadCallStackRow = new WebInspector.DetailsSectionRow;
+        this._singleThreadCallStackRow.element.appendChild(this._singleThreadCallStackTreeOutline.element);
+
+        this._callStackGroup = new WebInspector.DetailsSectionGroup([this._singleThreadCallStackRow]);
+        this._callStackSection = new WebInspector.DetailsSection(&quot;call-stack&quot;, WebInspector.UIString(&quot;Call Stack&quot;), [this._callStackGroup]);
+
+        this._showingSingleThreadCallStack = true;
+
+        this._activeCallFrameTreeElement = null;
+        this._singleThreadActiveCallFrameTreeElement = null;
+
</ins><span class="cx">         this._pauseReasonTreeOutline = null;
</span><span class="cx"> 
</span><span class="cx">         this._pauseReasonLinkContainerElement = document.createElement(&quot;span&quot;);
</span><span class="lines">@@ -321,6 +341,7 @@
</span><span class="cx">     _debuggerDidPause(event)
</span><span class="cx">     {
</span><span class="cx">         this.contentView.element.insertBefore(this._callStackSection.element, this.contentView.element.firstChild);
</span><ins>+
</ins><span class="cx">         if (this._updatePauseReason())
</span><span class="cx">             this.contentView.element.insertBefore(this._pauseReasonSection.element, this.contentView.element.firstChild);
</span><span class="cx"> 
</span><span class="lines">@@ -336,6 +357,7 @@
</span><span class="cx">     _debuggerDidResume(event)
</span><span class="cx">     {
</span><span class="cx">         this._callStackSection.element.remove();
</span><ins>+
</ins><span class="cx">         this._pauseReasonSection.element.remove();
</span><span class="cx"> 
</span><span class="cx">         this._debuggerPauseResumeButtonItem.enabled = true;
</span><span class="lines">@@ -576,6 +598,99 @@
</span><span class="cx">         this._removeDebuggerTreeElement(breakpointTreeElement);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _updateSingleThreadCallStacks()
+    {
+        let targetData = WebInspector.debuggerManager.dataForTarget(WebInspector.mainTarget);
+        let callFrames = targetData.callFrames;
+
+        this._singleThreadCallStackTreeOutline.removeChildren();
+
+        if (!callFrames.length) {
+            this._singleThreadCallStackTreeOutline.appendChild(new WebInspector.IdleTreeElement);
+            return;
+        }
+
+        let activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
+        let activeCallFrameTreeElement = null;
+
+        for (let callFrame of callFrames) {
+            let callFrameTreeElement = new WebInspector.CallFrameTreeElement(callFrame);
+            if (callFrame === activeCallFrame)
+                activeCallFrameTreeElement = callFrameTreeElement;
+            this._singleThreadCallStackTreeOutline.appendChild(callFrameTreeElement);
+        }
+
+        if (activeCallFrameTreeElement) {
+            activeCallFrameTreeElement.isActiveCallFrame = true;
+            if (this._showingSingleThreadCallStack)
+                activeCallFrameTreeElement.select(true, true);
+        }
+    }
+
+    _selectActiveCallFrameTreeElement(treeOutline)
+    {
+        let activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
+        if (activeCallFrame) {
+            let activeCallFrameTreeElement = treeOutline.findTreeElement(activeCallFrame);
+            if (activeCallFrameTreeElement)
+                activeCallFrameTreeElement.select(true, true);
+        }
+    }
+
+    _showSingleThreadCallStacks()
+    {
+        console.assert(!this._showingSingleThreadCallStack);
+        console.assert(WebInspector.targets.size === 1);
+
+        this._showingSingleThreadCallStack = true;
+
+        this._callStackGroup.rows = [this._singleThreadCallStackRow];
+
+        this._selectActiveCallFrameTreeElement(this._singleThreadCallStackTreeOutline);
+    }
+
+    _showMultipleThreadCallStacks()
+    {
+        console.assert(this._showingSingleThreadCallStack);
+        console.assert(WebInspector.targets.size &gt; 1);
+
+        this._showingSingleThreadCallStack = false;
+
+        this._callStackGroup.rows = [this._multipleThreadsCallStackRow];
+
+        this._selectActiveCallFrameTreeElement(this._callStackTreeOutline);
+    }
+
+    _findThreadTreeElementForTarget(target)
+    {
+        for (let child of this._callStackTreeOutline.children) {
+            if (child.target === target)
+                return child;
+        }
+
+        return null;
+    }
+
+    _targetAdded(event)
+    {
+        let target = event.data.target;
+        let treeElement = new WebInspector.ThreadTreeElement(target);
+        this._callStackTreeOutline.appendChild(treeElement);
+
+        if (this._showingSingleThreadCallStack)
+            this._showMultipleThreadCallStacks();
+    }
+
+    _targetRemoved(event)
+    {
+        let target = event.data.target;
+        let treeElement = this._findThreadTreeElementForTarget(target);
+        this._callStackTreeOutline.removeChild(treeElement);
+
+        if (WebInspector.targets.size === 1)
+            this._showSingleThreadCallStacks();
+    }
+
</ins><span class="cx">     _handleDebuggerObjectDisplayLocationDidChange(event)
</span><span class="cx">     {
</span><span class="cx">         var debuggerObject = event.target;
</span><span class="lines">@@ -617,59 +732,37 @@
</span><span class="cx">         parentTreeElement.treeOutline.removeChild(parentTreeElement);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _debuggerCallFramesDidChange()
</del><ins>+    _debuggerCallFramesDidChange(event)
</ins><span class="cx">     {
</span><del>-        this._callStackContentTreeOutline.removeChildren();
-        this._activeCallFrameTreeElement = null;
</del><ins>+        let target = event.data.target;
+        let treeElement = this._findThreadTreeElementForTarget(target);
+        treeElement.refresh();
</ins><span class="cx"> 
</span><del>-        if (!WebInspector.debuggerManager.activeCallFrame) {
-            this._callStackRow.showEmptyMessage();
-            return;
-        }
</del><ins>+        if (target === WebInspector.mainTarget)
+            this._updateSingleThreadCallStacks();
+    }
</ins><span class="cx"> 
</span><del>-        let target = WebInspector.debuggerManager.activeCallFrame.target;
-        let targetData = WebInspector.debuggerManager.dataForTarget(target);
-        let callFrames = targetData.callFrames;
-        if (!callFrames || !callFrames.length) {
-            this._callStackRow.showEmptyMessage();
-            return;
</del><ins>+    _debuggerActiveCallFrameDidChange()
+    {
+        if (this._activeCallFrameTreeElement) {
+            this._activeCallFrameTreeElement.isActiveCallFrame = false;
+            this._activeCallFrameTreeElement = null;
</ins><span class="cx">         }
</span><del>-
-        this._callStackRow.hideEmptyMessage();
-        this._callStackRow.element.appendChild(this._callStackContentTreeOutline.element);
-
-        let activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
-        for (let callFrame of callFrames) {
-            let callFrameTreeElement = new WebInspector.CallFrameTreeElement(callFrame);
-            if (callFrame === activeCallFrame)
-                this._activeCallFrameTreeElement = callFrameTreeElement;
-            this._callStackContentTreeOutline.appendChild(callFrameTreeElement);
</del><ins>+        if (this._singleThreadActiveCallFrameTreeElement) {
+            this._singleThreadActiveCallFrameTreeElement.isActiveCallFrame = false;
+            this._singleThreadActiveCallFrameTreeElement = null;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (this._activeCallFrameTreeElement) {
-            this._activeCallFrameTreeElement.select(true, true);
-            this._activeCallFrameTreeElement.isActiveCallFrame = true;
-        }
-    }
-
-    _debuggerActiveCallFrameDidChange()
-    {
</del><span class="cx">         if (!WebInspector.debuggerManager.activeCallFrame)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        let target = WebInspector.debuggerManager.activeCallFrame.target;
-        let targetData = WebInspector.debuggerManager.dataForTarget(target);
-        let callFrames = targetData.callFrames;
-        if (!callFrames)
-            return;
-
</del><ins>+        this._activeCallFrameTreeElement = this._callStackTreeOutline.findTreeElement(WebInspector.debuggerManager.activeCallFrame);
</ins><span class="cx">         if (this._activeCallFrameTreeElement)
</span><del>-            this._activeCallFrameTreeElement.isActiveCallFrame = false;
</del><ins>+            this._activeCallFrameTreeElement.isActiveCallFrame = true;
</ins><span class="cx"> 
</span><del>-        this._activeCallFrameTreeElement = this._callStackContentTreeOutline.findTreeElement(WebInspector.debuggerManager.activeCallFrame);
-
-        if (this._activeCallFrameTreeElement)
-            this._activeCallFrameTreeElement.isActiveCallFrame = true;
</del><ins>+        this._singleThreadActiveCallFrameTreeElement = this._singleThreadCallStackTreeOutline.findTreeElement(WebInspector.debuggerManager.activeCallFrame);
+        if (this._singleThreadActiveCallFrameTreeElement)
+            this._singleThreadActiveCallFrameTreeElement.isActiveCallFrame = true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _breakpointsBeneathTreeElement(treeElement)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsIdleTreeElementcss"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.css (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.css                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.css        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 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.
+ */
+
+.details-section.call-stack .idle .icon {
+    content: url(../Images/Native.svg);
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsIdleTreeElementjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.js (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/IdleTreeElement.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 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.
+ */
+
+WebInspector.IdleTreeElement = class IdleTreeElement extends WebInspector.GeneralTreeElement
+{
+    constructor(target)
+    {
+        super(&quot;idle&quot;, WebInspector.UIString(&quot;Idle&quot;));
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsLogContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -158,7 +158,8 @@
</span><span class="cx"> 
</span><span class="cx">         // Some results don't populate until further backend dispatches occur (like the DOM tree).
</span><span class="cx">         // We want to remove focusable children after those pending dispatches too.
</span><del>-        InspectorBackend.runAfterPendingDispatches(this._clearFocusableChildren.bind(this));
</del><ins>+        let target = messageView.message ? messageView.message.target : WebInspector.runtimeManager.activeExecutionContext.target;
+        target.connection.runAfterPendingDispatches(this._clearFocusableChildren.bind(this));
</ins><span class="cx"> 
</span><span class="cx">         if (type &amp;&amp; type !== WebInspector.ConsoleMessage.MessageType.EndGroup) {
</span><span class="cx">             console.assert(messageView.message instanceof WebInspector.ConsoleMessage);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNavigationSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js (208724 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js        2016-11-15 02:42:32 UTC (rev 208724)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -707,6 +707,8 @@
</span><span class="cx">             || treeElement instanceof WebInspector.DatabaseHostTreeElement
</span><span class="cx">             || treeElement instanceof WebInspector.IndexedDatabaseHostTreeElement
</span><span class="cx">             || treeElement instanceof WebInspector.ApplicationCacheManifestTreeElement
</span><ins>+            || treeElement instanceof WebInspector.ThreadTreeElement
+            || treeElement instanceof WebInspector.IdleTreeElement
</ins><span class="cx">             || typeof treeElement.representedObject === &quot;string&quot;
</span><span class="cx">             || treeElement.representedObject instanceof String;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsThreadTreeElementcss"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.css (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.css                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.css        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 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.
+ */
+
+.details-section.call-stack .thread .icon {
+    content: url(../Images/Thread.svg);
+    width: 15px;
+    height: 15px;
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsThreadTreeElementjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.js (0 => 208725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.js        2016-11-15 04:02:59 UTC (rev 208725)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 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.
+ */
+
+WebInspector.ThreadTreeElement = class ThreadTreeElement extends WebInspector.GeneralTreeElement
+{
+    constructor(target)
+    {
+        super(&quot;thread&quot;, target.displayName);
+
+        this._target = target;
+
+        this._idleTreeElement = new WebInspector.IdleTreeElement;
+    }
+
+    // Public
+
+    get target() { return this._target; }
+
+    refresh()
+    {
+        this.removeChildren();
+
+        let targetData = WebInspector.debuggerManager.dataForTarget(this._target);
+        let callFrames = targetData.callFrames;
+
+        if (targetData.pausing || !callFrames.length) {
+            this.appendChild(this._idleTreeElement);
+            this.expand();
+            return;
+        }
+
+        let activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
+        let activeCallFrameTreeElement = null;
+
+        for (let callFrame of callFrames) {
+            let callFrameTreeElement = new WebInspector.CallFrameTreeElement(callFrame);
+            if (callFrame === activeCallFrame)
+                activeCallFrameTreeElement = callFrameTreeElement;
+            this.appendChild(callFrameTreeElement);
+        }
+
+        if (activeCallFrameTreeElement) {
+            activeCallFrameTreeElement.select(true, true);
+            activeCallFrameTreeElement.isActiveCallFrame = true;
+        }
+
+        this.expand();
+    }
+
+    // Protected (GeneralTreeElement)
+
+    onattach()
+    {
+        super.onattach();
+
+        this.refresh();
+        this.expand();
+    }
+
+    oncontextmenu(event)
+    {
+        let targetData = WebInspector.debuggerManager.dataForTarget(this._target);
+
+        let contextMenu = WebInspector.ContextMenu.createFromEvent(event);
+        if (DebuggerAgent.continueUntilNextRunLoop) {
+            contextMenu.appendItem(WebInspector.UIString(&quot;Resume Thread&quot;), () =&gt; {
+                WebInspector.debuggerManager.continueUntilNextRunLoop(this._target);
+            }, !targetData.paused);
+        }
+    }
+};
</ins></span></pre>
</div>
</div>

</body>
</html>