Title: [202234] trunk
Revision
202234
Author
[email protected]
Date
2016-06-20 12:12:42 -0700 (Mon, 20 Jun 2016)

Log Message

Web Inspector: console.profile should use the new Sampling Profiler
https://bugs.webkit.org/show_bug.cgi?id=153499
<rdar://problem/24352431>

Reviewed by Timothy Hatcher.

Source/_javascript_Core:

Currently console.profile/profileEnd behave slightly differently
between JSContext and Web inspection. Unifying will be part of:
<https://webkit.org/b/158753> Generalize the concept of Instruments on the backend

Both JSContext and Web inspection keep track of active
profiles started and stopped via console.profile/profileEnd.

JSContext inspection sends its programmatic start/stop
via the ScriptProfiler domain.

Web inspection sends its programmatic start/stop
via the Timeline domain, and also will start/stop backend
list of Instruments.

The functional differences between these is that for JSContext
inspection, console.profile only starts/stops the ScriptProfiler
domain, and does not auto-start other instruments. This isn't really
a problem right now given the instruments available for JSContext
inspection; but it will be nice to unify as we add more instruments.
Also, JSContext inspection won't have "Profile (name)" records in
its Events view, since those are currently generated only by the
Web's Timeline domain.

* inspector/protocol/ScriptProfiler.json:
* inspector/protocol/Timeline.json:
Events to inform the frontend of programmatic start/stop.

* debugger/Debugger.h:
* inspector/agents/InspectorDebuggerAgent.cpp:
(Inspector::InspectorDebuggerAgent::breakpointsActive):
(Inspector::InspectorDebuggerAgent::isPaused):
* inspector/agents/InspectorDebuggerAgent.h:
Expose breakpoints active state, since programmatic recording
will temporarily disabled breakpoints if needed.

