[turbolizer] Schedule view/phase refactoring
Bug: v8:7327 Change-Id: I45085b4b2dcb76948e39e79fcf15711deb531541 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3764441 Commit-Queue: Danylo Boiko <danielboyko02@gmail.com> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/main@{#81824}
This commit is contained in:
parent
9230a278e1
commit
a1bdea56ca
@ -92,6 +92,20 @@ export class InstructionsPhase extends Phase {
|
||||
return this.blockIdToInstructionRange[blockId] ?? [-1, -1];
|
||||
}
|
||||
|
||||
public getInstructionMarker(start: number, end: number): [string, string] {
|
||||
if (start != end) {
|
||||
return ["⊙", `This node generated instructions in range [${start},${end}). ` +
|
||||
`This is currently unreliable for constants.`];
|
||||
}
|
||||
if (start != -1) {
|
||||
return ["·", `The instruction selector did not generate instructions ` +
|
||||
`for this node, but processed the node at instruction ${start}. ` +
|
||||
`This usually means that this node was folded into another node; ` +
|
||||
`the highlighted machine code is a guess.`];
|
||||
}
|
||||
return ["", `This not is not in the final schedule.`];
|
||||
}
|
||||
|
||||
public getInstructionKindForPCOffset(offset: number): InstructionKind {
|
||||
if (this.codeOffsetsInfo) {
|
||||
if (offset >= this.codeOffsetsInfo.deoptimizationExits) {
|
||||
|
@ -5,22 +5,16 @@
|
||||
import { Phase, PhaseType } from "./phase";
|
||||
|
||||
export class SchedulePhase extends Phase {
|
||||
data: string;
|
||||
schedule: { currentBlock, blocks: Array<any>, nodes: Array<any> };
|
||||
data: ScheduleData;
|
||||
|
||||
constructor(name: string, data: string) {
|
||||
constructor(name: string, dataJson) {
|
||||
super(name, PhaseType.Schedule);
|
||||
this.data = data;
|
||||
this.schedule = {
|
||||
currentBlock: undefined,
|
||||
blocks: new Array<any>(),
|
||||
nodes: new Array<any>()
|
||||
};
|
||||
this.parseScheduleFromJSON(data);
|
||||
this.data = new ScheduleData();
|
||||
this.parseScheduleFromJSON(dataJson);
|
||||
}
|
||||
|
||||
private parseScheduleFromJSON(scheduleDataJson): void {
|
||||
const lines = scheduleDataJson.split(/[\n]/);
|
||||
private parseScheduleFromJSON(dataJson): void {
|
||||
const lines = dataJson.split(/[\n]/);
|
||||
nextLine:
|
||||
for (const line of lines) {
|
||||
for (const rule of this.parsingRules) {
|
||||
@ -37,46 +31,39 @@ export class SchedulePhase extends Phase {
|
||||
}
|
||||
|
||||
private createNode = match => {
|
||||
let inputs = [];
|
||||
let inputs = new Array<number>();
|
||||
if (match.groups.args) {
|
||||
const nodeIdsString = match.groups.args.replace(/\s/g, '');
|
||||
const nodeIdStrings = nodeIdsString.split(',');
|
||||
const nodeIdsString = match.groups.args.replace(/\s/g, "");
|
||||
const nodeIdStrings = nodeIdsString.split(",");
|
||||
inputs = nodeIdStrings.map(n => Number.parseInt(n, 10));
|
||||
}
|
||||
const node = {
|
||||
id: Number.parseInt(match.groups.id, 10),
|
||||
label: match.groups.label,
|
||||
inputs: inputs
|
||||
};
|
||||
const nodeId = Number.parseInt(match.groups.id, 10);
|
||||
const node = new ScheduleNode(nodeId, match.groups.label, inputs);
|
||||
if (match.groups.blocks) {
|
||||
const nodeIdsString = match.groups.blocks.replace(/\s/g, '').replace(/B/g, '');
|
||||
const nodeIdStrings = nodeIdsString.split(',');
|
||||
this.schedule.currentBlock.succ = nodeIdStrings.map(n => Number.parseInt(n, 10));
|
||||
const nodeIdsString = match.groups.blocks.replace(/\s/g, "").replace(/B/g, "");
|
||||
const nodeIdStrings = nodeIdsString.split(",");
|
||||
this.data.lastBlock().successors = nodeIdStrings.map(n => Number.parseInt(n, 10));
|
||||
}
|
||||
this.schedule.nodes[node.id] = node;
|
||||
this.schedule.currentBlock.nodes.push(node);
|
||||
this.data.nodes[node.id] = node;
|
||||
this.data.lastBlock().nodes.push(node);
|
||||
}
|
||||
|
||||
private createBlock = match => {
|
||||
let predecessors = [];
|
||||
let predecessors = new Array<number>();
|
||||
if (match.groups.in) {
|
||||
const blockIdsString = match.groups.in.replace(/\s/g, '').replace(/B/g, '');
|
||||
const blockIdStrings = blockIdsString.split(',');
|
||||
const blockIdsString = match.groups.in.replace(/\s/g, "").replace(/B/g, "");
|
||||
const blockIdStrings = blockIdsString.split(",");
|
||||
predecessors = blockIdStrings.map(n => Number.parseInt(n, 10));
|
||||
}
|
||||
const block = {
|
||||
id: Number.parseInt(match.groups.id, 10),
|
||||
isDeferred: match.groups.deferred != undefined,
|
||||
pred: predecessors.sort(),
|
||||
succ: [],
|
||||
nodes: []
|
||||
};
|
||||
this.schedule.blocks[block.id] = block;
|
||||
this.schedule.currentBlock = block;
|
||||
const blockId = Number.parseInt(match.groups.id, 10);
|
||||
const block = new ScheduleBlock(blockId, match.groups.deferred !== undefined,
|
||||
predecessors.sort());
|
||||
this.data.blocks[block.id] = block;
|
||||
}
|
||||
|
||||
private setGotoSuccessor = match => {
|
||||
this.schedule.currentBlock.succ = [Number.parseInt(match.groups.successor.replace(/\s/g, ''), 10)];
|
||||
this.data.lastBlock().successors =
|
||||
[Number.parseInt(match.groups.successor.replace(/\s/g, ""), 10)];
|
||||
}
|
||||
|
||||
private parsingRules = [
|
||||
@ -98,3 +85,50 @@ export class SchedulePhase extends Phase {
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
export class ScheduleNode {
|
||||
id: number;
|
||||
label: string;
|
||||
inputs: Array<number>;
|
||||
|
||||
constructor(id: number, label: string, inputs: Array<number>) {
|
||||
this.id = id;
|
||||
this.label = label;
|
||||
this.inputs = inputs;
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return `${this.id}: ${this.label}(${this.inputs.join(", ")})`;
|
||||
}
|
||||
}
|
||||
|
||||
export class ScheduleBlock {
|
||||
id: number;
|
||||
deferred: boolean;
|
||||
predecessors: Array<number>;
|
||||
successors: Array<number>;
|
||||
nodes: Array<ScheduleNode>;
|
||||
|
||||
constructor(id: number, deferred: boolean, predecessors: Array<number>) {
|
||||
this.id = id;
|
||||
this.deferred = deferred;
|
||||
this.predecessors = predecessors;
|
||||
this.successors = new Array<number>();
|
||||
this.nodes = new Array<ScheduleNode>();
|
||||
}
|
||||
}
|
||||
|
||||
export class ScheduleData {
|
||||
nodes: Array<ScheduleNode>;
|
||||
blocks: Array<ScheduleBlock>;
|
||||
|
||||
constructor() {
|
||||
this.nodes = new Array<ScheduleNode>();
|
||||
this.blocks = new Array<ScheduleBlock>();
|
||||
}
|
||||
|
||||
public lastBlock(): ScheduleBlock {
|
||||
if (this.blocks.length == 0) return null;
|
||||
return this.blocks[this.blocks.length - 1];
|
||||
}
|
||||
}
|
||||
|
@ -12,13 +12,14 @@ export interface ClearableHandler {
|
||||
}
|
||||
|
||||
export interface NodeSelectionHandler {
|
||||
select(nodes: Iterable<TurboshaftGraphNode | GraphNode | string>, selected: boolean): void;
|
||||
select(nodes: Iterable<TurboshaftGraphNode | GraphNode | string | number>, selected: boolean):
|
||||
void;
|
||||
clear(): void;
|
||||
brokeredNodeSelect(nodeIds: Set<string>, selected: boolean): void;
|
||||
}
|
||||
|
||||
export interface BlockSelectionHandler {
|
||||
select(blocks: Iterable<TurboshaftGraphBlock | string>, selected: boolean): void;
|
||||
select(blocks: Iterable<TurboshaftGraphBlock | string | number>, selected: boolean): void;
|
||||
clear(): void;
|
||||
brokeredBlockSelect(blockIds: Array<string>, selected: boolean): void;
|
||||
}
|
||||
|
@ -2,32 +2,38 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import * as C from "./../common/constants";
|
||||
import { storageSetItem } from "../common/util";
|
||||
import { TextView } from "./text-view";
|
||||
import { SchedulePhase } from "../phases/schedule-phase";
|
||||
import { SelectionStorage } from "../selection/selection-storage";
|
||||
import { SelectionBroker } from "../selection/selection-broker";
|
||||
import { ScheduleBlock, ScheduleNode, SchedulePhase } from "../phases/schedule-phase";
|
||||
|
||||
export class ScheduleView extends TextView {
|
||||
schedule: SchedulePhase;
|
||||
|
||||
createViewElement() {
|
||||
const pane = document.createElement('div');
|
||||
pane.setAttribute('id', "schedule");
|
||||
constructor(parent: HTMLElement, broker: SelectionBroker) {
|
||||
super(parent, broker);
|
||||
this.sourceResolver = broker.sourceResolver;
|
||||
}
|
||||
|
||||
public createViewElement(): HTMLDivElement {
|
||||
const pane = document.createElement("div");
|
||||
pane.setAttribute("id", C.SCHEDULE_PANE_ID);
|
||||
pane.classList.add("scrollable");
|
||||
pane.setAttribute("tabindex", "0");
|
||||
return pane;
|
||||
}
|
||||
|
||||
constructor(parentId, broker) {
|
||||
super(parentId, broker);
|
||||
this.sourceResolver = broker.sourceResolver;
|
||||
}
|
||||
|
||||
private attachSelection(adaptedSelection: SelectionStorage): void {
|
||||
if (!(adaptedSelection instanceof SelectionStorage)) return;
|
||||
this.nodeSelectionHandler.clear();
|
||||
this.blockSelectionHandler.clear();
|
||||
this.nodeSelectionHandler.select(adaptedSelection.adaptedNodes, true);
|
||||
this.blockSelectionHandler.select(adaptedSelection.adaptedBocks, true);
|
||||
public initializeContent(schedule: SchedulePhase, rememberedSelection: SelectionStorage): void {
|
||||
this.divNode.innerHTML = "";
|
||||
this.schedule = schedule;
|
||||
this.addBlocks(schedule.data.blocks);
|
||||
this.show();
|
||||
if (rememberedSelection) {
|
||||
const adaptedSelection = this.adaptSelection(rememberedSelection);
|
||||
this.attachSelection(adaptedSelection);
|
||||
}
|
||||
}
|
||||
|
||||
public detachSelection(): SelectionStorage {
|
||||
@ -41,157 +47,134 @@ export class ScheduleView extends TextView {
|
||||
return selection;
|
||||
}
|
||||
|
||||
public initializeContent(schedule: SchedulePhase, rememberedSelection: SelectionStorage): void {
|
||||
this.divNode.innerHTML = "";
|
||||
this.schedule = schedule;
|
||||
this.addBlocks(schedule.schedule.blocks);
|
||||
this.show();
|
||||
if (rememberedSelection) {
|
||||
const adaptedSelection = this.adaptSelection(rememberedSelection);
|
||||
this.attachSelection(adaptedSelection);
|
||||
}
|
||||
}
|
||||
|
||||
createElementFromString(htmlString) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = htmlString.trim();
|
||||
return div.firstChild;
|
||||
}
|
||||
|
||||
elementForBlock(block) {
|
||||
const view = this;
|
||||
function createElement(tag: string, cls: string, content?: string) {
|
||||
const el = document.createElement(tag);
|
||||
el.className = cls;
|
||||
if (content != undefined) el.innerHTML = content;
|
||||
return el;
|
||||
}
|
||||
|
||||
function mkNodeLinkHandler(nodeId) {
|
||||
return function (e) {
|
||||
e.stopPropagation();
|
||||
if (!e.shiftKey) {
|
||||
view.nodeSelectionHandler.clear();
|
||||
}
|
||||
view.nodeSelectionHandler.select([nodeId], true);
|
||||
};
|
||||
}
|
||||
|
||||
function getMarker(start, end) {
|
||||
if (start != end) {
|
||||
return ["⊙", `This node generated instructions in range [${start},${end}). ` +
|
||||
`This is currently unreliable for constants.`];
|
||||
}
|
||||
if (start != -1) {
|
||||
return ["·", `The instruction selector did not generate instructions ` +
|
||||
`for this node, but processed the node at instruction ${start}. ` +
|
||||
`This usually means that this node was folded into another node; ` +
|
||||
`the highlighted machine code is a guess.`];
|
||||
}
|
||||
return ["", `This not is not in the final schedule.`];
|
||||
}
|
||||
|
||||
function createElementForNode(node) {
|
||||
const nodeEl = createElement("div", "node");
|
||||
|
||||
const [start, end] = view.sourceResolver.instructionsPhase.getInstruction(node.id);
|
||||
const [marker, tooltip] = getMarker(start, end);
|
||||
const instrMarker = createElement("div", "instr-marker com", marker);
|
||||
instrMarker.setAttribute("title", tooltip);
|
||||
instrMarker.onclick = mkNodeLinkHandler(node.id);
|
||||
nodeEl.appendChild(instrMarker);
|
||||
|
||||
const nodeId = createElement("div", "node-id tag clickable", node.id);
|
||||
nodeId.onclick = mkNodeLinkHandler(node.id);
|
||||
view.addHtmlElementForNodeId(node.id, nodeId);
|
||||
nodeEl.appendChild(nodeId);
|
||||
const nodeLabel = createElement("div", "node-label", node.label);
|
||||
nodeEl.appendChild(nodeLabel);
|
||||
if (node.inputs.length > 0) {
|
||||
const nodeParameters = createElement("div", "parameter-list comma-sep-list");
|
||||
for (const param of node.inputs) {
|
||||
const paramEl = createElement("div", "parameter tag clickable", param);
|
||||
nodeParameters.appendChild(paramEl);
|
||||
paramEl.onclick = mkNodeLinkHandler(param);
|
||||
view.addHtmlElementForNodeId(param, paramEl);
|
||||
}
|
||||
nodeEl.appendChild(nodeParameters);
|
||||
}
|
||||
|
||||
return nodeEl;
|
||||
}
|
||||
|
||||
function mkBlockLinkHandler(blockId) {
|
||||
return function (e) {
|
||||
e.stopPropagation();
|
||||
if (!e.shiftKey) {
|
||||
view.blockSelectionHandler.clear();
|
||||
}
|
||||
view.blockSelectionHandler.select(["" + blockId], true);
|
||||
};
|
||||
}
|
||||
|
||||
const scheduleBlock = createElement("div", "schedule-block");
|
||||
scheduleBlock.classList.toggle("deferred", block.isDeferred);
|
||||
|
||||
const [start, end] = view.sourceResolver.instructionsPhase
|
||||
.getInstructionRangeForBlock(block.id);
|
||||
const instrMarker = createElement("div", "instr-marker com", "⊙");
|
||||
instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`);
|
||||
instrMarker.onclick = mkBlockLinkHandler(block.id);
|
||||
scheduleBlock.appendChild(instrMarker);
|
||||
|
||||
const blockId = createElement("div", "block-id com clickable", block.id);
|
||||
blockId.onclick = mkBlockLinkHandler(block.id);
|
||||
scheduleBlock.appendChild(blockId);
|
||||
const blockPred = createElement("div", "predecessor-list block-list comma-sep-list");
|
||||
for (const pred of block.pred) {
|
||||
const predEl = createElement("div", "block-id com clickable", pred);
|
||||
predEl.onclick = mkBlockLinkHandler(pred);
|
||||
blockPred.appendChild(predEl);
|
||||
}
|
||||
if (block.pred.length) scheduleBlock.appendChild(blockPred);
|
||||
const nodes = createElement("div", "nodes");
|
||||
for (const node of block.nodes) {
|
||||
nodes.appendChild(createElementForNode(node));
|
||||
}
|
||||
scheduleBlock.appendChild(nodes);
|
||||
const blockSucc = createElement("div", "successor-list block-list comma-sep-list");
|
||||
for (const succ of block.succ) {
|
||||
const succEl = createElement("div", "block-id com clickable", succ);
|
||||
succEl.onclick = mkBlockLinkHandler(succ);
|
||||
blockSucc.appendChild(succEl);
|
||||
}
|
||||
if (block.succ.length) scheduleBlock.appendChild(blockSucc);
|
||||
this.addHtmlElementForBlockId(block.id, scheduleBlock);
|
||||
return scheduleBlock;
|
||||
}
|
||||
|
||||
addBlocks(blocks) {
|
||||
for (const block of blocks) {
|
||||
const blockEl = this.elementForBlock(block);
|
||||
this.divNode.appendChild(blockEl);
|
||||
}
|
||||
}
|
||||
|
||||
lineString(node) {
|
||||
return `${node.id}: ${node.label}(${node.inputs.join(", ")})`;
|
||||
}
|
||||
|
||||
searchInputAction(searchBar, e, onlyVisible) {
|
||||
public searchInputAction(searchBar: HTMLInputElement, e: KeyboardEvent, onlyVisible: boolean):
|
||||
void {
|
||||
e.stopPropagation();
|
||||
this.nodeSelectionHandler.clear();
|
||||
const query = searchBar.value;
|
||||
if (query.length == 0) return;
|
||||
const select = [];
|
||||
window.sessionStorage.setItem("lastSearch", query);
|
||||
const select = new Array<number>();
|
||||
storageSetItem("lastSearch", query);
|
||||
const reg = new RegExp(query);
|
||||
for (const node of this.schedule.schedule.nodes) {
|
||||
for (const node of this.schedule.data.nodes) {
|
||||
if (node === undefined) continue;
|
||||
if (reg.exec(this.lineString(node)) != null) {
|
||||
if (reg.exec(node.toString()) !== null) {
|
||||
select.push(node.id);
|
||||
}
|
||||
}
|
||||
this.nodeSelectionHandler.select(select, true);
|
||||
}
|
||||
|
||||
private addBlocks(blocks: Array<ScheduleBlock>) {
|
||||
for (const block of blocks) {
|
||||
const blockEl = this.createElementForBlock(block);
|
||||
this.divNode.appendChild(blockEl);
|
||||
}
|
||||
}
|
||||
|
||||
private attachSelection(adaptedSelection: SelectionStorage): void {
|
||||
if (!(adaptedSelection instanceof SelectionStorage)) return;
|
||||
this.nodeSelectionHandler.clear();
|
||||
this.blockSelectionHandler.clear();
|
||||
this.nodeSelectionHandler.select(adaptedSelection.adaptedNodes, true);
|
||||
this.blockSelectionHandler.select(adaptedSelection.adaptedBocks, true);
|
||||
}
|
||||
|
||||
private createElementForBlock(block: ScheduleBlock): HTMLElement {
|
||||
const scheduleBlock = this.createElement("div", "schedule-block");
|
||||
scheduleBlock.classList.toggle("deferred", block.deferred);
|
||||
|
||||
const [start, end] = this.sourceResolver.instructionsPhase
|
||||
.getInstructionRangeForBlock(block.id);
|
||||
const instrMarker = this.createElement("div", "instr-marker com", "⊙");
|
||||
instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`);
|
||||
instrMarker.onclick = this.mkBlockLinkHandler(block.id);
|
||||
scheduleBlock.appendChild(instrMarker);
|
||||
|
||||
const blockId = this.createElement("div", "block-id com clickable", String(block.id));
|
||||
blockId.onclick = this.mkBlockLinkHandler(block.id);
|
||||
scheduleBlock.appendChild(blockId);
|
||||
const blockPred = this.createElement("div", "predecessor-list block-list comma-sep-list");
|
||||
for (const pred of block.predecessors) {
|
||||
const predEl = this.createElement("div", "block-id com clickable", String(pred));
|
||||
predEl.onclick = this.mkBlockLinkHandler(pred);
|
||||
blockPred.appendChild(predEl);
|
||||
}
|
||||
if (block.predecessors.length) scheduleBlock.appendChild(blockPred);
|
||||
const nodes = this.createElement("div", "nodes");
|
||||
for (const node of block.nodes) {
|
||||
nodes.appendChild(this.createElementForNode(node));
|
||||
}
|
||||
scheduleBlock.appendChild(nodes);
|
||||
|
||||
const blockSucc = this.createElement("div", "successor-list block-list comma-sep-list");
|
||||
for (const succ of block.successors) {
|
||||
const succEl = this.createElement("div", "block-id com clickable", String(succ));
|
||||
succEl.onclick = this.mkBlockLinkHandler(succ);
|
||||
blockSucc.appendChild(succEl);
|
||||
}
|
||||
if (block.successors.length) scheduleBlock.appendChild(blockSucc);
|
||||
this.addHtmlElementForBlockId(block.id, scheduleBlock);
|
||||
return scheduleBlock;
|
||||
}
|
||||
|
||||
private createElementForNode(node: ScheduleNode): HTMLElement {
|
||||
const nodeEl = this.createElement("div", "node");
|
||||
|
||||
const [start, end] = this.sourceResolver.instructionsPhase.getInstruction(node.id);
|
||||
const [marker, tooltip] = this.sourceResolver.instructionsPhase
|
||||
.getInstructionMarker(start, end);
|
||||
const instrMarker = this.createElement("div", "instr-marker com", marker);
|
||||
instrMarker.setAttribute("title", tooltip);
|
||||
instrMarker.onclick = this.mkNodeLinkHandler(node.id);
|
||||
nodeEl.appendChild(instrMarker);
|
||||
|
||||
const nodeIdEl = this.createElement("div", "node-id tag clickable", String(node.id));
|
||||
nodeIdEl.onclick = this.mkNodeLinkHandler(node.id);
|
||||
this.addHtmlElementForNodeId(node.id, nodeIdEl);
|
||||
nodeEl.appendChild(nodeIdEl);
|
||||
const nodeLabel = this.createElement("div", "node-label", node.label);
|
||||
nodeEl.appendChild(nodeLabel);
|
||||
if (node.inputs.length > 0) {
|
||||
const nodeParameters = this.createElement("div", "parameter-list comma-sep-list");
|
||||
for (const param of node.inputs) {
|
||||
const paramEl = this.createElement("div", "parameter tag clickable", String(param));
|
||||
nodeParameters.appendChild(paramEl);
|
||||
paramEl.onclick = this.mkNodeLinkHandler(param);
|
||||
this.addHtmlElementForNodeId(param, paramEl);
|
||||
}
|
||||
nodeEl.appendChild(nodeParameters);
|
||||
}
|
||||
|
||||
return nodeEl;
|
||||
}
|
||||
|
||||
private mkBlockLinkHandler(blockId: number): (e: MouseEvent) => void {
|
||||
const view = this;
|
||||
return function (e: MouseEvent) {
|
||||
e.stopPropagation();
|
||||
if (!e.shiftKey) {
|
||||
view.blockSelectionHandler.clear();
|
||||
}
|
||||
view.blockSelectionHandler.select([blockId], true);
|
||||
};
|
||||
}
|
||||
|
||||
private mkNodeLinkHandler(nodeId: number): (e: MouseEvent) => void {
|
||||
const view = this;
|
||||
return function (e: MouseEvent) {
|
||||
e.stopPropagation();
|
||||
if (!e.shiftKey) {
|
||||
view.nodeSelectionHandler.clear();
|
||||
}
|
||||
view.nodeSelectionHandler.select([nodeId], true);
|
||||
};
|
||||
}
|
||||
|
||||
private createElement(tag: string, cls: string, content?: string) {
|
||||
const el = document.createElement(tag);
|
||||
el.className = cls;
|
||||
if (content !== undefined) el.innerHTML = content;
|
||||
return el;
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ export abstract class TextView extends PhaseView {
|
||||
nodeIdToBlockId: Array<string>;
|
||||
patterns: Array<Array<any>>;
|
||||
|
||||
constructor(parent: HTMLDivElement, broker: SelectionBroker) {
|
||||
constructor(parent: HTMLElement, broker: SelectionBroker) {
|
||||
super(parent);
|
||||
this.broker = broker;
|
||||
this.sourceResolver = broker.sourceResolver;
|
||||
@ -69,7 +69,7 @@ export abstract class TextView extends PhaseView {
|
||||
|
||||
public initializeContent(genericPhase: GenericTextPhase, _): void {
|
||||
this.clearText();
|
||||
if (!(genericPhase instanceof SequencePhase)) {
|
||||
if (genericPhase instanceof DisassemblyPhase) {
|
||||
this.processText(genericPhase.data);
|
||||
}
|
||||
this.show();
|
||||
@ -207,7 +207,7 @@ export abstract class TextView extends PhaseView {
|
||||
private initializeNodeSelectionHandler(): NodeSelectionHandler & ClearableHandler {
|
||||
const view = this;
|
||||
return {
|
||||
select: function (nodeIds: Array<string>, selected: boolean) {
|
||||
select: function (nodeIds: Array<string | number>, selected: boolean) {
|
||||
view.nodeSelection.select(nodeIds, selected);
|
||||
view.updateSelection();
|
||||
view.broker.broadcastNodeSelect(this, view.nodeSelection.selectedKeys(), selected);
|
||||
|
Loading…
Reference in New Issue
Block a user