OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library trydart.main; | 5 library trydart.main; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 import 'dart:isolate'; | 9 import 'dart:isolate'; |
10 import 'dart:uri'; | 10 import 'dart:uri'; |
11 | 11 |
12 import '../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' sh
ow StringScanner, EOF_TOKEN; | 12 import '../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' |
13 import '../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' as
scanner; | 13 show |
| 14 StringScanner, |
| 15 EOF_TOKEN; |
| 16 |
| 17 import '../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' |
| 18 as scanner; |
14 | 19 |
15 import 'decoration.dart'; | 20 import 'decoration.dart'; |
16 import 'themes.dart'; | 21 import 'themes.dart'; |
17 | 22 |
18 @lazy import 'compiler_isolate.dart'; | 23 @lazy import 'compiler_isolate.dart'; |
19 | 24 |
20 const lazy = const DeferredLibrary('compiler_isolate'); | 25 const lazy = const DeferredLibrary('compiler_isolate'); |
21 | 26 |
22 var inputPre; | 27 var inputPre; |
23 var outputDiv; | 28 var outputDiv; |
24 var hackDiv; | 29 var hackDiv; |
25 var outputFrame; | 30 var outputFrame; |
26 var compilerTimer; | 31 var compilerTimer; |
27 var compilerPort; | 32 var compilerPort; |
28 var observer; | 33 var observer; |
29 var cacheStatusElement; | 34 var cacheStatusElement; |
30 bool alwaysRunInWorker = window.localStorage['alwaysRunInWorker'] == 'true'; | 35 bool alwaysRunInWorker = window.localStorage['alwaysRunInWorker'] == 'true'; |
31 bool verboseCompiler = window.localStorage['verboseCompiler'] == 'true'; | 36 bool verboseCompiler = window.localStorage['verboseCompiler'] == 'true'; |
32 bool minified = window.localStorage['minified'] == 'true'; | 37 bool minified = window.localStorage['minified'] == 'true'; |
33 bool onlyAnalyze = window.localStorage['onlyAnalyze'] == 'true'; | 38 bool onlyAnalyze = window.localStorage['onlyAnalyze'] == 'true'; |
34 String codeFont = ((x) => x == null ? '' : x)(window.localStorage['codeFont']); | 39 final String rawCodeFont = window.localStorage['codeFont']; |
| 40 String codeFont = rawCodeFont == null ? '' : rawCodeFont; |
35 String currentSample = window.localStorage['currentSample']; | 41 String currentSample = window.localStorage['currentSample']; |
36 Theme currentTheme = Theme.named(window.localStorage['theme']); | 42 Theme currentTheme = Theme.named(window.localStorage['theme']); |
37 bool applyingSettings = false; | 43 bool applyingSettings = false; |
38 | 44 |
39 const String INDENT = '\u{a0}\u{a0}'; | 45 const String INDENT = '\u{a0}\u{a0}'; |
40 | 46 |
41 onKeyUp(KeyboardEvent e) { | 47 onKeyUp(KeyboardEvent e) { |
42 if (e.keyCode == 13) { | 48 if (e.keyCode == 13) { |
43 e.preventDefault(); | 49 e.preventDefault(); |
44 DomSelection selection = window.getSelection(); | 50 DomSelection selection = window.getSelection(); |
45 if (selection.isCollapsed && selection.anchorNode is Text) { | 51 if (selection.isCollapsed && selection.anchorNode is Text) { |
46 Text text = selection.anchorNode; | 52 Text text = selection.anchorNode; |
47 int offset = selection.anchorOffset; | 53 int offset = selection.anchorOffset; |
48 text.insertData(offset, '\n'); | 54 text.insertData(offset, '\n'); |
49 selection.collapse(text, offset + 1); | 55 selection.collapse(text, offset + 1); |
50 } | 56 } |
51 } | 57 } |
52 // This is a hack to get Safari to send mutation events on contenteditable. | 58 // This is a hack to get Safari to send mutation events on contenteditable. |
53 var newDiv = new DivElement(); | 59 var newDiv = new DivElement(); |
54 hackDiv.replaceWith(newDiv); | 60 hackDiv.replaceWith(newDiv); |
55 hackDiv = newDiv; | 61 hackDiv = newDiv; |
56 } | 62 } |
57 | 63 |
58 bool isMalformedInput = false; | 64 bool isMalformedInput = false; |
59 String currentSource = ""; | 65 String currentSource = ""; |
60 | 66 |
| 67 // TODO(ahe): This method should be cleaned up. It is too large. |
61 onMutation(List<MutationRecord> mutations, MutationObserver observer) { | 68 onMutation(List<MutationRecord> mutations, MutationObserver observer) { |
62 scheduleCompilation(); | 69 scheduleCompilation(); |
63 | 70 |
64 for (Element element in inputPre.queryAll('a[class="diagnostic"]>span')) { | 71 for (Element element in inputPre.queryAll('a[class="diagnostic"]>span')) { |
65 element.remove(); | 72 element.remove(); |
66 } | 73 } |
67 // Discard clean-up mutations. | 74 // Discard clean-up mutations. |
68 observer.takeRecords(); | 75 observer.takeRecords(); |
69 | 76 |
70 DomSelection selection = window.getSelection(); | 77 DomSelection selection = window.getSelection(); |
71 | 78 |
72 while (!mutations.isEmpty) { | 79 while (!mutations.isEmpty) { |
73 for (MutationRecord record in mutations) { | 80 for (MutationRecord record in mutations) { |
74 String type = record.type; | 81 String type = record.type; |
75 switch (type) { | 82 switch (type) { |
76 | 83 |
77 case 'characterData': | 84 case 'characterData': |
78 | 85 |
79 bool hasSelection = false; | 86 bool hasSelection = false; |
80 int offset = selection.anchorOffset; | 87 int offset = selection.anchorOffset; |
81 if (selection.isCollapsed && selection.anchorNode == record.target) { | 88 if (selection.isCollapsed && selection.anchorNode == record.target) { |
82 hasSelection = true; | 89 hasSelection = true; |
83 } | 90 } |
84 var parent = record.target.parentNode; | 91 var parent = record.target.parentNode; |
85 if (parent != inputPre) { | 92 if (parent != inputPre) { |
86 inlineChildren(parent); | 93 inlineChildren(parent); |
87 } | 94 } |
88 if (hasSelection) { | 95 if (hasSelection) { |
89 selection.collapse(record.target, offset); | 96 selection.collapse(record.target, offset); |
90 } | 97 } |
91 break; | 98 break; |
92 | 99 |
93 default: | 100 default: |
94 if (!record.addedNodes.isEmpty) { | 101 if (!record.addedNodes.isEmpty) { |
95 for (var node in record.addedNodes) { | 102 for (var node in record.addedNodes) { |
96 | 103 |
97 if (node.nodeType != Node.ELEMENT_NODE) continue; | 104 if (node.nodeType != Node.ELEMENT_NODE) continue; |
98 | 105 |
99 if (node is BRElement) { | 106 if (node is BRElement) { |
100 if (selection.anchorNode != node) { | 107 if (selection.anchorNode != node) { |
101 node.replaceWith(new Text('\n')); | 108 node.replaceWith(new Text('\n')); |
| 109 } |
| 110 } else { |
| 111 var parent = node.parentNode; |
| 112 if (parent == null) continue; |
| 113 var nodes = new List.from(node.nodes); |
| 114 var style = node.getComputedStyle(); |
| 115 if (style.display != 'inline') { |
| 116 var previous = node.previousNode; |
| 117 if (previous is Text) { |
| 118 previous.appendData('\n'); |
| 119 } else { |
| 120 parent.insertBefore(new Text('\n'), node); |
| 121 } |
| 122 } |
| 123 for (Node child in nodes) { |
| 124 child.remove(); |
| 125 parent.insertBefore(child, node); |
| 126 } |
| 127 node.remove(); |
102 } | 128 } |
103 } else { | |
104 var parent = node.parentNode; | |
105 if (parent == null) continue; | |
106 var nodes = new List.from(node.nodes); | |
107 var style = node.getComputedStyle(); | |
108 if (style.display != 'inline') { | |
109 var previous = node.previousNode; | |
110 if (previous is Text) { | |
111 previous.appendData('\n'); | |
112 } else { | |
113 parent.insertBefore(new Text('\n'), node); | |
114 } | |
115 } | |
116 for (Node child in nodes) { | |
117 child.remove(); | |
118 parent.insertBefore(child, node); | |
119 } | |
120 node.remove(); | |
121 } | 129 } |
122 } | 130 } |
123 } | |
124 } | 131 } |
125 } | 132 } |
126 mutations = observer.takeRecords(); | 133 mutations = observer.takeRecords(); |
127 } | 134 } |
128 | 135 |
129 if (!inputPre.nodes.isEmpty && inputPre.nodes.last is Text) { | 136 if (!inputPre.nodes.isEmpty && inputPre.nodes.last is Text) { |
130 Text text = inputPre.nodes.last; | 137 Text text = inputPre.nodes.last; |
131 if (!text.text.endsWith('\n')) { | 138 if (!text.text.endsWith('\n')) { |
132 text.appendData('\n'); | 139 text.appendData('\n'); |
133 } | 140 } |
134 } | 141 } |
135 | 142 |
136 int offset = 0; | 143 int offset = 0; |
137 int anchorOffset = 0; | 144 int anchorOffset = 0; |
138 bool hasSelection = false; | 145 bool hasSelection = false; |
139 Node anchorNode = selection.anchorNode; | 146 Node anchorNode = selection.anchorNode; |
| 147 // TODO(ahe): Try to share walk4 methods. |
140 void walk4(Node node) { | 148 void walk4(Node node) { |
141 // TODO(ahe): Use TreeWalker when that is exposed. | 149 // TODO(ahe): Use TreeWalker when that is exposed. |
142 // function textNodesUnder(root){ | 150 // function textNodesUnder(root){ |
143 // var n, a=[], walk=document.createTreeWalker(root,NodeFilter.SHOW_TEXT,n
ull,false); | 151 // var n, a=[], walk=document.createTreeWalker( |
| 152 // root,NodeFilter.SHOW_TEXT,null,false); |
144 // while(n=walk.nextNode()) a.push(n); | 153 // while(n=walk.nextNode()) a.push(n); |
145 // return a; | 154 // return a; |
146 // } | 155 // } |
147 int type = node.nodeType; | 156 int type = node.nodeType; |
148 if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) { | 157 if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) { |
149 if (anchorNode == node) { | 158 if (anchorNode == node) { |
150 hasSelection = true; | 159 hasSelection = true; |
151 anchorOffset = selection.anchorOffset + offset; | 160 anchorOffset = selection.anchorOffset + offset; |
152 return; | 161 return; |
153 } | 162 } |
154 offset += node.length; | 163 offset += node.length; |
155 } | 164 } |
156 | 165 |
157 var child = node.$dom_firstChild; | 166 var child = node.$dom_firstChild; |
158 while(child != null) { | 167 while (child != null) { |
159 walk4(child); | 168 walk4(child); |
160 if (hasSelection) return; | 169 if (hasSelection) return; |
161 child = child.nextNode; | 170 child = child.nextNode; |
162 } | 171 } |
163 } | 172 } |
164 if (selection.isCollapsed) { | 173 if (selection.isCollapsed) { |
165 walk4(inputPre); | 174 walk4(inputPre); |
166 } | 175 } |
167 | 176 |
168 currentSource = inputPre.text; | 177 currentSource = inputPre.text; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 child = child.nextNode; | 273 child = child.nextNode; |
265 } | 274 } |
266 } | 275 } |
267 walk4(inputPre); | 276 walk4(inputPre); |
268 | 277 |
269 if (!foundNode) { | 278 if (!foundNode) { |
270 outputDiv.appendText('$message\n'); | 279 outputDiv.appendText('$message\n'); |
271 } | 280 } |
272 | 281 |
273 observer.takeRecords(); | 282 observer.takeRecords(); |
274 observer.observe(inputPre, childList: true, characterData: true, subtree: true
); | 283 observer.observe( |
| 284 inputPre, childList: true, characterData: true, subtree: true); |
275 } | 285 } |
276 | 286 |
277 void inlineChildren(Element element) { | 287 void inlineChildren(Element element) { |
278 if (element == null) return; | 288 if (element == null) return; |
279 var parent = element.parentNode; | 289 var parent = element.parentNode; |
280 if (parent == null) return; | 290 if (parent == null) return; |
281 for (Node child in new List.from(element.nodes)) { | 291 for (Node child in new List.from(element.nodes)) { |
282 child.remove(); | 292 child.remove(); |
283 parent.insertBefore(child, element); | 293 parent.insertBefore(child, element); |
284 } | 294 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 | 366 |
357 void dispose() { | 367 void dispose() { |
358 if (worker != null) worker.terminate(); | 368 if (worker != null) worker.terminate(); |
359 objectUrls.forEach(Url.revokeObjectUrl); | 369 objectUrls.forEach(Url.revokeObjectUrl); |
360 } | 370 } |
361 | 371 |
362 onMessage(message, _) { | 372 onMessage(message, _) { |
363 String kind = message is String ? message : message[0]; | 373 String kind = message is String ? message : message[0]; |
364 var data = (message is List && message.length == 2) ? message[1] : null; | 374 var data = (message is List && message.length == 2) ? message[1] : null; |
365 switch (kind) { | 375 switch (kind) { |
366 case 'done': return onDone(data); | 376 case 'done': return onDone(data); |
367 case 'url': return onUrl(data); | 377 case 'url': return onUrl(data); |
368 case 'code': return onCode(data); | 378 case 'code': return onCode(data); |
369 case 'diagnostic': return onDiagnostic(data); | 379 case 'diagnostic': return onDiagnostic(data); |
370 case 'crash': return onCrash(data); | 380 case 'crash': return onCrash(data); |
371 case 'failed': return onFail(data); | 381 case 'failed': return onFail(data); |
372 case 'dart:html': return onDartHtml(data); | 382 case 'dart:html': return onDartHtml(data); |
373 default: | 383 default: |
374 throw ['Unknown message kind', message]; | 384 throw ['Unknown message kind', message]; |
375 } | 385 } |
376 } | 386 } |
377 | 387 |
378 onDartHtml(_) { | 388 onDartHtml(_) { |
379 usesDartHtml = true; | 389 usesDartHtml = true; |
380 } | 390 } |
381 | 391 |
382 onFail(_) { | 392 onFail(_) { |
383 clear(); | 393 clear(); |
384 consolePrint('Compilation failed'); | 394 consolePrint('Compilation failed'); |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
888 buildCheckBox(String text, bool defaultValue, void action(Event e)) { | 898 buildCheckBox(String text, bool defaultValue, void action(Event e)) { |
889 var checkBox = new CheckboxInputElement() | 899 var checkBox = new CheckboxInputElement() |
890 ..defaultChecked = defaultValue | 900 ..defaultChecked = defaultValue |
891 ..onChange.listen(action); | 901 ..onChange.listen(action); |
892 return new LabelElement() | 902 return new LabelElement() |
893 ..classes.add('checkbox') | 903 ..classes.add('checkbox') |
894 ..append(checkBox) | 904 ..append(checkBox) |
895 ..appendText(' $text'); | 905 ..appendText(' $text'); |
896 } | 906 } |
897 | 907 |
| 908 // TODO(ahe): Build abstraction for flags/options. |
898 fieldSet.append( | 909 fieldSet.append( |
899 buildCheckBox( | 910 buildCheckBox( |
900 'Always run in Worker thread.', alwaysRunInWorker, | 911 'Always run in Worker thread.', alwaysRunInWorker, |
901 (Event e) { alwaysRunInWorker = e.target.checked; })); | 912 (Event e) { alwaysRunInWorker = e.target.checked; })); |
902 | 913 |
903 fieldSet.append( | 914 fieldSet.append( |
904 buildCheckBox( | 915 buildCheckBox( |
905 'Verbose compiler output.', verboseCompiler, | 916 'Verbose compiler output.', verboseCompiler, |
906 (Event e) { verboseCompiler = e.target.checked; })); | 917 (Event e) { verboseCompiler = e.target.checked; })); |
907 | 918 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1258 } | 1269 } |
1259 | 1270 |
1260 .center { | 1271 .center { |
1261 display: block; | 1272 display: block; |
1262 margin: 0px auto; | 1273 margin: 0px auto; |
1263 text-align: center; | 1274 text-align: center; |
1264 } | 1275 } |
1265 """; | 1276 """; |
1266 | 1277 |
1267 '''; | 1278 '''; |
OLD | NEW |