* inspector/JSGlobalObjectConsoleClient.cpp:
(Inspector::JSGlobalObjectConsoleClient::JSGlobalObjectConsoleClient):
(Inspector::JSGlobalObjectConsoleClient::profile):
(Inspector::JSGlobalObjectConsoleClient::profileEnd):
(Inspector::JSGlobalObjectConsoleClient::startConsoleProfile):
(Inspector::JSGlobalObjectConsoleClient::stopConsoleProfile):
* inspector/JSGlobalObjectConsoleClient.h:
* inspector/JSGlobalObjectInspectorController.cpp:
(Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
* inspector/agents/InspectorScriptProfilerAgent.cpp:
(Inspector::InspectorScriptProfilerAgent::programmaticCaptureStarted):
(Inspector::InspectorScriptProfilerAgent::programmaticCaptureStopped):
* inspector/agents/InspectorScriptProfilerAgent.h:
JSContext implementation of console.profile/profileEnd.

Source/WebCore:

Test: inspector/timeline/setInstruments-programmatic-capture.html

* inspector/InspectorTimelineAgent.cpp:
(WebCore::InspectorTimelineAgent::startFromConsole):
(WebCore::InspectorTimelineAgent::stopFromConsole):
(WebCore::InspectorTimelineAgent::mainFrameStartedLoading):
(WebCore::InspectorTimelineAgent::startProgrammaticCapture):
(WebCore::InspectorTimelineAgent::stopProgrammaticCapture):
(WebCore::InspectorTimelineAgent::toggleInstruments):
(WebCore::InspectorTimelineAgent::toggleScriptProfilerInstrument):
(WebCore::InspectorTimelineAgent::toggleHeapInstrument):
(WebCore::InspectorTimelineAgent::toggleMemoryInstrument):
(WebCore::InspectorTimelineAgent::toggleTimelineInstrument):
* inspector/InspectorTimelineAgent.h:
Web implementation of console.profile/profileEnd.
Make helpers for startings / stopping instruments.

Source/WebInspectorUI:

* UserInterface/Controllers/TimelineManager.js:
(WebInspector.TimelineManager.prototype.programmaticCaptureStarted):
(WebInspector.TimelineManager.prototype.programmaticCaptureStopped):
(WebInspector.TimelineManager.prototype.scriptProfilerProgrammaticCaptureStarted):
(WebInspector.TimelineManager.prototype.scriptProfilerProgrammaticCaptureStopped):
For programmatic captures, automatically show the Script Timeline, since
that is guarenteed to have been started by the backend. Start capturing
without creating a new recording.

* UserInterface/Models/TimelineRecording.js:
(WebInspector.TimelineRecording.prototype.stop):
(WebInspector.TimelineRecording.prototype.addScriptInstrumentForProgrammaticCapture):
When stopping for programmatic capture we don't need to disable
instruments, the backend would have already done this.

* UserInterface/Protocol/ScriptProfilerObserver.js:
(WebInspector.ScriptProfilerObserver.prototype.programmaticCaptureStarted):
(WebInspector.ScriptProfilerObserver.prototype.programmaticCaptureStopped):
(WebInspector.ScriptProfilerObserver):
* UserInterface/Protocol/TimelineObserver.js:
(WebInspector.TimelineObserver.prototype.programmaticCaptureStarted):
(WebInspector.TimelineObserver.prototype.programmaticCaptureStopped):
(WebInspector.TimelineObserver):
Pass through Web and JSContext programmatic capture events.

LayoutTests:

* inspector/timeline/setInstruments-programmatic-capture-expected.txt: Added.
* inspector/timeline/setInstruments-programmatic-capture.html: Added.
New test that the backend auto-starts instruments during programmatic capture.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (202233 => 202234)


--- trunk/LayoutTests/ChangeLog	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/LayoutTests/ChangeLog	2016-06-20 19:12:42 UTC (rev 202234)
@@ -1,3 +1,15 @@
+2016-06-20  Joseph Pecoraro  <[email protected]>
+
+        Web Inspector: console.profile should use the new Sampling Profiler
+        https://bugs.webkit.org/show_bug.cgi?id=153499
+        <rdar://problem/24352431>
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/timeline/setInstruments-programmatic-capture-expected.txt: Added.
+        * inspector/timeline/setInstruments-programmatic-capture.html: Added.
+        New test that the backend auto-starts instruments during programmatic capture.
+
 2016-06-20  Chris Dumez  <[email protected]>
 
         Unreviewed, rebaseline test now that TouchEvent has a constructor.

Added: trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture-expected.txt (0 => 202234)


--- trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture-expected.txt	2016-06-20 19:12:42 UTC (rev 202234)
@@ -0,0 +1,26 @@
+CONSOLE MESSAGE: line 8: Inside NoInstrumentsProgrammaticCapture profile
+CONSOLE MESSAGE: line 8: Inside MultipleInstrumentsProgrammaticCapture profile
+CONSOLE MESSAGE: line 8: Inside NoInstrumentsProgrammaticCaptureAgain profile
+Tests programmatic capture (console.profile/profileEnd) automatically starts instruments set via Timeline.setInstruments.
+
+
+== Running test suite: Timeline.setInstruments.programmatic-capture
+-- Running test case: NoInstrumentsProgrammaticCapture
+PASS: Should not be an error setting valid instruments.
+PASS: Timeline.programmaticCaptureStarted
+PASS: ScriptProfiler.startTracking
+PASS: Timeline.programmaticCaptureStopped
+
+-- Running test case: MultipleInstrumentsProgrammaticCapture
+PASS: Should not be an error setting valid instruments.
+PASS: Timeline.programmaticCaptureStarted
+PASS: ScriptProfiler.startTracking
+PASS: Heap.trackingStart
+PASS: Timeline.programmaticCaptureStopped
+
+-- Running test case: NoInstrumentsProgrammaticCaptureAgain
+PASS: Should not be an error setting valid instruments.
+PASS: Timeline.programmaticCaptureStarted
+PASS: ScriptProfiler.startTracking
+PASS: Timeline.programmaticCaptureStopped
+

Added: trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture.html (0 => 202234)


--- trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture.html	2016-06-20 19:12:42 UTC (rev 202234)
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+function triggerProgrammaticCapture(message) {
+    console.profile();
+    console.log(`Inside ${message} profile`);
+    console.profileEnd();
+}
+
+function test()
+{
+    let suite = ProtocolTest.createAsyncSuite("Timeline.setInstruments.programmatic-capture");
+
+    let heapExpected = false;
+    let programmaticCaptureStopped = null;
+
+    InspectorProtocol.eventHandler["Timeline.programmaticCaptureStarted"] = () => {
+        ProtocolTest.pass("Timeline.programmaticCaptureStarted");
+    };
+    InspectorProtocol.eventHandler["Timeline.programmaticCaptureStopped"] = () => {
+        ProtocolTest.pass("Timeline.programmaticCaptureStopped");
+        programmaticCaptureStopped();
+    };
+
+    InspectorProtocol.eventHandler["ScriptProfiler.trackingStart"] = () => {
+        ProtocolTest.pass("ScriptProfiler.startTracking");
+    };
+
+    InspectorProtocol.eventHandler["Heap.trackingStart"] = () => {
+        if (heapExpected)
+            ProtocolTest.pass("Heap.trackingStart");
+        else
+            ProtocolTest.fail("Unexpected Heap.trackingStart");
+    };
+
+    suite.addTestCase({
+        name: "NoInstrumentsProgrammaticCapture",
+        test: (resolve, reject) => {
+            heapExpected = false;
+            programmaticCaptureStopped = resolve;
+
+            InspectorProtocol.sendCommand("Timeline.setInstruments", {instruments: []}, (messageObject) => {
+                ProtocolTest.expectThat(!messageObject.error, "Should not be an error setting valid instruments.");
+            });
+            ProtocolTest.evaluateInPage("triggerProgrammaticCapture('NoInstrumentsProgrammaticCapture')");
+        }
+    });
+
+    suite.addTestCase({
+        name: "MultipleInstrumentsProgrammaticCapture",
+        test: (resolve, reject) => {
+            heapExpected = true;
+            programmaticCaptureStopped = resolve;
+
+            InspectorProtocol.sendCommand("Timeline.setInstruments", {instruments: ["ScriptProfiler", "Heap"]}, (messageObject) => {
+                ProtocolTest.expectThat(!messageObject.error, "Should not be an error setting valid instruments.");
+            });
+            ProtocolTest.evaluateInPage("triggerProgrammaticCapture('MultipleInstrumentsProgrammaticCapture')");
+        }
+    });
+
+    suite.addTestCase({
+        name: "NoInstrumentsProgrammaticCaptureAgain",
+        test: (resolve, reject) => {
+            heapExpected = true;
+            programmaticCaptureStopped = resolve;
+
+            InspectorProtocol.sendCommand("Timeline.setInstruments", {instruments: []}, (messageObject) => {
+                ProtocolTest.expectThat(!messageObject.error, "Should not be an error setting valid instruments.");
+            });
+            ProtocolTest.evaluateInPage("triggerProgrammaticCapture('NoInstrumentsProgrammaticCaptureAgain')");
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+<p>Tests programmatic capture (console.profile/profileEnd) automatically starts instruments set via Timeline.setInstruments.</p>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/mac/TestExpectations (202233 => 202234)


--- trunk/LayoutTests/platform/mac/TestExpectations	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2016-06-20 19:12:42 UTC (rev 202234)
@@ -1251,6 +1251,7 @@
 webkit.org/b/156078 inspector/console/heapSnapshot.html [ Pass Timeout ]
 webkit.org/b/158006 inspector/console/console-time.html [ Pass Timeout ]
 webkit.org/b/156634 inspector/formatting/formatting-_javascript_.html [ Pass Timeout ]
+webkit.org/b/158948 inspector/timeline [ Pass Timeout ]
 
 # Colorspaces on CA OpenGL layers not available in Yosemite
 [ Yosemite ] fast/canvas/webgl/match-page-color-space.html [ Skip ]

Modified: trunk/Source/_javascript_Core/ChangeLog (202233 => 202234)


--- trunk/Source/_javascript_Core/ChangeLog	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-06-20 19:12:42 UTC (rev 202234)
@@ -1,3 +1,61 @@
+2016-06-20  Joseph Pecoraro  <[email protected]>
+
+        Web Inspector: console.profile should use the new Sampling Profiler
+        https://bugs.webkit.org/show_bug.cgi?id=153499
+        <rdar://problem/24352431>
+
+        Reviewed by Timothy Hatcher.
+
+        Currently console.profile/profileEnd behave slightly differently
+        between JSContext and Web inspection. Unifying will be part of:
+        <https://webkit.org/b/158753> Generalize the concept of Instruments on the backend
+
+        Both JSContext and Web inspection keep track of active
+        profiles started and stopped via console.profile/profileEnd.
+
+        JSContext inspection sends its programmatic start/stop
+        via the ScriptProfiler domain.
+
+        Web inspection sends its programmatic start/stop
+        via the Timeline domain, and also will start/stop backend
+        list of Instruments.
+
+        The functional differences between these is that for JSContext
+        inspection, console.profile only starts/stops the ScriptProfiler
+        domain, and does not auto-start other instruments. This isn't really
+        a problem right now given the instruments available for JSContext
+        inspection; but it will be nice to unify as we add more instruments.
+        Also, JSContext inspection won't have "Profile (name)" records in
+        its Events view, since those are currently generated only by the
+        Web's Timeline domain.
+
+        * inspector/protocol/ScriptProfiler.json:
+        * inspector/protocol/Timeline.json:
+        Events to inform the frontend of programmatic start/stop.
+
+        * debugger/Debugger.h:
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        (Inspector::InspectorDebuggerAgent::breakpointsActive):
+        (Inspector::InspectorDebuggerAgent::isPaused):
+        * inspector/agents/InspectorDebuggerAgent.h:
+        Expose breakpoints active state, since programmatic recording
+        will temporarily disabled breakpoints if needed.
+
+        * inspector/JSGlobalObjectConsoleClient.cpp:
+        (Inspector::JSGlobalObjectConsoleClient::JSGlobalObjectConsoleClient):
+        (Inspector::JSGlobalObjectConsoleClient::profile):
+        (Inspector::JSGlobalObjectConsoleClient::profileEnd):
+        (Inspector::JSGlobalObjectConsoleClient::startConsoleProfile):
+        (Inspector::JSGlobalObjectConsoleClient::stopConsoleProfile):
+        * inspector/JSGlobalObjectConsoleClient.h:
+        * inspector/JSGlobalObjectInspectorController.cpp:
+        (Inspector::JSGlobalObjectInspectorController::JSGlobalObjectInspectorController):
+        * inspector/agents/InspectorScriptProfilerAgent.cpp:
+        (Inspector::InspectorScriptProfilerAgent::programmaticCaptureStarted):
+        (Inspector::InspectorScriptProfilerAgent::programmaticCaptureStopped):
+        * inspector/agents/InspectorScriptProfilerAgent.h:
+        JSContext implementation of console.profile/profileEnd.
+
 2016-06-19  Saam Barati  <[email protected]>
 
         We should be able to generate more types of ICs inline

Modified: trunk/Source/_javascript_Core/debugger/Debugger.h (202233 => 202234)


--- trunk/Source/_javascript_Core/debugger/Debugger.h	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/debugger/Debugger.h	2016-06-20 19:12:42 UTC (rev 202234)
@@ -78,6 +78,7 @@
     void clearBreakpoints();
     void activateBreakpoints() { setBreakpointsActivated(true); }
     void deactivateBreakpoints() { setBreakpointsActivated(false); }
+    bool breakpointsActive() const { return m_breakpointsActivated; }
 
     enum PauseOnExceptionsState {
         DontPauseOnExceptions,

Modified: trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.cpp (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.cpp	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.cpp	2016-06-20 19:12:42 UTC (rev 202234)
@@ -28,6 +28,8 @@
 
 #include "ConsoleMessage.h"
 #include "InspectorConsoleAgent.h"
+#include "InspectorDebuggerAgent.h"
+#include "InspectorScriptProfilerAgent.h"
 #include "ScriptArguments.h"
 #include "ScriptCallStack.h"
 #include "ScriptCallStackFactory.h"
@@ -52,9 +54,11 @@
     sLogToSystemConsole = shouldLog;
 }
 
-JSGlobalObjectConsoleClient::JSGlobalObjectConsoleClient(InspectorConsoleAgent* consoleAgent)
+JSGlobalObjectConsoleClient::JSGlobalObjectConsoleClient(InspectorConsoleAgent* consoleAgent, InspectorDebuggerAgent* debuggerAgent, InspectorScriptProfilerAgent* scriptProfilerAgent)
     : ConsoleClient()
     , m_consoleAgent(consoleAgent)
+    , m_debuggerAgent(debuggerAgent)
+    , m_scriptProfilerAgent(scriptProfilerAgent)
 {
 }
 
@@ -73,16 +77,73 @@
     m_consoleAgent->count(exec, arguments);
 }
 
-void JSGlobalObjectConsoleClient::profile(JSC::ExecState*, const String&)
+void JSGlobalObjectConsoleClient::profile(JSC::ExecState*, const String& title)
 {
-    // FIXME: support |console.profile| for JSContexts. <https://webkit.org/b/136466>
+    if (!m_consoleAgent->enabled())
+        return;
+
+    // Allow duplicate unnamed profiles. Disallow duplicate named profiles.
+    if (!title.isEmpty()) {
+        for (auto& existingTitle : m_profiles) {
+            if (existingTitle == title) {
+                // FIXME: Send an enum to the frontend for localization?
+                String warning = title.isEmpty() ? ASCIILiteral("Unnamed Profile already exists") : makeString("Profile \"", title, "\" already exists");
+                m_consoleAgent->addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::ConsoleAPI, MessageType::Profile, MessageLevel::Warning, warning));
+                return;
+            }
+        }
+    }
+
+    m_profiles.append(title);
+    startConsoleProfile();
 }
 
-void JSGlobalObjectConsoleClient::profileEnd(JSC::ExecState*, const String&)
+void JSGlobalObjectConsoleClient::profileEnd(JSC::ExecState*, const String& title)
 {
-    // FIXME: support |console.profile| for JSContexts. <https://webkit.org/b/136466>
+    if (!m_consoleAgent->enabled())
+        return;
+
+    // Stop profiles in reverse order. If the title is empty, then stop the last profile.
+    // Otherwise, match the title of the profile to stop.
+    for (ptrdiff_t i = m_profiles.size() - 1; i >= 0; --i) {
+        if (title.isEmpty() || m_profiles[i] == title) {
+            m_profiles.remove(i);
+            if (m_profiles.isEmpty())
+                stopConsoleProfile();
+            return;
+        }
+    }
+
+    // FIXME: Send an enum to the frontend for localization?
+    String warning = title.isEmpty() ? ASCIILiteral("No profiles exist") : makeString("Profile \"", title, "\" does not exist");
+    m_consoleAgent->addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::ConsoleAPI, MessageType::ProfileEnd, MessageLevel::Warning, warning));
 }
 
+void JSGlobalObjectConsoleClient::startConsoleProfile()
+{
+    // FIXME: <https://webkit.org/b/158753> Generalize the concept of Instruments on the backend to work equally for JSContext and Web inspection
+    m_scriptProfilerAgent->programmaticCaptureStarted();
+
+    m_profileRestoreBreakpointActiveValue = m_debuggerAgent->breakpointsActive();
+
+    ErrorString unused;
+    m_debuggerAgent->setBreakpointsActive(unused, false);
+
+    const bool includeSamples = true;
+    m_scriptProfilerAgent->startTracking(unused, &includeSamples);
+}
+
+void JSGlobalObjectConsoleClient::stopConsoleProfile()
+{
+    ErrorString unused;
+    m_scriptProfilerAgent->stopTracking(unused);
+
+    m_debuggerAgent->setBreakpointsActive(unused, m_profileRestoreBreakpointActiveValue);
+
+    // FIXME: <https://webkit.org/b/158753> Generalize the concept of Instruments on the backend to work equally for JSContext and Web inspection
+    m_scriptProfilerAgent->programmaticCaptureStopped();
+}
+
 void JSGlobalObjectConsoleClient::takeHeapSnapshot(JSC::ExecState*, const String& title)
 {
     m_consoleAgent->takeHeapSnapshot(title);

Modified: trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.h (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.h	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.h	2016-06-20 19:12:42 UTC (rev 202234)
@@ -23,19 +23,22 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef JSGlobalObjectConsoleClient_h
-#define JSGlobalObjectConsoleClient_h
+#pragma once
 
 #include "ConsoleClient.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
 
 namespace Inspector {
 
 class InspectorConsoleAgent;
+class InspectorDebuggerAgent;
+class InspectorScriptProfilerAgent;
 
 class JSGlobalObjectConsoleClient final : public JSC::ConsoleClient {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit JSGlobalObjectConsoleClient(InspectorConsoleAgent*);
+    explicit JSGlobalObjectConsoleClient(InspectorConsoleAgent*, InspectorDebuggerAgent*, InspectorScriptProfilerAgent*);
     virtual ~JSGlobalObjectConsoleClient() { }
 
     static bool logToSystemConsole();
@@ -55,9 +58,14 @@
     void warnUnimplemented(const String& method);
     void internalAddMessage(MessageType, MessageLevel, JSC::ExecState*, RefPtr<ScriptArguments>&&);
 
+    void startConsoleProfile();
+    void stopConsoleProfile();
+
     InspectorConsoleAgent* m_consoleAgent;
+    InspectorDebuggerAgent* m_debuggerAgent;
+    InspectorScriptProfilerAgent* m_scriptProfilerAgent;
+    Vector<String> m_profiles;
+    bool m_profileRestoreBreakpointActiveValue { false };
 };
 
 }
-
-#endif // !defined(JSGlobalObjectConsoleClient_h)

Modified: trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp	2016-06-20 19:12:42 UTC (rev 202234)
@@ -88,11 +88,12 @@
     auto heapAgent = std::make_unique<InspectorHeapAgent>(context);
     auto consoleAgent = std::make_unique<JSGlobalObjectConsoleAgent>(context, heapAgent.get());
     auto debuggerAgent = std::make_unique<JSGlobalObjectDebuggerAgent>(context, consoleAgent.get());
+    auto scriptProfilerAgent = std::make_unique<InspectorScriptProfilerAgent>(context);
 
     m_inspectorAgent = inspectorAgent.get();
     m_debuggerAgent = debuggerAgent.get();
     m_consoleAgent = consoleAgent.get();
-    m_consoleClient = std::make_unique<JSGlobalObjectConsoleClient>(m_consoleAgent);
+    m_consoleClient = std::make_unique<JSGlobalObjectConsoleClient>(m_consoleAgent, m_debuggerAgent, scriptProfilerAgent.get());
 
     m_agents.append(WTFMove(inspectorAgent));
     m_agents.append(WTFMove(runtimeAgent));
@@ -99,7 +100,7 @@
     m_agents.append(WTFMove(consoleAgent));
     m_agents.append(WTFMove(debuggerAgent));
     m_agents.append(WTFMove(heapAgent));
-    m_agents.append(std::make_unique<InspectorScriptProfilerAgent>(context));
+    m_agents.append(WTFMove(scriptProfilerAgent));
 
     m_executionStopwatch->start();
 }

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2016-06-20 19:12:42 UTC (rev 202234)
@@ -125,6 +125,11 @@
     disable(false);
 }
 
+bool InspectorDebuggerAgent::breakpointsActive() const
+{
+    return m_scriptDebugServer.breakpointsActive();
+}
+
 void InspectorDebuggerAgent::setBreakpointsActive(ErrorString&, bool active)
 {
     if (active)
@@ -133,7 +138,7 @@
         m_scriptDebugServer.deactivateBreakpoints();
 }
 
-bool InspectorDebuggerAgent::isPaused()
+bool InspectorDebuggerAgent::isPaused() const
 {
     return m_scriptDebugServer.isPaused();
 }

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h	2016-06-20 19:12:42 UTC (rev 202234)
@@ -83,7 +83,8 @@
     void evaluateOnCallFrame(ErrorString&, const String& callFrameId, const String& _expression_, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Inspector::Protocol::OptOutput<bool>* wasThrown, Inspector::Protocol::OptOutput<int>* savedResultIndex) final;
     void setOverlayMessage(ErrorString&, const String*) override;
 
-    bool isPaused();
+    bool isPaused() const;
+    bool breakpointsActive() const;
 
     void setSuppressAllPauses(bool);
 

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.cpp (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.cpp	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.cpp	2016-06-20 19:12:42 UTC (rev 202234)
@@ -216,4 +216,14 @@
 #endif // ENABLE(SAMPLING_PROFILER)
 }
 
+void InspectorScriptProfilerAgent::programmaticCaptureStarted()
+{
+    m_frontendDispatcher->programmaticCaptureStarted();
+}
+
+void InspectorScriptProfilerAgent::programmaticCaptureStopped()
+{
+    m_frontendDispatcher->programmaticCaptureStopped();
+}
+
 } // namespace Inspector

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.h (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.h	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.h	2016-06-20 19:12:42 UTC (rev 202234)
@@ -53,6 +53,9 @@
     void startTracking(ErrorString&, const bool* includeSamples) override;
     void stopTracking(ErrorString&) override;
 
+    void programmaticCaptureStarted();
+    void programmaticCaptureStopped();
+
     // Debugger::ProfilingClient
     bool isAlreadyProfiling() const override;
     double willEvaluateScript() override;

Modified: trunk/Source/_javascript_Core/inspector/protocol/ScriptProfiler.json (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/protocol/ScriptProfiler.json	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/protocol/ScriptProfiler.json	2016-06-20 19:12:42 UTC (rev 202234)
@@ -86,6 +86,14 @@
             "parameters": [
                 { "name": "samples", "$ref": "Samples", "optional": true, "description": "Stack traces." }
             ]
+        },
+        {
+            "name": "programmaticCaptureStarted",
+            "description": "Fired when programmatic capture starts (console.profile). JSContext inspection only."
+        },
+        {
+            "name": "programmaticCaptureStopped",
+            "description": "Fired when programmatic capture stops (console.profileEnd). JSContext inspection only."
         }
     ]
 }

