2837 lines
131 KiB
JavaScript
2837 lines
131 KiB
JavaScript
/*
|
|
* Copyright (C) 2018 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.
|
|
*/
|
|
|
|
WI.SourcesNavigationSidebarPanel = class SourcesNavigationSidebarPanel extends WI.NavigationSidebarPanel
|
|
{
|
|
constructor()
|
|
{
|
|
const shouldAutoPruneStaleTopLevelResourceTreeElements = true;
|
|
super("sources", WI.UIString("Sources"), shouldAutoPruneStaleTopLevelResourceTreeElements);
|
|
|
|
this._workerTargetTreeElementMap = new Map;
|
|
this._mainFrameTreeElement = null;
|
|
this._extensionScriptsFolderTreeElement = null;
|
|
this._extensionStyleSheetsFolderTreeElement = null;
|
|
this._extraScriptsFolderTreeElement = null;
|
|
this._extraStyleSheetsFolderTreeElement = null;
|
|
this._anonymousScriptsFolderTreeElement = null;
|
|
this._anonymousStyleSheetsFolderTreeElement = null;
|
|
|
|
this._originTreeElementMap = new Map;
|
|
|
|
this._boundCompareTreeElements = this._compareTreeElements.bind(this);
|
|
|
|
this._debuggerNavigationBar = new WI.NavigationBar;
|
|
this.addSubview(this._debuggerNavigationBar);
|
|
|
|
let createActivateNavigationItem = ({identifier, defaultToolTip, activatedToolTip, image}) => {
|
|
let navigationItem = new WI.ActivateButtonNavigationItem(identifier, defaultToolTip, activatedToolTip, image, 15, 15);
|
|
this._debuggerNavigationBar.addNavigationItem(navigationItem);
|
|
return navigationItem;
|
|
};
|
|
|
|
let createToggleNavigationItem = ({identifier, defaultToolTip, alternateToolTip, defaultImage, alternateImage}) => {
|
|
let navigationItem = new WI.ToggleButtonNavigationItem(identifier, defaultToolTip, alternateToolTip, defaultImage, alternateImage, 15, 15);
|
|
this._debuggerNavigationBar.addNavigationItem(navigationItem);
|
|
return navigationItem;
|
|
};
|
|
|
|
let createButtonNavigationitem = ({identifier, toolTipOrLabel, image}) => {
|
|
let navigationItem = new WI.ButtonNavigationItem(identifier, toolTipOrLabel, image, 15, 15);
|
|
this._debuggerNavigationBar.addNavigationItem(navigationItem);
|
|
return navigationItem;
|
|
};
|
|
|
|
this._debuggerBreakpointsButtonItem = createActivateNavigationItem({
|
|
identifier: "debugger-breakpoints",
|
|
defaultToolTip: WI.UIString("Enable all breakpoints (%s)").format(WI.toggleBreakpointsKeyboardShortcut.displayName),
|
|
activatedToolTip: WI.UIString("Disable all breakpoints (%s)").format(WI.toggleBreakpointsKeyboardShortcut.displayName),
|
|
image: "Images/Breakpoints.svg",
|
|
});
|
|
this._debuggerBreakpointsButtonItem.activated = WI.debuggerManager.breakpointsEnabled;
|
|
this._debuggerBreakpointsButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerToggleBreakpoints, this);
|
|
|
|
this._debuggerPauseResumeButtonItem = createToggleNavigationItem({
|
|
identifier: "debugger-pause-resume",
|
|
defaultToolTip: WI.UIString("Pause script execution (%s or %s)").format(WI.pauseOrResumeKeyboardShortcut.displayName, WI.pauseOrResumeAlternateKeyboardShortcut.displayName),
|
|
alternateToolTip: WI.UIString("Continue script execution (%s or %s)").format(WI.pauseOrResumeKeyboardShortcut.displayName, WI.pauseOrResumeAlternateKeyboardShortcut.displayName),
|
|
defaultImage: "Images/Pause.svg",
|
|
alternateImage: "Images/Resume.svg",
|
|
});
|
|
this._debuggerPauseResumeButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerPauseResumeToggle, this);
|
|
|
|
this._debuggerStepOverButtonItem = createButtonNavigationitem({
|
|
identifier: "debugger-step-over",
|
|
toolTipOrLabel: WI.UIString("Step over (%s or %s)").format(WI.stepOverKeyboardShortcut.displayName, WI.stepOverAlternateKeyboardShortcut.displayName),
|
|
image: "Images/StepOver.svg",
|
|
});
|
|
this._debuggerStepOverButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepOver, this);
|
|
this._debuggerStepOverButtonItem.enabled = false;
|
|
|
|
this._debuggerStepIntoButtonItem = createButtonNavigationitem({
|
|
identifier: "debugger-step-into",
|
|
toolTipOrLabel: WI.UIString("Step into (%s or %s)").format(WI.stepIntoKeyboardShortcut.displayName, WI.stepIntoAlternateKeyboardShortcut.displayName),
|
|
image: "Images/StepInto.svg",
|
|
});
|
|
this._debuggerStepIntoButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepInto, this);
|
|
this._debuggerStepIntoButtonItem.enabled = false;
|
|
|
|
this._debuggerStepOutButtonItem = createButtonNavigationitem({
|
|
identifier: "debugger-step-out",
|
|
toolTipOrLabel: WI.UIString("Step out (%s or %s)").format(WI.stepOutKeyboardShortcut.displayName, WI.stepOutAlternateKeyboardShortcut.displayName),
|
|
image: "Images/StepOut.svg",
|
|
});
|
|
this._debuggerStepOutButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepOut, this);
|
|
this._debuggerStepOutButtonItem.enabled = false;
|
|
|
|
// COMPATIBILITY (iOS 13.4): Debugger.stepNext did not exist yet.
|
|
if (InspectorBackend.hasCommand("Debugger.stepNext")) {
|
|
this._debuggerStepNextButtonItem = createButtonNavigationitem({
|
|
identifier: "debugger-step-next",
|
|
toolTipOrLabel: WI.UIString("Step (%s or %s)").format(WI.stepNextKeyboardShortcut.displayName, WI.stepNextAlternateKeyboardShortcut.displayName),
|
|
image: "Images/StepNext.svg",
|
|
});
|
|
this._debuggerStepNextButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepNext, this);
|
|
this._debuggerStepNextButtonItem.enabled = false;
|
|
}
|
|
|
|
this._timelineRecordingWarningElement = null;
|
|
this._auditTestWarningElement = null;
|
|
this._breakpointsDisabledWarningElement = null;
|
|
|
|
this._pauseReasonTreeOutline = null;
|
|
this._pauseReasonLinkContainerElement = document.createElement("span");
|
|
this._pauseReasonTextRow = new WI.DetailsSectionTextRow;
|
|
this._pauseReasonGroup = new WI.DetailsSectionGroup([this._pauseReasonTextRow]);
|
|
this._pauseReasonSection = new WI.DetailsSection("paused-reason", WI.UIString("Pause Reason"), [this._pauseReasonGroup], this._pauseReasonLinkContainerElement);
|
|
|
|
this._pauseReasonContainer = this.contentView.element.appendChild(document.createElement("div"));
|
|
this._pauseReasonContainer.classList.add("pause-reason-container");
|
|
this._pauseReasonContainer.hidden = true;
|
|
this._pauseReasonContainer.appendChild(this._pauseReasonSection.element);
|
|
|
|
this._callStackTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
|
|
this._callStackTreeOutline.allowsMultipleSelection = true;
|
|
this._callStackTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
|
|
this._callStackTreeOutline.populateContextMenu = (contextMenu, event, treeElement) => {
|
|
if (this._callStackTreeOutline.selectedTreeElements.length) {
|
|
contextMenu.appendItem(WI.UIString("Copy"), () => {
|
|
this.handleCopyEvent(event);
|
|
});
|
|
|
|
contextMenu.appendSeparator();
|
|
}
|
|
|
|
WI.TreeOutline.prototype.populateContextMenu(contextMenu, event, treeElement);
|
|
};
|
|
|
|
let callStackRow = new WI.DetailsSectionRow;
|
|
callStackRow.element.appendChild(this._callStackTreeOutline.element);
|
|
|
|
let callStackGroup = new WI.DetailsSectionGroup([callStackRow]);
|
|
this._callStackSection = new WI.DetailsSection("call-stack", WI.UIString("Call Stack"), [callStackGroup]);
|
|
|
|
this._callStackContainer = this.contentView.element.appendChild(document.createElement("div"));
|
|
this._callStackContainer.classList.add("call-stack-container");
|
|
this._callStackContainer.hidden = true;
|
|
this._callStackContainer.appendChild(this._callStackSection.element);
|
|
|
|
this._mainTargetTreeElement = null;
|
|
this._activeCallFrameTreeElement = null;
|
|
|
|
// Prevent the breakpoints list from being used as the source of selection restoration (e.g. on reload or navigation).
|
|
this._breakpointsTreeOutline = this.createContentTreeOutline({ignoreCookieRestoration: true});
|
|
this._breakpointsTreeOutline.addEventListener(WI.TreeOutline.Event.ElementRemoved, this._handleBreakpointTreeOutlineElementRemoved, this);
|
|
this._breakpointsTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
|
|
this._breakpointsTreeOutline.ondelete = (selectedTreeElement) => {
|
|
console.assert(selectedTreeElement.selected);
|
|
|
|
if (selectedTreeElement.representedObject instanceof WI.Breakpoint && !selectedTreeElement.representedObject.removable) {
|
|
let treeElementToSelect = selectedTreeElement.nextSelectableSibling;
|
|
if (treeElementToSelect) {
|
|
const omitFocus = true;
|
|
const selectedByUser = true;
|
|
treeElementToSelect.select(omitFocus, selectedByUser);
|
|
}
|
|
} else if (selectedTreeElement instanceof WI.ResourceTreeElement || selectedTreeElement instanceof WI.ScriptTreeElement) {
|
|
let breakpoints = this._breakpointsBeneathTreeElement(selectedTreeElement);
|
|
this._removeAllBreakpoints(breakpoints);
|
|
} else if (selectedTreeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject) {
|
|
let eventBreakpointsOnWindow = WI.domManager.eventListenerBreakpoints.filter((eventBreakpoint) => eventBreakpoint.eventListener.onWindow);
|
|
for (let eventBreakpoint of eventBreakpointsOnWindow)
|
|
WI.domManager.removeBreakpointForEventListener(eventBreakpoint.eventListener);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
this._breakpointsTreeOutline.populateContextMenu = (contextMenu, event, treeElement) => {
|
|
// This check is necessary since the context menu is created by the TreeOutline, meaning
|
|
// that any child could be the target of the context menu event.
|
|
if (treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement) {
|
|
let breakpoints = this._breakpointsBeneathTreeElement(treeElement);
|
|
|
|
let shouldDisable = breakpoints.some((breakpoint) => !breakpoint.disabled);
|
|
contextMenu.appendItem(shouldDisable ? WI.UIString("Disable Breakpoints") : WI.UIString("Enable Breakpoints"), () => {
|
|
this._toggleAllBreakpoints(breakpoints, shouldDisable);
|
|
});
|
|
|
|
contextMenu.appendItem(WI.UIString("Delete Breakpoints"), () => {
|
|
this._removeAllBreakpoints(breakpoints);
|
|
});
|
|
}
|
|
|
|
WI.TreeOutline.prototype.populateContextMenu(contextMenu, event, treeElement);
|
|
};
|
|
|
|
let breakpointsRow = new WI.DetailsSectionRow;
|
|
breakpointsRow.element.appendChild(this._breakpointsTreeOutline.element);
|
|
|
|
let breakpointNavigationBarWrapper = document.createElement("div");
|
|
|
|
let breakpointNavigationBar = new WI.NavigationBar;
|
|
breakpointNavigationBarWrapper.appendChild(breakpointNavigationBar.element);
|
|
|
|
this._createBreakpointButton = new WI.ButtonNavigationItem("create-breakpoint", WI.UIString("Create Breakpoint"), "Images/Plus13.svg", 13, 13);
|
|
WI.addMouseDownContextMenuHandlers(this._createBreakpointButton.element, this._populateCreateBreakpointContextMenu.bind(this));
|
|
breakpointNavigationBar.addNavigationItem(this._createBreakpointButton);
|
|
|
|
let breakpointsGroup = new WI.DetailsSectionGroup([breakpointsRow]);
|
|
this._breakpointsSection = new WI.DetailsSection("breakpoints", WI.UIString("Breakpoints"), [breakpointsGroup], breakpointNavigationBarWrapper);
|
|
|
|
let breakpointsContainer = this.contentView.element.appendChild(document.createElement("div"));
|
|
breakpointsContainer.classList.add("breakpoints-container");
|
|
breakpointsContainer.appendChild(this._breakpointsSection.element);
|
|
|
|
this._localOverridesTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
|
|
this._localOverridesTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
|
|
|
|
this._localOverridesRow = new WI.DetailsSectionRow(WI.UIString("No Overrides"));
|
|
|
|
let localOverrideNavigationBarWrapper = document.createElement("div");
|
|
|
|
let localOverrideNavigationBar = new WI.NavigationBar;
|
|
localOverrideNavigationBarWrapper.appendChild(localOverrideNavigationBar.element);
|
|
|
|
this._createLocalOverrideButton = new WI.ButtonNavigationItem("create-local-override", WI.UIString("Create Local Override"), "Images/Plus13.svg", 13, 13);
|
|
WI.addMouseDownContextMenuHandlers(this._createLocalOverrideButton.element, this._populateCreateLocalOverrideContextMenu.bind(this));
|
|
localOverrideNavigationBar.addNavigationItem(this._createLocalOverrideButton);
|
|
|
|
let localOverridesGroup = new WI.DetailsSectionGroup([this._localOverridesRow]);
|
|
this._localOverridesSection = new WI.DetailsSection("local-overrides", WI.UIString("Local Overrides"), [localOverridesGroup], localOverrideNavigationBarWrapper);
|
|
|
|
this._localOverridesContainer = this.contentView.element.appendChild(document.createElement("div"));
|
|
this._localOverridesContainer.classList.add("local-overrides-container");
|
|
this._localOverridesContainer.hidden = true;
|
|
this._localOverridesContainer.appendChild(this._localOverridesSection.element);
|
|
|
|
this._consoleSnippetsTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
|
|
this._consoleSnippetsTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
|
|
|
|
this._consoleSnippetsRow = new WI.DetailsSectionRow(WI.UIString("No Console Snippets"));
|
|
|
|
let consoleSnippetNavigationBarWrapper = document.createElement("div");
|
|
|
|
let consoleSnippetNavigationBar = new WI.NavigationBar;
|
|
consoleSnippetNavigationBarWrapper.appendChild(consoleSnippetNavigationBar.element);
|
|
|
|
this._createConsoleSnippetButton = new WI.ButtonNavigationItem("create-console-snippet", WI.UIString("Create Console Snippet"), "Images/Plus13.svg", 13, 13);
|
|
this._createConsoleSnippetButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCreateConsoleSnippetButtonClicked, this);
|
|
consoleSnippetNavigationBar.addNavigationItem(this._createConsoleSnippetButton);
|
|
|
|
let consoleSnippetsGroup = new WI.DetailsSectionGroup([this._consoleSnippetsRow]);
|
|
this._consoleSnippetsSection = new WI.DetailsSection("console-snippets", WI.UIString("Console Snippets"), [consoleSnippetsGroup], consoleSnippetNavigationBarWrapper);
|
|
|
|
this._consoleSnippetsContainer = this.contentView.element.appendChild(document.createElement("div"));
|
|
this._consoleSnippetsContainer.classList.add("console-snippets-container");
|
|
this._consoleSnippetsContainer.hidden = true;
|
|
this._consoleSnippetsContainer.appendChild(this._consoleSnippetsSection.element);
|
|
|
|
this._resourcesNavigationBar = new WI.NavigationBar;
|
|
this.contentView.addSubview(this._resourcesNavigationBar);
|
|
|
|
this._resourceGroupingModeScopeBarItems = {};
|
|
let createResourceGroupingModeScopeBarItem = (mode, label) => {
|
|
this._resourceGroupingModeScopeBarItems[mode] = new WI.ScopeBarItem("sources-resource-grouping-mode-" + mode, label, {exclusive: true});
|
|
this._resourceGroupingModeScopeBarItems[mode][SourcesNavigationSidebarPanel.ResourceGroupingModeSymbol] = mode;
|
|
};
|
|
createResourceGroupingModeScopeBarItem(WI.Resource.GroupingMode.Type, WI.UIString("By Type"));
|
|
createResourceGroupingModeScopeBarItem(WI.Resource.GroupingMode.Path, WI.UIString("By Path"));
|
|
|
|
this._resourceGroupingModeScopeBar = new WI.ScopeBar("sources-resource-grouping-mode-scope-bar", Object.values(this._resourceGroupingModeScopeBarItems), this._resourceGroupingModeScopeBarItems[WI.settings.resourceGroupingMode.value]);
|
|
this._resourceGroupingModeScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._handleResourceGroupingModeScopeBarSelectionChanged, this);
|
|
this._resourcesNavigationBar.addNavigationItem(this._resourceGroupingModeScopeBar);
|
|
|
|
let resourcesContainer = this.contentView.element.appendChild(document.createElement("div"));
|
|
resourcesContainer.classList.add("resources-container");
|
|
|
|
this._resourcesTreeOutline = this.contentTreeOutline;
|
|
this._resourcesTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
|
|
this._resourcesTreeOutline.includeSourceMapResourceChildren = true;
|
|
resourcesContainer.appendChild(this._resourcesTreeOutline.element);
|
|
|
|
if (WI.NetworkManager.supportsOverridingResponses() || WI.NetworkManager.supportsBootstrapScript() || WI.CSSManager.supportsInspectorStyleSheet()) {
|
|
let createResourceNavigationBar = new WI.NavigationBar;
|
|
|
|
let createResourceButtonNavigationItem = new WI.ButtonNavigationItem("create-resource", WI.UIString("Create Resource"), "Images/Plus15.svg", 15, 15);
|
|
WI.addMouseDownContextMenuHandlers(createResourceButtonNavigationItem.element, this._populateCreateResourceContextMenu.bind(this));
|
|
createResourceNavigationBar.addNavigationItem(createResourceButtonNavigationItem);
|
|
|
|
this.filterBar.element.insertBefore(createResourceNavigationBar.element, this.filterBar.element.firstChild);
|
|
}
|
|
|
|
const activatedByDefault = false;
|
|
this.filterBar.addFilterBarButton("sources-only-show-resources-with-issues", this._filterByResourcesWithIssues.bind(this), activatedByDefault, WI.UIString("Only show resources with issues"), WI.UIString("Show all resources"), "Images/Errors.svg", 15, 15);
|
|
|
|
const resourceTypeScopeItemPrefix = "sources-resource-type-";
|
|
let resourceTypeScopeBarItems = [];
|
|
resourceTypeScopeBarItems.push(new WI.ScopeBarItem(resourceTypeScopeItemPrefix + "all", WI.UIString("All")));
|
|
for (let value of Object.values(WI.Resource.Type)) {
|
|
let scopeBarItem = new WI.ScopeBarItem(resourceTypeScopeItemPrefix + value, WI.Resource.displayNameForType(value, true));
|
|
scopeBarItem[SourcesNavigationSidebarPanel.ResourceTypeSymbol] = value;
|
|
resourceTypeScopeBarItems.push(scopeBarItem);
|
|
}
|
|
|
|
const shouldGroupNonExclusiveItems = true;
|
|
this._resourceTypeScopeBar = new WI.ScopeBar("sources-resource-type-scope-bar", resourceTypeScopeBarItems, resourceTypeScopeBarItems[0], shouldGroupNonExclusiveItems);
|
|
this._resourceTypeScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._handleResourceTypeScopeBarSelectionChanged, this);
|
|
this.filterBar.addFilterNavigationItem(this._resourceTypeScopeBar);
|
|
|
|
WI.settings.resourceGroupingMode.addEventListener(WI.Setting.Event.Changed, this._handleResourceGroupingModeChanged, this);
|
|
|
|
WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);
|
|
WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._handleResourceAdded, this);
|
|
WI.Target.addEventListener(WI.Target.Event.ResourceAdded, this._handleResourceAdded, this);
|
|
|
|
WI.networkManager.addEventListener(WI.NetworkManager.Event.FrameWasAdded, this._handleFrameWasAdded, this);
|
|
|
|
if (WI.NetworkManager.supportsBootstrapScript()) {
|
|
WI.networkManager.addEventListener(WI.NetworkManager.Event.BootstrapScriptCreated, this._handleBootstrapScriptCreated, this);
|
|
WI.networkManager.addEventListener(WI.NetworkManager.Event.BootstrapScriptDestroyed, this._handleBootstrapScriptDestroyed, this);
|
|
}
|
|
|
|
if (WI.NetworkManager.supportsOverridingResponses()) {
|
|
WI.networkManager.addEventListener(WI.NetworkManager.Event.LocalResourceOverrideAdded, this._handleLocalResourceOverrideAdded, this);
|
|
WI.networkManager.addEventListener(WI.NetworkManager.Event.LocalResourceOverrideRemoved, this._handleLocalResourceOverrideRemoved, this);
|
|
}
|
|
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.SymbolicBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.URLBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.SymbolicBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.URLBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointsEnabledDidChange, this._handleDebuggerBreakpointsEnabledDidChange, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptAdded, this._handleDebuggerScriptAdded, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptRemoved, this._handleDebuggerScriptRemoved, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptsCleared, this._handleDebuggerScriptsCleared, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, this._handleDebuggerPaused, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Resumed, this._handleDebuggerResumed, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.CallFramesDidChange, this._handleDebuggerCallFramesDidChange, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._handleDebuggerActiveCallFrameDidChange, this);
|
|
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.WaitingToPause, this._handleDebuggerWaitingToPause, this);
|
|
|
|
WI.JavaScriptBreakpoint.addEventListener(WI.JavaScriptBreakpoint.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
|
|
WI.IssueMessage.addEventListener(WI.IssueMessage.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
|
|
|
|
WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeWillChange, this._handleDOMBreakpointDOMNodeWillChange, this);
|
|
WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeDidChange, this._handleDOMBreakpointDOMNodeDidChange, this);
|
|
|
|
WI.consoleManager.addEventListener(WI.ConsoleManager.Event.IssueAdded, this._handleConsoleIssueAdded, this);
|
|
WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, this._handleConsoleCleared, this);
|
|
WI.consoleManager.addEventListener(WI.ConsoleManager.Event.SnippetAdded, this._handleConsoleSnippetAdded, this);
|
|
WI.consoleManager.addEventListener(WI.ConsoleManager.Event.SnippetRemoved, this._handleConsoleSnippetRemoved, this);
|
|
|
|
WI.timelineManager.addEventListener(WI.TimelineManager.Event.CapturingStateChanged, this._handleTimelineCapturingStateChanged, this);
|
|
|
|
WI.auditManager.addEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditManagerTestScheduled, this);
|
|
WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditManagerTestCompleted, this);
|
|
|
|
WI.cssManager.addEventListener(WI.CSSManager.Event.StyleSheetAdded, this._handleCSSStyleSheetAdded, this);
|
|
WI.cssManager.addEventListener(WI.CSSManager.Event.StyleSheetRemoved, this._handleCSSStyleSheetRemoved, this);
|
|
|
|
WI.targetManager.addEventListener(WI.TargetManager.Event.TargetAdded, this._handleTargetAdded, this);
|
|
WI.targetManager.addEventListener(WI.TargetManager.Event.TargetRemoved, this._handleTargetRemoved, this);
|
|
|
|
// COMPATIBILITY (iOS 14.0): Inspector.activateExtraDomains was removed in favor of a declared debuggable type
|
|
WI.notifications.addEventListener(WI.Notification.ExtraDomainsActivated, this._handleExtraDomainsActivated, this);
|
|
|
|
if (WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel()) {
|
|
this._resourcesTreeOutline.disclosureButtons = false;
|
|
WI.SourceCode.addEventListener(WI.SourceCode.Event.SourceMapAdded, function(event) {
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
}, this);
|
|
}
|
|
|
|
if (WI.debuggerManager.debuggerStatementsBreakpoint)
|
|
this._addBreakpoint(WI.debuggerManager.debuggerStatementsBreakpoint);
|
|
|
|
if (WI.debuggerManager.allExceptionsBreakpoint)
|
|
this._addBreakpoint(WI.debuggerManager.allExceptionsBreakpoint);
|
|
|
|
if (WI.debuggerManager.uncaughtExceptionsBreakpoint)
|
|
this._addBreakpoint(WI.debuggerManager.uncaughtExceptionsBreakpoint);
|
|
|
|
if (WI.debuggerManager.assertionFailuresBreakpoint)
|
|
this._addBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
|
|
|
|
if (WI.debuggerManager.allMicrotasksBreakpoint)
|
|
this._addBreakpoint(WI.debuggerManager.allMicrotasksBreakpoint);
|
|
|
|
for (let target of WI.targets)
|
|
this._addTarget(target);
|
|
|
|
this._updateCallStackTreeOutline();
|
|
|
|
this._handleResourceGroupingModeChanged();
|
|
|
|
if (WI.NetworkManager.supportsBootstrapScript()) {
|
|
let bootstrapScript = WI.networkManager.bootstrapScript;
|
|
if (bootstrapScript)
|
|
this._addLocalOverride(bootstrapScript);
|
|
}
|
|
|
|
if (WI.NetworkManager.supportsOverridingResponses()) {
|
|
for (let localResourceOverride of WI.networkManager.localResourceOverrides)
|
|
this._addLocalOverride(localResourceOverride);
|
|
}
|
|
|
|
if (WI.domDebuggerManager.supported) {
|
|
if (WI.domDebuggerManager.allAnimationFramesBreakpoint)
|
|
this._addBreakpoint(WI.domDebuggerManager.allAnimationFramesBreakpoint);
|
|
|
|
if (WI.domDebuggerManager.allTimeoutsBreakpoint)
|
|
this._addBreakpoint(WI.domDebuggerManager.allTimeoutsBreakpoint);
|
|
|
|
if (WI.domDebuggerManager.allIntervalsBreakpoint)
|
|
this._addBreakpoint(WI.domDebuggerManager.allIntervalsBreakpoint);
|
|
|
|
if (WI.domDebuggerManager.allListenersBreakpoint)
|
|
this._addBreakpoint(WI.domDebuggerManager.allListenersBreakpoint);
|
|
|
|
for (let eventBreakpoint of WI.domDebuggerManager.listenerBreakpoints)
|
|
this._addBreakpoint(eventBreakpoint);
|
|
|
|
for (let eventListenerBreakpoint of WI.domManager.eventListenerBreakpoints)
|
|
this._addBreakpoint(eventListenerBreakpoint);
|
|
|
|
for (let domBreakpoint of WI.domDebuggerManager.domBreakpoints)
|
|
this._addBreakpoint(domBreakpoint);
|
|
|
|
if (WI.domDebuggerManager.allRequestsBreakpoint)
|
|
this._addBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);
|
|
|
|
for (let urlBreakpoints of WI.domDebuggerManager.urlBreakpoints)
|
|
this._addBreakpoint(urlBreakpoints);
|
|
}
|
|
|
|
if (WI.debuggerManager.paused)
|
|
this._handleDebuggerPaused();
|
|
|
|
if (WI.debuggerManager.breakpointsDisabledTemporarily) {
|
|
this._handleTimelineCapturingStateChanged();
|
|
|
|
if (WI.auditManager.runningState === WI.AuditManager.RunningState.Active || WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping)
|
|
this._handleAuditManagerTestScheduled();
|
|
}
|
|
|
|
for (let consoleSnippet of WI.consoleManager.snippets)
|
|
this._addConsoleSnippet(consoleSnippet);
|
|
|
|
this._updateBreakpointsDisabledBanner();
|
|
}
|
|
|
|
// Static
|
|
|
|
static shouldPlaceResourcesAtTopLevel()
|
|
{
|
|
return WI.sharedApp.debuggableType === WI.DebuggableType.ITML
|
|
|| WI.sharedApp.debuggableType === WI.DebuggableType.JavaScript
|
|
|| WI.sharedApp.debuggableType === WI.DebuggableType.ServiceWorker;
|
|
}
|
|
|
|
// Public
|
|
|
|
get minimumWidth()
|
|
{
|
|
return Math.max(this._debuggerNavigationBar.minimumWidth, this._resourcesNavigationBar.minimumWidth);
|
|
}
|
|
|
|
closed()
|
|
{
|
|
WI.settings.resourceGroupingMode.removeEventListener(WI.Setting.Event.Changed, this._handleResourceGroupingModeChanged, this);
|
|
|
|
WI.Frame.removeEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);
|
|
WI.Frame.removeEventListener(WI.Frame.Event.ResourceWasAdded, this._handleResourceAdded, this);
|
|
WI.Target.removeEventListener(WI.Target.Event.ResourceAdded, this._handleResourceAdded, this);
|
|
|
|
WI.networkManager.removeEventListener(WI.NetworkManager.Event.FrameWasAdded, this._handleFrameWasAdded, this);
|
|
|
|
if (WI.NetworkManager.supportsBootstrapScript()) {
|
|
WI.networkManager.removeEventListener(WI.NetworkManager.Event.BootstrapScriptCreated, this._handleBootstrapScriptCreated, this);
|
|
WI.networkManager.removeEventListener(WI.NetworkManager.Event.BootstrapScriptDestroyed, this._handleBootstrapScriptDestroyed, this);
|
|
}
|
|
|
|
if (WI.NetworkManager.supportsOverridingResponses()) {
|
|
WI.networkManager.removeEventListener(WI.NetworkManager.Event.LocalResourceOverrideAdded, this._handleLocalResourceOverrideAdded, this);
|
|
WI.networkManager.removeEventListener(WI.NetworkManager.Event.LocalResourceOverrideRemoved, this._handleLocalResourceOverrideRemoved, this);
|
|
}
|
|
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.BreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.SymbolicBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.domDebuggerManager.removeEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.domDebuggerManager.removeEventListener(WI.DOMDebuggerManager.Event.EventBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
WI.domDebuggerManager.removeEventListener(WI.DOMDebuggerManager.Event.URLBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
|
|
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.BreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.SymbolicBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.domDebuggerManager.removeEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.domDebuggerManager.removeEventListener(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
WI.domDebuggerManager.removeEventListener(WI.DOMDebuggerManager.Event.URLBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
|
|
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.BreakpointsEnabledDidChange, this._handleDebuggerBreakpointsEnabledDidChange, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.ScriptAdded, this._handleDebuggerScriptAdded, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.ScriptRemoved, this._handleDebuggerScriptRemoved, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.ScriptsCleared, this._handleDebuggerScriptsCleared, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, this._handleDebuggerPaused, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Resumed, this._handleDebuggerResumed, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.CallFramesDidChange, this._handleDebuggerCallFramesDidChange, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._handleDebuggerActiveCallFrameDidChange, this);
|
|
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.WaitingToPause, this._handleDebuggerWaitingToPause, this);
|
|
|
|
WI.JavaScriptBreakpoint.removeEventListener(WI.JavaScriptBreakpoint.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
|
|
WI.IssueMessage.removeEventListener(WI.IssueMessage.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
|
|
|
|
WI.DOMBreakpoint.removeEventListener(WI.DOMBreakpoint.Event.DOMNodeWillChange, this._handleDOMBreakpointDOMNodeWillChange, this);
|
|
WI.DOMBreakpoint.removeEventListener(WI.DOMBreakpoint.Event.DOMNodeDidChange, this._handleDOMBreakpointDOMNodeDidChange, this);
|
|
|
|
WI.consoleManager.removeEventListener(WI.ConsoleManager.Event.IssueAdded, this._handleConsoleIssueAdded, this);
|
|
WI.consoleManager.removeEventListener(WI.ConsoleManager.Event.Cleared, this._handleConsoleCleared, this);
|
|
WI.consoleManager.removeEventListener(WI.ConsoleManager.Event.SnippetAdded, this._handleConsoleSnippetAdded, this);
|
|
WI.consoleManager.removeEventListener(WI.ConsoleManager.Event.SnippetRemoved, this._handleConsoleSnippetRemoved, this);
|
|
|
|
WI.timelineManager.removeEventListener(WI.TimelineManager.Event.CapturingStateChanged, this._handleTimelineCapturingStateChanged, this);
|
|
|
|
WI.auditManager.removeEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditManagerTestScheduled, this);
|
|
WI.auditManager.removeEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditManagerTestCompleted, this);
|
|
|
|
WI.cssManager.removeEventListener(WI.CSSManager.Event.StyleSheetAdded, this._handleCSSStyleSheetAdded, this);
|
|
WI.cssManager.removeEventListener(WI.CSSManager.Event.StyleSheetRemoved, this._handleCSSStyleSheetRemoved, this);
|
|
|
|
WI.targetManager.removeEventListener(WI.TargetManager.Event.TargetAdded, this._handleTargetAdded, this);
|
|
WI.targetManager.removeEventListener(WI.TargetManager.Event.TargetRemoved, this._handleTargetRemoved, this);
|
|
|
|
// COMPATIBILITY (iOS 14.0): Inspector.activateExtraDomains was removed in favor of a declared debuggable type
|
|
WI.notifications.removeEventListener(WI.Notification.ExtraDomainsActivated, this._handleExtraDomainsActivated, this);
|
|
|
|
super.closed();
|
|
}
|
|
|
|
showDefaultContentView()
|
|
{
|
|
if (WI.networkManager.mainFrame) {
|
|
this.contentBrowser.showContentViewForRepresentedObject(WI.networkManager.mainFrame);
|
|
return;
|
|
}
|
|
|
|
let firstTreeElement = this._resourcesTreeOutline.children[0];
|
|
if (firstTreeElement)
|
|
this.showDefaultContentViewForTreeElement(firstTreeElement);
|
|
}
|
|
|
|
treeElementForRepresentedObject(representedObject)
|
|
{
|
|
// A custom implementation is needed for this since the frames are populated lazily.
|
|
|
|
if (representedObject instanceof WI.LocalResourceOverride)
|
|
return this._localOverridesTreeOutline.findTreeElement(representedObject);
|
|
|
|
if (representedObject instanceof WI.LocalResource) {
|
|
let localResourceOverride = representedObject.localResourceOverride || WI.networkManager.localResourceOverridesForURL(representedObject.url)[0];
|
|
return this._localOverridesTreeOutline.findTreeElement(localResourceOverride);
|
|
}
|
|
|
|
if (representedObject instanceof WI.Script && representedObject === WI.networkManager.bootstrapScript)
|
|
return this._localOverridesTreeOutline.findTreeElement(representedObject);
|
|
|
|
if (representedObject instanceof WI.ConsoleSnippet)
|
|
return this._consoleSnippetsTreeOutline.findTreeElement(representedObject);
|
|
|
|
if (!this._mainFrameTreeElement && (representedObject instanceof WI.Resource || representedObject instanceof WI.Frame || representedObject instanceof WI.Collection)) {
|
|
// All resources are under the main frame, so we need to return early if we don't have the main frame yet.
|
|
return null;
|
|
}
|
|
|
|
switch (WI.settings.resourceGroupingMode.value) {
|
|
case WI.Resource.GroupingMode.Path:
|
|
if (representedObject instanceof WI.Frame)
|
|
representedObject = representedObject.mainResource;
|
|
break;
|
|
|
|
default:
|
|
WI.reportInternalError("Unknown resource grouping mode", {"Resource Grouping Mode": WI.settings.resourceGroupingMode.value});
|
|
// Fallthrough for default value.
|
|
|
|
case WI.Resource.GroupingMode.Type:
|
|
if (representedObject instanceof WI.Resource && representedObject.parentFrame && representedObject.parentFrame.mainResource === representedObject)
|
|
representedObject = representedObject.parentFrame;
|
|
break;
|
|
}
|
|
|
|
function isAncestor(ancestor, resourceOrFrame) {
|
|
// SourceMapResources are descendants of another SourceCode object.
|
|
if (resourceOrFrame instanceof WI.SourceMapResource) {
|
|
if (resourceOrFrame.sourceMap.originalSourceCode === ancestor)
|
|
return true;
|
|
|
|
// Not a direct ancestor, so check the ancestors of the parent SourceCode object.
|
|
resourceOrFrame = resourceOrFrame.sourceMap.originalSourceCode;
|
|
}
|
|
|
|
let currentFrame = resourceOrFrame.parentFrame;
|
|
while (currentFrame) {
|
|
if (currentFrame === ancestor)
|
|
return true;
|
|
currentFrame = currentFrame.parentFrame;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function getParent(resourceOrFrame) {
|
|
// SourceMapResources are descendants of another SourceCode object.
|
|
if (resourceOrFrame instanceof WI.SourceMapResource)
|
|
return resourceOrFrame.sourceMap.originalSourceCode;
|
|
return resourceOrFrame.parentFrame;
|
|
}
|
|
|
|
function searchTreeOutline(treeOutline, forceSearch) {
|
|
if (!treeOutline || (!treeOutline.selectedTreeElement && !forceSearch))
|
|
return null;
|
|
return treeOutline.findTreeElement(representedObject, isAncestor, getParent);
|
|
}
|
|
let treeElement = searchTreeOutline(this._pauseReasonTreeOutline) || searchTreeOutline(this._callStackTreeOutline) || searchTreeOutline(this._breakpointsTreeOutline) || searchTreeOutline(this._resourcesTreeOutline, true);
|
|
if (treeElement)
|
|
return treeElement;
|
|
|
|
if (representedObject instanceof WI.Script) {
|
|
// If the Script has a URL we should have found it earlier.
|
|
if (representedObject.url) {
|
|
console.assert(false, "Didn't find a ScriptTreeElement for a Script with a URL.", representedObject);
|
|
return null;
|
|
}
|
|
|
|
console.assert(representedObject.anonymous, representedObject);
|
|
|
|
// Since the Script does not have a URL we consider it an 'anonymous' script. These scripts happen from calls to
|
|
// window.eval() or browser features like Auto Fill and Reader. They are not normally added to the sidebar, but since
|
|
// we have a ScriptContentView asking for the tree element we will make a ScriptTreeElement on demand and add it.
|
|
|
|
if (!this._anonymousScriptsFolderTreeElement)
|
|
this._anonymousScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Anonymous Scripts"), new WI.ScriptCollection);
|
|
|
|
if (!this._anonymousScriptsFolderTreeElement.parent) {
|
|
let index = insertionIndexForObjectInListSortedByFunction(this._anonymousScriptsFolderTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
|
|
this._resourcesTreeOutline.insertChild(this._anonymousScriptsFolderTreeElement, index);
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
}
|
|
|
|
this._anonymousScriptsFolderTreeElement.representedObject.add(representedObject);
|
|
|
|
let scriptTreeElement = new WI.ScriptTreeElement(representedObject);
|
|
this._anonymousScriptsFolderTreeElement.appendChild(scriptTreeElement);
|
|
return scriptTreeElement;
|
|
}
|
|
|
|
if (representedObject instanceof WI.CSSStyleSheet) {
|
|
// If the CSSStyleSheet has a URL we should have found it earlier.
|
|
if (representedObject.url) {
|
|
console.assert(false, "Didn't find a CSSStyleSheetTreeElement for a CSSStyleSheet with a URL.", representedObject);
|
|
return null;
|
|
}
|
|
|
|
console.assert(representedObject.anonymous, representedObject);
|
|
|
|
if (!this._anonymousStyleSheetsFolderTreeElement)
|
|
this._anonymousStyleSheetsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Anonymous Style Sheets"), new WI.CSSStyleSheetCollection);
|
|
|
|
if (!this._anonymousStyleSheetsFolderTreeElement.parent) {
|
|
let index = insertionIndexForObjectInListSortedByFunction(this._anonymousStyleSheetsFolderTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
|
|
this._resourcesTreeOutline.insertChild(this._anonymousStyleSheetsFolderTreeElement, index);
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
}
|
|
|
|
let cssStyleSheetTreeElement = new WI.CSSStyleSheetTreeElement(representedObject);
|
|
this._anonymousStyleSheetsFolderTreeElement.appendChild(cssStyleSheetTreeElement);
|
|
return cssStyleSheetTreeElement;
|
|
}
|
|
|
|
console.assert(false, "Didn't find a TreeElement for representedObject", representedObject);
|
|
return null;
|
|
}
|
|
|
|
handleCopyEvent(event)
|
|
{
|
|
let selectedTreeElements = new Set(this._callStackTreeOutline.selectedTreeElements);
|
|
if (!selectedTreeElements.size)
|
|
return;
|
|
|
|
let treeElement = this._callStackTreeOutline.children[0];
|
|
|
|
const ignoreHidden = true;
|
|
const skipUnrevealed = true;
|
|
const stayWithin = null;
|
|
const dontPopulate = true;
|
|
while (!treeElement.revealed(ignoreHidden))
|
|
treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
|
|
|
|
let indentString = WI.indentString();
|
|
let threads = [];
|
|
let asyncBoundary = null;
|
|
|
|
function addCallFrame(callFrame) {
|
|
if (asyncBoundary) {
|
|
threads.lastValue.frames.push("--- " + asyncBoundary + " ---");
|
|
asyncBoundary = null;
|
|
}
|
|
|
|
let line = callFrame.displayName;
|
|
|
|
let sourceCodeLocation = callFrame.sourceCodeLocation;
|
|
if (sourceCodeLocation)
|
|
line += " (" + sourceCodeLocation.displayLocationString() + ")";
|
|
|
|
threads.lastValue.frames.push(line);
|
|
}
|
|
|
|
for (; treeElement; treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate)) {
|
|
if (treeElement instanceof WI.ThreadTreeElement) {
|
|
threads.push({
|
|
name: treeElement.mainTitle,
|
|
frames: [],
|
|
});
|
|
|
|
asyncBoundary = null;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (treeElement.isAsyncBoundaryCallFrame || treeElement.isTruncatedBoundaryCallFrame)
|
|
asyncBoundary = treeElement.mainTitle;
|
|
|
|
if (!selectedTreeElements.has(treeElement))
|
|
continue;
|
|
|
|
if (treeElement instanceof WI.CallFrameTreeElement) {
|
|
addCallFrame(treeElement.callFrame);
|
|
continue;
|
|
}
|
|
|
|
if (treeElement instanceof WI.BlackboxedGroupTreeElement) {
|
|
for (let callFrame of treeElement.callFrames)
|
|
addCallFrame(callFrame);
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
let multipleFramesSelected = threads.filter(({frames}) => frames.length).length > 1;
|
|
|
|
let lines = [];
|
|
for (let {name, frames} of threads) {
|
|
if (multipleFramesSelected)
|
|
lines.push(name);
|
|
|
|
for (let frame of frames) {
|
|
let prefix = "";
|
|
if (multipleFramesSelected)
|
|
prefix = indentString;
|
|
lines.push(prefix + frame);
|
|
}
|
|
}
|
|
if (!lines.length)
|
|
return;
|
|
|
|
setTimeout(() => {
|
|
InspectorFrontendHost.copyText(lines.join("\n"));
|
|
});
|
|
|
|
event.stop();
|
|
}
|
|
|
|
// Protected
|
|
|
|
createContentTreeOutline(options = {})
|
|
{
|
|
let treeOutline = super.createContentTreeOutline(options);
|
|
|
|
treeOutline.addEventListener(WI.TreeOutline.Event.ElementRevealed, function(event) {
|
|
let treeElement = event.data.element;
|
|
let detailsSections = [
|
|
this._pauseReasonSection,
|
|
this._callStackSection,
|
|
this._breakpointsSection,
|
|
this._localOverridesSection,
|
|
this._consoleSnippetsSection,
|
|
];
|
|
let detailsSection = detailsSections.find((detailsSection) => detailsSection.element.contains(treeElement.listItemElement));
|
|
if (!detailsSection)
|
|
return;
|
|
|
|
// Revealing a TreeElement at the scroll container's topmost edge with
|
|
// scrollIntoViewIfNeeded may result in the element being covered by the
|
|
// DetailsSection header, which uses sticky positioning. Detect this case,
|
|
// and adjust the sidebar content's scroll position to compensate.
|
|
let offset = detailsSection.headerElement.totalOffsetBottom - treeElement.listItemElement.totalOffsetTop;
|
|
if (offset > 0)
|
|
this.scrollElement.scrollBy(0, -offset);
|
|
}, this);
|
|
|
|
return treeOutline;
|
|
}
|
|
|
|
resetFilter()
|
|
{
|
|
this._resourceTypeScopeBar.resetToDefault();
|
|
|
|
super.resetFilter();
|
|
}
|
|
|
|
hasCustomFilters()
|
|
{
|
|
console.assert(this._resourceTypeScopeBar.selectedItems.length === 1);
|
|
let selectedScopeBarItem = this._resourceTypeScopeBar.selectedItems[0];
|
|
return selectedScopeBarItem && selectedScopeBarItem !== this._resourceTypeScopeBar.defaultItem;
|
|
}
|
|
|
|
matchTreeElementAgainstCustomFilters(treeElement, flags)
|
|
{
|
|
// Only apply the resource type filter to the resources list.
|
|
if (treeElement.treeOutline !== this._resourcesTreeOutline)
|
|
return true;
|
|
|
|
console.assert(this._resourceTypeScopeBar.selectedItems.length === 1);
|
|
let selectedScopeBarItem = this._resourceTypeScopeBar.selectedItems[0];
|
|
|
|
// Show everything if there is no selection or "All Resources" is selected (the default item).
|
|
if (!selectedScopeBarItem || selectedScopeBarItem === this._resourceTypeScopeBar.defaultItem)
|
|
return true;
|
|
|
|
// Folders are hidden on the first pass, but visible childen under the folder will force the folder visible again.
|
|
if (treeElement instanceof WI.FolderTreeElement || treeElement instanceof WI.OriginTreeElement)
|
|
return false;
|
|
|
|
if (treeElement instanceof WI.IssueTreeElement)
|
|
treeElement = treeElement.parent;
|
|
|
|
function match()
|
|
{
|
|
if (treeElement instanceof WI.FrameTreeElement)
|
|
return selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.Document;
|
|
|
|
if (treeElement instanceof WI.ScriptTreeElement)
|
|
return selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.Script;
|
|
|
|
if (treeElement instanceof WI.CSSStyleSheetTreeElement)
|
|
return selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.StyleSheet;
|
|
|
|
console.assert(treeElement instanceof WI.ResourceTreeElement, "Unknown treeElement", treeElement);
|
|
if (!(treeElement instanceof WI.ResourceTreeElement))
|
|
return false;
|
|
|
|
return treeElement.resource.type === selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol];
|
|
}
|
|
|
|
let matched = match();
|
|
if (matched)
|
|
flags.expandTreeElement = true;
|
|
return matched;
|
|
}
|
|
|
|
// Popover delegate
|
|
|
|
willDismissPopover(popover)
|
|
{
|
|
if (popover instanceof WI.LocalResourceOverridePopover) {
|
|
this._willDismissLocalOverridePopover(popover);
|
|
return;
|
|
}
|
|
|
|
if (popover instanceof WI.InputPopover) {
|
|
this._willDismissConsoleSnippetPopover(popover);
|
|
return;
|
|
}
|
|
|
|
if (popover instanceof WI.EventBreakpointPopover) {
|
|
this._willDismissEventBreakpointPopover(popover);
|
|
return;
|
|
}
|
|
|
|
if (popover instanceof WI.URLBreakpointPopover) {
|
|
this._willDismissURLBreakpointPopover(popover);
|
|
return;
|
|
}
|
|
|
|
if (popover instanceof WI.SymbolicBreakpointPopover) {
|
|
this._willDismissSymbolicBreakpointPopover(popover);
|
|
return;
|
|
}
|
|
|
|
console.assert(false, "not reached", popover);
|
|
}
|
|
|
|
// Private
|
|
|
|
_willDismissLocalOverridePopover(popover)
|
|
{
|
|
let serializedData = popover.serializedData;
|
|
if (!serializedData) {
|
|
if (!this._localOverridesTreeOutline.children.length)
|
|
this._localOverridesContainer.hidden = true;
|
|
|
|
InspectorFrontendHost.beep();
|
|
return;
|
|
}
|
|
|
|
// Do not conflict with an existing override.
|
|
if (WI.networkManager.localResourceOverrides.some((existingOverride) => existingOverride.equals(serializedData))) {
|
|
InspectorFrontendHost.beep();
|
|
return;
|
|
}
|
|
|
|
let localResourceOverride = WI.LocalResourceOverride.create(serializedData.url, serializedData.type, serializedData);
|
|
WI.networkManager.addLocalResourceOverride(localResourceOverride);
|
|
WI.showLocalResourceOverride(localResourceOverride);
|
|
}
|
|
|
|
_willDismissConsoleSnippetPopover(popover)
|
|
{
|
|
let title = popover.value?.trim();
|
|
if (!title) {
|
|
if (!this._consoleSnippetsTreeOutline.children.length)
|
|
this._consoleSnippetsContainer.hidden = true;
|
|
|
|
InspectorFrontendHost.beep();
|
|
return;
|
|
}
|
|
|
|
// Do not conflict with an existing consoleSnippet.
|
|
if (WI.consoleManager.snippets.some((consoleSnippet) => consoleSnippet.title === title)) {
|
|
InspectorFrontendHost.beep();
|
|
return;
|
|
}
|
|
|
|
let consoleSnippet = WI.ConsoleSnippet.createDefaultWithTitle(title);
|
|
WI.consoleManager.addSnippet(consoleSnippet);
|
|
|
|
const cookie = null;
|
|
WI.showRepresentedObject(consoleSnippet, cookie, {
|
|
ignoreNetworkTab: true,
|
|
ignoreSearchTab: true,
|
|
});
|
|
}
|
|
|
|
_willDismissEventBreakpointPopover(popover)
|
|
{
|
|
let breakpoint = popover.breakpoint;
|
|
if (!breakpoint) {
|
|
InspectorFrontendHost.beep();
|
|
return;
|
|
}
|
|
|
|
if (!WI.domDebuggerManager.addEventBreakpoint(breakpoint))
|
|
InspectorFrontendHost.beep();
|
|
}
|
|
|
|
_willDismissURLBreakpointPopover(popover)
|
|
{
|
|
let breakpoint = popover.breakpoint;
|
|
if (!breakpoint) {
|
|
InspectorFrontendHost.beep();
|
|
return;
|
|
}
|
|
|
|
if (!WI.domDebuggerManager.addURLBreakpoint(breakpoint))
|
|
InspectorFrontendHost.beep();
|
|
}
|
|
|
|
_willDismissSymbolicBreakpointPopover(popover)
|
|
{
|
|
let breakpoint = popover.breakpoint;
|
|
if (!breakpoint) {
|
|
InspectorFrontendHost.beep();
|
|
return;
|
|
}
|
|
|
|
if (!WI.debuggerManager.addSymbolicBreakpoint(breakpoint))
|
|
InspectorFrontendHost.beep();
|
|
}
|
|
|
|
_filterByResourcesWithIssues(treeElement)
|
|
{
|
|
if (treeElement.treeOutline !== this._resourcesTreeOutline)
|
|
return true;
|
|
|
|
if (treeElement instanceof WI.IssueTreeElement)
|
|
return true;
|
|
|
|
if (treeElement.hasChildren) {
|
|
for (let child of treeElement.children) {
|
|
if (child instanceof WI.IssueTreeElement)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
_compareTreeElements(a, b)
|
|
{
|
|
const rankFunctions = [
|
|
(treeElement) => treeElement instanceof WI.ScriptTreeElement && treeElement.representedObject === WI.networkManager.bootstrapScript,
|
|
(treeElement) => treeElement instanceof WI.LocalResourceOverrideTreeElement,
|
|
(treeElement) => treeElement instanceof WI.ScriptTreeElement && treeElement.representedObject instanceof WI.ConsoleSnippet,
|
|
(treeElement) => treeElement instanceof WI.CSSStyleSheetTreeElement && treeElement.representedObject.isInspectorStyleSheet(),
|
|
(treeElement) => treeElement === this._mainFrameTreeElement,
|
|
(treeElement) => treeElement instanceof WI.FrameTreeElement,
|
|
(treeElement) => treeElement instanceof WI.OriginTreeElement,
|
|
(treeElement) => {
|
|
return treeElement !== this._extensionScriptsFolderTreeElement
|
|
&& treeElement !== this._extensionStyleSheetsFolderTreeElement
|
|
&& treeElement !== this._extraScriptsFolderTreeElement
|
|
&& treeElement !== this._extraStyleSheetsFolderTreeElement
|
|
&& treeElement !== this._anonymousScriptsFolderTreeElement
|
|
&& treeElement !== this._anonymousStyleSheetsFolderTreeElement;
|
|
},
|
|
(treeElement) => treeElement === this._extensionScriptsFolderTreeElement,
|
|
(treeElement) => treeElement === this._extensionStyleSheetsFolderTreeElement,
|
|
(treeElement) => treeElement === this._extraScriptsFolderTreeElement,
|
|
(treeElement) => treeElement === this._extraStyleSheetsFolderTreeElement,
|
|
(treeElement) => treeElement === this._anonymousScriptsFolderTreeElement,
|
|
(treeElement) => treeElement === this._anonymousStyleSheetsFolderTreeElement,
|
|
];
|
|
|
|
let aRank = rankFunctions.findIndex((rankFunction) => rankFunction(a));
|
|
let bRank = rankFunctions.findIndex((rankFunction) => rankFunction(b));
|
|
if ((aRank >= 0 && bRank < 0) || aRank < bRank)
|
|
return -1;
|
|
if ((bRank >= 0 && aRank < 0) || bRank < aRank)
|
|
return 1;
|
|
|
|
return a.mainTitle.extendedLocaleCompare(b.mainTitle) || a.subtitle.extendedLocaleCompare(b.subtitle);
|
|
}
|
|
|
|
_closeContentViewsFilter(contentView)
|
|
{
|
|
// Local Resource Override content views do not need to be closed across page navigations.
|
|
if (contentView.representedObject instanceof WI.LocalResource && contentView.representedObject.localResourceOverride)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
_updateMainFrameTreeElement(mainFrame)
|
|
{
|
|
if (this.didInitialLayout)
|
|
this.contentBrowser.contentViewContainer.closeAllContentViews(this._closeContentViewsFilter);
|
|
|
|
let oldMainFrameTreeElement = this._mainFrameTreeElement;
|
|
if (this._mainFrameTreeElement) {
|
|
this._resourcesTreeOutline.removeChild(this._mainFrameTreeElement);
|
|
this._mainFrameTreeElement = null;
|
|
}
|
|
|
|
if (!mainFrame)
|
|
return;
|
|
|
|
switch (WI.settings.resourceGroupingMode.value) {
|
|
case WI.Resource.GroupingMode.Path: {
|
|
for (let treeElement of this._originTreeElementMap.values()) {
|
|
if (treeElement !== oldMainFrameTreeElement)
|
|
this._resourcesTreeOutline.removeChild(treeElement);
|
|
}
|
|
this._originTreeElementMap.clear();
|
|
|
|
let origin = mainFrame.urlComponents.origin;
|
|
this._mainFrameTreeElement = new WI.OriginTreeElement(origin, mainFrame, {hasChildren: true});
|
|
this._originTreeElementMap.set(origin, this._mainFrameTreeElement);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
WI.reportInternalError("Unknown resource grouping mode", {"Resource Grouping Mode": WI.settings.resourceGroupingMode.value});
|
|
// Fallthrough for default value.
|
|
|
|
case WI.Resource.GroupingMode.Type:
|
|
this._mainFrameTreeElement = new WI.FrameTreeElement(mainFrame);
|
|
break;
|
|
}
|
|
|
|
this._resourcesTreeOutline.insertChild(this._mainFrameTreeElement, 0);
|
|
|
|
// Cookie restoration will attempt to re-select the resource we were showing.
|
|
// Give it time to do that before selecting the main frame resource.
|
|
setTimeout(() => {
|
|
if (this._resourcesTreeOutline.selectedTreeElement)
|
|
return;
|
|
|
|
let currentContentView = this.contentBrowser.currentContentView;
|
|
let treeElement = currentContentView ? this.treeElementForRepresentedObject(currentContentView.representedObject) : null;
|
|
if (!treeElement)
|
|
treeElement = this.treeElementForRepresentedObject(WI.networkManager.mainFrame);
|
|
this.showDefaultContentViewForTreeElement(treeElement);
|
|
});
|
|
}
|
|
|
|
_addTarget(target)
|
|
{
|
|
let treeElement = new WI.ThreadTreeElement(target);
|
|
this._callStackTreeOutline.appendChild(treeElement);
|
|
|
|
// FIXME: When WI.mainTarget changes?
|
|
if (target === WI.mainTarget)
|
|
this._mainTargetTreeElement = treeElement;
|
|
|
|
this._updateCallStackTreeOutline();
|
|
}
|
|
|
|
_findCallStackTargetTreeElement(target)
|
|
{
|
|
for (let child of this._callStackTreeOutline.children) {
|
|
if (child.target === target)
|
|
return child;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
_updateCallStackTreeOutline()
|
|
{
|
|
let singleThreadShowing = WI.targets.length <= 1;
|
|
this._callStackTreeOutline.element.classList.toggle("single-thread", singleThreadShowing);
|
|
if (this._mainTargetTreeElement)
|
|
this._mainTargetTreeElement.selectable = !singleThreadShowing;
|
|
}
|
|
|
|
_addResource(resource)
|
|
{
|
|
if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Path) {
|
|
if (!this._mainFrameTreeElement || this._resourcesTreeOutline.findTreeElement(resource))
|
|
return;
|
|
|
|
let parentTreeElement = null;
|
|
|
|
if (resource instanceof WI.CSSStyleSheet) {
|
|
console.assert(resource.isInspectorStyleSheet());
|
|
parentTreeElement = this._resourcesTreeOutline.findTreeElement(resource.parentFrame.mainResource);
|
|
}
|
|
|
|
if (!parentTreeElement) {
|
|
let origin = resource.urlComponents.origin;
|
|
if (origin) {
|
|
let originTreeElement = this._originTreeElementMap.get(origin);
|
|
if (!originTreeElement) {
|
|
let representedObject = resource.type === WI.Resource.Type.Document ? resource.parentFrame : null;
|
|
originTreeElement = new WI.OriginTreeElement(origin, representedObject, {hasChildren: true});
|
|
this._originTreeElementMap.set(origin, originTreeElement);
|
|
|
|
let index = insertionIndexForObjectInListSortedByFunction(originTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
|
|
this._resourcesTreeOutline.insertChild(originTreeElement, index);
|
|
}
|
|
|
|
let subpath = resource.urlComponents.path;
|
|
if (subpath && subpath[0] === "/")
|
|
subpath = subpath.substring(1);
|
|
|
|
parentTreeElement = originTreeElement.createFoldersAsNeededForSubpath(subpath, this._boundCompareTreeElements);
|
|
} else
|
|
parentTreeElement = this._resourcesTreeOutline;
|
|
}
|
|
|
|
let resourceTreeElement = null;
|
|
if (resource instanceof WI.CSSStyleSheet)
|
|
resourceTreeElement = new WI.CSSStyleSheetTreeElement(resource);
|
|
else {
|
|
let constructor = resource.type === WI.Resource.Type.WebSocket ? WI.WebSocketResourceTreeElement : WI.ResourceTreeElement;
|
|
resourceTreeElement = new constructor(resource, resource, {allowDirectoryAsName: true, hideOrigin: true});
|
|
}
|
|
|
|
let index = insertionIndexForObjectInListSortedByFunction(resourceTreeElement, parentTreeElement.children, this._boundCompareTreeElements);
|
|
parentTreeElement.insertChild(resourceTreeElement, index);
|
|
}
|
|
|
|
if (resource.type === WI.Resource.Type.Document || resource.type === WI.Resource.Type.Script) {
|
|
this._addBreakpointsForSourceCode(resource);
|
|
this._addIssuesForSourceCode(resource);
|
|
}
|
|
}
|
|
|
|
_addResourcesRecursivelyForFrame(frame)
|
|
{
|
|
this._addResource(frame.mainResource);
|
|
|
|
for (let resource of frame.resourceCollection)
|
|
this._addResource(resource);
|
|
|
|
for (let childFrame of frame.childFrameCollection)
|
|
this._addResourcesRecursivelyForFrame(childFrame);
|
|
|
|
if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Path) {
|
|
for (let styleSheet of WI.cssManager.inspectorStyleSheetsForFrame(frame))
|
|
this._addResource(styleSheet);
|
|
}
|
|
}
|
|
|
|
_addStyleSheet(styleSheet)
|
|
{
|
|
console.assert(styleSheet instanceof WI.CSSStyleSheet);
|
|
console.assert(!styleSheet.isInspectorStyleSheet());
|
|
|
|
// We don't add style sheets without URLs here. Those style sheets can quickly clutter the
|
|
// interface and are usually more transient. They will get added if/when they need to be
|
|
// shown in a content view.
|
|
if (styleSheet.anonymous)
|
|
return;
|
|
|
|
let parentTreeElement = null;
|
|
|
|
if (WI.browserManager.isExtensionScheme(styleSheet.urlComponents.scheme)) {
|
|
if (!this._extensionStyleSheetsFolderTreeElement)
|
|
this._extensionStyleSheetsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extension Style Sheets"), new WI.CSSStyleSheetCollection);
|
|
parentTreeElement = this._extensionStyleSheetsFolderTreeElement;
|
|
} else {
|
|
if (!this._extraStyleSheetsFolderTreeElement)
|
|
this._extraStyleSheetsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extra Style Sheets"), new WI.CSSStyleSheetCollection);
|
|
parentTreeElement = this._extraStyleSheetsFolderTreeElement;
|
|
}
|
|
|
|
if (!parentTreeElement.parent) {
|
|
let index = insertionIndexForObjectInListSortedByFunction(parentTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
|
|
this._resourcesTreeOutline.insertChild(parentTreeElement, index);
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
}
|
|
|
|
let treeElement = new WI.CSSStyleSheetTreeElement(styleSheet);
|
|
|
|
let index = insertionIndexForObjectInListSortedByFunction(treeElement, parentTreeElement.children, this._boundCompareTreeElements);
|
|
parentTreeElement.insertChild(treeElement, index);
|
|
}
|
|
|
|
_addScript(script)
|
|
{
|
|
console.assert(script instanceof WI.Script);
|
|
|
|
// We don't add scripts without URLs here. Those scripts can quickly clutter the interface and
|
|
// are usually more transient. They will get added if/when they need to be shown in a content view.
|
|
if (script.anonymous)
|
|
return;
|
|
|
|
// Target main resource.
|
|
if (WI.sharedApp.debuggableType !== WI.DebuggableType.JavaScript && WI.sharedApp.debuggableType !== WI.DebuggableType.ITML) {
|
|
if (script.target !== WI.pageTarget) {
|
|
if (script.isMainResource()) {
|
|
this._addWorkerTargetWithMainResource(script.target);
|
|
this._addBreakpointsForSourceCode(script);
|
|
this._addIssuesForSourceCode(script);
|
|
}
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If the script URL matches a resource we can assume it is part of that resource and does not need added.
|
|
if (script.resource || script.dynamicallyAddedScriptElement)
|
|
return;
|
|
|
|
let scriptTreeElement = new WI.ScriptTreeElement(script);
|
|
|
|
if (!script.injected && WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel()) {
|
|
let index = insertionIndexForObjectInListSortedByFunction(scriptTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
|
|
this._resourcesTreeOutline.insertChild(scriptTreeElement, index);
|
|
} else {
|
|
let parentFolderTreeElement = null;
|
|
|
|
if (WI.browserManager.isExtensionScheme(script.urlComponents.scheme)) {
|
|
if (!this._extensionScriptsFolderTreeElement) {
|
|
let collection = new WI.ScriptCollection;
|
|
this._extensionScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extension Scripts"), collection);
|
|
}
|
|
|
|
parentFolderTreeElement = this._extensionScriptsFolderTreeElement;
|
|
} else {
|
|
if (!this._extraScriptsFolderTreeElement) {
|
|
let collection = new WI.ScriptCollection;
|
|
this._extraScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extra Scripts"), collection);
|
|
}
|
|
|
|
parentFolderTreeElement = this._extraScriptsFolderTreeElement;
|
|
}
|
|
|
|
if (parentFolderTreeElement)
|
|
parentFolderTreeElement.representedObject.add(script);
|
|
|
|
if (!parentFolderTreeElement.parent) {
|
|
let index = insertionIndexForObjectInListSortedByFunction(parentFolderTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
|
|
this._resourcesTreeOutline.insertChild(parentFolderTreeElement, index);
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
}
|
|
|
|
parentFolderTreeElement.appendChild(scriptTreeElement);
|
|
}
|
|
|
|
this._addBreakpointsForSourceCode(script);
|
|
this._addIssuesForSourceCode(script);
|
|
}
|
|
|
|
_addWorkerTargetWithMainResource(target)
|
|
{
|
|
console.assert(target.type === WI.TargetType.Worker || target.type === WI.TargetType.ServiceWorker);
|
|
|
|
let targetTreeElement = new WI.WorkerTreeElement(target);
|
|
this._workerTargetTreeElementMap.set(target, targetTreeElement);
|
|
|
|
let index = insertionIndexForObjectInListSortedByFunction(targetTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
|
|
this._resourcesTreeOutline.insertChild(targetTreeElement, index);
|
|
}
|
|
|
|
_addDebuggerTreeElementForSourceCode(sourceCode)
|
|
{
|
|
let treeElement = this._breakpointsTreeOutline.findTreeElement(sourceCode);
|
|
if (!treeElement) {
|
|
if (sourceCode instanceof WI.SourceMapResource)
|
|
treeElement = new WI.SourceMapResourceTreeElement(sourceCode);
|
|
else if (sourceCode instanceof WI.Resource)
|
|
treeElement = new WI.ResourceTreeElement(sourceCode);
|
|
else if (sourceCode instanceof WI.Script)
|
|
treeElement = new WI.ScriptTreeElement(sourceCode);
|
|
}
|
|
|
|
if (!treeElement) {
|
|
console.error("Unknown sourceCode instance", sourceCode);
|
|
return null;
|
|
}
|
|
|
|
if (!treeElement.parent) {
|
|
treeElement.hasChildren = false;
|
|
treeElement.expand();
|
|
|
|
this._insertDebuggerTreeElement(treeElement, this._breakpointsTreeOutline);
|
|
}
|
|
|
|
return treeElement;
|
|
}
|
|
|
|
_insertDebuggerTreeElement(treeElement, parentTreeElement)
|
|
{
|
|
let comparator = (a, b) => {
|
|
const rankFunctions = [
|
|
(treeElement) => treeElement.representedObject === WI.debuggerManager.debuggerStatementsBreakpoint,
|
|
(treeElement) => treeElement.representedObject === WI.debuggerManager.allExceptionsBreakpoint,
|
|
(treeElement) => treeElement.representedObject === WI.debuggerManager.uncaughtExceptionsBreakpoint,
|
|
(treeElement) => treeElement.representedObject === WI.debuggerManager.assertionFailuresBreakpoint,
|
|
(treeElement) => treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement || (treeElement instanceof WI.JavaScriptBreakpointTreeElement && !treeElement.representedObject.special),
|
|
(treeElement) => treeElement instanceof WI.SymbolicBreakpointTreeElement,
|
|
(treeElement) => treeElement.representedObject === WI.debuggerManager.allMicrotasksBreakpoint,
|
|
(treeElement) => treeElement.representedObject === WI.domDebuggerManager.allAnimationFramesBreakpoint,
|
|
(treeElement) => treeElement.representedObject === WI.domDebuggerManager.allTimeoutsBreakpoint,
|
|
(treeElement) => treeElement.representedObject === WI.domDebuggerManager.allIntervalsBreakpoint,
|
|
(treeElement) => treeElement.representedObject === WI.domDebuggerManager.allListenersBreakpoint,
|
|
(treeElement) => treeElement instanceof WI.EventBreakpointTreeElement,
|
|
(treeElement) => treeElement instanceof WI.DOMNodeTreeElement,
|
|
(treeElement) => treeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject,
|
|
(treeElement) => treeElement instanceof WI.DOMBreakpointTreeElement,
|
|
(treeElement) => treeElement.representedObject === WI.domDebuggerManager.allRequestsBreakpoint,
|
|
(treeElement) => treeElement instanceof WI.URLBreakpointTreeElement,
|
|
];
|
|
|
|
let aRank = rankFunctions.findIndex((rankFunction) => rankFunction(a));
|
|
let bRank = rankFunctions.findIndex((rankFunction) => rankFunction(b));
|
|
if (aRank >= 0 && bRank >= 0) {
|
|
if (aRank < bRank)
|
|
return -1;
|
|
if (bRank < aRank)
|
|
return 1;
|
|
}
|
|
|
|
if (a instanceof WI.JavaScriptBreakpointTreeElement && b instanceof WI.JavaScriptBreakpointTreeElement)
|
|
return this._compareJavaScriptBreakpointTreeElements(a, b);
|
|
|
|
return a.mainTitle.extendedLocaleCompare(b.mainTitle) || a.subtitle.extendedLocaleCompare(b.subtitle);
|
|
};
|
|
|
|
parentTreeElement.insertChild(treeElement, insertionIndexForObjectInListSortedByFunction(treeElement, parentTreeElement.children, comparator));
|
|
}
|
|
|
|
_compareJavaScriptBreakpointTreeElements(a, b)
|
|
{
|
|
if (!a.representedObject || !b.representedObject)
|
|
return 0;
|
|
|
|
let aLocation = a.representedObject.sourceCodeLocation;
|
|
let bLocation = b.representedObject.sourceCodeLocation;
|
|
if (!aLocation || !bLocation)
|
|
return 0;
|
|
|
|
return aLocation.displayLineNumber - bLocation.displayLineNumber || aLocation.displayColumnNumber - bLocation.displayColumnNumber;
|
|
}
|
|
|
|
_addBreakpoint(breakpoint)
|
|
{
|
|
if (this._breakpointsTreeOutline.findTreeElement(breakpoint))
|
|
return null;
|
|
|
|
let constructor = WI.JavaScriptBreakpointTreeElement;
|
|
let options = {};
|
|
let parentTreeElement = this._breakpointsTreeOutline;
|
|
|
|
let getDOMNodeTreeElement = (domNode) => {
|
|
let domNodeTreeElement = this._breakpointsTreeOutline.findTreeElement(domNode);
|
|
if (!domNodeTreeElement) {
|
|
domNodeTreeElement = new WI.DOMNodeTreeElement(domNode);
|
|
this._insertDebuggerTreeElement(domNodeTreeElement, this._breakpointsTreeOutline);
|
|
}
|
|
return domNodeTreeElement;
|
|
};
|
|
|
|
if (breakpoint === WI.debuggerManager.debuggerStatementsBreakpoint)
|
|
options.classNames = ["debugger-statement"];
|
|
else if (breakpoint === WI.debuggerManager.allExceptionsBreakpoint)
|
|
options.classNames = ["exception"];
|
|
else if (breakpoint === WI.debuggerManager.uncaughtExceptionsBreakpoint)
|
|
options.classNames = ["exception"];
|
|
else if (breakpoint === WI.debuggerManager.assertionFailuresBreakpoint)
|
|
options.classNames = ["assertion"];
|
|
else if (breakpoint === WI.debuggerManager.allMicrotasksBreakpoint)
|
|
options.classNames = ["microtask"];
|
|
else if (breakpoint instanceof WI.DOMBreakpoint) {
|
|
if (!breakpoint.domNode)
|
|
return null;
|
|
|
|
constructor = WI.DOMBreakpointTreeElement;
|
|
|
|
parentTreeElement = getDOMNodeTreeElement(breakpoint.domNode);
|
|
} else if (breakpoint instanceof WI.EventBreakpoint) {
|
|
constructor = WI.EventBreakpointTreeElement;
|
|
|
|
if (breakpoint.eventListener) {
|
|
let eventTargetTreeElement = null;
|
|
if (breakpoint.eventListener.onWindow) {
|
|
if (!SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject)
|
|
SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject = {__window: true};
|
|
|
|
eventTargetTreeElement = this._breakpointsTreeOutline.findTreeElement(SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject);
|
|
if (!eventTargetTreeElement) {
|
|
const subtitle = null;
|
|
eventTargetTreeElement = new WI.GeneralTreeElement(["event-target-window"], WI.unlocalizedString("window"), subtitle, SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject);
|
|
this._insertDebuggerTreeElement(eventTargetTreeElement, this._breakpointsTreeOutline);
|
|
}
|
|
} else if (breakpoint.eventListener.node)
|
|
eventTargetTreeElement = getDOMNodeTreeElement(breakpoint.eventListener.node);
|
|
if (eventTargetTreeElement)
|
|
parentTreeElement = eventTargetTreeElement;
|
|
}
|
|
} else if (breakpoint instanceof WI.URLBreakpoint)
|
|
constructor = WI.URLBreakpointTreeElement;
|
|
else if (breakpoint instanceof WI.SymbolicBreakpoint)
|
|
constructor = WI.SymbolicBreakpointTreeElement;
|
|
else {
|
|
let sourceCode = breakpoint.sourceCodeLocation && breakpoint.sourceCodeLocation.displaySourceCode;
|
|
if (!sourceCode)
|
|
return null;
|
|
|
|
parentTreeElement = this._addDebuggerTreeElementForSourceCode(sourceCode);
|
|
|
|
// Mark disabled breakpoints as resolved if there is source code loaded with that URL.
|
|
// This gives the illusion the breakpoint was resolved, but since we don't send disabled
|
|
// breakpoints to the backend we don't know for sure. If the user enables the breakpoint
|
|
// it will be resolved properly.
|
|
if (breakpoint.disabled)
|
|
breakpoint.resolved = true;
|
|
}
|
|
|
|
let breakpointTreeElement = new constructor(breakpoint, options);
|
|
this._insertDebuggerTreeElement(breakpointTreeElement, parentTreeElement);
|
|
if (parentTreeElement.children.length === 1)
|
|
parentTreeElement.expand();
|
|
return breakpointTreeElement;
|
|
}
|
|
|
|
_removeBreakpoint(breakpoint)
|
|
{
|
|
if (this._pauseReasonTreeOutline) {
|
|
let pauseReasonBreakpointTreeElement = this._pauseReasonTreeOutline.findTreeElement(breakpoint);
|
|
if (pauseReasonBreakpointTreeElement)
|
|
pauseReasonBreakpointTreeElement.status = null;
|
|
}
|
|
|
|
let breakpointTreeElement = this._breakpointsTreeOutline.findTreeElement(breakpoint);
|
|
if (!breakpointTreeElement)
|
|
return;
|
|
|
|
this._removeDebuggerTreeElement(breakpointTreeElement);
|
|
}
|
|
|
|
_removeAllBreakpoints(breakpoints)
|
|
{
|
|
for (let breakpoint of breakpoints) {
|
|
if (breakpoint.removable)
|
|
WI.debuggerManager.removeBreakpoint(breakpoint);
|
|
}
|
|
}
|
|
|
|
_toggleAllBreakpoints(breakpoints, disabled)
|
|
{
|
|
for (let breakpoint of breakpoints)
|
|
breakpoint.disabled = disabled;
|
|
}
|
|
|
|
_breakpointsBeneathTreeElement(treeElement)
|
|
{
|
|
console.assert(treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement);
|
|
if (!(treeElement instanceof WI.ResourceTreeElement) && !(treeElement instanceof WI.ScriptTreeElement))
|
|
return [];
|
|
|
|
let breakpoints = [];
|
|
for (let child of treeElement.children) {
|
|
console.assert(child instanceof WI.JavaScriptBreakpointTreeElement);
|
|
let breakpoint = child.breakpoint;
|
|
console.assert(breakpoint);
|
|
if (breakpoint)
|
|
breakpoints.push(breakpoint);
|
|
}
|
|
return breakpoints;
|
|
}
|
|
|
|
_addIssue(issueMessage, sourceCode)
|
|
{
|
|
let issueTreeElement = this._resourcesTreeOutline.findTreeElement(issueMessage);
|
|
if (!issueTreeElement) {
|
|
console.assert(sourceCode || (issueMessage.sourceCodeLocation && issueMessage.sourceCodeLocation.sourceCode));
|
|
let parentTreeElement = this._resourcesTreeOutline.findTreeElement(sourceCode || issueMessage.sourceCodeLocation.sourceCode);
|
|
if (!parentTreeElement)
|
|
return null;
|
|
|
|
issueTreeElement = new WI.IssueTreeElement(issueMessage);
|
|
|
|
parentTreeElement.insertChild(issueTreeElement, insertionIndexForObjectInListSortedByFunction(issueTreeElement, parentTreeElement.children, this._compareJavaScriptBreakpointTreeElements));
|
|
if (parentTreeElement.children.length === 1)
|
|
parentTreeElement.expand();
|
|
}
|
|
return issueTreeElement;
|
|
}
|
|
|
|
_removeDebuggerTreeElement(debuggerTreeElement)
|
|
{
|
|
// If this is a BreakpointTreeElement being deleted because of a cause
|
|
// outside of the TreeOutline then deselect if it is selected to avoid
|
|
// TreeOutline selection changes causing unexpected ContentView changes.
|
|
if (!debuggerTreeElement.__deletedViaDeleteKeyboardShortcut)
|
|
debuggerTreeElement.deselect();
|
|
|
|
let parentTreeElement = debuggerTreeElement.parent;
|
|
parentTreeElement.removeChild(debuggerTreeElement);
|
|
|
|
if (parentTreeElement.children.length || parentTreeElement === this._breakpointsTreeOutline)
|
|
return;
|
|
|
|
parentTreeElement.treeOutline.removeChild(parentTreeElement);
|
|
}
|
|
|
|
_addBreakpointsForSourceCode(sourceCode)
|
|
{
|
|
for (let breakpoint of WI.debuggerManager.breakpointsForSourceCode(sourceCode))
|
|
this._addBreakpoint(breakpoint);
|
|
}
|
|
|
|
_addIssuesForSourceCode(sourceCode)
|
|
{
|
|
for (let issue of WI.consoleManager.issuesForSourceCode(sourceCode))
|
|
this._addIssue(issue, sourceCode);
|
|
}
|
|
|
|
_addLocalOverride(localOverride)
|
|
{
|
|
console.assert(WI.NetworkManager.supportsBootstrapScript() || WI.NetworkManager.supportsOverridingResponses());
|
|
|
|
if (this._localOverridesTreeOutline.findTreeElement(localOverride))
|
|
return;
|
|
|
|
let parentTreeElement = this._localOverridesTreeOutline;
|
|
|
|
let localOverrideTreeElement = null;
|
|
if (localOverride === WI.networkManager.bootstrapScript)
|
|
localOverrideTreeElement = new WI.BootstrapScriptTreeElement(localOverride);
|
|
else if (localOverride instanceof WI.LocalResourceOverride)
|
|
localOverrideTreeElement = new WI.LocalResourceOverrideTreeElement(localOverride);
|
|
console.assert(localOverrideTreeElement);
|
|
|
|
let index = insertionIndexForObjectInListSortedByFunction(localOverrideTreeElement, parentTreeElement.children, this._boundCompareTreeElements);
|
|
parentTreeElement.insertChild(localOverrideTreeElement, index);
|
|
|
|
this._localOverridesRow.hideEmptyMessage();
|
|
this._localOverridesRow.element.appendChild(this._localOverridesTreeOutline.element);
|
|
this._localOverridesContainer.hidden = false;
|
|
}
|
|
|
|
_removeResourceOverride(localOverride)
|
|
{
|
|
console.assert(WI.NetworkManager.supportsBootstrapScript() || WI.NetworkManager.supportsOverridingResponses());
|
|
|
|
let resourceTreeElement = this._localOverridesTreeOutline.findTreeElement(localOverride);
|
|
if (!resourceTreeElement)
|
|
return;
|
|
|
|
let wasSelected = resourceTreeElement.selected;
|
|
|
|
let parentTreeElement = this._localOverridesTreeOutline;
|
|
parentTreeElement.removeChild(resourceTreeElement);
|
|
|
|
if (!parentTreeElement.children.length) {
|
|
this._localOverridesContainer.hidden = true;
|
|
|
|
if (wasSelected && WI.networkManager.mainFrame && WI.networkManager.mainFrame.mainResource)
|
|
WI.showRepresentedObject(WI.networkManager.mainFrame.mainResource);
|
|
}
|
|
}
|
|
|
|
_addConsoleSnippet(consoleSnippet)
|
|
{
|
|
console.assert(consoleSnippet instanceof WI.ConsoleSnippet, consoleSnippet);
|
|
|
|
if (this._consoleSnippetsTreeOutline.findTreeElement(consoleSnippet))
|
|
return;
|
|
|
|
let parentTreeElement = this._consoleSnippetsTreeOutline;
|
|
|
|
let consoleSnippetTreeElement = new WI.ConsoleSnippetTreeElement(consoleSnippet);
|
|
|
|
let index = insertionIndexForObjectInListSortedByFunction(consoleSnippetTreeElement, parentTreeElement.children, this._boundCompareTreeElements);
|
|
parentTreeElement.insertChild(consoleSnippetTreeElement, index);
|
|
|
|
this._consoleSnippetsRow.hideEmptyMessage();
|
|
this._consoleSnippetsRow.element.appendChild(this._consoleSnippetsTreeOutline.element);
|
|
this._consoleSnippetsContainer.hidden = false;
|
|
}
|
|
|
|
_removeConsoleSnippet(consoleSnippet)
|
|
{
|
|
console.assert(consoleSnippet instanceof WI.ConsoleSnippet, consoleSnippet);
|
|
|
|
let consoleSnippetTreeElement = this._consoleSnippetsTreeOutline.findTreeElement(consoleSnippet);
|
|
if (!consoleSnippetTreeElement)
|
|
return;
|
|
|
|
let wasSelected = consoleSnippetTreeElement.selected;
|
|
|
|
let parentTreeElement = this._consoleSnippetsTreeOutline;
|
|
parentTreeElement.removeChild(consoleSnippetTreeElement);
|
|
|
|
if (!parentTreeElement.children.length) {
|
|
this._consoleSnippetsContainer.hidden = true;
|
|
|
|
if (wasSelected && WI.networkManager.mainFrame && WI.networkManager.mainFrame.mainResource)
|
|
WI.showRepresentedObject(WI.networkManager.mainFrame.mainResource);
|
|
}
|
|
}
|
|
|
|
_updateTemporarilyDisabledBreakpointsButtons()
|
|
{
|
|
let breakpointsDisabledTemporarily = WI.debuggerManager.breakpointsDisabledTemporarily;
|
|
this._debuggerBreakpointsButtonItem.enabled = !breakpointsDisabledTemporarily;
|
|
this._debuggerPauseResumeButtonItem.enabled = !breakpointsDisabledTemporarily;
|
|
}
|
|
|
|
_updateBreakpointsDisabledBanner()
|
|
{
|
|
if (!WI.debuggerManager.breakpointsEnabled && !this._timelineRecordingWarningElement && !this._auditTestWarningElement) {
|
|
if (!this._breakpointsDisabledWarningElement) {
|
|
let enableBreakpointsButton = document.createElement("button");
|
|
enableBreakpointsButton.textContent = WI.UIString("Enable Breakpoints");
|
|
enableBreakpointsButton.addEventListener("click", () => {
|
|
WI.debuggerToggleBreakpoints();
|
|
});
|
|
|
|
this._breakpointsDisabledWarningElement = document.createElement("div");
|
|
this._breakpointsDisabledWarningElement.classList.add("warning-banner");
|
|
this._breakpointsDisabledWarningElement.append(WI.UIString("Breakpoints disabled"), document.createElement("br"), enableBreakpointsButton);
|
|
}
|
|
|
|
this.contentView.element.insertBefore(this._breakpointsDisabledWarningElement, this.contentView.element.firstChild);
|
|
} else if (this._breakpointsDisabledWarningElement) {
|
|
this._breakpointsDisabledWarningElement.remove();
|
|
this._breakpointsDisabledWarningElement = null;
|
|
}
|
|
}
|
|
|
|
_updatePauseReason()
|
|
{
|
|
this._pauseReasonTreeOutline = null;
|
|
|
|
this._updatePauseReasonGotoArrow();
|
|
|
|
let target = WI.debuggerManager.activeCallFrame.target;
|
|
let targetData = WI.debuggerManager.dataForTarget(target);
|
|
return this._updatePauseReasonSection(target, targetData.pauseReason, targetData.pauseData);
|
|
}
|
|
|
|
_updatePauseReasonGotoArrow()
|
|
{
|
|
this._pauseReasonLinkContainerElement.removeChildren();
|
|
|
|
let activeCallFrame = WI.debuggerManager.activeCallFrame;
|
|
if (!activeCallFrame)
|
|
return;
|
|
|
|
let sourceCodeLocation = activeCallFrame.sourceCodeLocation;
|
|
if (!sourceCodeLocation)
|
|
return;
|
|
|
|
const options = {
|
|
useGoToArrowButton: true,
|
|
};
|
|
let linkElement = WI.createSourceCodeLocationLink(sourceCodeLocation, options);
|
|
this._pauseReasonLinkContainerElement.appendChild(linkElement);
|
|
}
|
|
|
|
_updatePauseReasonSection(target, pauseReason, pauseData)
|
|
{
|
|
switch (pauseReason) {
|
|
case WI.DebuggerManager.PauseReason.AnimationFrame:
|
|
if (!this._updatePauseReasonForBreakpoint(WI.domDebuggerManager.allAnimationFramesBreakpoint, WI.UIString("requestAnimationFrame Fired"))) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
|
|
case WI.DebuggerManager.PauseReason.Assertion: {
|
|
// FIXME: We should include the assertion condition string.
|
|
console.assert(pauseData, "Expected data with an assertion, but found none.");
|
|
|
|
let title = pauseData?.message ? this._createBreakpointPauseReasonTitleWithTooltip(WI.UIString("Assertion Failed: %s"), pauseData.message) : WI.UIString("Assertion Failed");
|
|
if (!this._updatePauseReasonForBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint, title)) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.BlackboxedScript: {
|
|
console.assert(pauseData);
|
|
if (pauseData)
|
|
this._updatePauseReasonSection(target, WI.DebuggerManager.pauseReasonFromPayload(pauseData.originalReason), pauseData.originalData);
|
|
|
|
// Don't use `_pauseReasonTextRow` as it may have already been set.
|
|
let blackboxReasonTextRow = new WI.DetailsSectionTextRow(WI.UIString("Deferred pause from blackboxed script"));
|
|
blackboxReasonTextRow.__blackboxReason = true;
|
|
|
|
let existingRows = this._pauseReasonGroup.rows.filter((row) => !row.__blackboxReason);
|
|
this._pauseReasonGroup.rows = [blackboxReasonTextRow, ...existingRows];
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.Breakpoint: {
|
|
console.assert(pauseData, "Expected breakpoint identifier, but found none.");
|
|
if (!pauseData || !pauseData.breakpointId)
|
|
break;
|
|
|
|
let breakpoint = WI.debuggerManager.breakpointForIdentifier(pauseData.breakpointId);
|
|
console.assert(breakpoint, pauseData.breakpointId);
|
|
if (!breakpoint)
|
|
break;
|
|
|
|
if (!this._updatePauseReasonForBreakpoint(breakpoint, WI.UIString("Triggered Breakpoint"))) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.CSPViolation: {
|
|
console.assert(pauseData, "Expected data with a CSP Violation, but found none.");
|
|
if (!pauseData)
|
|
break;
|
|
|
|
let breakpoint = WI.debuggerManager.allExceptionsBreakpoint || WI.debuggerManager.uncaughtExceptionsBreakpoint;
|
|
let titleElement = this._createBreakpointPauseReasonTitleWithTooltip(WI.UIString("Content Security Policy violation of directive: %s"), pauseData.directive);
|
|
if (!this._updatePauseReasonForBreakpoint(breakpoint, titleElement)) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.DebuggerStatement:
|
|
if (!WI.JavaScriptBreakpoint.supportsDebuggerStatements()) {
|
|
this._pauseReasonTextRow.text = WI.UIString("Debugger Statement");
|
|
this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
|
|
return true;
|
|
}
|
|
|
|
if (!this._updatePauseReasonForBreakpoint(WI.debuggerManager.debuggerStatementsBreakpoint, WI.UIString("Debugger Statement"))) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
|
|
case WI.DebuggerManager.PauseReason.DOM: {
|
|
console.assert(WI.domDebuggerManager.supported);
|
|
console.assert(pauseData, "Expected DOM breakpoint data, but found none.");
|
|
if (!pauseData || !pauseData.nodeId)
|
|
break;
|
|
|
|
let domNode = WI.domManager.nodeForId(pauseData.nodeId);
|
|
let domBreakpoints = WI.domDebuggerManager.domBreakpointsForNode(domNode);
|
|
let domBreakpoint;
|
|
for (let breakpoint of domBreakpoints) {
|
|
if (breakpoint.type === pauseData.type) {
|
|
domBreakpoint = breakpoint;
|
|
break;
|
|
}
|
|
}
|
|
|
|
console.assert(domBreakpoint, "Missing DOM breakpoint of type for node", pauseData.type, domNode);
|
|
if (!domBreakpoint)
|
|
break;
|
|
|
|
if (!this._updatePauseReasonForBreakpoint(domBreakpoint, WI.DOMBreakpoint.displayNameForType(domBreakpoint.type))) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
|
|
let ownerElementRow = new WI.DetailsSectionSimpleRow(WI.UIString("Element"), WI.linkifyNodeReference(domNode));
|
|
this._pauseReasonGroup.rows = this._pauseReasonGroup.rows.concat(ownerElementRow);
|
|
|
|
let updateTargetDescription = (nodeId) => {
|
|
if (!nodeId)
|
|
return;
|
|
|
|
let node = WI.domManager.nodeForId(nodeId);
|
|
console.assert(node, "Missing node for id.", nodeId);
|
|
if (!node)
|
|
return;
|
|
|
|
let fragment = document.createDocumentFragment();
|
|
|
|
let description = null;
|
|
switch (domBreakpoint.type) {
|
|
case WI.DOMBreakpoint.Type.SubtreeModified:
|
|
description = pauseData.insertion ? WI.UIString("Child added to ") : WI.UIString("Removed descendant ");
|
|
break;
|
|
case WI.DOMBreakpoint.Type.NodeRemoved:
|
|
description = WI.UIString("Removed ancestor ");
|
|
break;
|
|
}
|
|
console.assert(description);
|
|
fragment.append(description, WI.linkifyNodeReference(node));
|
|
|
|
let targetDescriptionRow = new WI.DetailsSectionSimpleRow(WI.UIString("Details"), fragment);
|
|
targetDescriptionRow.element.classList.add("target-description");
|
|
|
|
this._pauseReasonGroup.rows = this._pauseReasonGroup.rows.concat(targetDescriptionRow);
|
|
};
|
|
|
|
if (pauseData.targetNodeId) {
|
|
console.assert(domBreakpoint.type === WI.DOMBreakpoint.Type.SubtreeModified || domBreakpoint.type === WI.DOMBreakpoint.Type.NodeRemoved);
|
|
console.assert(pauseData.targetNodeId !== domBreakpoint.domNode.id, pauseData.targetNodeId, domBreakpoint);
|
|
updateTargetDescription(pauseData.targetNodeId);
|
|
} else if (pauseData.targetNode) { // COMPATIBILITY (iOS 13): `targetNode` was renamed to `targetNodeId` and was changed from a `Runtime.RemoteObject` to a `DOM.NodeId`.
|
|
console.assert(domBreakpoint.type === WI.DOMBreakpoint.Type.SubtreeModified);
|
|
let remoteObject = WI.RemoteObject.fromPayload(pauseData.targetNode, target);
|
|
remoteObject.pushNodeToFrontend(updateTargetDescription);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.Listener:
|
|
case WI.DebuggerManager.PauseReason.EventListener: {
|
|
console.assert(pauseData, "Expected data with an event listener, but found none.");
|
|
if (!pauseData)
|
|
break;
|
|
|
|
let eventBreakpoint = null;
|
|
if (pauseData.eventListenerId)
|
|
eventBreakpoint = WI.domManager.breakpointForEventListenerId(pauseData.eventListenerId);
|
|
if (!eventBreakpoint)
|
|
eventBreakpoint = WI.domDebuggerManager.listenerBreakpointsForEventName(pauseData.eventName)[0];
|
|
|
|
console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName);
|
|
if (!eventBreakpoint)
|
|
break;
|
|
|
|
let titleElement = this._createBreakpointPauseReasonTitleWithTooltip(WI.UIString("\u201C%s\u201D Event Fired"), pauseData.eventName);
|
|
if (!this._updatePauseReasonForBreakpoint(eventBreakpoint, titleElement)) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
|
|
let eventListener = eventBreakpoint.eventListener;
|
|
if (eventListener) {
|
|
console.assert(eventListener.eventListenerId === pauseData.eventListenerId);
|
|
|
|
let value = null;
|
|
if (eventListener.onWindow)
|
|
value = WI.unlocalizedString("window");
|
|
else if (eventListener.node)
|
|
value = WI.linkifyNodeReference(eventListener.node);
|
|
if (value)
|
|
this._pauseReasonGroup.rows = this._pauseReasonGroup.rows.concat(new WI.DetailsSectionSimpleRow(WI.UIString("Target"), value));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.Exception: {
|
|
console.assert(pauseData, "Expected data with an exception, but found none.");
|
|
if (!pauseData)
|
|
break;
|
|
|
|
// FIXME: We should improve the appearance of thrown objects. This works well for exception strings.
|
|
let data = WI.RemoteObject.fromPayload(pauseData, target);
|
|
|
|
let breakpoint = WI.debuggerManager.allExceptionsBreakpoint || WI.debuggerManager.uncaughtExceptionsBreakpoint;
|
|
let titleElement = this._createBreakpointPauseReasonTitleWithTooltip(WI.UIString("Exception with thrown value: %s"), data.description);
|
|
if (!this._updatePauseReasonForBreakpoint(breakpoint, titleElement)) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.FunctionCall: {
|
|
console.assert(pauseData, "Expected data with an event listener, but found none.");
|
|
if (!pauseData)
|
|
break;
|
|
|
|
let symbolicBreakpoint = WI.debuggerManager.symbolicBreakpointsForSymbol(pauseData.name)[0];
|
|
console.assert(symbolicBreakpoint, "Expected Symbolic breakpoint for function name.", pauseData.name);
|
|
if (!symbolicBreakpoint)
|
|
break;
|
|
|
|
const format = WI.UIString("Calling Function \u201C%s\u201D", "Calling Function \u201C%s\u201D @ Sources Navigation Sidebar Panel", "Label shown when JavaScript execution is paused due to a symbolic breakpoint.");
|
|
let titleElement = this._createBreakpointPauseReasonTitleWithTooltip(format, pauseData.name);
|
|
if (!this._updatePauseReasonForBreakpoint(symbolicBreakpoint, titleElement)) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.Interval:
|
|
if (!this._updatePauseReasonForBreakpoint(WI.debuggerManager.allIntervalsBreakpoint, WI.UIString("setInterval Fired"))) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
|
|
case WI.DebuggerManager.PauseReason.Microtask:
|
|
if (!this._updatePauseReasonForBreakpoint(WI.debuggerManager.allMicrotasksBreakpoint, WI.UIString("Microtask Fired"))) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
|
|
case WI.DebuggerManager.PauseReason.PauseOnNextStatement:
|
|
this._pauseReasonTextRow.text = WI.UIString("Immediate Pause Requested");
|
|
this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
|
|
return true;
|
|
|
|
case WI.DebuggerManager.PauseReason.Timer: {
|
|
console.assert(pauseData, "Expected data with a timer, but found none.");
|
|
if (!pauseData)
|
|
break;
|
|
|
|
switch (pauseData.eventName) {
|
|
case "setTimeout":
|
|
if (!this._updatePauseReasonForBreakpoint(WI.domDebuggerManager.allTimeoutsBreakpoint, WI.UIString("setTimeout Fired")))
|
|
break;
|
|
return true;
|
|
|
|
case "setInterval":
|
|
if (!this._updatePauseReasonForBreakpoint(WI.domDebuggerManager.allIntervalsBreakpoint, WI.UIString("setInterval Fired")))
|
|
break;
|
|
return true;
|
|
}
|
|
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.Timeout:
|
|
this._updatePauseReasonForBreakpoint(WI.domDebuggerManager.allTimeoutsBreakpoint, WI.UIString("setTimeout Fired"));
|
|
return true;
|
|
|
|
case WI.DebuggerManager.PauseReason.URL: {
|
|
console.assert(WI.domDebuggerManager.supported);
|
|
console.assert(pauseData, "Expected URL breakpoint data, but found none.");
|
|
if (!pauseData)
|
|
break;
|
|
|
|
let urlBreakpoint = null;
|
|
if (pauseData.breakpointURL)
|
|
urlBreakpoint = WI.domDebuggerManager.urlBreakpointForURL(pauseData.breakpointURL);
|
|
else {
|
|
console.assert(pauseData.breakpointURL === "", "Should be the All Requests breakpoint which has an empty URL");
|
|
urlBreakpoint = WI.domDebuggerManager.allRequestsBreakpoint;
|
|
}
|
|
console.assert(urlBreakpoint, pauseData.breakpointURL);
|
|
if (!urlBreakpoint)
|
|
break;
|
|
|
|
let titleElement = this._createBreakpointPauseReasonTitleWithTooltip(WI.UIString("Requesting \u201C%s\u201D"), pauseData.url);
|
|
if (!this._updatePauseReasonForBreakpoint(urlBreakpoint, titleElement)) {
|
|
console.assert(false, "not reached");
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
case WI.DebuggerManager.PauseReason.Other:
|
|
console.error("Paused for unknown reason. We should always have a reason.");
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
_updatePauseReasonForBreakpoint(breakpoint, title)
|
|
{
|
|
let Constructor = null;
|
|
if (breakpoint instanceof WI.JavaScriptBreakpoint)
|
|
Constructor = WI.JavaScriptBreakpointTreeElement;
|
|
else if (breakpoint instanceof WI.DOMBreakpoint)
|
|
Constructor = WI.DOMBreakpointTreeElement;
|
|
else if (breakpoint instanceof WI.EventBreakpoint)
|
|
Constructor = WI.EventBreakpointTreeElement;
|
|
else if (breakpoint instanceof WI.URLBreakpoint)
|
|
Constructor = WI.URLBreakpointTreeElement;
|
|
else if (breakpoint instanceof WI.SymbolicBreakpoint)
|
|
Constructor = WI.SymbolicBreakpointTreeElement;
|
|
console.assert(Constructor);
|
|
if (!Constructor)
|
|
return false;
|
|
|
|
this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
|
|
this._pauseReasonTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
|
|
|
|
let breakpointTreeElement = new Constructor(breakpoint, {
|
|
classNames: ["paused"],
|
|
title,
|
|
})
|
|
this._pauseReasonTreeOutline.appendChild(breakpointTreeElement);
|
|
|
|
let breakpointRow = new WI.DetailsSectionRow;
|
|
breakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
|
|
|
|
this._pauseReasonGroup.rows = [breakpointRow];
|
|
|
|
return true;
|
|
}
|
|
|
|
_createBreakpointPauseReasonTitleWithTooltip(format, title)
|
|
{
|
|
let titleElement = document.createElement("span");
|
|
titleElement.textContent = format.format(title);
|
|
titleElement.title = title;
|
|
return titleElement;
|
|
}
|
|
|
|
_handleResourceGroupingModeScopeBarSelectionChanged(event)
|
|
{
|
|
console.assert(this._resourceGroupingModeScopeBar.selectedItems.length === 1);
|
|
let selectedScopeBarItem = this._resourceGroupingModeScopeBar.selectedItems[0];
|
|
WI.settings.resourceGroupingMode.value = selectedScopeBarItem[SourcesNavigationSidebarPanel.ResourceGroupingModeSymbol] || WI.Resource.GroupingMode.Type;
|
|
}
|
|
|
|
_handleResourceTypeScopeBarSelectionChanged(event)
|
|
{
|
|
this.updateFilter();
|
|
}
|
|
|
|
_handleTreeSelectionDidChange(event)
|
|
{
|
|
if (!this.selected)
|
|
return;
|
|
|
|
let treeElement = event.target.selectedTreeElement;
|
|
if (!treeElement)
|
|
return;
|
|
|
|
if (treeElement instanceof WI.DOMNodeTreeElement
|
|
|| treeElement instanceof WI.DOMBreakpointTreeElement
|
|
|| treeElement instanceof WI.EventBreakpointTreeElement
|
|
|| treeElement instanceof WI.URLBreakpointTreeElement
|
|
|| treeElement instanceof WI.SymbolicBreakpointTreeElement)
|
|
return;
|
|
|
|
if (treeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject)
|
|
return;
|
|
|
|
if (treeElement instanceof WI.LocalResourceOverrideTreeElement) {
|
|
WI.showRepresentedObject(treeElement.representedObject);
|
|
return;
|
|
}
|
|
|
|
// Silently select the corresponding tree element in the resources tree outline to update
|
|
// the hierarchical path components to show the right ancestor(s).
|
|
let selectTreeElementInResourcesTreeOutline = (sourceCode) => {
|
|
let resourceTreeElement = this._resourcesTreeOutline.findTreeElement(sourceCode);
|
|
if (!resourceTreeElement)
|
|
return;
|
|
|
|
const omitFocus = true;
|
|
const selectedByUser = false;
|
|
const suppressNotification = true;
|
|
resourceTreeElement.select(omitFocus, selectedByUser, suppressNotification);
|
|
};
|
|
|
|
if (treeElement instanceof WI.FolderTreeElement
|
|
|| treeElement instanceof WI.OriginTreeElement
|
|
|| treeElement instanceof WI.ResourceTreeElement
|
|
|| treeElement instanceof WI.ScriptTreeElement
|
|
|| treeElement instanceof WI.CSSStyleSheetTreeElement) {
|
|
let representedObject = treeElement.representedObject;
|
|
|
|
if (representedObject instanceof WI.Script && representedObject.resource)
|
|
representedObject = representedObject.resource;
|
|
|
|
if (treeElement.treeOutline !== this._resourcesTreeOutline)
|
|
selectTreeElementInResourcesTreeOutline(representedObject);
|
|
|
|
if (representedObject instanceof WI.Collection || representedObject instanceof WI.SourceCode || representedObject instanceof WI.Frame)
|
|
WI.showRepresentedObject(representedObject);
|
|
return;
|
|
}
|
|
|
|
if (treeElement instanceof WI.CallFrameTreeElement) {
|
|
let callFrame = treeElement.callFrame;
|
|
if (callFrame.id)
|
|
WI.debuggerManager.activeCallFrame = callFrame;
|
|
if (callFrame.sourceCodeLocation)
|
|
WI.showSourceCodeLocation(callFrame.sourceCodeLocation);
|
|
return;
|
|
}
|
|
|
|
if (treeElement instanceof WI.IssueTreeElement) {
|
|
WI.showSourceCodeLocation(treeElement.issueMessage.sourceCodeLocation);
|
|
return;
|
|
}
|
|
|
|
if (treeElement instanceof WI.JavaScriptBreakpointTreeElement) {
|
|
let breakpoint = treeElement.breakpoint;
|
|
if (breakpoint.special)
|
|
return;
|
|
|
|
let sourceCode = breakpoint.sourceCodeLocation.displaySourceCode;
|
|
if (sourceCode instanceof WI.Script && sourceCode.resource)
|
|
sourceCode = sourceCode.resource;
|
|
selectTreeElementInResourcesTreeOutline(sourceCode);
|
|
|
|
WI.showSourceCodeLocation(breakpoint.sourceCodeLocation);
|
|
return;
|
|
}
|
|
|
|
if (treeElement instanceof WI.BlackboxedGroupTreeElement)
|
|
return;
|
|
|
|
console.error("Unknown tree element", treeElement);
|
|
}
|
|
|
|
_handleBreakpointTreeOutlineElementRemoved(event)
|
|
{
|
|
let selectedTreeElement = this._breakpointsTreeOutline.selectedTreeElement;
|
|
if (!selectedTreeElement)
|
|
return;
|
|
|
|
// Select the next removable breakpoint instead of a non-removable breakpoint.
|
|
if (selectedTreeElement.representedObject instanceof WI.Breakpoint && !selectedTreeElement.representedObject.removable) {
|
|
const skipUnrevealed = true;
|
|
const stayWithin = null;
|
|
const dontPopulate = true;
|
|
let treeElementToSelect = selectedTreeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
|
|
if (treeElementToSelect) {
|
|
const omitFocus = true;
|
|
const selectedByUser = true;
|
|
treeElementToSelect.select(omitFocus, selectedByUser);
|
|
}
|
|
}
|
|
}
|
|
|
|
_populateCreateBreakpointContextMenu(contextMenu)
|
|
{
|
|
function addToggleForSpecialBreakpoint(label, breakpoint, callback) {
|
|
contextMenu.appendCheckboxItem(label, () => {
|
|
if (breakpoint)
|
|
breakpoint.remove();
|
|
else
|
|
callback();
|
|
}, !!breakpoint);
|
|
}
|
|
|
|
if (WI.SymbolicBreakpoint.supported()) {
|
|
contextMenu.appendItem(WI.UIString("Symbolic Breakpoint\u2026", "Symbolic Breakpoint\u2026 @ Sources Navigation Sidebar Panel", "Context menu item for creating a new symbolic breakpoint."), () => {
|
|
let popover = new WI.SymbolicBreakpointPopover(this);
|
|
popover.show(this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
|
|
});
|
|
|
|
contextMenu.appendSeparator();
|
|
}
|
|
|
|
addToggleForSpecialBreakpoint(WI.repeatedUIString.assertionFailures(), WI.debuggerManager.assertionFailuresBreakpoint, () => {
|
|
WI.debuggerManager.createAssertionFailuresBreakpoint();
|
|
});
|
|
|
|
contextMenu.appendSeparator();
|
|
|
|
if (WI.JavaScriptBreakpoint.supportsMicrotasks()) {
|
|
addToggleForSpecialBreakpoint(WI.repeatedUIString.allMicrotasks(), WI.debuggerManager.allMicrotasksBreakpoint, () => {
|
|
WI.debuggerManager.createAllMicrotasksBreakpoint();
|
|
});
|
|
}
|
|
|
|
if (WI.DOMDebuggerManager.supportsEventBreakpoints() || WI.DOMDebuggerManager.supportsEventListenerBreakpoints()) {
|
|
addToggleForSpecialBreakpoint(WI.repeatedUIString.allAnimationFrames(), WI.domDebuggerManager.allAnimationFramesBreakpoint, () => {
|
|
WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(WI.EventBreakpoint.Type.AnimationFrame));
|
|
});
|
|
addToggleForSpecialBreakpoint(WI.repeatedUIString.allTimeouts(), WI.domDebuggerManager.allTimeoutsBreakpoint, () => {
|
|
WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(WI.EventBreakpoint.Type.Timeout));
|
|
});
|
|
addToggleForSpecialBreakpoint(WI.repeatedUIString.allIntervals(), WI.domDebuggerManager.allIntervalsBreakpoint, () => {
|
|
WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(WI.EventBreakpoint.Type.Interval));
|
|
});
|
|
|
|
contextMenu.appendSeparator();
|
|
|
|
if (WI.DOMDebuggerManager.supportsAllListenersBreakpoint())
|
|
addToggleForSpecialBreakpoint(WI.repeatedUIString.allEvents(), WI.domDebuggerManager.allListenersBreakpoint, () => {
|
|
WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(WI.EventBreakpoint.Type.Listener));
|
|
});
|
|
|
|
contextMenu.appendItem(WI.UIString("Event Breakpoint\u2026"), () => {
|
|
let popover = new WI.EventBreakpointPopover(this);
|
|
popover.show(this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
|
|
});
|
|
}
|
|
|
|
if (WI.DOMDebuggerManager.supportsURLBreakpoints() || WI.DOMDebuggerManager.supportsXHRBreakpoints()) {
|
|
contextMenu.appendSeparator();
|
|
|
|
addToggleForSpecialBreakpoint(WI.repeatedUIString.allRequests(), WI.domDebuggerManager.allRequestsBreakpoint, () => {
|
|
const url = "";
|
|
WI.domDebuggerManager.addURLBreakpoint(new WI.URLBreakpoint(WI.URLBreakpoint.Type.Text, url));
|
|
});
|
|
|
|
contextMenu.appendItem(WI.DOMDebuggerManager.supportsURLBreakpoints() ? WI.UIString("URL Breakpoint\u2026") : WI.UIString("XHR Breakpoint\u2026"), () => {
|
|
let popover = new WI.URLBreakpointPopover(this);
|
|
popover.show(this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
|
|
});
|
|
}
|
|
}
|
|
|
|
_populateCreateLocalOverrideContextMenu(contextMenu)
|
|
{
|
|
if (WI.NetworkManager.supportsOverridingResponses()) {
|
|
contextMenu.appendItem(WI.UIString("Local Override\u2026"), () => {
|
|
let popover = new WI.LocalResourceOverridePopover(this);
|
|
popover.show(null, this._createLocalOverrideButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
|
|
});
|
|
}
|
|
|
|
if (WI.NetworkManager.supportsBootstrapScript()) {
|
|
contextMenu.appendItem(WI.UIString("Inspector Bootstrap Script"), async () => {
|
|
await WI.networkManager.createBootstrapScript();
|
|
WI.networkManager.bootstrapScriptEnabled = true;
|
|
WI.showRepresentedObject(WI.networkManager.bootstrapScript);
|
|
});
|
|
}
|
|
}
|
|
|
|
_handleCreateConsoleSnippetButtonClicked(event)
|
|
{
|
|
let popover = new WI.InputPopover("create-snippet-popover", WI.UIString("Name"), this);
|
|
popover.show(this._createConsoleSnippetButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
|
|
}
|
|
|
|
_populateCreateResourceContextMenu(contextMenu)
|
|
{
|
|
if (WI.NetworkManager.supportsOverridingResponses()) {
|
|
contextMenu.appendItem(WI.UIString("Local Override\u2026"), () => {
|
|
if (!this._localOverridesTreeOutline.children.length)
|
|
this._localOverridesRow.showEmptyMessage();
|
|
|
|
this._localOverridesContainer.hidden = false;
|
|
|
|
this._createLocalOverrideButton.element.scrollIntoViewIfNeeded(false);
|
|
requestAnimationFrame(() => {
|
|
let popover = new WI.LocalResourceOverridePopover(this);
|
|
popover.show(null, this._createLocalOverrideButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
|
|
});
|
|
});
|
|
}
|
|
|
|
contextMenu.appendItem(WI.UIString("Console Snippet\u2026"), () => {
|
|
if (!this._consoleSnippetsTreeOutline.children.length)
|
|
this._consoleSnippetsRow.showEmptyMessage();
|
|
|
|
this._consoleSnippetsContainer.hidden = false;
|
|
|
|
this._createConsoleSnippetButton.element.scrollIntoViewIfNeeded(false);
|
|
requestAnimationFrame(() => {
|
|
let popover = new WI.InputPopover("create-snippet-popover", WI.UIString("Name"), this);
|
|
popover.show(this._createConsoleSnippetButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
|
|
});
|
|
});
|
|
|
|
if (WI.NetworkManager.supportsBootstrapScript()) {
|
|
contextMenu.appendItem(WI.UIString("Inspector Bootstrap Script"), async () => {
|
|
await WI.networkManager.createBootstrapScript();
|
|
WI.networkManager.bootstrapScriptEnabled = true;
|
|
WI.showRepresentedObject(WI.networkManager.bootstrapScript);
|
|
});
|
|
}
|
|
|
|
if (WI.CSSManager.supportsInspectorStyleSheet()) {
|
|
let addInspectorStyleSheetItem = (menu, frame) => {
|
|
menu.appendItem(WI.UIString("Inspector Style Sheet"), () => {
|
|
if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Path) {
|
|
// Force the parent to populate.
|
|
let parentFrameTreeElement = this._resourcesTreeOutline.findTreeElement(frame.mainResource);
|
|
parentFrameTreeElement.reveal();
|
|
parentFrameTreeElement.expand();
|
|
}
|
|
|
|
WI.cssManager.preferredInspectorStyleSheetForFrame(frame, (styleSheet) => {
|
|
WI.showRepresentedObject(styleSheet);
|
|
});
|
|
});
|
|
};
|
|
|
|
addInspectorStyleSheetItem(contextMenu, WI.networkManager.mainFrame);
|
|
|
|
let frames = WI.networkManager.frames;
|
|
if (frames.length > 2) {
|
|
let framesSubMenu = contextMenu.appendSubMenuItem(WI.UIString("Frames"));
|
|
|
|
for (let frame of frames) {
|
|
if (frame === WI.networkManager.mainFrame || frame.mainResource.type !== WI.Resource.Type.Document)
|
|
continue;
|
|
|
|
let frameSubMenuItem = framesSubMenu.appendSubMenuItem(frame.name ? WI.UIString("%s (%s)").format(frame.name, frame.mainResource.displayName) : frame.mainResource.displayName);
|
|
|
|
addInspectorStyleSheetItem(frameSubMenuItem, frame);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_handleResourceGroupingModeChanged(event)
|
|
{
|
|
this._workerTargetTreeElementMap.clear();
|
|
this._mainFrameTreeElement = null;
|
|
this._extensionScriptsFolderTreeElement = null;
|
|
this._extensionStyleSheetsFolderTreeElement = null;
|
|
this._extraScriptsFolderTreeElement = null;
|
|
this._extraStyleSheetsFolderTreeElement = null;
|
|
this._anonymousScriptsFolderTreeElement = null;
|
|
this._anonymousStyleSheetsFolderTreeElement = null;
|
|
|
|
this._originTreeElementMap.clear();
|
|
|
|
let resourceGroupingModeScopeBarItem = this._resourceGroupingModeScopeBarItems[WI.settings.resourceGroupingMode.value];
|
|
console.assert(resourceGroupingModeScopeBarItem);
|
|
if (resourceGroupingModeScopeBarItem)
|
|
resourceGroupingModeScopeBarItem.selected = true;
|
|
|
|
this._resourcesTreeOutline.removeChildren();
|
|
|
|
let mainFrame = WI.networkManager.mainFrame;
|
|
if (mainFrame) {
|
|
this._updateMainFrameTreeElement(mainFrame);
|
|
this._addResourcesRecursivelyForFrame(mainFrame);
|
|
|
|
for (let frame of WI.networkManager.frames) {
|
|
if (frame !== mainFrame)
|
|
this._addResourcesRecursivelyForFrame(frame);
|
|
}
|
|
}
|
|
|
|
for (let script of WI.debuggerManager.knownNonResourceScripts) {
|
|
this._addScript(script);
|
|
|
|
if (script.sourceMaps.length && WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel())
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
}
|
|
|
|
for (let styleSheet of WI.cssManager.styleSheets) {
|
|
if (styleSheet.origin !== WI.CSSStyleSheet.Type.Author && !styleSheet.isInspectorStyleSheet())
|
|
this._addStyleSheet(styleSheet);
|
|
}
|
|
}
|
|
|
|
_handleFrameMainResourceDidChange(event)
|
|
{
|
|
let frame = event.target;
|
|
if (frame.isMainFrame()) {
|
|
this._updateMainFrameTreeElement(frame);
|
|
this._addResourcesRecursivelyForFrame(frame);
|
|
|
|
for (let domBreakpoint of WI.domDebuggerManager.domBreakpoints)
|
|
this._removeBreakpoint(domBreakpoint);
|
|
}
|
|
|
|
if (!event.data.oldMainResource) {
|
|
let resource = event.target.mainResource;
|
|
this._addBreakpointsForSourceCode(resource);
|
|
this._addIssuesForSourceCode(resource);
|
|
}
|
|
}
|
|
|
|
_handleResourceAdded(event)
|
|
{
|
|
this._addResource(event.data.resource);
|
|
}
|
|
|
|
_handleFrameWasAdded(event)
|
|
{
|
|
let {frame} = event.data;
|
|
|
|
if (frame.isMainFrame())
|
|
this._updateMainFrameTreeElement(frame);
|
|
|
|
this._addResourcesRecursivelyForFrame(frame);
|
|
}
|
|
|
|
_handleBootstrapScriptCreated(event)
|
|
{
|
|
this._addLocalOverride(event.data.bootstrapScript);
|
|
}
|
|
|
|
_handleBootstrapScriptDestroyed(event)
|
|
{
|
|
this._removeResourceOverride(event.data.bootstrapScript);
|
|
}
|
|
|
|
_handleLocalResourceOverrideAdded(event)
|
|
{
|
|
this._addLocalOverride(event.data.localResourceOverride);
|
|
}
|
|
|
|
_handleLocalResourceOverrideRemoved(event)
|
|
{
|
|
this._removeResourceOverride(event.data.localResourceOverride);
|
|
}
|
|
|
|
_handleDebuggerBreakpointAdded(event)
|
|
{
|
|
this._addBreakpoint(event.data.breakpoint);
|
|
}
|
|
|
|
_handleDebuggerBreakpointRemoved(event)
|
|
{
|
|
this._removeBreakpoint(event.data.breakpoint);
|
|
}
|
|
|
|
_handleDebuggerBreakpointsEnabledDidChange(event)
|
|
{
|
|
this._debuggerBreakpointsButtonItem.activated = WI.debuggerManager.breakpointsEnabled;
|
|
|
|
this._updateBreakpointsDisabledBanner();
|
|
}
|
|
|
|
_handleDebuggerScriptAdded(event)
|
|
{
|
|
this._addScript(event.data.script);
|
|
}
|
|
|
|
_handleDebuggerScriptRemoved(event)
|
|
{
|
|
let script = event.data.script;
|
|
let scriptTreeElement = this._resourcesTreeOutline.findTreeElement(script);
|
|
if (!scriptTreeElement)
|
|
return;
|
|
|
|
let parentTreeElement = scriptTreeElement.parent;
|
|
parentTreeElement.removeChild(scriptTreeElement);
|
|
|
|
if (parentTreeElement instanceof WI.FolderTreeElement || parentTreeElement instanceof WI.OriginTreeElement) {
|
|
parentTreeElement.representedObject.remove(script);
|
|
|
|
if (!parentTreeElement.children.length)
|
|
parentTreeElement.parent.removeChild(parentTreeElement);
|
|
}
|
|
}
|
|
|
|
_handleDebuggerScriptsCleared(event)
|
|
{
|
|
const suppressOnDeselect = true;
|
|
const suppressSelectSibling = true;
|
|
|
|
for (let i = this._breakpointsTreeOutline.children.length - 1; i >= 0; --i) {
|
|
let treeElement = this._breakpointsTreeOutline.children[i];
|
|
if (!(treeElement instanceof WI.ScriptTreeElement))
|
|
continue;
|
|
|
|
this._breakpointsTreeOutline.removeChild(treeElement, suppressOnDeselect, suppressSelectSibling);
|
|
}
|
|
|
|
if (this._extensionScriptsFolderTreeElement) {
|
|
if (this._extensionScriptsFolderTreeElement.parent)
|
|
this._extensionScriptsFolderTreeElement.parent.removeChild(this._extensionScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);
|
|
|
|
this._extensionScriptsFolderTreeElement.representedObject.clear();
|
|
this._extensionScriptsFolderTreeElement = null;
|
|
}
|
|
|
|
if (this._extraScriptsFolderTreeElement) {
|
|
if (this._extraScriptsFolderTreeElement.parent)
|
|
this._extraScriptsFolderTreeElement.parent.removeChild(this._extraScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);
|
|
|
|
this._extraScriptsFolderTreeElement.representedObject.clear();
|
|
this._extraScriptsFolderTreeElement = null;
|
|
}
|
|
|
|
if (this._anonymousScriptsFolderTreeElement) {
|
|
if (this._anonymousScriptsFolderTreeElement.parent)
|
|
this._anonymousScriptsFolderTreeElement.parent.removeChild(this._anonymousScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);
|
|
|
|
this._anonymousScriptsFolderTreeElement.representedObject.clear();
|
|
this._anonymousScriptsFolderTreeElement = null;
|
|
}
|
|
|
|
if (this._workerTargetTreeElementMap.size) {
|
|
for (let treeElement of this._workerTargetTreeElementMap.values())
|
|
treeElement.parent.removeChild(treeElement, suppressOnDeselect, suppressSelectSibling);
|
|
this._workerTargetTreeElementMap.clear();
|
|
}
|
|
|
|
this._addResourcesRecursivelyForFrame(WI.networkManager.mainFrame);
|
|
}
|
|
|
|
_handleDebuggerPaused(event)
|
|
{
|
|
this._callStackContainer.hidden = false;
|
|
|
|
if (this._updatePauseReason())
|
|
this._pauseReasonContainer.hidden = false;
|
|
|
|
this._debuggerPauseResumeButtonItem.enabled = true;
|
|
this._debuggerPauseResumeButtonItem.toggled = true;
|
|
this._debuggerStepOverButtonItem.enabled = true;
|
|
this._debuggerStepIntoButtonItem.enabled = true;
|
|
this._debuggerStepOutButtonItem.enabled = true;
|
|
if (this._debuggerStepNextButtonItem)
|
|
this._debuggerStepNextButtonItem.enabled = true;
|
|
|
|
this.element.classList.add("paused");
|
|
}
|
|
|
|
_handleDebuggerResumed(event)
|
|
{
|
|
this._callStackContainer.hidden = true;
|
|
|
|
this._pauseReasonContainer.hidden = true;
|
|
|
|
this._debuggerPauseResumeButtonItem.enabled = true;
|
|
this._debuggerPauseResumeButtonItem.toggled = false;
|
|
this._debuggerStepOverButtonItem.enabled = false;
|
|
this._debuggerStepIntoButtonItem.enabled = false;
|
|
this._debuggerStepOutButtonItem.enabled = false;
|
|
if (this._debuggerStepNextButtonItem)
|
|
this._debuggerStepNextButtonItem.enabled = false;
|
|
|
|
this.element.classList.remove("paused");
|
|
}
|
|
|
|
_handleDebuggerCallFramesDidChange(event)
|
|
{
|
|
let {target} = event.data;
|
|
let treeElement = this._findCallStackTargetTreeElement(target);
|
|
console.assert(treeElement);
|
|
if (treeElement)
|
|
treeElement.refresh();
|
|
|
|
let activeCallFrameTreeElement = this._callStackTreeOutline.findTreeElement(WI.debuggerManager.activeCallFrame);
|
|
if (activeCallFrameTreeElement)
|
|
activeCallFrameTreeElement.reveal();
|
|
}
|
|
|
|
_handleDebuggerActiveCallFrameDidChange(event)
|
|
{
|
|
if (this._activeCallFrameTreeElement) {
|
|
this._activeCallFrameTreeElement.isActiveCallFrame = false;
|
|
this._activeCallFrameTreeElement = null;
|
|
}
|
|
|
|
if (!WI.debuggerManager.activeCallFrame)
|
|
return;
|
|
|
|
this._activeCallFrameTreeElement = this._callStackTreeOutline.findTreeElement(WI.debuggerManager.activeCallFrame);
|
|
if (this._activeCallFrameTreeElement)
|
|
this._activeCallFrameTreeElement.isActiveCallFrame = true;
|
|
}
|
|
|
|
_handleDebuggerWaitingToPause(event)
|
|
{
|
|
this._debuggerPauseResumeButtonItem.enabled = false;
|
|
}
|
|
|
|
_handleDebuggerObjectDisplayLocationDidChange(event)
|
|
{
|
|
let debuggerObject = event.target;
|
|
|
|
if (event.data.oldDisplaySourceCode === debuggerObject.sourceCodeLocation.displaySourceCode)
|
|
return;
|
|
|
|
// A known debugger object (breakpoint, issueMessage, etc.) moved between resources. Remove
|
|
// the old tree element and create a new tree element with the updated file.
|
|
|
|
let wasSelected = false;
|
|
let oldDebuggerTreeElement = null;
|
|
let newDebuggerTreeElement = null;
|
|
if (debuggerObject instanceof WI.JavaScriptBreakpoint) {
|
|
oldDebuggerTreeElement = this._breakpointsTreeOutline.findTreeElement(debuggerObject);
|
|
if (oldDebuggerTreeElement)
|
|
wasSelected = oldDebuggerTreeElement.selected;
|
|
|
|
newDebuggerTreeElement = this._addBreakpoint(debuggerObject);
|
|
} else if (debuggerObject instanceof WI.IssueMessage) {
|
|
oldDebuggerTreeElement = this._resourcesTreeOutline.findTreeElement(debuggerObject);
|
|
if (oldDebuggerTreeElement)
|
|
wasSelected = oldDebuggerTreeElement.selected;
|
|
|
|
newDebuggerTreeElement = this._addIssue(debuggerObject);
|
|
}
|
|
|
|
if (!newDebuggerTreeElement)
|
|
return;
|
|
|
|
if (oldDebuggerTreeElement)
|
|
this._removeDebuggerTreeElement(oldDebuggerTreeElement);
|
|
|
|
if (wasSelected)
|
|
newDebuggerTreeElement.revealAndSelect(true, false, true);
|
|
}
|
|
|
|
_handleDOMBreakpointDOMNodeWillChange(event)
|
|
{
|
|
let breakpoint = event.target;
|
|
this._removeBreakpoint(breakpoint);
|
|
}
|
|
|
|
_handleDOMBreakpointDOMNodeDidChange(event)
|
|
{
|
|
let breakpoint = event.target;
|
|
this._addBreakpoint(breakpoint);
|
|
}
|
|
|
|
_handleConsoleIssueAdded(event)
|
|
{
|
|
let {issue} = event.data;
|
|
|
|
// We only want to show issues originating from JavaScript source code.
|
|
if (!issue.sourceCodeLocation || !issue.sourceCodeLocation.sourceCode || (issue.source !== "javascript" && issue.source !== "console-api"))
|
|
return;
|
|
|
|
this._addIssue(issue);
|
|
}
|
|
|
|
_handleConsoleCleared(event)
|
|
{
|
|
let issueTreeElements = [];
|
|
let currentTreeElement = this._resourcesTreeOutline.children[0];
|
|
while (currentTreeElement && !currentTreeElement.root) {
|
|
if (currentTreeElement instanceof WI.IssueTreeElement)
|
|
issueTreeElements.push(currentTreeElement);
|
|
|
|
const skipUnrevealed = false;
|
|
const stayWithin = null;
|
|
const dontPopulate = true;
|
|
currentTreeElement = currentTreeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
|
|
}
|
|
|
|
issueTreeElements.forEach((treeElement) => treeElement.parent.removeChild(treeElement));
|
|
}
|
|
|
|
_handleConsoleSnippetAdded(event)
|
|
{
|
|
this._addConsoleSnippet(event.data.snippet);
|
|
}
|
|
|
|
_handleConsoleSnippetRemoved(event)
|
|
{
|
|
this._removeConsoleSnippet(event.data.snippet);
|
|
}
|
|
|
|
_handleTimelineCapturingStateChanged(event)
|
|
{
|
|
this._updateTemporarilyDisabledBreakpointsButtons();
|
|
|
|
switch (WI.timelineManager.capturingState) {
|
|
case WI.TimelineManager.CapturingState.Starting:
|
|
if (!this._timelineRecordingWarningElement) {
|
|
let stopRecordingButton = document.createElement("button");
|
|
stopRecordingButton.textContent = WI.UIString("Stop recording");
|
|
stopRecordingButton.addEventListener("click", () => {
|
|
WI.timelineManager.stopCapturing();
|
|
});
|
|
|
|
this._timelineRecordingWarningElement = document.createElement("div");
|
|
this._timelineRecordingWarningElement.classList.add("warning-banner");
|
|
this._timelineRecordingWarningElement.append(WI.UIString("Debugger disabled during Timeline recording"), document.createElement("br"), stopRecordingButton);
|
|
}
|
|
|
|
this.contentView.element.insertBefore(this._timelineRecordingWarningElement, this.contentView.element.firstChild);
|
|
break;
|
|
|
|
case WI.TimelineManager.CapturingState.Inactive:
|
|
if (this._timelineRecordingWarningElement) {
|
|
this._timelineRecordingWarningElement.remove();
|
|
this._timelineRecordingWarningElement = null;
|
|
}
|
|
break;
|
|
}
|
|
|
|
this._updateBreakpointsDisabledBanner();
|
|
}
|
|
|
|
_handleAuditManagerTestScheduled(event)
|
|
{
|
|
this._updateTemporarilyDisabledBreakpointsButtons();
|
|
|
|
if (!this._auditTestWarningElement) {
|
|
let stopAuditButton = document.createElement("button");
|
|
stopAuditButton.textContent = WI.UIString("Stop Audit");
|
|
stopAuditButton.addEventListener("click", (event) => {
|
|
WI.auditManager.stop();
|
|
});
|
|
|
|
this._auditTestWarningElement = document.createElement("div");
|
|
this._auditTestWarningElement.classList.add("warning-banner");
|
|
this._auditTestWarningElement.append(WI.UIString("Debugger disabled during Audit"), document.createElement("br"), stopAuditButton);
|
|
}
|
|
|
|
this.contentView.element.insertBefore(this._auditTestWarningElement, this.contentView.element.firstChild);
|
|
|
|
this._updateBreakpointsDisabledBanner();
|
|
}
|
|
|
|
_handleAuditManagerTestCompleted(event)
|
|
{
|
|
this._updateTemporarilyDisabledBreakpointsButtons();
|
|
|
|
if (this._auditTestWarningElement) {
|
|
this._auditTestWarningElement.remove();
|
|
this._auditTestWarningElement = null;
|
|
}
|
|
|
|
this._updateBreakpointsDisabledBanner();
|
|
}
|
|
|
|
_handleCSSStyleSheetAdded(event)
|
|
{
|
|
let {styleSheet} = event.data;
|
|
if (styleSheet.origin === WI.CSSStyleSheet.Type.Author)
|
|
return;
|
|
|
|
if (styleSheet.isInspectorStyleSheet()) {
|
|
if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Type) {
|
|
let frameTreeElement = this.treeElementForRepresentedObject(styleSheet.parentFrame);
|
|
if (frameTreeElement) {
|
|
frameTreeElement.addRepresentedObjectToNewChildQueue(styleSheet);
|
|
return;
|
|
}
|
|
}
|
|
|
|
this._addResource(styleSheet);
|
|
} else
|
|
this._addStyleSheet(styleSheet);
|
|
}
|
|
|
|
_handleCSSStyleSheetRemoved(event)
|
|
{
|
|
let {styleSheet} = event.data;
|
|
if (styleSheet.origin === WI.CSSStyleSheet.Type.Author)
|
|
return;
|
|
|
|
let treeElement = this._resourcesTreeOutline.findTreeElement(styleSheet);
|
|
if (!treeElement)
|
|
return;
|
|
|
|
let parent = treeElement.parent;
|
|
treeElement.parent.removeChild(treeElement);
|
|
|
|
if (!parent.children.length)
|
|
parent.parent.removeChild(parent);
|
|
|
|
switch (parent) {
|
|
case this._extensionStyleSheetsFolderTreeElement:
|
|
this._extensionStyleSheetsFolderTreeElement = null;
|
|
break;
|
|
|
|
case this._extraStyleSheetsFolderTreeElement:
|
|
this._extraStyleSheetsFolderTreeElement = null;
|
|
break;
|
|
|
|
case this._anonymousStyleSheetsFolderTreeElement:
|
|
this._anonymousStyleSheetsFolderTreeElement = null;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_handleTargetAdded(event)
|
|
{
|
|
this._addTarget(event.data.target);
|
|
}
|
|
|
|
_handleTargetRemoved(event)
|
|
{
|
|
let {target} = event.data;
|
|
|
|
let workerTreeElement = this._workerTargetTreeElementMap.take(target);
|
|
if (workerTreeElement)
|
|
workerTreeElement.parent.removeChild(workerTreeElement);
|
|
|
|
let callStackTreeElement = this._findCallStackTargetTreeElement(target);
|
|
console.assert(callStackTreeElement);
|
|
if (callStackTreeElement)
|
|
this._callStackTreeOutline.removeChild(callStackTreeElement);
|
|
|
|
this._updateCallStackTreeOutline();
|
|
}
|
|
|
|
_handleExtraDomainsActivated()
|
|
{
|
|
// COMPATIBILITY (iOS 14.0): Inspector.activateExtraDomains was removed in favor of a declared debuggable type
|
|
|
|
if (WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel())
|
|
this._resourcesTreeOutline.disclosureButtons = true;
|
|
}
|
|
};
|
|
|
|
WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol = Symbol("resource-type");
|
|
WI.SourcesNavigationSidebarPanel.ResourceGroupingModeSymbol = Symbol("resource-grouping-mode");
|