Files
palemoon27/devtools/client/debugger/views/stack-frames-view.js
roytam1 c656138b3f import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1165052 - Part 9: Use ArraySpeciesCreate in Array.prototype.filter. r=efaust (198da18845)
- Bug 1165052 - Part 10: Use ArraySpeciesCreate in Array.prototype.map. r=efaust (9dcd625daa)
- Bug 1263618: Adapt assertions in RegExp*Raw functions for int32_t; r=arai (8ad46db66d)
- Bug 1263340 - Part 1: Use internal slot for global and sticky flags in RegExpBuiltinExec. r=h4writer (9b5fbe6358)
- Bug 1263340 - Part 2: Use internal slot for sticky flag in @@replace and @@search optimized path. r=h4writer (2b64567c6a)
- Bug 1264264 - Add optimized path for RegExp.prototype[@@replace] with functional replace and substitution. r=till (e55722bc0a)
- Bug 1263340 - Part 3: Use internal slot for sticky flag in RegExp native functions. r=h4writer (725cf7b9b0)
- Bug 1264264 - Part 2: Enable optimization for packers again in RegExp.prototype[@@replace]. r=h4writer (7f4b819e40)
- Bug 1268056 - Check if |this| value is a RegExp object in the optimized path in RegExpSplit. r=h4writer (8891f0a3ef)
- Bug 1263340 - Part 4: Followup for @@split - Apply optimized path for empty string too. r=till (956d1804a5)
- Bug 1261207 - Forward declare js::ScriptSource instead of casting `¦void*` pointers; r=jimb (4914273e96)
- Bug 1041586 - Implement Symbol.isConcatSpreadable. r=arai (238e5f97c6)
- Bug 1041586 - Use IsConcatSpreadable in Array.prototype.concat. r=arai (33333cb30f)
- Bug 1165052 - Part 11: Use ArraySpeciesCreate in Array.prototype.slice. r=efaust (45f34c0a87)
- Bug 1165052 - Part 12: Use ArraySpeciesCreate in Array.prototype.splice. r=efaust,evilpie (096f9ff03d)
- Bug 1165052 - Part 13: Add tests for ArraySpeciesCreate. r=efaust (4403642d3c)
- Bug 1041586 - Tests. r=arai (efc2d06863)
- Bug 1267364 - Check isNative every time in GetStringDataProperty. r=h4writer (6e7898c494)
- Bug 1041586 - Fold away property accesses to not-defined properties. r=jandem (216e6387db)
- add emacs (fa858771bf)
- Bug 1268574 - Check the outparam JSFunction* value after GetGetterPure. r=lth (3d80c79337)
- Bug 1263888 - Push TypeBarrier after ArraySlice. r=jandem (2617518401)
- Bug 1255316 - IonMonkey: Enable folding of MLoadUnboxedObjectOrNull with the stored value, r=jandem (0f75675721)
- Bug 1252313 - Fix wasm i64 shift ops with a constant rhs. r=bbouvier (2c05b901c6)
- Bug 1263609: SharedStubs - Port JSOP_POW to shared stubs, r=efaust (54523590d9)
- Bug 1247880 - Only remove MUrsh operands when the input of MUrsh is guaranteed to be unsigned. r=sunfish (4a29e0b071)
- Bug 1254528: IonMonkey - Check slot before removing load with value of store, r=nbp (3527eb5263)
- Bug 1255316 - IonMonkey: Also take into account the offsetAdjustment when folding MLoadUnboxedObjectOrNull, r=jandem (9cbea97df1)
- Bug 1263558 - Part 1: Self-host Array generics. r=till,bholley (e1dc0c54c8)
- Bug 1103588 - Part 1: Replace deprecated String#contains with String#includes in browser tests and extensions. r=dolske (37558174e8)
- Bug 1103588 - Part 3: Replace deprecated String#contains warning with an expression closure warning in sharedWorker_sharedWorker.js test. r=bz (221ff40ebc)
- Bug 1103588 - Part 4: Replace deprecated String#contains in js tests. r=till (a794c0b385)
- Bug 1103588 - Part 5: Remove deprecated String#contains function; use String#includes instead. r=till (bc1365603e)
- Bug 964709 - Updates Parser regex and tests to support self-closing script tags, r=vporof (f04c475ec8)
- Bug 1224726 - Do not attempt to parse source file when searching in debugger if text > 1MB;r=jlongster (8743b7bf19)
- Bug 1243243 - Use standard license boilerplate in debugger js files. r=jlongster (82684adab3)
- Bug 1240804 - Allow remaining unhandled rejections. r=ejpbruel (c30bd6dad2)
- Bug 1207702 - Fix a bug in test_promises_object_timetosettle-02.js;r=fitzgen (de776ce006)
- Bug 1103588 - Part 2: Replace deprecated String#contains with String#includes in devtools tests. r=jryans (801926270d)
- Bug 1263558 - Part 2: Self-host String generics. r=till (4e5766489b)
- Bug 1263558 - Part 3: Remove JSFUN_GENERIC_NATIVE. r=till (3f94c198b0)
- Bug 1263558 - Part 4: Call initBuiltinConstructor after defining properties in InitStringClass. r=till (f25edc6096)
- Bug 1263558 - Part 0.1: Handle OOM inside BuildDominatorTree at AnalyzeNewScriptDefiniteProperties and AnalyzeArgumentsUsage. r=jandem (0f4745e9d4)
- Bug 1266573 - Add the JS::ubi::dumpPaths debug utility; r=jimb (9a8680d7c7)
- Bug 1266835 - Request names from the rootlist in JS::ubi::dumpPaths and clean up formatting of dumped paths. r=jimb (1e15dd3ab9)
- Bug 1263332 - Avoid startup JavaScript strict warning in DirectoryLinksProvider.jsm. r=MattN (06ff76be4d)
- Bug 1259911: Only add predecessors to the join block once; r=sunfish (53a9522e68)
- Bug 1258905: Remove a bunch of dead IPC code. r=jld (0d9f930a14)
- Bug 1266869 - Print a message when no retaining paths are found in JS::ubi::dumpPaths. r=jimb (77a541b4d1)
2024-04-12 11:43:55 +08:00