Modified: trunk/Source/_javascript_Core/inspector/protocol/Timeline.json (202233 => 202234)


--- trunk/Source/_javascript_Core/inspector/protocol/Timeline.json	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/_javascript_Core/inspector/protocol/Timeline.json	2016-06-20 19:12:42 UTC (rev 202234)
@@ -105,6 +105,14 @@
         {
             "name": "autoCaptureStarted",
             "description": "Fired when auto capture started."
+        },
+        {
+            "name": "programmaticCaptureStarted",
+            "description": "Fired when programmatic capture starts (console.profile)."
+        },
+        {
+            "name": "programmaticCaptureStopped",
+            "description": "Fired when programmatic capture stops (console.profileEnd)."
         }
     ]
 }

Modified: trunk/Source/WebCore/ChangeLog (202233 => 202234)


--- trunk/Source/WebCore/ChangeLog	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebCore/ChangeLog	2016-06-20 19:12:42 UTC (rev 202234)
@@ -1,3 +1,28 @@
+2016-06-20  Joseph Pecoraro  <[email protected]>
+
+        Web Inspector: console.profile should use the new Sampling Profiler
+        https://bugs.webkit.org/show_bug.cgi?id=153499
+        <rdar://problem/24352431>
+
+        Reviewed by Timothy Hatcher.
+
+        Test: inspector/timeline/setInstruments-programmatic-capture.html
+
+        * inspector/InspectorTimelineAgent.cpp:
+        (WebCore::InspectorTimelineAgent::startFromConsole):
+        (WebCore::InspectorTimelineAgent::stopFromConsole):
+        (WebCore::InspectorTimelineAgent::mainFrameStartedLoading):
+        (WebCore::InspectorTimelineAgent::startProgrammaticCapture):
+        (WebCore::InspectorTimelineAgent::stopProgrammaticCapture):
+        (WebCore::InspectorTimelineAgent::toggleInstruments):
+        (WebCore::InspectorTimelineAgent::toggleScriptProfilerInstrument):
+        (WebCore::InspectorTimelineAgent::toggleHeapInstrument):
+        (WebCore::InspectorTimelineAgent::toggleMemoryInstrument):
+        (WebCore::InspectorTimelineAgent::toggleTimelineInstrument):
+        * inspector/InspectorTimelineAgent.h:
+        Web implementation of console.profile/profileEnd.
+        Make helpers for startings / stopping instruments.
+
 2016-06-20  Andreas Kling  <[email protected]>
 
         When navigating, discard decoded image data that is only live due to page cache.

Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp (202233 => 202234)


