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("&#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      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