1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { BaseElement, element } from "../../base-ui/BaseElement.js"; 17 18@element('tab-native-data-modal') 19export class DisassemblingWindow extends BaseElement { 20 private canvas: HTMLCanvasElement | undefined | null; 21 private window: HTMLElement | undefined | null; 22 private loading: HTMLElement | undefined | null; 23 private ctx: CanvasRenderingContext2D | null | undefined; 24 private hintLine = 0; 25 private addrArray = new Array<string>(); 26 private maxBinSize = 0; 27 private close: Function | undefined | null; 28 setCloseListener(callback:Function){ 29 this.close = callback; 30 } 31 32 removeCloseListener(){ 33 this.close = null; 34 }; 35 36 private getMap(content: string, hintAttr: string) { 37 let lines = content.split('\n'); 38 this.addrArray = new Array<string>(); 39 let lineMap = new Map<string, Disassembling>(); 40 let effectLint = 0; 41 this.maxBinSize = 0; 42 for (let line of lines) { 43 let lineContents = line.split(':'); 44 if (lineContents.length === 2) { 45 let addrHex = lineContents[0].trim(); 46 let addr = '0x' + addrHex; 47 let value = lineContents[1].split('\t'); 48 try { 49 let binary = value[0]; 50 let lineStruct = new Disassembling(); 51 if (binary === '') { 52 if (line.includes('Disassembly') || line.includes('file format')) { 53 continue 54 } else { 55 if (addr.includes(' ')) { 56 let funcs = addr.split(' '); 57 lineStruct.addr = funcs[0]; 58 lineStruct.binary = funcs[1]; 59 } 60 } 61 } else { 62 lineStruct.addr = addr; 63 lineStruct.binary = value[0].trim(); 64 lineStruct.type = value.length > 1 ? value[1] : ''; 65 lineStruct.code = value.length > 2 ? value[2] : ''; 66 } 67 lineMap.set(addrHex, lineStruct); 68 this.maxBinSize = Math.max(this.ctx!.measureText(lineStruct.addr + lineStruct.binary).width, this.maxBinSize); 69 this.addrArray.push(addrHex); 70 if (addrHex === hintAttr) this.hintLine = effectLint; 71 effectLint++; 72 } catch (e) { 73 console.log(e); 74 } 75 } 76 } 77 return lineMap; 78 } 79 80 public showContent(content: string, hintAddr: string): void { 81 this.loading!.style.display = "none"; 82 this.window!.style.display = "block"; 83 if (content.startsWith('error')) { 84 this.window!.innerHTML = `<span class="column1" style="width:100%;text-align: center;">${content}</span>`; 85 return; 86 } 87 let lineMap = this.getMap(content, hintAddr); 88 this.maxBinSize = this.maxBinSize * 1.7; 89 this.window!.innerHTML = ''; 90 for (let addr of this.addrArray) { 91 if (!lineMap.has(addr)) continue; 92 let struct = lineMap.get(addr); 93 if (this.addrArray[this.hintLine] == addr) { 94 this.window!.innerHTML += `<div class="line" id="emphasis" style = background:red"> 95 <span class="column0" style="width:${this.maxBinSize}px;">${struct!.addr} : ${struct!.binary}</span> 96 <span class="column1" style="width:100px;">${struct!.type}</span> 97 <span class="column2" style="width:300px;">${struct!.code}</span></div>`; 98 (this.window!.querySelector("#emphasis") as HTMLElement)!.style.width = this.window!.scrollWidth + 'px'; 99 (this.window!.querySelector("#emphasis") as HTMLElement)!.style.background = '#0A59F7'; 100 } else { 101 this.window!.innerHTML += `<div class="line"> 102 <span class="column0" style="width:${this.maxBinSize}px;">${struct!.addr} : ${struct!.binary}</span> 103 <span class="column1" style="width:100px;">${struct!.type}</span> 104 <span class="column2" style="width:300px;">${struct!.code}</span></div>`; 105 } 106 } 107 this.window!.scrollTo(0, (this.hintLine - 1) * (this.shadowRoot!.querySelector("#window>.line")!.clientHeight) - this.window!.clientHeight / 2); 108 } 109 110 private resetCanvas(styleWidth: number, styleHeight: number, width: number, height: number): void { 111 this.canvas!.style.width = styleWidth + "px"; 112 this.canvas!.style.height = styleHeight + "px"; 113 this.canvas!.width = width; 114 this.canvas!.height = height; 115 } 116 117 public showLoading(): void { 118 this.loading!.style.display = 'block'; 119 this.window!.style.display = 'none'; 120 this.style.display = 'block'; 121 this.style.position = 'absolute'; 122 this.style.left = '0px'; 123 this.style.border = '1px solid #d8d8d8'; 124 } 125 126 initElements(): void { 127 this.canvas = this.shadowRoot?.querySelector<HTMLCanvasElement>("#canvas"); 128 let close = this.shadowRoot?.querySelector("#close"); 129 this.window = this.shadowRoot?.querySelector("#window"); 130 this.loading = this.shadowRoot?.querySelector("#loading"); 131 this.ctx = this.canvas!.getContext('2d'); 132 this.resetCanvas(0, 0, 0, 0); 133 close!.addEventListener("click", () => { 134 if(this.close){ 135 this.close(); 136 } 137 return true; 138 }); 139 } 140 141 initHtml(): string { 142 return ` 143 <style> 144 #close{ 145 position:absolute; 146 top:0px; 147 right: 0px; 148 color: #D6D6D6; 149 } 150 #modal-wrap{ 151 position: absolute; 152 top: 0; 153 left: 0; 154 width:100%; 155 height:100%; 156 background: var(--dark-background,#ffffff); 157 z-index: 2000; 158 } 159 #window{ 160 overflow: auto; 161 position: absolute; 162 top: 21px; 163 left: 0; 164 width: calc(100% - 10px); 165 height: calc(100% - 21px); 166 padding-left: 10px; 167 } 168 #loading{ 169 position: absolute; 170 left: calc(50% - 20px); 171 top: calc(50% - 20px); 172 width:40px; 173 height:40px; 174 transform: rotate(360deg); 175 animation: rotation 2s linear infinite; 176 -webkit-animation: rotation 2s linear infinite; 177 } 178 @keyframes rotation{ 179 from { 180 -webkit-transform: rotate(0deg); 181 } 182 to { 183 -webkit-transform: rotate(360deg); 184 } 185 } 186 .line{ 187 line-height:27px; 188 white-space: nowrap; 189 } 190 span{ 191 display: inline-block; 192 } 193 </style> 194 <div id="modal-wrap"> 195 <canvas id="canvas" style="display: none"> </canvas> 196 <lit-icon id="close" name="close" size="20"> </lit-icon> 197 <div id="window"> </div> 198 <lit-icon id="loading" name="loading" size="40"> </lit-icon> 199 </div> 200 `; 201 } 202} 203 204class Disassembling { 205 addr = ''; 206 binary = ''; 207 type = ''; 208 code = ''; 209}