--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp	2016-06-20 19:12:42 UTC (rev 202234)
@@ -43,6 +43,8 @@
 #include "RenderView.h"
 #include "ScriptState.h"
 #include "TimelineRecordFactory.h"
+#include "WebConsoleAgent.h"
+#include <inspector/ConsoleMessage.h>
 #include <inspector/ScriptBreakpoint.h>
 #include <inspector/agents/InspectorDebuggerAgent.h>
 #include <inspector/agents/InspectorHeapAgent.h>
@@ -241,14 +243,55 @@
     return m_environment.executionStopwatch()->elapsedTime();
 }
 
-void InspectorTimelineAgent::startFromConsole(JSC::ExecState*, const String&)
+void InspectorTimelineAgent::startFromConsole(JSC::ExecState* exec, const String& title)
 {
-    // FIXME: <https://webkit.org/b/153499> Web Inspector: console.profile should use the new Sampling Profiler
+    // Allow duplicate unnamed profiles. Disallow duplicate named profiles.
+    if (!title.isEmpty()) {
+        for (const TimelineRecordEntry& record : m_pendingConsoleProfileRecords) {
+            String recordTitle;
+            record.data->getString(ASCIILiteral("title"), recordTitle);
+            if (recordTitle == title) {
+                if (WebConsoleAgent* consoleAgent = m_instrumentingAgents.webConsoleAgent()) {
+                    // FIXME: Send an enum to the frontend for localization?
+                    String warning = title.isEmpty() ? ASCIILiteral("Unnamed Profile already exists") : makeString("Profile \"", title, "\" already exists");
+                    consoleAgent->addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::ConsoleAPI, MessageType::Profile, MessageLevel::Warning, warning));
+                }
+                return;
+            }
+        }
+    }
+
+    if (!m_enabled && m_pendingConsoleProfileRecords.isEmpty())
+        startProgrammaticCapture();
+
+    m_pendingConsoleProfileRecords.append(createRecordEntry(TimelineRecordFactory::createConsoleProfileData(title), TimelineRecordType::ConsoleProfile, true, frameFromExecState(exec)));
 }
 
