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();
+ }
};