| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:html'; | 5 import 'dart:html'; |
| 6 import 'dart:convert'; | 6 import 'dart:convert'; |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'package:source_maps/source_maps.dart'; | 8 import 'package:source_maps/source_maps.dart'; |
| 9 | 9 |
| 10 Element targetFileName = querySelector("#target_filename"); | 10 Element targetFileName = querySelector("#target_filename"); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 generatedOutput.style.height = "${window.innerHeight / 3 - 50}px"; | 24 generatedOutput.style.height = "${window.innerHeight / 3 - 50}px"; |
| 25 selectedSource.style.height = "${window.innerHeight / 3 - 50}px"; | 25 selectedSource.style.height = "${window.innerHeight / 3 - 50}px"; |
| 26 decodedMap.style.height = "${window.innerHeight / 3 - 50}px"; | 26 decodedMap.style.height = "${window.innerHeight / 3 - 50}px"; |
| 27 originalMap.style.height = "${window.innerHeight / 3 - 50}px"; | 27 originalMap.style.height = "${window.innerHeight / 3 - 50}px"; |
| 28 } | 28 } |
| 29 | 29 |
| 30 Future getMap() { | 30 Future getMap() { |
| 31 Completer c = new Completer(); | 31 Completer c = new Completer(); |
| 32 HttpRequest httpRequest = new HttpRequest(); | 32 HttpRequest httpRequest = new HttpRequest(); |
| 33 httpRequest | 33 httpRequest |
| 34 ..open('GET', '/map') | 34 ..open('GET', '/map') |
| 35 ..onLoadEnd.listen((_) => c.complete(httpRequest.responseText)) | 35 ..onLoadEnd.listen((_) => c.complete(httpRequest.responseText)) |
| 36 ..send(''); | 36 ..send(''); |
| 37 return c.future; | 37 return c.future; |
| 38 } | 38 } |
| 39 | 39 |
| 40 Future fetchFile(String path) { | 40 Future fetchFile(String path) { |
| 41 Completer c = new Completer(); | 41 Completer c = new Completer(); |
| 42 HttpRequest httpRequest = new HttpRequest(); | 42 HttpRequest httpRequest = new HttpRequest(); |
| 43 sourceFileName.text = path; | 43 sourceFileName.text = path; |
| 44 httpRequest | 44 httpRequest |
| 45 ..open('GET', path) | 45 ..open('GET', path) |
| 46 ..onLoadEnd.listen((_) => c.complete(httpRequest.responseText)) | 46 ..onLoadEnd.listen((_) => c.complete(httpRequest.responseText)) |
| 47 ..send(''); | 47 ..send(''); |
| 48 return c.future; | 48 return c.future; |
| 49 } | 49 } |
| 50 | 50 |
| 51 displaySource(String filename, List<String> source, TargetEntry entry) { | 51 displaySource(String filename, List<String> source, TargetEntry entry) { |
| 52 int line = entry.sourceLine; | 52 int line = entry.sourceLine; |
| 53 int column = entry.sourceColumn; | 53 int column = entry.sourceColumn; |
| 54 int nameId = entry.sourceNameId; | 54 int nameId = entry.sourceNameId; |
| 55 String id = nameId == null ? null : sourceMap.names[nameId]; | 55 String id = nameId == null ? null : sourceMap.names[nameId]; |
| 56 selectedSource.children.clear(); | 56 selectedSource.children.clear(); |
| 57 SpanElement marker = new SpanElement() | 57 SpanElement marker = new SpanElement() |
| 58 ..className = "marker" | 58 ..className = "marker" |
| 59 ..appendText("*"); | 59 ..appendText("*"); |
| 60 for (int pos = 0; pos < source.length; pos++) { | 60 for (int pos = 0; pos < source.length; pos++) { |
| 61 String l = source[pos]; | 61 String l = source[pos]; |
| 62 if (pos != line) { | 62 if (pos != line) { |
| 63 selectedSource.children.add(l.isEmpty ? new BRElement() : new DivElement() | 63 selectedSource.children.add(l.isEmpty ? new BRElement() : new DivElement() |
| 64 ..appendText(l)); | 64 ..appendText(l)); |
| 65 } else { | 65 } else { |
| 66 selectedSource.children.add(new DivElement() | 66 selectedSource.children.add(new DivElement() |
| 67 ..appendText(l.substring(0, column)) | 67 ..appendText(l.substring(0, column)) |
| 68 ..children.add(marker) | 68 ..children.add(marker) |
| 69 ..appendText(l.substring(column))); | 69 ..appendText(l.substring(column))); |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 sourceFileName.text = filename; | 72 sourceFileName.text = filename; |
| 73 marker.scrollIntoView(); | 73 marker.scrollIntoView(); |
| 74 } | 74 } |
| 75 | 75 |
| 76 void highlightSelectedSpan(TargetEntry entry, TargetLineEntry lineEntry) { | 76 void highlightSelectedSpan(TargetEntry entry, TargetLineEntry lineEntry) { |
| 77 selectedOutputSpan.children.clear(); | 77 selectedOutputSpan.children.clear(); |
| 78 String spanEndCol; | 78 String spanEndCol; |
| 79 TargetEntry spanEnd; | 79 TargetEntry spanEnd; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 99 if (entry.sourceUrlId == null) { | 99 if (entry.sourceUrlId == null) { |
| 100 targetSpan += ' Source: unknown'; | 100 targetSpan += ' Source: unknown'; |
| 101 selectedOutputSpan.children.add(getTextElement(targetSpan)); | 101 selectedOutputSpan.children.add(getTextElement(targetSpan)); |
| 102 return; | 102 return; |
| 103 } | 103 } |
| 104 | 104 |
| 105 String source = sourceMap.urls[entry.sourceUrlId]; | 105 String source = sourceMap.urls[entry.sourceUrlId]; |
| 106 String sourceName = source.substring(source.lastIndexOf('/') + 1); | 106 String sourceName = source.substring(source.lastIndexOf('/') + 1); |
| 107 String sourcePoint = | 107 String sourcePoint = |
| 108 'Source: Line ${entry.sourceLine} Col. ${entry.sourceColumn}'; | 108 'Source: Line ${entry.sourceLine} Col. ${entry.sourceColumn}'; |
| 109 sourcePoint += | 109 sourcePoint += entry.sourceNameId == null |
| 110 entry.sourceNameId == null ? '' | 110 ? '' |
| 111 : ' (${sourceMap.names[entry.sourceNameId]})'; | 111 : ' (${sourceMap.names[entry.sourceNameId]})'; |
| 112 sourcePoint += ' in $sourceName'; | 112 sourcePoint += ' in $sourceName'; |
| 113 selectedOutputSpan.children.add(getTextElement(targetSpan)); | 113 selectedOutputSpan.children.add(getTextElement(targetSpan)); |
| 114 selectedOutputSpan.children.add(new BRElement()); | 114 selectedOutputSpan.children.add(new BRElement()); |
| 115 selectedOutputSpan.children.add(getTextElement(sourcePoint)); | 115 selectedOutputSpan.children.add(getTextElement(sourcePoint)); |
| 116 | 116 |
| 117 if (highlightedMapEntry != null) { | 117 if (highlightedMapEntry != null) { |
| 118 highlightedMapEntry[0].style.background = 'white'; | 118 highlightedMapEntry[0].style.background = 'white'; |
| 119 highlightedMapEntry[1].style.background = 'white'; | 119 highlightedMapEntry[1].style.background = 'white'; |
| 120 } | 120 } |
| 121 | 121 |
| 122 String highlightColor = "#99ff99"; | 122 String highlightColor = "#99ff99"; |
| 123 highlightedMapEntry = targetEntryMap[entry]; | 123 highlightedMapEntry = targetEntryMap[entry]; |
| 124 highlightedMapEntry[0] | 124 highlightedMapEntry[0] |
| 125 ..scrollIntoView() | 125 ..scrollIntoView() |
| 126 ..style.backgroundColor = highlightColor; | 126 ..style.backgroundColor = highlightColor; |
| 127 highlightedMapEntry[1] | 127 highlightedMapEntry[1] |
| 128 ..scrollIntoView() | 128 ..scrollIntoView() |
| 129 ..style.backgroundColor = highlightColor; | 129 ..style.backgroundColor = highlightColor; |
| 130 highlightedMapEntry[1].onMouseOver.listen((e) { | 130 highlightedMapEntry[1].onMouseOver.listen((e) { |
| 131 selectedOutputSpan.style.zIndex = "2"; | 131 selectedOutputSpan.style.zIndex = "2"; |
| 132 selectedOutputSpan.style.visibility = "visible"; | 132 selectedOutputSpan.style.visibility = "visible"; |
| 133 selectedOutputSpan.style.top = "${decodedMap.offsetTo(document.body).y + | 133 selectedOutputSpan.style.top = "${decodedMap.offsetTo(document.body).y + |
| 134 decodedMap.clientHeight - 20}px"; | 134 decodedMap.clientHeight - 20}px"; |
| 135 selectedOutputSpan.style.left = "${decodedMap.offsetTo(document.body).x}px"; | 135 selectedOutputSpan.style.left = "${decodedMap.offsetTo(document.body).x}px"; |
| 136 selectedOutputSpan.style.width= "${decodedMap.clientWidth}px"; | 136 selectedOutputSpan.style.width = "${decodedMap.clientWidth}px"; |
| 137 }); | 137 }); |
| 138 | 138 |
| 139 highlightedMapEntry[1].onMouseOut.listen( (e) { | 139 highlightedMapEntry[1].onMouseOut.listen((e) { |
| 140 selectedOutputSpan.style.visibility = "hidden"; | 140 selectedOutputSpan.style.visibility = "hidden"; |
| 141 }); | 141 }); |
| 142 | 142 |
| 143 adjustDivHeightsToWindow(); | 143 adjustDivHeightsToWindow(); |
| 144 } | 144 } |
| 145 | 145 |
| 146 void loadSource(TargetEntry entry) { | 146 void loadSource(TargetEntry entry) { |
| 147 if (entry.sourceUrlId == null) { | 147 if (entry.sourceUrlId == null) { |
| 148 return; | 148 return; |
| 149 } | 149 } |
| 150 | 150 |
| 151 String source = sourceMap.urls[entry.sourceUrlId]; | 151 String source = sourceMap.urls[entry.sourceUrlId]; |
| 152 fetchFile(new Uri(path: "/file", | 152 fetchFile( |
| 153 queryParameters: {"path": source}).toString()).then((text) | 153 new Uri(path: "/file", queryParameters: {"path": source}).toString()) |
| 154 => displaySource(source, text.split("\n"), entry)); | 154 .then((text) => displaySource(source, text.split("\n"), entry)); |
| 155 selectedSource.text = "loading"; | 155 selectedSource.text = "loading"; |
| 156 } | 156 } |
| 157 | 157 |
| 158 SpanElement createSpan(String content, TargetEntry entry, | 158 SpanElement createSpan( |
| 159 TargetLineEntry lineEntry) { | 159 String content, TargetEntry entry, TargetLineEntry lineEntry) { |
| 160 return new SpanElement() | 160 return new SpanElement() |
| 161 ..addEventListener('click', (e) { | 161 ..addEventListener('click', (e) { |
| 162 loadSource(entry); | 162 loadSource(entry); |
| 163 highlightSelectedSpan(entry, lineEntry); | 163 highlightSelectedSpan(entry, lineEntry); |
| 164 }, false) | 164 }, false) |
| 165 ..className = "range${entry.sourceUrlId % 4}" | 165 ..className = "range${entry.sourceUrlId % 4}" |
| 166 ..appendText(content); | 166 ..appendText(content); |
| 167 } | 167 } |
| 168 | 168 |
| 169 Element getLineNumberElement(int line) { | 169 Element getLineNumberElement(int line) { |
| 170 SpanElement result = new SpanElement(); | 170 SpanElement result = new SpanElement(); |
| 171 result.style.fontFamily = "Courier"; | 171 result.style.fontFamily = "Courier"; |
| 172 result.style.fontSize = "10pt"; | 172 result.style.fontSize = "10pt"; |
| 173 result.appendText("${line} "); | 173 result.appendText("${line} "); |
| 174 return result; | 174 return result; |
| 175 } | 175 } |
| 176 | 176 |
| 177 Element getTextElement(String text) { | 177 Element getTextElement(String text) { |
| 178 SpanElement result = new SpanElement(); | 178 SpanElement result = new SpanElement(); |
| 179 result.text = text; | 179 result.text = text; |
| 180 return result; | 180 return result; |
| 181 } | 181 } |
| 182 | 182 |
| 183 addTargetLine(int lineNumber, String content, TargetLineEntry lineEntry) { | 183 addTargetLine(int lineNumber, String content, TargetLineEntry lineEntry) { |
| 184 if (content.isEmpty) { | 184 if (content.isEmpty) { |
| 185 generatedOutput.children.add(new DivElement() | 185 generatedOutput.children |
| 186 ..children.add(getLineNumberElement(lineNumber))); | 186 .add(new DivElement()..children.add(getLineNumberElement(lineNumber))); |
| 187 return; | 187 return; |
| 188 } | 188 } |
| 189 if (lineEntry == null) { | 189 if (lineEntry == null) { |
| 190 generatedOutput.children.add(new DivElement() | 190 generatedOutput.children.add(new DivElement() |
| 191 ..children.add(getLineNumberElement(lineNumber)) | 191 ..children.add(getLineNumberElement(lineNumber)) |
| 192 ..children.add(getTextElement(content))); | 192 ..children.add(getTextElement(content))); |
| 193 return; | 193 return; |
| 194 } | 194 } |
| 195 DivElement div = new DivElement(); | 195 DivElement div = new DivElement(); |
| 196 div.children.add(getLineNumberElement(lineNumber)); | 196 div.children.add(getLineNumberElement(lineNumber)); |
| 197 | 197 |
| 198 int pos = 0; | 198 int pos = 0; |
| 199 TargetEntry previous = null; | 199 TargetEntry previous = null; |
| 200 for (TargetEntry next in lineEntry.entries) { | 200 for (TargetEntry next in lineEntry.entries) { |
| 201 if (previous == null) { | 201 if (previous == null) { |
| 202 if (pos < next.column) { | 202 if (pos < next.column) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 225 } | 225 } |
| 226 generatedOutput.children.add(div); | 226 generatedOutput.children.add(div); |
| 227 } | 227 } |
| 228 | 228 |
| 229 // Display the target source in the HTML. | 229 // Display the target source in the HTML. |
| 230 void displayTargetSource() { | 230 void displayTargetSource() { |
| 231 List<TargetLineEntry> targetLines = sourceMap.lines; | 231 List<TargetLineEntry> targetLines = sourceMap.lines; |
| 232 int linesIndex = 0; | 232 int linesIndex = 0; |
| 233 for (int line = 0; line < target.length; line++) { | 233 for (int line = 0; line < target.length; line++) { |
| 234 TargetLineEntry entry = null; | 234 TargetLineEntry entry = null; |
| 235 if (linesIndex < targetLines.length | 235 if (linesIndex < targetLines.length && |
| 236 && targetLines[linesIndex].line == line) { | 236 targetLines[linesIndex].line == line) { |
| 237 entry = targetLines[linesIndex]; | 237 entry = targetLines[linesIndex]; |
| 238 linesIndex++; | 238 linesIndex++; |
| 239 } | 239 } |
| 240 if (entry != null) { | 240 if (entry != null) { |
| 241 addTargetLine(line, target[line], entry); | 241 addTargetLine(line, target[line], entry); |
| 242 } else { | 242 } else { |
| 243 addTargetLine(line, target[line], null); | 243 addTargetLine(line, target[line], null); |
| 244 } | 244 } |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 | 247 |
| 248 String getMappedData(String mapFileContent) { | 248 String getMappedData(String mapFileContent) { |
| 249 // Source map contains mapping information in this format: | 249 // Source map contains mapping information in this format: |
| 250 // "mappings": "A;A,yC;" | 250 // "mappings": "A;A,yC;" |
| 251 List<String> mapEntry = mapFileContent.split('mappings'); | 251 List<String> mapEntry = mapFileContent.split('mappings'); |
| 252 return mapEntry[mapEntry.length-1].split('"')[2]; | 252 return mapEntry[mapEntry.length - 1].split('"')[2]; |
| 253 } | 253 } |
| 254 | 254 |
| 255 SpanElement createMapSpan(String segment) { | 255 SpanElement createMapSpan(String segment) { |
| 256 return new SpanElement()..text = segment; | 256 return new SpanElement()..text = segment; |
| 257 } | 257 } |
| 258 | 258 |
| 259 SpanElement createDecodedMapSpan(TargetEntry entry) { | 259 SpanElement createDecodedMapSpan(TargetEntry entry) { |
| 260 return new SpanElement()..text = '(${entry.column}, ${entry.sourceUrlId},' | 260 return new SpanElement() |
| 261 ' ${entry.sourceLine},' | 261 ..text = '(${entry.column}, ${entry.sourceUrlId},' |
| 262 ' ${entry.sourceColumn})'; | 262 ' ${entry.sourceLine},' |
| 263 ' ${entry.sourceColumn})'; |
| 263 } | 264 } |
| 264 | 265 |
| 265 displayMap(String mapFileContent) { | 266 displayMap(String mapFileContent) { |
| 266 String mappedData = getMappedData(mapFileContent); | 267 String mappedData = getMappedData(mapFileContent); |
| 267 int sourceMapLine = 0; | 268 int sourceMapLine = 0; |
| 268 for (String group in mappedData.split(';')) { | 269 for (String group in mappedData.split(';')) { |
| 269 if (group.length == 0) continue; | 270 if (group.length == 0) continue; |
| 270 | 271 |
| 271 List<String> segments = []; | 272 List<String> segments = []; |
| 272 if (!group.contains(',')) { | 273 if (!group.contains(',')) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 295 ++entryNumber; | 296 ++entryNumber; |
| 296 targetEntryMap.putIfAbsent(entry, () => [orignalMapSpan, decodedMapSpan]); | 297 targetEntryMap.putIfAbsent(entry, () => [orignalMapSpan, decodedMapSpan]); |
| 297 } | 298 } |
| 298 originalMap.children.add(new BRElement()); | 299 originalMap.children.add(new BRElement()); |
| 299 decodedMap.children.add(new BRElement()); | 300 decodedMap.children.add(new BRElement()); |
| 300 ++sourceMapLine; | 301 ++sourceMapLine; |
| 301 } | 302 } |
| 302 } | 303 } |
| 303 | 304 |
| 304 void main() { | 305 void main() { |
| 305 Future load(String q) => fetchFile(new Uri(path: "/file", queryParameters: { | 306 Future load(String q) => fetchFile( |
| 306 "path": q | 307 new Uri(path: "/file", queryParameters: {"path": q}).toString()); |
| 307 }).toString()); | |
| 308 | 308 |
| 309 getMap().then((mapFileName) { | 309 getMap().then((mapFileName) { |
| 310 load(mapFileName).then((mapFileContent) { | 310 load(mapFileName).then((mapFileContent) { |
| 311 sourceMap = new SingleMapping.fromJson(JSON.decode(mapFileContent)); | 311 sourceMap = new SingleMapping.fromJson(JSON.decode(mapFileContent)); |
| 312 displayMap(mapFileContent); | 312 displayMap(mapFileContent); |
| 313 targetFileName.text = sourceMap.targetUrl; | 313 targetFileName.text = sourceMap.targetUrl; |
| 314 load(targetFileName.text).then((targetFileContent) { | 314 load(targetFileName.text).then((targetFileContent) { |
| 315 target = targetFileContent.split('\n'); | 315 target = targetFileContent.split('\n'); |
| 316 displayTargetSource(); | 316 displayTargetSource(); |
| 317 adjustDivHeightsToWindow(); | 317 adjustDivHeightsToWindow(); |
| 318 }); | 318 }); |
| 319 }); | 319 }); |
| 320 }); | 320 }); |
| 321 | 321 |
| 322 sourceFileName.text = "<source not selected>"; | 322 sourceFileName.text = "<source not selected>"; |
| 323 } | 323 } |
| OLD | NEW |