-void InspectorTimelineAgent::stopFromConsole(JSC::ExecState*, const String&)
+void InspectorTimelineAgent::stopFromConsole(JSC::ExecState*, const String& title)
 {
-    // FIXME: <https://webkit.org/b/153499> Web Inspector: console.profile should use the new Sampling Profiler
+    // Stop profiles in reverse order. If the title is empty, then stop the last profile.
+    // Otherwise, match the title of the profile to stop.
+    for (int i = m_pendingConsoleProfileRecords.size() - 1; i >= 0; --i) {
+        const TimelineRecordEntry& record = m_pendingConsoleProfileRecords[i];
+
+        String recordTitle;
+        record.data->getString(ASCIILiteral("title"), recordTitle);
+        if (title.isEmpty() || recordTitle == title) {
+            didCompleteRecordEntry(record);
+            m_pendingConsoleProfileRecords.remove(i);
+
+            if (!m_enabledFromFrontend && m_pendingConsoleProfileRecords.isEmpty())
+                stopProgrammaticCapture();
+
+            return;
+        }
+    }
+
+    if (WebConsoleAgent* consoleAgent = m_instrumentingAgents.webConsoleAgent()) {
+        // FIXME: Send an enum to the frontend for localization?
+        String warning = title.isEmpty() ? ASCIILiteral("No profiles exist") : makeString("Profile \"", title, "\" does not exist");
+        consoleAgent->addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::ConsoleAPI, MessageType::ProfileEnd, MessageLevel::Warning, warning));    
+    }
 }
 
 void InspectorTimelineAgent::willCallFunction(const String& scriptName, int scriptLine, Frame* frame)
