summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js418
1 files changed, 418 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js b/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js
new file mode 100644
index 000000000..4a4231d82
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScriptTimelineRecord = class ScriptTimelineRecord extends WebInspector.TimelineRecord
+{
+ constructor(eventType, startTime, endTime, callFrames, sourceCodeLocation, details, profilePayload)
+ {
+ super(WebInspector.TimelineRecord.Type.Script, startTime, endTime, callFrames, sourceCodeLocation);
+
+ console.assert(eventType);
+
+ if (eventType in WebInspector.ScriptTimelineRecord.EventType)
+ eventType = WebInspector.ScriptTimelineRecord.EventType[eventType];
+
+ this._eventType = eventType;
+ this._details = details || "";
+ this._profilePayload = profilePayload || null;
+ this._profile = null;
+
+ // COMPATIBILITY(iOS 9): Before the ScriptProfilerAgent we did not have sample data. Return NaN to match old behavior.
+ if (!window.ScriptProfilerAgent)
+ this._callCountOrSamples = NaN;
+ else {
+ // NOTE: _callCountOrSamples is being treated as the number of samples.
+ this._callCountOrSamples = 0;
+ }
+ }
+
+ // Public
+
+ get eventType()
+ {
+ return this._eventType;
+ }
+
+ get details()
+ {
+ return this._details;
+ }
+
+ get profile()
+ {
+ this._initializeProfileFromPayload();
+ return this._profile;
+ }
+
+ get callCountOrSamples()
+ {
+ return this._callCountOrSamples;
+ }
+
+ isGarbageCollection()
+ {
+ return this._eventType === WebInspector.ScriptTimelineRecord.EventType.GarbageCollected;
+ }
+
+ saveIdentityToCookie(cookie)
+ {
+ super.saveIdentityToCookie(cookie);
+
+ cookie[WebInspector.ScriptTimelineRecord.EventTypeCookieKey] = this._eventType;
+ cookie[WebInspector.ScriptTimelineRecord.DetailsCookieKey] = this._details;
+ }
+
+ get profilePayload()
+ {
+ return this._profilePayload;
+ }
+
+ set profilePayload(payload)
+ {
+ this._profilePayload = payload;
+ }
+
+ // Private
+
+ _initializeProfileFromPayload(payload)
+ {
+ if (this._profile || !this._profilePayload)
+ return;
+
+ var payload = this._profilePayload;
+ this._profilePayload = undefined;
+
+ console.assert(payload.rootNodes instanceof Array);
+
+ function profileNodeFromPayload(nodePayload)
+ {
+ console.assert("id" in nodePayload);
+
+ if (nodePayload.url) {
+ var sourceCode = WebInspector.frameResourceManager.resourceForURL(nodePayload.url);
+ if (!sourceCode)
+ sourceCode = WebInspector.debuggerManager.scriptsForURL(nodePayload.url, WebInspector.assumingMainTarget())[0];
+
+ // The lineNumber is 1-based, but we expect 0-based.
+ var lineNumber = nodePayload.lineNumber - 1;
+
+ var sourceCodeLocation = sourceCode ? sourceCode.createLazySourceCodeLocation(lineNumber, nodePayload.columnNumber) : null;
+ }
+
+ var isProgramCode = nodePayload.functionName === "(program)";
+ var isAnonymousFunction = nodePayload.functionName === "(anonymous function)";
+
+ var type = isProgramCode ? WebInspector.ProfileNode.Type.Program : WebInspector.ProfileNode.Type.Function;
+ var functionName = !isProgramCode && !isAnonymousFunction && nodePayload.functionName !== "(unknown)" ? nodePayload.functionName : null;
+
+ // COMPATIBILITY (iOS 8): Timeline.CPUProfileNodes used to include an array of complete
+ // call information instead of the aggregated "callInfo" data.
+ var calls = null;
+ if ("calls" in nodePayload) {
+ console.assert(nodePayload.calls instanceof Array);
+ calls = nodePayload.calls.map(profileNodeCallFromPayload);
+ }
+
+ return new WebInspector.ProfileNode(nodePayload.id, type, functionName, sourceCodeLocation, nodePayload.callInfo, calls, nodePayload.children);
+ }
+
+ function profileNodeCallFromPayload(nodeCallPayload)
+ {
+ console.assert("startTime" in nodeCallPayload);
+ console.assert("totalTime" in nodeCallPayload);
+
+ var startTime = WebInspector.timelineManager.computeElapsedTime(nodeCallPayload.startTime);
+
+ return new WebInspector.ProfileNodeCall(startTime, nodeCallPayload.totalTime);
+ }
+
+ var rootNodes = payload.rootNodes;
+
+ // Iterate over the node tree using a stack. Doing this recursively can easily cause a stack overflow.
+ // We traverse the profile in post-order and convert the payloads in place until we get back to the root.
+ var stack = [{parent: {children: rootNodes}, index: 0, root: true}];
+ while (stack.length) {
+ var entry = stack.lastValue;
+
+ if (entry.index < entry.parent.children.length) {
+ var childNodePayload = entry.parent.children[entry.index];
+ if (childNodePayload.children && childNodePayload.children.length)
+ stack.push({parent: childNodePayload, index: 0});
+
+ ++entry.index;
+ } else {
+ if (!entry.root)
+ entry.parent.children = entry.parent.children.map(profileNodeFromPayload);
+ else
+ rootNodes = rootNodes.map(profileNodeFromPayload);
+
+ stack.pop();
+ }
+ }
+
+ // COMPATIBILITY (iOS 9): We only do this when we have ScriptProfilerAgent because before that we didn't have a Sampling Profiler.
+ if (window.ScriptProfilerAgent) {
+ for (let i = 0; i < rootNodes.length; i++)
+ this._callCountOrSamples += rootNodes[i].callInfo.callCount;
+ }
+
+ this._profile = new WebInspector.Profile(rootNodes);
+ }
+};
+
+WebInspector.ScriptTimelineRecord.EventType = {
+ ScriptEvaluated: "script-timeline-record-script-evaluated",
+ APIScriptEvaluated: "script-timeline-record-api-script-evaluated",
+ MicrotaskDispatched: "script-timeline-record-microtask-dispatched",
+ EventDispatched: "script-timeline-record-event-dispatched",
+ ProbeSampleRecorded: "script-timeline-record-probe-sample-recorded",
+ TimerFired: "script-timeline-record-timer-fired",
+ TimerInstalled: "script-timeline-record-timer-installed",
+ TimerRemoved: "script-timeline-record-timer-removed",
+ AnimationFrameFired: "script-timeline-record-animation-frame-fired",
+ AnimationFrameRequested: "script-timeline-record-animation-frame-requested",
+ AnimationFrameCanceled: "script-timeline-record-animation-frame-canceled",
+ ConsoleProfileRecorded: "script-timeline-record-console-profile-recorded",
+ GarbageCollected: "script-timeline-record-garbage-collected",
+};
+
+WebInspector.ScriptTimelineRecord.EventType.displayName = function(eventType, details, includeDetailsInMainTitle)
+{
+ if (details && !WebInspector.ScriptTimelineRecord._eventDisplayNames) {
+ // These display names are not localized because they closely represent
+ // the real API name, just with word spaces and Title Case.
+
+ var nameMap = new Map;
+ nameMap.set("DOMActivate", "DOM Activate");
+ nameMap.set("DOMCharacterDataModified", "DOM Character Data Modified");
+ nameMap.set("DOMContentLoaded", "DOM Content Loaded");
+ nameMap.set("DOMFocusIn", "DOM Focus In");
+ nameMap.set("DOMFocusOut", "DOM Focus Out");
+ nameMap.set("DOMNodeInserted", "DOM Node Inserted");
+ nameMap.set("DOMNodeInsertedIntoDocument", "DOM Node Inserted Into Document");
+ nameMap.set("DOMNodeRemoved", "DOM Node Removed");
+ nameMap.set("DOMNodeRemovedFromDocument", "DOM Node Removed From Document");
+ nameMap.set("DOMSubtreeModified", "DOM Sub-Tree Modified");
+ nameMap.set("addsourcebuffer", "Add Source Buffer");
+ nameMap.set("addstream", "Add Stream");
+ nameMap.set("addtrack", "Add Track");
+ nameMap.set("animationend", "Animation End");
+ nameMap.set("animationiteration", "Animation Iteration");
+ nameMap.set("animationstart", "Animation Start");
+ nameMap.set("audioend", "Audio End");
+ nameMap.set("audioprocess", "Audio Process");
+ nameMap.set("audiostart", "Audio Start");
+ nameMap.set("beforecopy", "Before Copy");
+ nameMap.set("beforecut", "Before Cut");
+ nameMap.set("beforeload", "Before Load");
+ nameMap.set("beforepaste", "Before Paste");
+ nameMap.set("beforeunload", "Before Unload");
+ nameMap.set("canplay", "Can Play");
+ nameMap.set("canplaythrough", "Can Play Through");
+ nameMap.set("chargingchange", "Charging Change");
+ nameMap.set("chargingtimechange", "Charging Time Change");
+ nameMap.set("compositionend", "Composition End");
+ nameMap.set("compositionstart", "Composition Start");
+ nameMap.set("compositionupdate", "Composition Update");
+ nameMap.set("contextmenu", "Context Menu");
+ nameMap.set("cuechange", "Cue Change");
+ nameMap.set("datachannel", "Data Channel");
+ nameMap.set("dblclick", "Double Click");
+ nameMap.set("devicemotion", "Device Motion");
+ nameMap.set("deviceorientation", "Device Orientation");
+ nameMap.set("dischargingtimechange", "Discharging Time Change");
+ nameMap.set("dragend", "Drag End");
+ nameMap.set("dragenter", "Drag Enter");
+ nameMap.set("dragleave", "Drag Leave");
+ nameMap.set("dragover", "Drag Over");
+ nameMap.set("dragstart", "Drag Start");
+ nameMap.set("durationchange", "Duration Change");
+ nameMap.set("focusin", "Focus In");
+ nameMap.set("focusout", "Focus Out");
+ nameMap.set("gesturechange", "Gesture Change");
+ nameMap.set("gestureend", "Gesture End");
+ nameMap.set("gesturescrollend", "Gesture Scroll End");
+ nameMap.set("gesturescrollstart", "Gesture Scroll Start");
+ nameMap.set("gesturescrollupdate", "Gesture Scroll Update");
+ nameMap.set("gesturestart", "Gesture Start");
+ nameMap.set("gesturetap", "Gesture Tap");
+ nameMap.set("gesturetapdown", "Gesture Tap Down");
+ nameMap.set("hashchange", "Hash Change");
+ nameMap.set("icecandidate", "ICE Candidate");
+ nameMap.set("iceconnectionstatechange", "ICE Connection State Change");
+ nameMap.set("keydown", "Key Down");
+ nameMap.set("keypress", "Key Press");
+ nameMap.set("keyup", "Key Up");
+ nameMap.set("levelchange", "Level Change");
+ nameMap.set("loadeddata", "Loaded Data");
+ nameMap.set("loadedmetadata", "Loaded Metadata");
+ nameMap.set("loadend", "Load End");
+ nameMap.set("loadingdone", "Loading Done");
+ nameMap.set("loadstart", "Load Start");
+ nameMap.set("mousedown", "Mouse Down");
+ nameMap.set("mouseenter", "Mouse Enter");
+ nameMap.set("mouseleave", "Mouse Leave");
+ nameMap.set("mousemove", "Mouse Move");
+ nameMap.set("mouseout", "Mouse Out");
+ nameMap.set("mouseover", "Mouse Over");
+ nameMap.set("mouseup", "Mouse Up");
+ nameMap.set("mousewheel", "Mouse Wheel");
+ nameMap.set("negotiationneeded", "Negotiation Needed");
+ nameMap.set("nomatch", "No Match");
+ nameMap.set("noupdate", "No Update");
+ nameMap.set("orientationchange", "Orientation Change");
+ nameMap.set("overflowchanged", "Overflow Changed");
+ nameMap.set("pagehide", "Page Hide");
+ nameMap.set("pageshow", "Page Show");
+ nameMap.set("popstate", "Pop State");
+ nameMap.set("ratechange", "Rate Change");
+ nameMap.set("readystatechange", "Ready State Change");
+ nameMap.set("removesourcebuffer", "Remove Source Buffer");
+ nameMap.set("removestream", "Remove Stream");
+ nameMap.set("removetrack", "Remove Track");
+ nameMap.set("resize", "Resize");
+ nameMap.set("securitypolicyviolation", "Security Policy Violation");
+ nameMap.set("selectionchange", "Selection Change");
+ nameMap.set("selectstart", "Select Start");
+ nameMap.set("signalingstatechange", "Signaling State Change");
+ nameMap.set("soundend", "Sound End");
+ nameMap.set("soundstart", "Sound Start");
+ nameMap.set("sourceclose", "Source Close");
+ nameMap.set("sourceended", "Source Ended");
+ nameMap.set("sourceopen", "Source Open");
+ nameMap.set("speechend", "Speech End");
+ nameMap.set("speechstart", "Speech Start");
+ nameMap.set("textInput", "Text Input");
+ nameMap.set("timeupdate", "Time Update");
+ nameMap.set("tonechange", "Tone Change");
+ nameMap.set("touchcancel", "Touch Cancel");
+ nameMap.set("touchend", "Touch End");
+ nameMap.set("touchmove", "Touch Move");
+ nameMap.set("touchstart", "Touch Start");
+ nameMap.set("transitionend", "Transition End");
+ nameMap.set("updateend", "Update End");
+ nameMap.set("updateready", "Update Ready");
+ nameMap.set("updatestart", "Update Start");
+ nameMap.set("upgradeneeded", "Upgrade Needed");
+ nameMap.set("versionchange", "Version Change");
+ nameMap.set("visibilitychange", "Visibility Change");
+ nameMap.set("volumechange", "Volume Change");
+ nameMap.set("webglcontextcreationerror", "WebGL Context Creation Error");
+ nameMap.set("webglcontextlost", "WebGL Context Lost");
+ nameMap.set("webglcontextrestored", "WebGL Context Restored");
+ nameMap.set("webkitAnimationEnd", "Animation End");
+ nameMap.set("webkitAnimationIteration", "Animation Iteration");
+ nameMap.set("webkitAnimationStart", "Animation Start");
+ nameMap.set("webkitBeforeTextInserted", "Before Text Inserted");
+ nameMap.set("webkitEditableContentChanged", "Editable Content Changed");
+ nameMap.set("webkitTransitionEnd", "Transition End");
+ nameMap.set("webkitaddsourcebuffer", "Add Source Buffer");
+ nameMap.set("webkitbeginfullscreen", "Begin Fullscreen");
+ nameMap.set("webkitcurrentplaybacktargetiswirelesschanged", "Current Playback Target Is Wireless Changed");
+ nameMap.set("webkitdeviceproximity", "Device Proximity");
+ nameMap.set("webkitendfullscreen", "End Fullscreen");
+ nameMap.set("webkitfullscreenchange", "Fullscreen Change");
+ nameMap.set("webkitfullscreenerror", "Fullscreen Error");
+ nameMap.set("webkitkeyadded", "Key Added");
+ nameMap.set("webkitkeyerror", "Key Error");
+ nameMap.set("webkitkeymessage", "Key Message");
+ nameMap.set("webkitneedkey", "Need Key");
+ nameMap.set("webkitnetworkinfochange", "Network Info Change");
+ nameMap.set("webkitplaybacktargetavailabilitychanged", "Playback Target Availability Changed");
+ nameMap.set("webkitpointerlockchange", "Pointer Lock Change");
+ nameMap.set("webkitpointerlockerror", "Pointer Lock Error");
+ nameMap.set("webkitregionlayoutupdate", "Region Layout Update"); // COMPATIBILITY (iOS 7): regionLayoutUpdated was removed and replaced by regionOversetChanged.
+ nameMap.set("webkitregionoversetchange", "Region Overset Change");
+ nameMap.set("webkitremovesourcebuffer", "Remove Source Buffer");
+ nameMap.set("webkitresourcetimingbufferfull", "Resource Timing Buffer Full");
+ nameMap.set("webkitsourceclose", "Source Close");
+ nameMap.set("webkitsourceended", "Source Ended");
+ nameMap.set("webkitsourceopen", "Source Open");
+ nameMap.set("webkitspeechchange", "Speech Change");
+ nameMap.set("writeend", "Write End");
+ nameMap.set("writestart", "Write Start");
+
+ WebInspector.ScriptTimelineRecord._eventDisplayNames = nameMap;
+ }
+
+ switch (eventType) {
+ case WebInspector.ScriptTimelineRecord.EventType.ScriptEvaluated:
+ case WebInspector.ScriptTimelineRecord.EventType.APIScriptEvaluated:
+ return WebInspector.UIString("Script Evaluated");
+ case WebInspector.ScriptTimelineRecord.EventType.MicrotaskDispatched:
+ return WebInspector.UIString("Microtask Dispatched");
+ case WebInspector.ScriptTimelineRecord.EventType.EventDispatched:
+ if (details && (details instanceof String || typeof details === "string")) {
+ var eventDisplayName = WebInspector.ScriptTimelineRecord._eventDisplayNames.get(details) || details.capitalize();
+ return WebInspector.UIString("%s Event Dispatched").format(eventDisplayName);
+ }
+ return WebInspector.UIString("Event Dispatched");
+ case WebInspector.ScriptTimelineRecord.EventType.ProbeSampleRecorded:
+ return WebInspector.UIString("Probe Sample Recorded");
+ case WebInspector.ScriptTimelineRecord.EventType.ConsoleProfileRecorded:
+ if (details && (details instanceof String || typeof details === "string"))
+ return WebInspector.UIString("ā€œ%sā€ Profile Recorded").format(details);
+ return WebInspector.UIString("Console Profile Recorded");
+ case WebInspector.ScriptTimelineRecord.EventType.GarbageCollected:
+ console.assert(details);
+ if (details && (details instanceof WebInspector.GarbageCollection) && includeDetailsInMainTitle) {
+ switch (details.type) {
+ case WebInspector.GarbageCollection.Type.Partial:
+ return WebInspector.UIString("Partial Garbage Collection");
+ case WebInspector.GarbageCollection.Type.Full:
+ return WebInspector.UIString("Full Garbage Collection");
+ }
+ }
+ return WebInspector.UIString("Garbage Collection");
+ case WebInspector.ScriptTimelineRecord.EventType.TimerFired:
+ if (details && includeDetailsInMainTitle)
+ return WebInspector.UIString("Timer %s Fired").format(details);
+ return WebInspector.UIString("Timer Fired");
+ case WebInspector.ScriptTimelineRecord.EventType.TimerInstalled:
+ if (details && includeDetailsInMainTitle)
+ return WebInspector.UIString("Timer %s Installed").format(details.timerId);
+ return WebInspector.UIString("Timer Installed");
+ case WebInspector.ScriptTimelineRecord.EventType.TimerRemoved:
+ if (details && includeDetailsInMainTitle)
+ return WebInspector.UIString("Timer %s Removed").format(details);
+ return WebInspector.UIString("Timer Removed");
+ case WebInspector.ScriptTimelineRecord.EventType.AnimationFrameFired:
+ if (details && includeDetailsInMainTitle)
+ return WebInspector.UIString("Animation Frame %s Fired").format(details);
+ return WebInspector.UIString("Animation Frame Fired");
+ case WebInspector.ScriptTimelineRecord.EventType.AnimationFrameRequested:
+ if (details && includeDetailsInMainTitle)
+ return WebInspector.UIString("Animation Frame %s Requested").format(details);
+ return WebInspector.UIString("Animation Frame Requested");
+ case WebInspector.ScriptTimelineRecord.EventType.AnimationFrameCanceled:
+ if (details && includeDetailsInMainTitle)
+ return WebInspector.UIString("Animation Frame %s Canceled").format(details);
+ return WebInspector.UIString("Animation Frame Canceled");
+ }
+};
+
+WebInspector.ScriptTimelineRecord.TypeIdentifier = "script-timeline-record";
+WebInspector.ScriptTimelineRecord.EventTypeCookieKey = "script-timeline-record-event-type";
+WebInspector.ScriptTimelineRecord.DetailsCookieKey = "script-timeline-record-details";