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, 75);
22  const sourceTabsContainer = document.getElementById(C.SOURCE_PANE_ID);
23  const sourceTabs = new Tabs(sourceTabsContainer);
24  sourceTabs.addTab("&#x2b;").classList.add("last-tab", "persistent-tab");
25  const disassemblyTabsContainer = document.getElementById(C.GENERATED_PANE_ID);
26  const disassemblyTabs = new Tabs(disassemblyTabsContainer);
27  disassemblyTabs.addTab("&#x2b;").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      document.getElementById("ranges").innerHTML = '';
52      document.getElementById('ranges').style.visibility = "hidden";
53      document.getElementById('show-hide-ranges').style.visibility = "hidden";
54      if (disassemblyView) disassemblyView.hide();
55      sourceViews = [];
56      sourceResolver = new SourceResolver();
57      selectionBroker = new SelectionBroker(sourceResolver);
58
59      const jsonObj = JSON.parse(txtRes);
60
61      let fnc = null;
62      // Backwards compatibility.
63      if (typeof jsonObj.function == 'string') {
64        fnc = {
65          functionName: fnc,
66          sourceId: -1,
67          startPosition: jsonObj.sourcePosition,
68          endPosition: jsonObj.sourcePosition + jsonObj.source.length,
69          sourceText: jsonObj.source,
70          backwardsCompatibility: true
71        };
72      } else {
73        fnc = Object.assign(jsonObj.function, { backwardsCompatibility: false });
74      }
75
76      sourceResolver.setInlinings(jsonObj.inlinings);
77      sourceResolver.setSourceLineToBytecodePosition(jsonObj.sourceLineToBytecodePosition);
78      sourceResolver.setSources(jsonObj.sources, fnc);
79      sourceResolver.setNodePositionMap(jsonObj.nodePositions);
80      sourceResolver.parsePhases(jsonObj.phases);
81
82      const [sourceTab, sourceContainer] = sourceTabs.addTabAndContent("Source");
83      sourceContainer.classList.add("viewpane", "scrollable");
84      sourceTabs.activateTab(sourceTab);
85      const sourceView = new CodeView(sourceContainer, selectionBroker, sourceResolver, fnc, CodeMode.MAIN_SOURCE);
86      sourceView.show();
87      sourceViews.push(sourceView);
88
89      sourceResolver.forEachSource(source => {
90        const sourceView = new CodeView(sourceContainer, selectionBroker, sourceResolver, source, CodeMode.INLINED_SOURCE);
91        sourceView.show();
92        sourceViews.push(sourceView);
93      });
94
95      const [disassemblyTab, disassemblyContainer] = disassemblyTabs.addTabAndContent("Disassembly");
96      disassemblyContainer.classList.add("viewpane", "scrollable");
97      disassemblyTabs.activateTab(disassemblyTab);
98      disassemblyView = new DisassemblyView(disassemblyContainer, selectionBroker);
99      disassemblyView.initializeCode(fnc.sourceText);
100      if (sourceResolver.disassemblyPhase) {
101        disassemblyView.initializePerfProfile(jsonObj.eventCounts);
102        disassemblyView.showContent(sourceResolver.disassemblyPhase.data);
103        disassemblyView.show();
104      }
105
106      multiview = new GraphMultiView(C.INTERMEDIATE_PANE_ID, selectionBroker, sourceResolver);
107      multiview.show();
108    } catch (err) {
109      if (window.confirm("Error: Exception during load of TurboFan JSON file:\n" +
110        "error: " + err.message + "\nDo you want to clear session storage?")) {
111        window.sessionStorage.clear();
112      }
113      return;
114    }
115  }
116
117  function initializeUploadHandlers() {
118    // The <input> form #upload-helper with type file can't be a picture.
119    // We hence keep it hidden, and forward the click from the picture
120    // button #upload.
121    document.getElementById("upload").addEventListener("click", e => {
122      document.getElementById("upload-helper").click();
123      e.stopPropagation();
124    });
125    document.getElementById("upload-helper").addEventListener("change",
126      function (this: HTMLInputElement) {
127        const uploadFile = this.files && this.files[0];
128        if (uploadFile) {
129          const filereader = new FileReader();
130          filereader.onload = () => {
131            const txtRes = filereader.result;
132            if (typeof txtRes == 'string') {
133              loadFile(txtRes);
134            }
135          };
136          filereader.readAsText(uploadFile);
137        }
138      }
139    );
140    window.addEventListener("keydown", (e: KeyboardEvent) => {
141      if (e.keyCode == 76 && e.ctrlKey) { // CTRL + L
142        document.getElementById("upload-helper").click();
143        e.stopPropagation();
144        e.preventDefault();
145      }
146    });
147  }
148
149  initializeUploadHandlers();
150  resizer.updatePanes();
151};
152