11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciimport { PhaseView } from "../src/view"; 61cb0ef41Sopenharmony_ciimport { anyToString, ViewElements, isIterable } from "../src/util"; 71cb0ef41Sopenharmony_ciimport { MySelection } from "../src/selection"; 81cb0ef41Sopenharmony_ciimport { SourceResolver } from "./source-resolver"; 91cb0ef41Sopenharmony_ciimport { SelectionBroker } from "./selection-broker"; 101cb0ef41Sopenharmony_ciimport { NodeSelectionHandler, BlockSelectionHandler, RegisterAllocationSelectionHandler } from "./selection-handler"; 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciexport abstract class TextView extends PhaseView { 131cb0ef41Sopenharmony_ci selectionHandler: NodeSelectionHandler; 141cb0ef41Sopenharmony_ci blockSelectionHandler: BlockSelectionHandler; 151cb0ef41Sopenharmony_ci registerAllocationSelectionHandler: RegisterAllocationSelectionHandler; 161cb0ef41Sopenharmony_ci selection: MySelection; 171cb0ef41Sopenharmony_ci blockSelection: MySelection; 181cb0ef41Sopenharmony_ci registerAllocationSelection: MySelection; 191cb0ef41Sopenharmony_ci textListNode: HTMLUListElement; 201cb0ef41Sopenharmony_ci instructionIdToHtmlElementsMap: Map<string, Array<HTMLElement>>; 211cb0ef41Sopenharmony_ci nodeIdToHtmlElementsMap: Map<string, Array<HTMLElement>>; 221cb0ef41Sopenharmony_ci blockIdToHtmlElementsMap: Map<string, Array<HTMLElement>>; 231cb0ef41Sopenharmony_ci blockIdToNodeIds: Map<string, Array<string>>; 241cb0ef41Sopenharmony_ci nodeIdToBlockId: Array<string>; 251cb0ef41Sopenharmony_ci patterns: any; 261cb0ef41Sopenharmony_ci sourceResolver: SourceResolver; 271cb0ef41Sopenharmony_ci broker: SelectionBroker; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci constructor(id, broker) { 301cb0ef41Sopenharmony_ci super(id); 311cb0ef41Sopenharmony_ci const view = this; 321cb0ef41Sopenharmony_ci view.textListNode = view.divNode.getElementsByTagName('ul')[0]; 331cb0ef41Sopenharmony_ci view.patterns = null; 341cb0ef41Sopenharmony_ci view.instructionIdToHtmlElementsMap = new Map(); 351cb0ef41Sopenharmony_ci view.nodeIdToHtmlElementsMap = new Map(); 361cb0ef41Sopenharmony_ci view.blockIdToHtmlElementsMap = new Map(); 371cb0ef41Sopenharmony_ci view.blockIdToNodeIds = new Map(); 381cb0ef41Sopenharmony_ci view.nodeIdToBlockId = []; 391cb0ef41Sopenharmony_ci view.selection = new MySelection(anyToString); 401cb0ef41Sopenharmony_ci view.blockSelection = new MySelection(anyToString); 411cb0ef41Sopenharmony_ci view.broker = broker; 421cb0ef41Sopenharmony_ci view.sourceResolver = broker.sourceResolver; 431cb0ef41Sopenharmony_ci const selectionHandler = { 441cb0ef41Sopenharmony_ci clear: function () { 451cb0ef41Sopenharmony_ci view.selection.clear(); 461cb0ef41Sopenharmony_ci view.updateSelection(); 471cb0ef41Sopenharmony_ci broker.broadcastClear(selectionHandler); 481cb0ef41Sopenharmony_ci }, 491cb0ef41Sopenharmony_ci select: function (nodeIds, selected) { 501cb0ef41Sopenharmony_ci view.selection.select(nodeIds, selected); 511cb0ef41Sopenharmony_ci view.updateSelection(); 521cb0ef41Sopenharmony_ci broker.broadcastNodeSelect(selectionHandler, view.selection.selectedKeys(), selected); 531cb0ef41Sopenharmony_ci }, 541cb0ef41Sopenharmony_ci brokeredNodeSelect: function (nodeIds, selected) { 551cb0ef41Sopenharmony_ci const firstSelect = view.blockSelection.isEmpty(); 561cb0ef41Sopenharmony_ci view.selection.select(nodeIds, selected); 571cb0ef41Sopenharmony_ci view.updateSelection(firstSelect); 581cb0ef41Sopenharmony_ci }, 591cb0ef41Sopenharmony_ci brokeredClear: function () { 601cb0ef41Sopenharmony_ci view.selection.clear(); 611cb0ef41Sopenharmony_ci view.updateSelection(); 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci }; 641cb0ef41Sopenharmony_ci this.selectionHandler = selectionHandler; 651cb0ef41Sopenharmony_ci broker.addNodeHandler(selectionHandler); 661cb0ef41Sopenharmony_ci view.divNode.addEventListener('click', e => { 671cb0ef41Sopenharmony_ci if (!e.shiftKey) { 681cb0ef41Sopenharmony_ci view.selectionHandler.clear(); 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci e.stopPropagation(); 711cb0ef41Sopenharmony_ci }); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci const blockSelectionHandler = { 741cb0ef41Sopenharmony_ci clear: function () { 751cb0ef41Sopenharmony_ci view.blockSelection.clear(); 761cb0ef41Sopenharmony_ci view.updateSelection(); 771cb0ef41Sopenharmony_ci broker.broadcastClear(blockSelectionHandler); 781cb0ef41Sopenharmony_ci }, 791cb0ef41Sopenharmony_ci select: function (blockIds, selected) { 801cb0ef41Sopenharmony_ci view.blockSelection.select(blockIds, selected); 811cb0ef41Sopenharmony_ci view.updateSelection(); 821cb0ef41Sopenharmony_ci broker.broadcastBlockSelect(blockSelectionHandler, blockIds, selected); 831cb0ef41Sopenharmony_ci }, 841cb0ef41Sopenharmony_ci brokeredBlockSelect: function (blockIds, selected) { 851cb0ef41Sopenharmony_ci const firstSelect = view.blockSelection.isEmpty(); 861cb0ef41Sopenharmony_ci view.blockSelection.select(blockIds, selected); 871cb0ef41Sopenharmony_ci view.updateSelection(firstSelect); 881cb0ef41Sopenharmony_ci }, 891cb0ef41Sopenharmony_ci brokeredClear: function () { 901cb0ef41Sopenharmony_ci view.blockSelection.clear(); 911cb0ef41Sopenharmony_ci view.updateSelection(); 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci }; 941cb0ef41Sopenharmony_ci this.blockSelectionHandler = blockSelectionHandler; 951cb0ef41Sopenharmony_ci broker.addBlockHandler(blockSelectionHandler); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci view.registerAllocationSelection = new MySelection(anyToString); 981cb0ef41Sopenharmony_ci const registerAllocationSelectionHandler = { 991cb0ef41Sopenharmony_ci clear: function () { 1001cb0ef41Sopenharmony_ci view.registerAllocationSelection.clear(); 1011cb0ef41Sopenharmony_ci view.updateSelection(); 1021cb0ef41Sopenharmony_ci broker.broadcastClear(registerAllocationSelectionHandler); 1031cb0ef41Sopenharmony_ci }, 1041cb0ef41Sopenharmony_ci select: function (instructionIds, selected) { 1051cb0ef41Sopenharmony_ci view.registerAllocationSelection.select(instructionIds, selected); 1061cb0ef41Sopenharmony_ci view.updateSelection(); 1071cb0ef41Sopenharmony_ci broker.broadcastInstructionSelect(null, [instructionIds], selected); 1081cb0ef41Sopenharmony_ci }, 1091cb0ef41Sopenharmony_ci brokeredRegisterAllocationSelect: function (instructionIds, selected) { 1101cb0ef41Sopenharmony_ci const firstSelect = view.blockSelection.isEmpty(); 1111cb0ef41Sopenharmony_ci view.registerAllocationSelection.select(instructionIds, selected); 1121cb0ef41Sopenharmony_ci view.updateSelection(firstSelect); 1131cb0ef41Sopenharmony_ci }, 1141cb0ef41Sopenharmony_ci brokeredClear: function () { 1151cb0ef41Sopenharmony_ci view.registerAllocationSelection.clear(); 1161cb0ef41Sopenharmony_ci view.updateSelection(); 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci }; 1191cb0ef41Sopenharmony_ci broker.addRegisterAllocatorHandler(registerAllocationSelectionHandler); 1201cb0ef41Sopenharmony_ci view.registerAllocationSelectionHandler = registerAllocationSelectionHandler; 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci // instruction-id are the divs for the register allocator phase 1241cb0ef41Sopenharmony_ci addHtmlElementForInstructionId(anyInstructionId: any, htmlElement: HTMLElement) { 1251cb0ef41Sopenharmony_ci const instructionId = anyToString(anyInstructionId); 1261cb0ef41Sopenharmony_ci if (!this.instructionIdToHtmlElementsMap.has(instructionId)) { 1271cb0ef41Sopenharmony_ci this.instructionIdToHtmlElementsMap.set(instructionId, []); 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci this.instructionIdToHtmlElementsMap.get(instructionId).push(htmlElement); 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci addHtmlElementForNodeId(anyNodeId: any, htmlElement: HTMLElement) { 1331cb0ef41Sopenharmony_ci const nodeId = anyToString(anyNodeId); 1341cb0ef41Sopenharmony_ci if (!this.nodeIdToHtmlElementsMap.has(nodeId)) { 1351cb0ef41Sopenharmony_ci this.nodeIdToHtmlElementsMap.set(nodeId, []); 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci this.nodeIdToHtmlElementsMap.get(nodeId).push(htmlElement); 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci addHtmlElementForBlockId(anyBlockId, htmlElement) { 1411cb0ef41Sopenharmony_ci const blockId = anyToString(anyBlockId); 1421cb0ef41Sopenharmony_ci if (!this.blockIdToHtmlElementsMap.has(blockId)) { 1431cb0ef41Sopenharmony_ci this.blockIdToHtmlElementsMap.set(blockId, []); 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci this.blockIdToHtmlElementsMap.get(blockId).push(htmlElement); 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci addNodeIdToBlockId(anyNodeId, anyBlockId) { 1491cb0ef41Sopenharmony_ci const blockId = anyToString(anyBlockId); 1501cb0ef41Sopenharmony_ci if (!this.blockIdToNodeIds.has(blockId)) { 1511cb0ef41Sopenharmony_ci this.blockIdToNodeIds.set(blockId, []); 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci this.blockIdToNodeIds.get(blockId).push(anyToString(anyNodeId)); 1541cb0ef41Sopenharmony_ci this.nodeIdToBlockId[anyNodeId] = blockId; 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci blockIdsForNodeIds(nodeIds) { 1581cb0ef41Sopenharmony_ci const blockIds = []; 1591cb0ef41Sopenharmony_ci for (const nodeId of nodeIds) { 1601cb0ef41Sopenharmony_ci const blockId = this.nodeIdToBlockId[nodeId]; 1611cb0ef41Sopenharmony_ci if (blockId == undefined) continue; 1621cb0ef41Sopenharmony_ci blockIds.push(blockId); 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci return blockIds; 1651cb0ef41Sopenharmony_ci } 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci updateSelection(scrollIntoView: boolean = false) { 1681cb0ef41Sopenharmony_ci if (this.divNode.parentNode == null) return; 1691cb0ef41Sopenharmony_ci const mkVisible = new ViewElements(this.divNode.parentNode as HTMLElement); 1701cb0ef41Sopenharmony_ci const view = this; 1711cb0ef41Sopenharmony_ci const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset]`); 1721cb0ef41Sopenharmony_ci for (const el of elementsToSelect) { 1731cb0ef41Sopenharmony_ci el.classList.toggle("selected", false); 1741cb0ef41Sopenharmony_ci } 1751cb0ef41Sopenharmony_ci for (const [blockId, elements] of this.blockIdToHtmlElementsMap.entries()) { 1761cb0ef41Sopenharmony_ci const isSelected = view.blockSelection.isSelected(blockId); 1771cb0ef41Sopenharmony_ci for (const element of elements) { 1781cb0ef41Sopenharmony_ci mkVisible.consider(element, isSelected); 1791cb0ef41Sopenharmony_ci element.classList.toggle("selected", isSelected); 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci for (const key of this.instructionIdToHtmlElementsMap.keys()) { 1841cb0ef41Sopenharmony_ci for (const element of this.instructionIdToHtmlElementsMap.get(key)) { 1851cb0ef41Sopenharmony_ci element.classList.toggle("selected", false); 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci } 1881cb0ef41Sopenharmony_ci for (const instrId of view.registerAllocationSelection.selectedKeys()) { 1891cb0ef41Sopenharmony_ci const elements = this.instructionIdToHtmlElementsMap.get(instrId); 1901cb0ef41Sopenharmony_ci if (!elements) continue; 1911cb0ef41Sopenharmony_ci for (const element of elements) { 1921cb0ef41Sopenharmony_ci mkVisible.consider(element, true); 1931cb0ef41Sopenharmony_ci element.classList.toggle("selected", true); 1941cb0ef41Sopenharmony_ci } 1951cb0ef41Sopenharmony_ci } 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci for (const key of this.nodeIdToHtmlElementsMap.keys()) { 1981cb0ef41Sopenharmony_ci for (const element of this.nodeIdToHtmlElementsMap.get(key)) { 1991cb0ef41Sopenharmony_ci element.classList.toggle("selected", false); 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci for (const nodeId of view.selection.selectedKeys()) { 2031cb0ef41Sopenharmony_ci const elements = this.nodeIdToHtmlElementsMap.get(nodeId); 2041cb0ef41Sopenharmony_ci if (!elements) continue; 2051cb0ef41Sopenharmony_ci for (const element of elements) { 2061cb0ef41Sopenharmony_ci mkVisible.consider(element, true); 2071cb0ef41Sopenharmony_ci element.classList.toggle("selected", true); 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci mkVisible.apply(scrollIntoView); 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci setPatterns(patterns) { 2141cb0ef41Sopenharmony_ci this.patterns = patterns; 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci clearText() { 2181cb0ef41Sopenharmony_ci while (this.textListNode.firstChild) { 2191cb0ef41Sopenharmony_ci this.textListNode.removeChild(this.textListNode.firstChild); 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci createFragment(text, style) { 2241cb0ef41Sopenharmony_ci const fragment = document.createElement("SPAN"); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci if (typeof style.associateData == 'function') { 2271cb0ef41Sopenharmony_ci if (style.associateData(text, fragment) === false) { 2281cb0ef41Sopenharmony_ci return null; 2291cb0ef41Sopenharmony_ci } 2301cb0ef41Sopenharmony_ci } else { 2311cb0ef41Sopenharmony_ci if (style.css != undefined) { 2321cb0ef41Sopenharmony_ci const css = isIterable(style.css) ? style.css : [style.css]; 2331cb0ef41Sopenharmony_ci for (const cls of css) { 2341cb0ef41Sopenharmony_ci fragment.classList.add(cls); 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci } 2371cb0ef41Sopenharmony_ci fragment.innerText = text; 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci return fragment; 2411cb0ef41Sopenharmony_ci } 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci processLine(line) { 2441cb0ef41Sopenharmony_ci const view = this; 2451cb0ef41Sopenharmony_ci const result = []; 2461cb0ef41Sopenharmony_ci let patternSet = 0; 2471cb0ef41Sopenharmony_ci while (true) { 2481cb0ef41Sopenharmony_ci const beforeLine = line; 2491cb0ef41Sopenharmony_ci for (const pattern of view.patterns[patternSet]) { 2501cb0ef41Sopenharmony_ci const matches = line.match(pattern[0]); 2511cb0ef41Sopenharmony_ci if (matches != null) { 2521cb0ef41Sopenharmony_ci if (matches[0] != '') { 2531cb0ef41Sopenharmony_ci const style = pattern[1] != null ? pattern[1] : {}; 2541cb0ef41Sopenharmony_ci const text = matches[0]; 2551cb0ef41Sopenharmony_ci if (text != '') { 2561cb0ef41Sopenharmony_ci const fragment = view.createFragment(matches[0], style); 2571cb0ef41Sopenharmony_ci if (fragment !== null) result.push(fragment); 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci line = line.substr(matches[0].length); 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci let nextPatternSet = patternSet; 2621cb0ef41Sopenharmony_ci if (pattern.length > 2) { 2631cb0ef41Sopenharmony_ci nextPatternSet = pattern[2]; 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci if (line == "") { 2661cb0ef41Sopenharmony_ci if (nextPatternSet != -1) { 2671cb0ef41Sopenharmony_ci throw ("illegal parsing state in text-view in patternSet" + patternSet); 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci return result; 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci patternSet = nextPatternSet; 2721cb0ef41Sopenharmony_ci break; 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci if (beforeLine == line) { 2761cb0ef41Sopenharmony_ci throw ("input not consumed in text-view in patternSet" + patternSet); 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci } 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci processText(text) { 2821cb0ef41Sopenharmony_ci const view = this; 2831cb0ef41Sopenharmony_ci const textLines = text.split(/[\n]/); 2841cb0ef41Sopenharmony_ci let lineNo = 0; 2851cb0ef41Sopenharmony_ci for (const line of textLines) { 2861cb0ef41Sopenharmony_ci const li = document.createElement("LI"); 2871cb0ef41Sopenharmony_ci li.className = "nolinenums"; 2881cb0ef41Sopenharmony_ci li.dataset.lineNo = "" + lineNo++; 2891cb0ef41Sopenharmony_ci const fragments = view.processLine(line); 2901cb0ef41Sopenharmony_ci for (const fragment of fragments) { 2911cb0ef41Sopenharmony_ci li.appendChild(fragment); 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci view.textListNode.appendChild(li); 2941cb0ef41Sopenharmony_ci } 2951cb0ef41Sopenharmony_ci } 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci initializeContent(data, rememberedSelection) { 2981cb0ef41Sopenharmony_ci this.clearText(); 2991cb0ef41Sopenharmony_ci this.processText(data); 3001cb0ef41Sopenharmony_ci this.show(); 3011cb0ef41Sopenharmony_ci } 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ci public onresize(): void {} 3041cb0ef41Sopenharmony_ci} 305