Diving into the source frames
Javascript Editor
The javascript editor in devtools parlance is refereed to as a Source Frame. There are two source frames in devtools, the javascript editor and css editor.
The javascript editor not surprisingly has a custom logic for communicating with the console and handling breakpoints.
The main source frame, is more concerned with showing content, searching, jumping to lines.
The editor is in many ways a glorified wrapper in that a lot of the actual work is handled by the text editor (codemirror). For example, when the editor wants to jump to a nother search result it tells the editor to highlight the result.
jumpToSearchResult: function(index) {
this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
this._currentSearchMatchChangedCallback(this._currentSearchResultIndex);
var result = this._searchResults[this._currentSearchResultIndex]
this._textEditor.highlightSearchResults(this._searchRegex, result);
}
Shortcuts
All of the shortcuts are defined in an object WebInspector.ShortcutsScreen.SourcesPanelShortcuts
. Here’s a dump of them for fun:
- SelectNextOccurrence
- SoftUndo
- GotoMatchingBracket
- ToggleAutocompletion
- IncreaseCSSUnitByOne
- DecreaseCSSUnitByOne
- IncreaseCSSUnitByTen
- DecreaseCSSUnitByTen
- EvaluateSelectionInConsole
- AddSelectionToWatch
- GoToMember
- GoToLine
- ToggleBreakpoint
- NextCallFrame
- PrevCallFrame
- ToggleComment
- JumpToPreviousLocation
- JumpToNextLocation
- CloseEditorTab
- Save
- SaveAll
How do the function links work?
The function link in the object popover is a little know trick for jumping to a function definition.
Not surprisingly, the link is setup inside the ObjectHelper
When you hover over a function showObjectPopover
is called. That then kicks off a _queryObject
fetch. Then, if the result is a function, the result is re-fetched for its properties result.getOwnProperties
and shown didGetFunctionProperties
.
The formatting for the popover is done in didGetFunctionDetails
function didGetFunctionDetails(popoverContentElement, anchorElement, response) {
var container = createElementWithClass("div", "object-popover-container");
var title = container.createChild("div", "function-popover-title source-code");
var functionName = title.createChild("span", "function-name").textContent = response.functionName;
var link = this._lazyLinkifier().linkifyRawLocation(response.location, response.sourceURL, "function-location-link");
title.appendChild(link);
container.appendChild(popoverContentElement);
popover.showForAnchor(container, anchorElement);
}
I think it’s pretty cool that the popover is shown with showForAnchor
w/ the anchor element being passed in.
Linkifier
The ObjectHelper
sets up a basic Linkifier for jumping to function definitions.
WebInspector.Linkifier = function(formatter) {
this._formatter = formatter || new WebInspector.Linkifier.DefaultFormatter(WebInspector.Linkifier.MaxLengthForDisplayedURLs);
this._liveLocationsByTarget = new Map();
WebInspector.targetManager.observeTargets(this);
}
When building a link, it uses the standard Linkifier
instance method linkifyRawLocation
.
linkifyRawLocation: function(rawLocation, fallbackUrl, classes) {
return this.linkifyScriptLocation(
rawLocation.target(),
rawLocation.scriptId,
fallbackUrl,
rawLocation.lineNumber,
rawLocation.columnNumber,
classes // these will be the <a> classses
);
}
linkifyScriptLocation: function(target, scriptId, sourceURL, lineNumber, columnNumber, classes) {
var fallbackAnchor = WebInspector.linkifyResourceAsNode(sourceURL, lineNumber, classes);
var rawLocation = scriptId ?
target.debuggerModel.createRawLocationByScriptId(scriptId, lineNumber, columnNumber || 0) :
target.debuggerModel.createRawLocationByURL(sourceURL, lineNumber, columnNumber || 0);
var anchor = this._createAnchor(classes);
var liveLocation = WebInspector.debuggerWorkspaceBinding.createLiveLocation(
rawLocation, this._updateAnchor.bind(this, anchor));
this._liveLocationsByTarget.get(rawLocation.target()).set(anchor, liveLocation);
anchor[WebInspector.Linkifier._fallbackAnchorSymbol] = fallbackAnchor;
return anchor;
},