1// Copyright 2017 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import { SourceResolver } from "../src/source-resolver"; 6import { SelectionBroker } from "../src/selection-broker"; 7import { DisassemblyView } from "../src/disassembly-view"; 8import { GraphMultiView } from "../src/graphmultiview"; 9import { CodeMode, CodeView } from "../src/code-view"; 10import { Tabs } from "../src/tabs"; 11import { Resizer } from "../src/resizer"; 12import * as C from "../src/constants"; 13import { InfoView } from "./info-view"; 14 15window.onload = function () { 16 let multiview: GraphMultiView = null; 17 let disassemblyView: DisassemblyView = null; 18 let sourceViews: Array<CodeView> = []; 19 let selectionBroker: SelectionBroker = null; 20 let sourceResolver: SourceResolver = null; 21 const resizer = new Resizer(panesUpdatedCallback, 75); 22 const sourceTabsContainer = document.getElementById(C.SOURCE_PANE_ID); 23 const sourceTabs = new Tabs(sourceTabsContainer); 24 sourceTabs.addTab("+").classList.add("last-tab", "persistent-tab"); 25 const disassemblyTabsContainer = document.getElementById(C.GENERATED_PANE_ID); 26 const disassemblyTabs = new Tabs(disassemblyTabsContainer); 27 disassemblyTabs.addTab("+").classList.add("last-tab", "persistent-tab"); 28 const [infoTab, infoContainer] = sourceTabs.addTabAndContent("Info"); 29 infoTab.classList.add("persistent-tab"); 30 infoContainer.classList.add("viewpane", "scrollable"); 31 const infoView = new InfoView(infoContainer); 32 infoView.show(); 33 sourceTabs.activateTab(infoTab); 34 35 function panesUpdatedCallback() { 36 if (multiview) multiview.onresize(); 37 } 38 39 function loadFile(txtRes: string) { 40 sourceTabs.clearTabsAndContent(); 41 disassemblyTabs.clearTabsAndContent(); 42 // If the JSON isn't properly terminated, assume compiler crashed and 43 // add best-guess empty termination 44 if (txtRes[txtRes.length - 2] == ',') { 45 txtRes += '{"name":"disassembly","type":"disassembly","data":""}]}'; 46 } 47 try { 48 sourceViews.forEach(sv => sv.hide()); 49 if (multiview) multiview.hide(); 50 multiview = null; 51 if (disassemblyView) disassemblyView.hide(); 52 sourceViews = []; 53 sourceResolver = new SourceResolver(); 54 selectionBroker = new SelectionBroker(sourceResolver); 55 56 const jsonObj = JSON.parse(txtRes); 57 58 let fnc = null; 59 // Backwards compatibility. 60 if (typeof jsonObj.function == 'string') { 61 fnc = { 62 functionName: fnc, 63 sourceId: -1, 64 startPosition: jsonObj.sourcePosition, 65 endPosition: jsonObj.sourcePosition + jsonObj.source.length, 66 sourceText: jsonObj.source, 67 backwardsCompatibility: true 68 }; 69 } else { 70 fnc = Object.assign(jsonObj.function, { backwardsCompatibility: false }); 71 } 72 73 sourceResolver.setInlinings(jsonObj.inlinings); 74 sourceResolver.setSourceLineToBytecodePosition(jsonObj.sourceLineToBytecodePosition); 75 sourceResolver.setSources(jsonObj.sources, fnc); 76 sourceResolver.setNodePositionMap(jsonObj.nodePositions); 77 sourceResolver.parsePhases(jsonObj.phases); 78 79 const [sourceTab, sourceContainer] = sourceTabs.addTabAndContent("Source"); 80 sourceContainer.classList.add("viewpane", "scrollable"); 81 sourceTabs.activateTab(sourceTab); 82 const sourceView = new CodeView(sourceContainer, selectionBroker, sourceResolver, fnc, CodeMode.MAIN_SOURCE); 83 sourceView.show(); 84 sourceViews.push(sourceView); 85 86 sourceResolver.forEachSource(source => { 87 const sourceView = new CodeView(sourceContainer, selectionBroker, sourceResolver, source, CodeMode.INLINED_SOURCE); 88 sourceView.show(); 89 sourceViews.push(sourceView); 90 }); 91 92 const [disassemblyTab, disassemblyContainer] = disassemblyTabs.addTabAndContent("Disassembly"); 93 disassemblyContainer.classList.add("viewpane", "scrollable"); 94 disassemblyTabs.activateTab(disassemblyTab); 95 disassemblyView = new DisassemblyView(disassemblyContainer, selectionBroker); 96 disassemblyView.initializeCode(fnc.sourceText); 97 if (sourceResolver.disassemblyPhase) { 98 disassemblyView.initializePerfProfile(jsonObj.eventCounts); 99 disassemblyView.showContent(sourceResolver.disassemblyPhase.data); 100 disassemblyView.show(); 101 } 102 103 multiview = new GraphMultiView(C.INTERMEDIATE_PANE_ID, selectionBroker, sourceResolver); 104 multiview.show(); 105 } catch (err) { 106 if (window.confirm("Error: Exception during load of TurboFan JSON file:\n" + 107 "error: " + err.message + "\nDo you want to clear session storage?")) { 108 window.sessionStorage.clear(); 109 } 110 return; 111 } 112 } 113 114 function initializeUploadHandlers() { 115 // The <input> form #upload-helper with type file can't be a picture. 116 // We hence keep it hidden, and forward the click from the picture 117 // button #upload. 118 document.getElementById("upload").addEventListener("click", e => { 119 document.getElementById("upload-helper").click(); 120 e.stopPropagation(); 121 }); 122 document.getElementById("upload-helper").addEventListener("change", 123 function (this: HTMLInputElement) { 124 const uploadFile = this.files && this.files[0]; 125 if (uploadFile) { 126 const filereader = new FileReader(); 127 filereader.onload = () => { 128 const txtRes = filereader.result; 129 if (typeof txtRes == 'string') { 130 loadFile(txtRes); 131 } 132 }; 133 filereader.readAsText(uploadFile); 134 } 135 } 136 ); 137 window.addEventListener("keydown", (e: KeyboardEvent) => { 138 if (e.keyCode == 76 && e.ctrlKey) { // CTRL + L 139 document.getElementById("upload-helper").click(); 140 e.stopPropagation(); 141 e.preventDefault(); 142 } 143 }); 144 } 145 146 initializeUploadHandlers(); 147 resizer.updatePanes(); 148}; 149