284 lines
9.2 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* import-globals-from ../debugger-controller.js */
/* import-globals-from ../debugger-view.js */
/* import-globals-from ../utils.js */
/* globals document, window */
"use strict";
/**
* Functions handling the stackframes UI.
*/
function StackFramesView(DebuggerController, DebuggerView) {
dumpn("StackFramesView was instantiated");
this.StackFrames = DebuggerController.StackFrames;
this.DebuggerView = DebuggerView;
this._onStackframeRemoved = this._onStackframeRemoved.bind(this);
this._onSelect = this._onSelect.bind(this);
this._onScroll = this._onScroll.bind(this);
this._afterScroll = this._afterScroll.bind(this);
this._getStackAsString = this._getStackAsString.bind(this);
}
StackFramesView.prototype = Heritage.extend(WidgetMethods, {
/**
* Initialization function, called when the debugger is started.
*/
initialize: function() {
dumpn("Initializing the StackFramesView");
this._popupset = document.getElementById("debuggerPopupset");
this.widget = new BreadcrumbsWidget(document.getElementById("stackframes"));
this.widget.addEventListener("select", this._onSelect, false);
this.widget.addEventListener("scroll", this._onScroll, true);
this.widget.setAttribute("context", "stackFramesContextMenu");
window.addEventListener("resize", this._onScroll, true);
this.autoFocusOnFirstItem = false;
this.autoFocusOnSelection = false;
// This view's contents are also mirrored in a different container.
this._mirror = this.DebuggerView.StackFramesClassicList;
},
/**
* Destruction function, called when the debugger is closed.
*/
destroy: function() {
dumpn("Destroying the StackFramesView");
this.widget.removeEventListener("select", this._onSelect, false);
this.widget.removeEventListener("scroll", this._onScroll, true);
window.removeEventListener("resize", this._onScroll, true);
},
/**
* Adds a frame in this stackframes container.
*
* @param string aTitle
* The frame title (function name).
* @param string aUrl
* The frame source url.
* @param string aLine
* The frame line number.
* @param number aDepth
* The frame depth in the stack.
* @param boolean aIsBlackBoxed
* Whether or not the frame is black boxed.
*/
addFrame: function(aFrame, aLine, aColumn, aDepth, aIsBlackBoxed) {
let { source } = aFrame;
// The source may not exist in the source listing yet because it's
// an unnamed eval source, which we hide, so we need to add it
if(!DebuggerView.Sources.getItemByValue(source.actor)) {
DebuggerView.Sources.addSource(source, { force: true });
}
let location = DebuggerView.Sources.getDisplayURL(source);
let title = StackFrameUtils.getFrameTitle(aFrame);
// Blackboxed stack frames are collapsed into a single entry in
// the view. By convention, only the first frame is displayed.
if (aIsBlackBoxed) {
if (this._prevBlackBoxedUrl == location) {
return;
}
this._prevBlackBoxedUrl = location;
} else {
this._prevBlackBoxedUrl = null;
}
// Create the element node for the stack frame item.
let frameView = this._createFrameView(
title, location, aLine, aDepth, aIsBlackBoxed
);
// Append a stack frame item to this container.
this.push([frameView], {
index: 0, /* specifies on which position should the item be appended */
attachment: {
title: title,
url: location,
line: aLine,
depth: aDepth,
column: aColumn
},
// Make sure that when the stack frame item is removed, the corresponding
// mirrored item in the classic list is also removed.
finalize: this._onStackframeRemoved
});
// Mirror this newly inserted item inside the "Call Stack" tab.
this._mirror.addFrame(title, location, aLine, aDepth);
},
_getStackAsString: function() {
return [...this].map(frameItem => {
const { attachment: { title, url, line, column }} = frameItem;
return title + "@" + url + ":" + line + ":" + column;
}).join("\n")
},
addCopyContextMenu: function() {
let menupopup = document.createElement("menupopup");
let menuitem = document.createElement("menuitem");
menupopup.id = "stackFramesContextMenu";
menuitem.id = "copyStackMenuItem";
menuitem.setAttribute("label", "Copy");
menuitem.addEventListener("command", () => {
let stack = this._getStackAsString();
clipboardHelper.copyString(stack);
}, false);
menupopup.appendChild(menuitem);
this._popupset.appendChild(menupopup);
},
/**
* Selects the frame at the specified depth in this container.
* @param number aDepth
*/
set selectedDepth(aDepth) {
this.selectedItem = aItem => aItem.attachment.depth == aDepth;
},
/**
* Gets the currently selected stack frame's depth in this container.
* This will essentially be the opposite of |selectedIndex|, which deals
* with the position in the view, where the last item added is actually
* the bottommost, not topmost.
* @return number
*/
get selectedDepth() {
return this.selectedItem.attachment.depth;
},
/**
* Specifies if the active thread has more frames that need to be loaded.
*/
dirty: false,
/**
* Customization function for creating an item's UI.
*
* @param string aTitle
* The frame title to be displayed in the list.
* @param string aUrl
* The frame source url.
* @param string aLine
* The frame line number.
* @param number aDepth
* The frame depth in the stack.
* @param boolean aIsBlackBoxed
* Whether or not the frame is black boxed.
* @return nsIDOMNode
* The stack frame view.
*/
_createFrameView: function(aTitle, aUrl, aLine, aDepth, aIsBlackBoxed) {
let container = document.createElement("hbox");
container.id = "stackframe-" + aDepth;
container.className = "dbg-stackframe";
let frameDetails = SourceUtils.trimUrlLength(
SourceUtils.getSourceLabel(aUrl),
STACK_FRAMES_SOURCE_URL_MAX_LENGTH,
STACK_FRAMES_SOURCE_URL_TRIM_SECTION);
if (aIsBlackBoxed) {
container.classList.add("dbg-stackframe-black-boxed");
} else {
let frameTitleNode = document.createElement("label");
frameTitleNode.className = "plain dbg-stackframe-title breadcrumbs-widget-item-tag";
frameTitleNode.setAttribute("value", aTitle);
container.appendChild(frameTitleNode);
frameDetails += SEARCH_LINE_FLAG + aLine;
}
let frameDetailsNode = document.createElement("label");
frameDetailsNode.className = "plain dbg-stackframe-details breadcrumbs-widget-item-id";
frameDetailsNode.setAttribute("value", frameDetails);
container.appendChild(frameDetailsNode);
return container;
},
/**
* Function called each time a stack frame item is removed.
*
* @param object aItem
* The corresponding item.
*/
_onStackframeRemoved: function(aItem) {
dumpn("Finalizing stackframe item: " + aItem.stringify());
// Remove the mirrored item in the classic list.
let depth = aItem.attachment.depth;
this._mirror.remove(this._mirror.getItemForAttachment(e => e.depth == depth));
// Forget the previously blackboxed stack frame url.
this._prevBlackBoxedUrl = null;
},
/**
* The select listener for the stackframes container.
*/
_onSelect: function(e) {
let stackframeItem = this.selectedItem;
if (stackframeItem) {
// The container is not empty and an actual item was selected.
let depth = stackframeItem.attachment.depth;
// Mirror the selected item in the classic list.
this.suppressSelectionEvents = true;
this._mirror.selectedItem = e => e.attachment.depth == depth;
this.suppressSelectionEvents = false;
DebuggerController.StackFrames.selectFrame(depth);
}
},
/**
* The scroll listener for the stackframes container.
*/
_onScroll: function() {
// Update the stackframes container only if we have to.
if (!this.dirty) {
return;
}
// Allow requests to settle down first.
setNamedTimeout("stack-scroll", STACK_FRAMES_SCROLL_DELAY, this._afterScroll);
},
/**
* Requests the addition of more frames from the controller.
*/
_afterScroll: function() {
let scrollPosition = this.widget.getAttribute("scrollPosition");
let scrollWidth = this.widget.getAttribute("scrollWidth");
// If the stackframes container scrolled almost to the end, with only
// 1/10 of a breadcrumb remaining, load more content.
if (scrollPosition - scrollWidth / 10 < 1) {
this.ensureIndexIsVisible(CALL_STACK_PAGE_SIZE - 1);
this.dirty = false;
// Loads more stack frames from the debugger server cache.
DebuggerController.StackFrames.addMoreFrames();
}
},
_mirror: null,
_prevBlackBoxedUrl: null
});
DebuggerView.StackFrames = new StackFramesView(DebuggerController, DebuggerView);