@@ -405,40 +448,119 @@
     // Inform the frontend we started an auto capture. The frontend must stop capture.
     m_frontendDispatcher->autoCaptureStarted();
 
-    // Enable instruments.
+    toggleInstruments(InstrumentState::Start);
+}
+
+void InspectorTimelineAgent::startProgrammaticCapture()
+{
+    ASSERT(!m_enabled);
+
+    // Disable breakpoints during programmatic capture.
+    if (InspectorDebuggerAgent* debuggerAgent = m_instrumentingAgents.inspectorDebuggerAgent()) {
+        m_programmaticCaptureRestoreBreakpointActiveValue = debuggerAgent->breakpointsActive();
+        if (m_programmaticCaptureRestoreBreakpointActiveValue) {
+            ErrorString unused;
+            debuggerAgent->setBreakpointsActive(unused, false);
+        }
+    } else
+        m_programmaticCaptureRestoreBreakpointActiveValue = false;
+
+    m_frontendDispatcher->programmaticCaptureStarted();
+
+    toggleScriptProfilerInstrument(InstrumentState::Start); // Ensure _javascript_ samping data.
+    toggleTimelineInstrument(InstrumentState::Start); // Ensure Console Profile event records.
+    toggleInstruments(InstrumentState::Start); // Any other instruments the frontend wants us to record.
+}
+
+void InspectorTimelineAgent::stopProgrammaticCapture()
+{
+    ASSERT(m_enabled);
+    ASSERT(!m_enabledFromFrontend);
+
+    toggleInstruments(InstrumentState::Stop);
+    toggleTimelineInstrument(InstrumentState::Stop);
+    toggleScriptProfilerInstrument(InstrumentState::Stop);
+
+    // Re-enable breakpoints if they were enabled.
+    if (m_programmaticCaptureRestoreBreakpointActiveValue) {
+        if (InspectorDebuggerAgent* debuggerAgent = m_instrumentingAgents.inspectorDebuggerAgent()) {
+            ErrorString unused;
+            debuggerAgent->setBreakpointsActive(unused, true);
+        }
+    }
+
+    m_frontendDispatcher->programmaticCaptureStopped();
+}
+
+void InspectorTimelineAgent::toggleInstruments(InstrumentState state)
+{
     for (auto instrumentType : m_instruments) {
         switch (instrumentType) {
         case Inspector::Protocol::Timeline::Instrument::ScriptProfiler: {
-            if (m_scriptProfilerAgent) {
-                ErrorString unused;
-                const bool includeSamples = true;
-                m_scriptProfilerAgent->startTracking(unused, &includeSamples);
-            }
+            toggleScriptProfilerInstrument(state);
             break;
         }
         case Inspector::Protocol::Timeline::Instrument::Heap: {
-            if (m_heapAgent) {
-                ErrorString unused;
-                m_heapAgent->startTracking(unused);
-            }
+            toggleHeapInstrument(state);
             break;
         }
         case Inspector::Protocol::Timeline::Instrument::Memory: {
-#if ENABLE(RESOURCE_USAGE)
-            if (InspectorMemoryAgent* memoryAgent = m_instrumentingAgents.inspectorMemoryAgent()) {
-                ErrorString unused;
-                memoryAgent->startTracking(unused);
-            }
-#endif
+            toggleMemoryInstrument(state);
             break;
         }
         case Inspector::Protocol::Timeline::Instrument::Timeline:
-            internalStart();
+            toggleTimelineInstrument(state);
             break;
         }
     }
 }
 
