Title: [202152] trunk
Revision
202152
Author
[email protected]
Date
2016-06-16 19:26:47 -0700 (Thu, 16 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>

Patch by Joseph Pecoraro <[email protected]> on 2016-06-16
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 (202151 => 202152)


--- trunk/LayoutTests/ChangeLog	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/LayoutTests/ChangeLog	2016-06-17 02:26:47 UTC (rev 202152)
@@ -1,3 +1,15 @@
+2016-06-16  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-16  John Wilander  <[email protected]>
 
         Restrict security origin inheritance to empty, about:blank, and about:srcdoc URLs

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


--- trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture-expected.txt	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 => 202152)


--- trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/timeline/setInstruments-programmatic-capture.html	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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/Source/_javascript_Core/ChangeLog (202151 => 202152)


--- trunk/Source/_javascript_Core/ChangeLog	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-06-17 02:26:47 UTC (rev 202152)
@@ -1,3 +1,61 @@
+2016-06-16  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-16  Filip Pizlo  <[email protected]>
 
         Kraken/stanford-crypto-pbkdf2.js sometimes crashes with an OSR assertion in FTL

Modified: trunk/Source/_javascript_Core/debugger/Debugger.h (202151 => 202152)


--- trunk/Source/_javascript_Core/debugger/Debugger.h	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/debugger/Debugger.h	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.cpp	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.cpp	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.h	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectConsoleClient.h	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/JSGlobalObjectInspectorController.cpp	2016-06-17 02:26:47 UTC (rev 202152)
@@ -88,18 +88,19 @@
     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));
     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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.cpp	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.cpp	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.h	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorScriptProfilerAgent.h	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/protocol/ScriptProfiler.json	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/protocol/ScriptProfiler.json	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/_javascript_Core/inspector/protocol/Timeline.json	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/_javascript_Core/inspector/protocol/Timeline.json	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/WebCore/ChangeLog	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebCore/ChangeLog	2016-06-17 02:26:47 UTC (rev 202152)
@@ -1,3 +1,28 @@
+2016-06-16  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-16  John Wilander  <[email protected]>
 
         Restrict security origin inheritance to empty, about:blank, and about:srcdoc URLs

Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp (202151 => 202152)


--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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,12 +212,14 @@
     InspectorPageAgent* m_pageAgent;
 
     Vector<TimelineRecordEntry> m_recordStack;
+    Vector<TimelineRecordEntry> m_pendingConsoleProfileRecords;
 
     int m_id { 1 };
     int m_maxCallStackDepth { 5 };
 
     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 (202151 => 202152)


--- trunk/Source/WebInspectorUI/ChangeLog	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebInspectorUI/ChangeLog	2016-06-17 02:26:47 UTC (rev 202152)
@@ -1,5 +1,38 @@
 2016-06-16  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-16  Joseph Pecoraro  <[email protected]>
+
         REGRESSION (r201538): Web Inspector: Border over Allocations Views is too thick
         https://bugs.webkit.org/show_bug.cgi?id=158846
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js (202151 => 202152)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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 (202151 => 202152)


--- trunk/Source/WebInspectorUI/UserInterface/Models/ScriptInstrument.js	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScriptInstrument.js	2016-06-17 02:26:47 UTC (rev 202152)
@@ -56,5 +56,4 @@
 
         ScriptProfilerAgent.stopTracking();
     }
-
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js (202151 => 202152)


--- trunk/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js	2016-06-17 02:26:47 UTC (rev 202152)
@@ -127,15 +127,17 @@
             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.");
 
         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 (202151 => 202152)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/ScriptProfilerObserver.js	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/ScriptProfilerObserver.js	2016-06-17 02:26:47 UTC (rev 202152)
@@ -41,4 +41,14 @@
     {
         WebInspector.timelineManager.scriptProfilerTrackingCompleted(samples);
     }
+    
+    programmaticCaptureStarted()
+    {
+        WebInspector.timelineManager.scriptProfilerProgrammaticCaptureStarted();
+    }
+
+    programmaticCaptureStopped()
+    {
+        WebInspector.timelineManager.scriptProfilerProgrammaticCaptureStopped();
+    }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/TimelineObserver.js (202151 => 202152)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/TimelineObserver.js	2016-06-17 01:10:08 UTC (rev 202151)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/TimelineObserver.js	2016-06-17 02:26:47 UTC (rev 202152)
@@ -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