summaryrefslogtreecommitdiff
path: root/deps/v8/tools/turbolizer/code-view.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/tools/turbolizer/code-view.js')
-rw-r--r--deps/v8/tools/turbolizer/code-view.js329
1 files changed, 210 insertions, 119 deletions
diff --git a/deps/v8/tools/turbolizer/code-view.js b/deps/v8/tools/turbolizer/code-view.js
index 7f9728a83a..0b190b92ba 100644
--- a/deps/v8/tools/turbolizer/code-view.js
+++ b/deps/v8/tools/turbolizer/code-view.js
@@ -5,166 +5,257 @@
"use strict";
class CodeView extends View {
- constructor(divID, PR, sourceText, sourcePosition, broker) {
- super(divID, broker, null, false);
+ static get MAIN_SOURCE() {
+ return "main function";
+ }
+ static get INLINED_SOURCE() {
+ return "inlined function";
+ }
+
+ createViewElement() {
+ const sourceContainer = document.createElement("div");
+ sourceContainer.classList.add("source-container");
+ return sourceContainer;
+ }
+
+ constructor(parentId, broker, sourceResolver, sourceFunction, codeMode) {
+ super(parentId, broker, null, false);
let view = this;
- view.PR = PR;
view.mouseDown = false;
view.broker = broker;
- view.allSpans = [];
-
- var selectionHandler = {
- clear: function() { broker.clear(selectionHandler); },
- select: function(items, selected) {
- var handler = this;
- var broker = view.broker;
- for (let span of items) {
- if (selected) {
- span.classList.add("selected");
- } else {
- span.classList.remove("selected");
- }
- }
- var locations = [];
- for (var span of items) {
- locations.push({pos_start: span.start, pos_end: span.end});
- }
- broker.clear(selectionHandler);
- broker.select(selectionHandler, locations, selected);
+ view.source = null;
+ view.sourceResolver = sourceResolver;
+ view.source = sourceFunction;
+ view.codeMode = codeMode;
+ this.lineToSourcePositions = new Map();
+ this.sourcePositionToHtmlElement = new Map();
+ this.showAdditionalInliningPosition = false;
+
+ const selectionHandler = {
+ clear: function () {
+ view.selection.clear();
+ view.updateSelection();
+ broker.broadcastClear(this)
},
- selectionDifference: function(span1, inclusive1, span2, inclusive2) {
- var pos1 = span1.start;
- var pos2 = span2.start;
- var result = [];
- var lineListDiv = view.divNode.firstChild.firstChild.childNodes;
- for (var i = 0; i < lineListDiv.length; i++) {
- var currentLineElement = lineListDiv[i];
- var spans = currentLineElement.childNodes;
- for (var j = 0; j < spans.length; ++j) {
- var currentSpan = spans[j];
- if (currentSpan.start > pos1 ||
- (inclusive1 && currentSpan.start == pos1)) {
- if (currentSpan.start < pos2 ||
- (inclusive2 && currentSpan.start == pos2)) {
- result.push(currentSpan);
- }
- }
- }
+ select: function (sourcePositions, selected) {
+ const locations = [];
+ for (var sourcePosition of sourcePositions) {
+ locations.push(sourcePosition);
+ sourceResolver.addInliningPositions(sourcePosition, locations);
}
- return result;
+ if (locations.length == 0) return;
+ view.selection.select(locations, selected);
+ view.updateSelection();
+ broker.broadcastSourcePositionSelect(this, locations, selected);
},
- brokeredSelect: function(locations, selected) {
- let firstSelect = view.selection.isEmpty();
- for (let location of locations) {
- let start = location.pos_start;
- let end = location.pos_end;
- if (start && end) {
- let lower = 0;
- let upper = view.allSpans.length;
- if (upper > 0) {
- while ((upper - lower) > 1) {
- var middle = Math.floor((upper + lower) / 2);
- var lineStart = view.allSpans[middle].start;
- if (lineStart < start) {
- lower = middle;
- } else if (lineStart > start) {
- upper = middle;
- } else {
- lower = middle;
- break;
- }
- }
- var currentSpan = view.allSpans[lower];
- var currentLineElement = currentSpan.parentNode;
- if ((currentSpan.start <= start && start < currentSpan.end) ||
- (currentSpan.start <= end && end < currentSpan.end)) {
- if (firstSelect) {
- makeContainerPosVisible(
- view.divNode, currentLineElement.offsetTop);
- firstSelect = false;
- }
- view.selection.select(currentSpan, selected);
- }
- }
- }
+ brokeredSourcePositionSelect: function (locations, selected) {
+ const firstSelect = view.selection.isEmpty();
+ for (const location of locations) {
+ const translated = sourceResolver.translateToSourceId(view.source.sourceId, location);
+ if (!translated) continue;
+ view.selection.select(translated, selected);
}
+ view.updateSelection(firstSelect);
+ },
+ brokeredClear: function () {
+ view.selection.clear();
+ view.updateSelection();
},
- brokeredClear: function() { view.selection.clear(); },
};
- view.selection = new Selection(selectionHandler);
- broker.addSelectionHandler(selectionHandler);
+ view.selection = new Selection(sourcePositionToStringKey);
+ broker.addSourcePositionHandler(selectionHandler);
+ this.selectionHandler = selectionHandler;
+ this.initializeCode();
+ }
- view.handleSpanMouseDown = function(e) {
- e.stopPropagation();
- if (!e.shiftKey) {
- view.selection.clear();
- }
- view.selection.select(this, true);
- view.mouseDown = true;
+ addSourcePositionToLine(lineNumber, sourcePosition) {
+ const lineNumberString = anyToString(lineNumber);
+ if (!this.lineToSourcePositions.has(lineNumberString)) {
+ this.lineToSourcePositions.set(lineNumberString, []);
}
+ this.lineToSourcePositions.get(lineNumberString).push(sourcePosition);
+ }
- view.handleSpanMouseMove = function(e) {
- if (view.mouseDown) {
- view.selection.extendTo(this);
- }
+ addHtmlElementToSourcePosition(sourcePosition, element) {
+ const key = sourcePositionToStringKey(sourcePosition);
+ if (this.sourcePositionToHtmlElement.has(key)) {
+ console.log("Warning: duplicate source position", sourcePosition);
}
+ this.sourcePositionToHtmlElement.set(key, element);
+ }
- view.handleCodeMouseDown = function(e) { view.selection.clear(); }
+ getHtmlElementForSourcePosition(sourcePosition) {
+ const key = sourcePositionToStringKey(lineNumber);
+ return this.sourcePositionToHtmlElement.get(key);
+ }
+
+ updateSelection(scrollIntoView) {
+ const mkVisible = new ViewElements(this.divNode.parentNode);
+ for (const [sp, el] of this.sourcePositionToHtmlElement.entries()) {
+ const isSelected = this.selection.isKeySelected(sp);
+ mkVisible.consider(el, isSelected);
+ el.classList.toggle("selected", isSelected);
+ }
+ mkVisible.apply(scrollIntoView);
+ }
- document.addEventListener('mouseup', function(e) {
- view.mouseDown = false;
- }, false);
+ initializeContent(data, rememberedSelection) {
+ this.data = data;
+ }
- view.initializeCode(sourceText, sourcePosition);
+ getCodeHtmlElementName() {
+ return `source-pre-${this.source.sourceId}`;
}
- initializeContent(data, rememberedSelection) { this.data = data; }
+ getCodeHeaderHtmlElementName() {
+ return `source-pre-${this.source.sourceId}-header`;
+ }
- initializeCode(sourceText, sourcePosition) {
+ getHtmlCodeLines() {
+ const lineListDiv = this.divNode.querySelector(`#${this.getCodeHtmlElementName()} ol`).childNodes;
+ return lineListDiv;
+ }
+
+ onSelectLine(lineNumber, doClear) {
+ const sourcePositions = this.lineToSourcePositions.get(anyToString(lineNumber));
+ if (doClear) {
+ this.selectionHandler.clear();
+ }
+ if (!sourcePositions) return;
+ this.selectionHandler.select(sourcePositions, undefined);
+ }
+
+ onSelectSourcePosition(sourcePosition, doClear) {
+ if (doClear) {
+ this.selectionHandler.clear();
+ }
+ this.selectionHandler.select([sourcePosition], undefined);
+ }
+
+ initializeCode() {
var view = this;
+ const source = this.source;
+ const sourceText = source.sourceText;
+ if (!sourceText) return;
+ const sourceContainer = view.divNode;
+ if (this.codeMode == CodeView.MAIN_SOURCE) {
+ sourceContainer.classList.add("main-source");
+ } else {
+ sourceContainer.classList.add("inlined-source");
+ }
+ var codeHeader = document.createElement("div");
+ codeHeader.setAttribute("id", this.getCodeHeaderHtmlElementName());
+ codeHeader.classList.add("code-header");
+ var codeFileFunction = document.createElement("div");
+ codeFileFunction.classList.add("code-file-function");
+ codeFileFunction.innerHTML = `${source.sourceName}:${source.functionName}`;
+ codeHeader.appendChild(codeFileFunction);
+ var codeModeDiv = document.createElement("div");
+ codeModeDiv.classList.add("code-mode");
+ codeModeDiv.innerHTML = `${this.codeMode}`;
+ codeHeader.appendChild(codeModeDiv);
+ var clearDiv = document.createElement("div");
+ clearDiv.style = "clear:both;"
+ codeHeader.appendChild(clearDiv);
+ sourceContainer.appendChild(codeHeader);
var codePre = document.createElement("pre");
+ codePre.setAttribute("id", this.getCodeHtmlElementName());
codePre.classList.add("prettyprint");
- view.divNode.innerHTML = "";
- view.divNode.appendChild(codePre);
+ sourceContainer.appendChild(codePre);
+
+ codeHeader.onclick = function myFunction() {
+ if (codePre.style.display === "none") {
+ codePre.style.display = "block";
+ } else {
+ codePre.style.display = "none";
+ }
+ }
if (sourceText != "") {
codePre.classList.add("linenums");
codePre.textContent = sourceText;
try {
// Wrap in try to work when offline.
- view.PR.prettyPrint();
+ PR.prettyPrint(undefined, sourceContainer);
} catch (e) {
+ console.log(e);
}
- view.divNode.onmousedown = this.handleCodeMouseDown;
+ view.divNode.onclick = function (e) {
+ view.selectionHandler.clear();
+ }
- var base = sourcePosition;
- var current = 0;
- var lineListDiv = view.divNode.firstChild.firstChild.childNodes;
+ const base = source.startPosition;
+ let current = 0;
+ const lineListDiv = this.getHtmlCodeLines();
+ let newlineAdjust = 0;
for (let i = 0; i < lineListDiv.length; i++) {
- var currentLineElement = lineListDiv[i];
+ // Line numbers are not zero-based.
+ const lineNumber = i + 1;
+ const currentLineElement = lineListDiv[i];
currentLineElement.id = "li" + i;
- var pos = base + current;
- currentLineElement.pos = pos;
- var spans = currentLineElement.childNodes;
+ currentLineElement.dataset.lineNumber = lineNumber;
+ const spans = currentLineElement.childNodes;
for (let j = 0; j < spans.length; ++j) {
- var currentSpan = spans[j];
- if (currentSpan.nodeType == 1) {
- currentSpan.start = pos;
- currentSpan.end = pos + currentSpan.textContent.length;
- currentSpan.onmousedown = this.handleSpanMouseDown;
- currentSpan.onmousemove = this.handleSpanMouseMove;
- view.allSpans.push(currentSpan);
- }
+ const currentSpan = spans[j];
+ const pos = base + current;
+ const end = pos + currentSpan.textContent.length;
current += currentSpan.textContent.length;
- pos = base + current;
+ this.insertSourcePositions(currentSpan, lineNumber, pos, end, newlineAdjust);
+ newlineAdjust = 0;
}
+
+ this.insertLineNumber(currentLineElement, lineNumber);
+
while ((current < sourceText.length) &&
- (sourceText[current] == '\n' || sourceText[current] == '\r')) {
+ (sourceText[current] == '\n' || sourceText[current] == '\r')) {
++current;
+ ++newlineAdjust;
}
}
}
}
- deleteContent() {}
+ insertSourcePositions(currentSpan, lineNumber, pos, end, adjust) {
+ const view = this;
+ const sps = this.sourceResolver.sourcePositionsInRange(this.source.sourceId, pos - adjust, end);
+ for (const sourcePosition of sps) {
+ view.addSourcePositionToLine(lineNumber, sourcePosition);
+ const textnode = currentSpan.tagName == 'SPAN' ? currentSpan.firstChild : currentSpan;
+ const replacementNode = textnode.splitText(Math.max(0, sourcePosition.scriptOffset - pos));
+ const span = document.createElement('span');
+ span.setAttribute("scriptOffset", sourcePosition.scriptOffset);
+ span.classList.add("source-position")
+ const marker = document.createElement('span');
+ marker.classList.add("marker")
+ span.appendChild(marker);
+ const inlining = this.sourceResolver.getInliningForPosition(sourcePosition);
+ if (inlining != undefined && view.showAdditionalInliningPosition) {
+ const sourceName = this.sourceResolver.getSourceName(inlining.sourceId);
+ const inliningMarker = document.createElement('span');
+ inliningMarker.classList.add("inlining-marker")
+ inliningMarker.setAttribute("data-descr", `${sourceName} was inlined here`)
+ span.appendChild(inliningMarker);
+ }
+ span.onclick = function (e) {
+ e.stopPropagation();
+ view.onSelectSourcePosition(sourcePosition, !e.shiftKey)
+ };
+ view.addHtmlElementToSourcePosition(sourcePosition, span);
+ textnode.parentNode.insertBefore(span, replacementNode);
+ }
+ }
+
+ insertLineNumber(lineElement, lineNumber) {
+ const view = this;
+ const lineNumberElement = document.createElement("div");
+ lineNumberElement.classList.add("line-number");
+ lineNumberElement.innerText = lineNumber;
+ lineNumberElement.onclick = function (e) {
+ e.stopPropagation();
+ view.onSelectLine(lineNumber, !e.shiftKey);
+ }
+ lineElement.insertBefore(lineNumberElement, lineElement.firstChild)
+ }
+
+ deleteContent() { }
}