+void InspectorTimelineAgent::toggleScriptProfilerInstrument(InstrumentState state)
+{
+    if (m_scriptProfilerAgent) {
+        ErrorString unused;
+        if (state == InstrumentState::Start) {
+            const bool includeSamples = true;
+            m_scriptProfilerAgent->startTracking(unused, &includeSamples);
+        } else
+            m_scriptProfilerAgent->stopTracking(unused);
+    }
+}
+
+void InspectorTimelineAgent::toggleHeapInstrument(InstrumentState state)
+{
+    if (m_heapAgent) {
+        ErrorString unused;
+        if (state == InstrumentState::Start)
+            m_heapAgent->startTracking(unused);
+        else
+            m_heapAgent->stopTracking(unused);
+    }
+}
+
+void InspectorTimelineAgent::toggleMemoryInstrument(InstrumentState state)
+{
+#if ENABLE(RESOURCE_USAGE)
+    if (InspectorMemoryAgent* memoryAgent = m_instrumentingAgents.inspectorMemoryAgent()) {
+        ErrorString unused;
+        if (state == InstrumentState::Start)
+            memoryAgent->startTracking(unused);
+        else
+            memoryAgent->stopTracking(unused);
+    }
+#else
+    UNUSED_PARAM(state);
+#endif
+}
+
+void InspectorTimelineAgent::toggleTimelineInstrument(InstrumentState state)
+{
+    if (state == InstrumentState::Start)
+        internalStart();
+    else
+        internalStop();
+}
+
 void InspectorTimelineAgent::didCommitLoad()
 {
     clearRecordStack();

Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.h (202233 => 202234)


--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2016-06-20 19:12:42 UTC (rev 202234)
@@ -153,6 +153,18 @@
     void breakpointActionSound(int) final { }
     void breakpointActionProbe(JSC::ExecState&, const Inspector::ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, JSC::JSValue result) final;
 
+    void startProgrammaticCapture();
+    void stopProgrammaticCapture();
+
+    enum class InstrumentState { Start, Stop };
+    void toggleInstruments(InstrumentState);
+    void toggleScriptProfilerInstrument(InstrumentState);
+    void toggleHeapInstrument(InstrumentState);
+    void toggleMemoryInstrument(InstrumentState);
+    void toggleTimelineInstrument(InstrumentState);
+    void disableBreakpoints();
+    void enableBreakpoints();
+
     friend class TimelineRecordStack;
 
     struct TimelineRecordEntry {
@@ -200,6 +212,7 @@
     InspectorPageAgent* m_pageAgent;
 
     Vector<TimelineRecordEntry> m_recordStack;
+    Vector<TimelineRecordEntry> m_pendingConsoleProfileRecords;
 
     int m_id { 1 };
     int m_maxCallStackDepth { 5 };
@@ -206,6 +219,7 @@
 
     bool m_enabled { false };
     bool m_enabledFromFrontend { false };
+    bool m_programmaticCaptureRestoreBreakpointActiveValue { false };
 
     bool m_autoCaptureEnabled { false };
     Vector<Inspector::Protocol::Timeline::Instrument> m_instruments;

Modified: trunk/Source/WebInspectorUI/ChangeLog (202233 => 202234)


--- trunk/Source/WebInspectorUI/ChangeLog	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebInspectorUI/ChangeLog	2016-06-20 19:12:42 UTC (rev 202234)
@@ -1,3 +1,36 @@
+2016-06-20  Joseph Pecoraro  <[email protected]>
+
+        Web Inspector: console.profile should use the new Sampling Profiler
+        https://bugs.webkit.org/show_bug.cgi?id=153499
+        <rdar://problem/24352431>
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Controllers/TimelineManager.js:
+        (WebInspector.TimelineManager.prototype.programmaticCaptureStarted):
+        (WebInspector.TimelineManager.prototype.programmaticCaptureStopped):
+        (WebInspector.TimelineManager.prototype.scriptProfilerProgrammaticCaptureStarted):
+        (WebInspector.TimelineManager.prototype.scriptProfilerProgrammaticCaptureStopped):
+        For programmatic captures, automatically show the Script Timeline, since
+        that is guarenteed to have been started by the backend. Start capturing
+        without creating a new recording.
+
+        * UserInterface/Models/TimelineRecording.js:
+        (WebInspector.TimelineRecording.prototype.stop):
+        (WebInspector.TimelineRecording.prototype.addScriptInstrumentForProgrammaticCapture):
+        When stopping for programmatic capture we don't need to disable
+        instruments, the backend would have already done this.
+
+        * UserInterface/Protocol/ScriptProfilerObserver.js:
+        (WebInspector.ScriptProfilerObserver.prototype.programmaticCaptureStarted):
+        (WebInspector.ScriptProfilerObserver.prototype.programmaticCaptureStopped):
+        (WebInspector.ScriptProfilerObserver):
+        * UserInterface/Protocol/TimelineObserver.js:
+        (WebInspector.TimelineObserver.prototype.programmaticCaptureStarted):
+        (WebInspector.TimelineObserver.prototype.programmaticCaptureStopped):
+        (WebInspector.TimelineObserver):
+        Pass through Web and JSContext programmatic capture events.
+
 2016-06-19  Nikita Vasilyev  <[email protected]>
 
         Web Inspector: Remove Sidebar z-index:0 workaround for scrollbars and position:sticky section headers

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js (202233 => 202234)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js	2016-06-20 19:12:42 UTC (rev 202234)
@@ -262,7 +262,7 @@
         this.dispatchEventToListeners(WebInspector.TimelineManager.Event.CapturingStopped, {endTime});
     }
 
-    autoCaptureStarted(startTime)
+    autoCaptureStarted()
     {
         // Called from WebInspector.TimelineObserver.
 
@@ -272,12 +272,36 @@
         // We may already have an fresh TimelineRecording created if autoCaptureStarted is received
         // between sending the Timeline.start command and receiving Timeline.capturingStarted event.
         // In that case, there is no need to call startCapturing again. Reuse the fresh recording.
-        if (!this._waitingForCapturingStartedEvent)
-            this.startCapturing(true);
+        if (!this._waitingForCapturingStartedEvent) {
+            const createNewRecording = true;
+            this.startCapturing(createNewRecording);
+        }
 
         this._shouldSetAutoCapturingMainResource = true;
     }
 
+    programmaticCaptureStarted()
+    {
+        // Called from WebInspector.TimelineObserver.
+
+        this._activeRecording.addScriptInstrumentForProgrammaticCapture();
+
+        const createNewRecording = false;
+        this.startCapturing(createNewRecording);
+    }
+
+    programmaticCaptureStopped()
+    {
+        // Called from WebInspector.TimelineObserver.
+
+        // FIXME: This is purely to avoid a noisy assert. Previously
+        // it was impossible to stop without stopping from the UI.
+        console.assert(!this._isCapturing);
+        this._isCapturing = true;
+
+        this.stopCapturing();
+    }
+
     eventRecorded(recordPayload)
     {
         // Called from WebInspector.TimelineObserver.
@@ -485,7 +509,8 @@
 
         case TimelineAgent.EventType.ConsoleProfile:
             var profileData = recordPayload.data.profile;
-            console.assert(profileData);
+            // COMPATIBILITY (iOS 9): With the Sampling Profiler, profiles no longer include legacy profile data.
+            console.assert(profileData || TimelineAgent.setInstruments);
             return new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.ConsoleProfileRecorded, startTime, endTime, callFrames, sourceCodeLocation, recordPayload.data.title, profileData);
 
         case TimelineAgent.EventType.TimerFire:
@@ -834,6 +859,24 @@
         }
     }
 
+    scriptProfilerProgrammaticCaptureStarted()
+    {
+        // FIXME: <https://webkit.org/b/158753> Generalize the concept of Instruments on the backend to work equally for JSContext and Web inspection
+        console.assert(WebInspector.debuggableType === WebInspector.DebuggableType._javascript_);
+        console.assert(!this._isCapturing);
+
+        this.programmaticCaptureStarted();
+    }
+
+    scriptProfilerProgrammaticCaptureStopped()
+    {
+        // FIXME: <https://webkit.org/b/158753> Generalize the concept of Instruments on the backend to work equally for JSContext and Web inspection
+        console.assert(WebInspector.debuggableType === WebInspector.DebuggableType._javascript_);
+        console.assert(this._isCapturing);
+
+        this.programmaticCaptureStopped();
+    }
+
     scriptProfilerTrackingStarted(timestamp)
     {
         this._scriptProfilerRecords = [];

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScriptInstrument.js (202233 => 202234)


--- trunk/Source/WebInspectorUI/UserInterface/Models/ScriptInstrument.js	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScriptInstrument.js	2016-06-20 19:12:42 UTC (rev 202234)
@@ -56,5 +56,4 @@
 
         ScriptProfilerAgent.stopTracking();
     }
-
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js (202233 => 202234)


--- trunk/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js	2016-06-20 19:12:42 UTC (rev 202234)
@@ -127,7 +127,7 @@
             instrument.startInstrumentation();
     }
 
-    stop()
+    stop(programmatic)
     {
         console.assert(this._capturing, "Attempted to stop an already stopped session.");
         console.assert(!this._readonly, "Attempted to stop a readonly session.");
@@ -134,8 +134,10 @@
 
         this._capturing = false;
 
-        for (let instrument of this._instruments)
-            instrument.stopInstrumentation();
+        if (!programmatic) {
+            for (let instrument of this._instruments)
+                instrument.stopInstrumentation();
+        }
     }
 
     saveIdentityToCookie()
@@ -307,6 +309,19 @@
         return this._discontinuities.filter((item) => item.startTime < endTime && item.endTime > startTime);
     }
 
+    addScriptInstrumentForProgrammaticCapture()
+    {
+        for (let instrument of this._instruments) {
+            if (instrument instanceof WebInspector.ScriptInstrument)
+                return;
+        }
+
+        this.addInstrument(new WebInspector.ScriptInstrument);
+
+        let instrumentTypes = this._instruments.map((instrument) => instrument.timelineRecordType);
+        WebInspector.timelineManager.enabledTimelineTypes = instrumentTypes;
+    }
+
     computeElapsedTime(timestamp)
     {
         if (!timestamp || isNaN(timestamp))

Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/ScriptProfilerObserver.js (202233 => 202234)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/ScriptProfilerObserver.js	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/ScriptProfilerObserver.js	2016-06-20 19:12:42 UTC (rev 202234)
@@ -41,4 +41,14 @@
     {
         WebInspector.timelineManager.scriptProfilerTrackingCompleted(samples);
     }
+    
+    programmaticCaptureStarted()
+    {
+        WebInspector.timelineManager.scriptProfilerProgrammaticCaptureStarted();
+    }
+
+    programmaticCaptureStopped()
+    {
+        WebInspector.timelineManager.scriptProfilerProgrammaticCaptureStopped();
+    }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/TimelineObserver.js (202233 => 202234)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/TimelineObserver.js	2016-06-20 19:10:00 UTC (rev 202233)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/TimelineObserver.js	2016-06-20 19:12:42 UTC (rev 202234)
@@ -46,4 +46,14 @@
     {
         WebInspector.timelineManager.autoCaptureStarted();
     }
+
+    programmaticCaptureStarted()
+    {
+        WebInspector.timelineManager.programmaticCaptureStarted();
+    }
+
+    programmaticCaptureStopped()
+    {
+        WebInspector.timelineManager.programmaticCaptureStopped();
+    }
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to