| 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'; | |
| 11 | 10 |
| 12 import '../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' | 11 import '../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' |
| 13 show | 12 show |
| 13 EOF_TOKEN, |
| 14 StringScanner, | 14 StringScanner, |
| 15 EOF_TOKEN; | 15 Token; |
| 16 | 16 |
| 17 import '../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' | 17 import '../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart' |
| 18 as scanner; | 18 as scanner; |
| 19 |
| 20 import '../../sdk/lib/_internal/compiler/implementation/source_file.dart' show |
| 21 StringSourceFile; |
| 19 | 22 |
| 20 import 'decoration.dart'; | 23 import 'decoration.dart'; |
| 21 import 'themes.dart'; | 24 import 'themes.dart'; |
| 22 | 25 |
| 26 import 'isolate_legacy.dart'; |
| 27 |
| 23 @lazy import 'compiler_isolate.dart'; | 28 @lazy import 'compiler_isolate.dart'; |
| 24 | 29 |
| 25 const lazy = const DeferredLibrary('compiler_isolate'); | 30 // const lazy = const DeferredLibrary('compiler_isolate'); |
| 31 const lazy = null; |
| 26 | 32 |
| 27 var inputPre; | 33 DivElement inputPre; |
| 28 var outputDiv; | 34 PreElement outputDiv; |
| 29 var hackDiv; | 35 DivElement hackDiv; |
| 30 var outputFrame; | 36 IFrameElement outputFrame; |
| 31 var compilerTimer; | 37 Timer compilerTimer; |
| 32 var compilerPort; | 38 SendPort compilerPort; |
| 33 var observer; | 39 MutationObserver observer; |
| 34 var cacheStatusElement; | 40 SpanElement cacheStatusElement; |
| 35 bool alwaysRunInWorker = window.localStorage['alwaysRunInWorker'] == 'true'; | 41 bool alwaysRunInWorker = window.localStorage['alwaysRunInWorker'] == 'true'; |
| 36 bool verboseCompiler = window.localStorage['verboseCompiler'] == 'true'; | 42 bool verboseCompiler = window.localStorage['verboseCompiler'] == 'true'; |
| 37 bool minified = window.localStorage['minified'] == 'true'; | 43 bool minified = window.localStorage['minified'] == 'true'; |
| 38 bool onlyAnalyze = window.localStorage['onlyAnalyze'] == 'true'; | 44 bool onlyAnalyze = window.localStorage['onlyAnalyze'] == 'true'; |
| 39 final String rawCodeFont = window.localStorage['codeFont']; | 45 final String rawCodeFont = window.localStorage['codeFont']; |
| 40 String codeFont = rawCodeFont == null ? '' : rawCodeFont; | 46 String codeFont = rawCodeFont == null ? '' : rawCodeFont; |
| 41 String currentSample = window.localStorage['currentSample']; | 47 String currentSample = window.localStorage['currentSample']; |
| 42 Theme currentTheme = Theme.named(window.localStorage['theme']); | 48 Theme currentTheme = Theme.named(window.localStorage['theme']); |
| 43 bool applyingSettings = false; | 49 bool applyingSettings = false; |
| 44 | 50 |
| 45 const String INDENT = '\u{a0}\u{a0}'; | 51 const String INDENT = '\u{a0}\u{a0}'; |
| 46 | 52 |
| 47 onKeyUp(KeyboardEvent e) { | 53 onKeyUp(KeyboardEvent e) { |
| 48 if (e.keyCode == 13) { | 54 if (e.keyCode == 13) { |
| 49 e.preventDefault(); | 55 e.preventDefault(); |
| 50 DomSelection selection = window.getSelection(); | 56 Selection selection = window.getSelection(); |
| 51 if (selection.isCollapsed && selection.anchorNode is Text) { | 57 if (selection.isCollapsed && selection.anchorNode is Text) { |
| 52 Text text = selection.anchorNode; | 58 Text text = selection.anchorNode; |
| 53 int offset = selection.anchorOffset; | 59 int offset = selection.anchorOffset; |
| 54 text.insertData(offset, '\n'); | 60 text.insertData(offset, '\n'); |
| 55 selection.collapse(text, offset + 1); | 61 selection.collapse(text, offset + 1); |
| 56 } | 62 } |
| 57 } | 63 } |
| 58 // This is a hack to get Safari to send mutation events on contenteditable. | 64 // This is a hack to get Safari to send mutation events on contenteditable. |
| 59 var newDiv = new DivElement(); | 65 var newDiv = new DivElement(); |
| 60 hackDiv.replaceWith(newDiv); | 66 hackDiv.replaceWith(newDiv); |
| 61 hackDiv = newDiv; | 67 hackDiv = newDiv; |
| 62 } | 68 } |
| 63 | 69 |
| 64 bool isMalformedInput = false; | 70 bool isMalformedInput = false; |
| 65 String currentSource = ""; | 71 String currentSource = ""; |
| 66 | 72 |
| 67 // TODO(ahe): This method should be cleaned up. It is too large. | 73 // TODO(ahe): This method should be cleaned up. It is too large. |
| 68 onMutation(List<MutationRecord> mutations, MutationObserver observer) { | 74 onMutation(List<MutationRecord> mutations, MutationObserver observer) { |
| 69 scheduleCompilation(); | 75 scheduleCompilation(); |
| 70 | 76 |
| 71 for (Element element in inputPre.queryAll('a[class="diagnostic"]>span')) { | 77 for (Element element in inputPre.queryAll('a[class="diagnostic"]>span')) { |
| 72 element.remove(); | 78 element.remove(); |
| 73 } | 79 } |
| 74 // Discard clean-up mutations. | 80 // Discard clean-up mutations. |
| 75 observer.takeRecords(); | 81 observer.takeRecords(); |
| 76 | 82 |
| 77 DomSelection selection = window.getSelection(); | 83 Selection selection = window.getSelection(); |
| 78 | 84 |
| 79 while (!mutations.isEmpty) { | 85 while (!mutations.isEmpty) { |
| 80 for (MutationRecord record in mutations) { | 86 for (MutationRecord record in mutations) { |
| 81 String type = record.type; | 87 String type = record.type; |
| 82 switch (type) { | 88 switch (type) { |
| 83 | 89 |
| 84 case 'characterData': | 90 case 'characterData': |
| 85 | 91 |
| 86 bool hasSelection = false; | 92 bool hasSelection = false; |
| 87 int offset = selection.anchorOffset; | 93 int offset = selection.anchorOffset; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 void walk4(Node node) { | 154 void walk4(Node node) { |
| 149 // TODO(ahe): Use TreeWalker when that is exposed. | 155 // TODO(ahe): Use TreeWalker when that is exposed. |
| 150 // function textNodesUnder(root){ | 156 // function textNodesUnder(root){ |
| 151 // var n, a=[], walk=document.createTreeWalker( | 157 // var n, a=[], walk=document.createTreeWalker( |
| 152 // root,NodeFilter.SHOW_TEXT,null,false); | 158 // root,NodeFilter.SHOW_TEXT,null,false); |
| 153 // while(n=walk.nextNode()) a.push(n); | 159 // while(n=walk.nextNode()) a.push(n); |
| 154 // return a; | 160 // return a; |
| 155 // } | 161 // } |
| 156 int type = node.nodeType; | 162 int type = node.nodeType; |
| 157 if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) { | 163 if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) { |
| 164 CharacterData text = node; |
| 158 if (anchorNode == node) { | 165 if (anchorNode == node) { |
| 159 hasSelection = true; | 166 hasSelection = true; |
| 160 anchorOffset = selection.anchorOffset + offset; | 167 anchorOffset = selection.anchorOffset + offset; |
| 161 return; | 168 return; |
| 162 } | 169 } |
| 163 offset += node.length; | 170 offset += text.length; |
| 164 } | 171 } |
| 165 | 172 |
| 166 var child = node.$dom_firstChild; | 173 var child = node.firstChild; |
| 167 while (child != null) { | 174 while (child != null) { |
| 168 walk4(child); | 175 walk4(child); |
| 169 if (hasSelection) return; | 176 if (hasSelection) return; |
| 170 child = child.nextNode; | 177 child = child.nextNode; |
| 171 } | 178 } |
| 172 } | 179 } |
| 173 if (selection.isCollapsed) { | 180 if (selection.isCollapsed) { |
| 174 walk4(inputPre); | 181 walk4(inputPre); |
| 175 } | 182 } |
| 176 | 183 |
| 177 currentSource = inputPre.text; | 184 currentSource = inputPre.text; |
| 178 inputPre.nodes.clear(); | 185 inputPre.nodes.clear(); |
| 179 inputPre.appendText(currentSource); | 186 inputPre.appendText(currentSource); |
| 180 if (hasSelection) { | 187 if (hasSelection) { |
| 181 selection.collapse(inputPre.$dom_firstChild, anchorOffset); | 188 selection.collapse(inputPre.firstChild, anchorOffset); |
| 182 } | 189 } |
| 183 | 190 |
| 184 isMalformedInput = false; | 191 isMalformedInput = false; |
| 185 for (Node node in new List.from(inputPre.nodes)) { | 192 for (var n in new List.from(inputPre.nodes)) { |
| 186 if (node is! Text) continue; | 193 if (n is! Text) continue; |
| 194 Text node = n; |
| 187 String text = node.text; | 195 String text = node.text; |
| 188 | 196 |
| 189 var token = new StringScanner(text, includeComments: true).tokenize(); | 197 Token token = new StringScanner( |
| 198 new StringSourceFile('', text), includeComments: true).tokenize(); |
| 190 int offset = 0; | 199 int offset = 0; |
| 191 for (;token.kind != EOF_TOKEN; token = token.next) { | 200 for (;token.kind != EOF_TOKEN; token = token.next) { |
| 192 Decoration decoration = getDecoration(token); | 201 Decoration decoration = getDecoration(token); |
| 193 if (decoration == null) continue; | 202 if (decoration == null) continue; |
| 194 bool hasSelection = false; | 203 bool hasSelection = false; |
| 195 int selectionOffset = selection.anchorOffset; | 204 int selectionOffset = selection.anchorOffset; |
| 196 | 205 |
| 197 if (selection.isCollapsed && selection.anchorNode == node) { | 206 if (selection.isCollapsed && selection.anchorNode == node) { |
| 198 hasSelection = true; | 207 hasSelection = true; |
| 199 selectionOffset = selection.anchorOffset; | 208 selectionOffset = selection.anchorOffset; |
| 200 } | 209 } |
| 201 int splitPoint = token.charOffset - offset; | 210 int splitPoint = token.charOffset - offset; |
| 202 Text str = node.splitText(splitPoint); | 211 Text str = node.splitText(splitPoint); |
| 203 Text after = str.splitText(token.slowCharCount); | 212 Text after = str.splitText(token.charCount); |
| 204 offset += splitPoint + token.slowCharCount; | 213 offset += splitPoint + token.charCount; |
| 205 inputPre.insertBefore(after, node.nextNode); | 214 inputPre.insertBefore(after, node.nextNode); |
| 206 inputPre.insertBefore(decoration.applyTo(str), after); | 215 inputPre.insertBefore(decoration.applyTo(str), after); |
| 207 | 216 |
| 208 if (hasSelection && selectionOffset > node.length) { | 217 if (hasSelection && selectionOffset > node.length) { |
| 209 selectionOffset -= node.length; | 218 selectionOffset -= node.length; |
| 210 if (selectionOffset > str.length) { | 219 if (selectionOffset > str.length) { |
| 211 selectionOffset -= str.length; | 220 selectionOffset -= str.length; |
| 212 selection.collapse(after, selectionOffset); | 221 selection.collapse(after, selectionOffset); |
| 213 } else { | 222 } else { |
| 214 selection.collapse(str, selectionOffset); | 223 selection.collapse(str, selectionOffset); |
| 215 } | 224 } |
| 216 } | 225 } |
| 217 node = after; | 226 node = after; |
| 218 } | 227 } |
| 219 } | 228 } |
| 220 | 229 |
| 221 window.localStorage['currentSource'] = currentSource; | 230 window.localStorage['currentSource'] = currentSource; |
| 222 | 231 |
| 223 // Discard highlighting mutations. | 232 // Discard highlighting mutations. |
| 224 observer.takeRecords(); | 233 observer.takeRecords(); |
| 225 } | 234 } |
| 226 | 235 |
| 227 addDiagnostic(String kind, String message, int begin, int end) { | 236 addDiagnostic(String kind, String message, int begin, int end) { |
| 228 observer.disconnect(); | 237 observer.disconnect(); |
| 229 DomSelection selection = window.getSelection(); | 238 Selection selection = window.getSelection(); |
| 230 int offset = 0; | 239 int offset = 0; |
| 231 int anchorOffset = 0; | 240 int anchorOffset = 0; |
| 232 bool hasSelection = false; | 241 bool hasSelection = false; |
| 233 Node anchorNode = selection.anchorNode; | 242 Node anchorNode = selection.anchorNode; |
| 234 bool foundNode = false; | 243 bool foundNode = false; |
| 235 void walk4(Node node) { | 244 void walk4(Node node) { |
| 236 // TODO(ahe): Use TreeWalker when that is exposed. | 245 // TODO(ahe): Use TreeWalker when that is exposed. |
| 237 int type = node.nodeType; | 246 int type = node.nodeType; |
| 238 if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) { | 247 if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) { |
| 248 CharacterData cdata = node; |
| 239 // print('walking: ${node.data}'); | 249 // print('walking: ${node.data}'); |
| 240 if (anchorNode == node) { | 250 if (anchorNode == node) { |
| 241 hasSelection = true; | 251 hasSelection = true; |
| 242 anchorOffset = selection.anchorOffset + offset; | 252 anchorOffset = selection.anchorOffset + offset; |
| 243 } | 253 } |
| 244 int newOffset = offset + node.length; | 254 int newOffset = offset + cdata.length; |
| 245 if (offset <= begin && begin < newOffset) { | 255 if (offset <= begin && begin < newOffset) { |
| 246 hasSelection = node == anchorNode; | 256 hasSelection = node == anchorNode; |
| 247 anchorOffset = selection.anchorOffset; | 257 anchorOffset = selection.anchorOffset; |
| 248 Node marker = new Text(""); | 258 Node marker = new Text(""); |
| 249 node.replaceWith(marker); | 259 node.replaceWith(marker); |
| 250 // TODO(ahe): Don't highlight everything in the node. Find | 260 // TODO(ahe): Don't highlight everything in the node. Find |
| 251 // the relevant token. | 261 // the relevant token. |
| 252 if (kind == 'error') { | 262 if (kind == 'error') { |
| 253 marker.replaceWith(diagnostic(node, error(message))); | 263 marker.replaceWith(diagnostic(node, error(message))); |
| 254 } else if (kind == 'warning') { | 264 } else if (kind == 'warning') { |
| 255 marker.replaceWith(diagnostic(node, warning(message))); | 265 marker.replaceWith(diagnostic(node, warning(message))); |
| 256 } else { | 266 } else { |
| 257 marker.replaceWith(diagnostic(node, info(message))); | 267 marker.replaceWith(diagnostic(node, info(message))); |
| 258 } | 268 } |
| 259 if (hasSelection) { | 269 if (hasSelection) { |
| 260 selection.collapse(node, anchorOffset); | 270 selection.collapse(node, anchorOffset); |
| 261 } | 271 } |
| 262 foundNode = true; | 272 foundNode = true; |
| 263 return; | 273 return; |
| 264 } | 274 } |
| 265 offset = newOffset; | 275 offset = newOffset; |
| 266 } else if (type == Node.ELEMENT_NODE) { | 276 } else if (type == Node.ELEMENT_NODE) { |
| 267 if (node.classes.contains('alert')) return; | 277 Element element = node; |
| 278 if (element.classes.contains('alert')) return; |
| 268 } | 279 } |
| 269 | 280 |
| 270 var child = node.$dom_firstChild; | 281 var child = node.firstChild; |
| 271 while(child != null && !foundNode) { | 282 while(child != null && !foundNode) { |
| 272 walk4(child); | 283 walk4(child); |
| 273 child = child.nextNode; | 284 child = child.nextNode; |
| 274 } | 285 } |
| 275 } | 286 } |
| 276 walk4(inputPre); | 287 walk4(inputPre); |
| 277 | 288 |
| 278 if (!foundNode) { | 289 if (!foundNode) { |
| 279 outputDiv.appendText('$message\n'); | 290 outputDiv.appendText('$message\n'); |
| 280 } | 291 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 if (!isMalformedInput) scheduleCompilation(); | 360 if (!isMalformedInput) scheduleCompilation(); |
| 350 return; | 361 return; |
| 351 } | 362 } |
| 352 if (current != null) current.dispose(); | 363 if (current != null) current.dispose(); |
| 353 current = this; | 364 current = this; |
| 354 console.nodes.clear(); | 365 console.nodes.clear(); |
| 355 var options = []; | 366 var options = []; |
| 356 if (verboseCompiler) options.add('--verbose'); | 367 if (verboseCompiler) options.add('--verbose'); |
| 357 if (minified) options.add('--minify'); | 368 if (minified) options.add('--minify'); |
| 358 if (onlyAnalyze) options.add('--analyze-only'); | 369 if (onlyAnalyze) options.add('--analyze-only'); |
| 359 compilerPort.send(['options', options], receivePort.toSendPort()); | 370 compilerPort.send([['options', options], receivePort.sendPort]); |
| 360 console.appendHtml('<i class="icon-spinner icon-spin"></i>'); | 371 console.appendHtml('<i class="icon-spinner icon-spin"></i>'); |
| 361 console.appendText(' Compiling Dart program...\n'); | 372 console.appendText(' Compiling Dart program...\n'); |
| 362 outputFrame.style.display = 'none'; | 373 outputFrame.style.display = 'none'; |
| 363 receivePort.receive(onMessage); | 374 receivePort.listen(onMessage); |
| 364 compilerPort.send(source, receivePort.toSendPort()); | 375 compilerPort.send([source, receivePort.sendPort]); |
| 365 } | 376 } |
| 366 | 377 |
| 367 void dispose() { | 378 void dispose() { |
| 368 if (worker != null) worker.terminate(); | 379 if (worker != null) worker.terminate(); |
| 369 objectUrls.forEach(Url.revokeObjectUrl); | 380 objectUrls.forEach(Url.revokeObjectUrl); |
| 370 } | 381 } |
| 371 | 382 |
| 372 onMessage(message, _) { | 383 onMessage(message) { |
| 373 String kind = message is String ? message : message[0]; | 384 String kind = message is String ? message : message[0]; |
| 374 var data = (message is List && message.length == 2) ? message[1] : null; | 385 var data = (message is List && message.length == 2) ? message[1] : null; |
| 375 switch (kind) { | 386 switch (kind) { |
| 376 case 'done': return onDone(data); | 387 case 'done': return onDone(data); |
| 377 case 'url': return onUrl(data); | 388 case 'url': return onUrl(data); |
| 378 case 'code': return onCode(data); | 389 case 'code': return onCode(data); |
| 379 case 'diagnostic': return onDiagnostic(data); | 390 case 'diagnostic': return onDiagnostic(data); |
| 380 case 'crash': return onCrash(data); | 391 case 'crash': return onCrash(data); |
| 381 case 'failed': return onFail(data); | 392 case 'failed': return onFail(data); |
| 382 case 'dart:html': return onDartHtml(data); | 393 case 'dart:html': return onDartHtml(data); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 onCrash(data) { | 520 onCrash(data) { |
| 510 consolePrint(data); | 521 consolePrint(data); |
| 511 } | 522 } |
| 512 | 523 |
| 513 void consolePrint(message) { | 524 void consolePrint(message) { |
| 514 console.appendText('$message\n'); | 525 console.appendText('$message\n'); |
| 515 } | 526 } |
| 516 } | 527 } |
| 517 | 528 |
| 518 Decoration getDecoration(scanner.Token token) { | 529 Decoration getDecoration(scanner.Token token) { |
| 519 String tokenValue = token.slowToString(); | 530 String tokenValue = token.value; |
| 520 String tokenInfo = token.info.value.slowToString(); | 531 String tokenInfo = token.info.value; |
| 521 if (tokenInfo == 'string') return currentTheme.string; | 532 if (tokenInfo == 'string') return currentTheme.string; |
| 522 // if (tokenInfo == 'identifier') return identifier; | 533 // if (tokenInfo == 'identifier') return identifier; |
| 523 if (tokenInfo == 'keyword') return currentTheme.keyword; | 534 if (tokenInfo == 'keyword') return currentTheme.keyword; |
| 524 if (tokenInfo == 'comment') return currentTheme.singleLineComment; | 535 if (tokenInfo == 'comment') return currentTheme.singleLineComment; |
| 525 if (tokenInfo == 'malformed input') { | 536 if (tokenInfo == 'malformed input') { |
| 526 isMalformedInput = true; | 537 isMalformedInput = true; |
| 527 return new DiagnosticDecoration('error', tokenValue); | 538 return new DiagnosticDecoration('error', tokenValue); |
| 528 } | 539 } |
| 529 return null; | 540 return null; |
| 530 } | 541 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 ..style.width = '100%' | 574 ..style.width = '100%' |
| 564 ..style.height = '0px' | 575 ..style.height = '0px' |
| 565 ..seamless = false; | 576 ..seamless = false; |
| 566 } | 577 } |
| 567 | 578 |
| 568 const String HAS_NON_DOM_HTTP_REQUEST = 'spawnFunction supports HttpRequest'; | 579 const String HAS_NON_DOM_HTTP_REQUEST = 'spawnFunction supports HttpRequest'; |
| 569 const String NO_NON_DOM_HTTP_REQUEST = | 580 const String NO_NON_DOM_HTTP_REQUEST = |
| 570 'spawnFunction does not support HttpRequest'; | 581 'spawnFunction does not support HttpRequest'; |
| 571 | 582 |
| 572 | 583 |
| 573 checkHttpRequest() { | 584 checkHttpRequest(SendPort replyTo) { |
| 574 port.receive((String uri, SendPort replyTo) { | 585 try { |
| 575 try { | 586 new HttpRequest(); |
| 576 new HttpRequest(); | 587 replyTo.send(HAS_NON_DOM_HTTP_REQUEST); |
| 577 replyTo.send(HAS_NON_DOM_HTTP_REQUEST); | 588 } catch (e, trace) { |
| 578 } catch (e, trace) { | 589 replyTo.send(NO_NON_DOM_HTTP_REQUEST); |
| 579 replyTo.send(NO_NON_DOM_HTTP_REQUEST); | 590 } |
| 580 } | |
| 581 port.close(); | |
| 582 }); | |
| 583 } | 591 } |
| 584 | 592 |
| 585 main() { | 593 main() { |
| 586 if (window.localStorage['currentSource'] == null) { | 594 if (window.localStorage['currentSource'] == null) { |
| 587 window.localStorage['currentSource'] = EXAMPLE_HELLO; | 595 window.localStorage['currentSource'] = EXAMPLE_HELLO; |
| 588 } | 596 } |
| 589 | 597 |
| 590 buildUI(); | 598 buildUI(); |
| 591 spawnFunction(checkHttpRequest).call('').then((reply) { | 599 spawnFunction(checkHttpRequest).first.then((reply) { |
| 592 var compilerFuture; | 600 ReceivePort port; |
| 593 if (reply == HAS_NON_DOM_HTTP_REQUEST) { | 601 if (reply == HAS_NON_DOM_HTTP_REQUEST) { |
| 594 compilerFuture = spawnFunction(compilerIsolate); | 602 port = spawnFunction(compilerIsolate); |
| 595 } else { | 603 } else { |
| 596 compilerFuture = spawnDomFunction(compilerIsolate); | 604 port = spawnDomFunction(compilerIsolate); |
| 597 } | 605 } |
| 598 if (compilerFuture is! Future) { | 606 LinkElement link = query('link[rel="dart-sdk"]'); |
| 599 compilerFuture = new Future.value(compilerFuture); | 607 String sdk = link.href; |
| 600 } | 608 print('Using Dart SDK: $sdk'); |
| 601 compilerFuture.then((port) { | 609 int messageCount = 0; |
| 602 String sdk = query('link[rel="dart-sdk"]').href; | 610 SendPort sendPort; |
| 603 print('Using Dart SDK: $sdk'); | 611 port.listen((message) { |
| 604 port.call(sdk).then((_) { | 612 messageCount++; |
| 605 compilerPort = port; | 613 switch (messageCount) { |
| 606 onMutation([], observer); | 614 case 1: |
| 607 }); | 615 sendPort = message as SendPort; |
| 616 sendPort.send([sdk, port.sendPort]); |
| 617 break; |
| 618 case 2: |
| 619 // Acknowledged Receiving the SDK URI. |
| 620 compilerPort = sendPort; |
| 621 onMutation([], observer); |
| 622 break; |
| 623 default: |
| 624 // TODO(ahe): Close [port]? |
| 625 print('Unexpected message received: $message'); |
| 626 break; |
| 627 } |
| 608 }); | 628 }); |
| 609 }); | 629 }); |
| 610 } | 630 } |
| 611 | 631 |
| 612 buildButton(message, action) { | 632 buildButton(message, action) { |
| 613 if (message is String) { | 633 if (message is String) { |
| 614 message = new Text(message); | 634 message = new Text(message); |
| 615 } | 635 } |
| 616 return new ButtonElement() | 636 return new ButtonElement() |
| 617 ..onClick.listen(action) | 637 ..onClick.listen(action) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 inputPre | 680 inputPre |
| 661 ..nodes.clear() | 681 ..nodes.clear() |
| 662 ..appendText(EXAMPLE_HELLO); | 682 ..appendText(EXAMPLE_HELLO); |
| 663 })); | 683 })); |
| 664 inspirationTabs.append(buildTab('Fibonacci', 'EXAMPLE_FIBONACCI', (_) { | 684 inspirationTabs.append(buildTab('Fibonacci', 'EXAMPLE_FIBONACCI', (_) { |
| 665 inputPre | 685 inputPre |
| 666 ..nodes.clear() | 686 ..nodes.clear() |
| 667 ..appendText(EXAMPLE_FIBONACCI); | 687 ..appendText(EXAMPLE_FIBONACCI); |
| 668 })); | 688 })); |
| 669 inspirationTabs.append(htmlGroup); | 689 inspirationTabs.append(htmlGroup); |
| 670 inspirationTabs.append(benchmarkGroup); | 690 // TODO(ahe): Restore benchmarks. |
| 691 // inspirationTabs.append(benchmarkGroup); |
| 671 | 692 |
| 672 htmlGroup.append( | 693 htmlGroup.append( |
| 673 buildTab('Hello, World!', 'EXAMPLE_HELLO_HTML', (_) { | 694 buildTab('Hello, World!', 'EXAMPLE_HELLO_HTML', (_) { |
| 674 inputPre | 695 inputPre |
| 675 ..nodes.clear() | 696 ..nodes.clear() |
| 676 ..appendText(EXAMPLE_HELLO_HTML); | 697 ..appendText(EXAMPLE_HELLO_HTML); |
| 677 })); | 698 })); |
| 678 htmlGroup.append( | 699 htmlGroup.append( |
| 679 buildTab('Fibonacci', 'EXAMPLE_FIBONACCI_HTML', (_) { | 700 buildTab('Fibonacci', 'EXAMPLE_FIBONACCI_HTML', (_) { |
| 680 inputPre | 701 inputPre |
| 681 ..nodes.clear() | 702 ..nodes.clear() |
| 682 ..appendText(EXAMPLE_FIBONACCI_HTML); | 703 ..appendText(EXAMPLE_FIBONACCI_HTML); |
| 683 })); | 704 })); |
| 684 htmlGroup.append(buildTab('Sunflower', 'EXAMPLE_SUNFLOWER', (_) { | 705 htmlGroup.append(buildTab('Sunflower', 'EXAMPLE_SUNFLOWER', (_) { |
| 685 inputPre | 706 inputPre |
| 686 ..nodes.clear() | 707 ..nodes.clear() |
| 687 ..appendText(EXAMPLE_SUNFLOWER); | 708 ..appendText(EXAMPLE_SUNFLOWER); |
| 688 })); | 709 })); |
| 689 | 710 |
| 690 benchmarkGroup.append(buildTab('DeltaBlue', 'BENCHMARK_DELTA_BLUE', (_) { | 711 benchmarkGroup.append(buildTab('DeltaBlue', 'BENCHMARK_DELTA_BLUE', (_) { |
| 691 inputPre.contentEditable = 'false'; | 712 inputPre.contentEditable = 'false'; |
| 692 String deltaBlueUri = query('link[rel="benchmark-DeltaBlue"]').href; | 713 LinkElement link = query('link[rel="benchmark-DeltaBlue"]'); |
| 693 String benchmarkBaseUri = query('link[rel="benchmark-base"]').href; | 714 String deltaBlueUri = link.href; |
| 715 link = query('link[rel="benchmark-base"]'); |
| 716 String benchmarkBaseUri = link.href; |
| 694 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { | 717 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { |
| 695 HttpRequest.getString(deltaBlueUri).then((String deltaBlue) { | 718 HttpRequest.getString(deltaBlueUri).then((String deltaBlue) { |
| 696 benchmarkBase = benchmarkBase.replaceFirst( | 719 benchmarkBase = benchmarkBase.replaceFirst( |
| 697 'part of benchmark_harness;', '// part of benchmark_harness;'); | 720 'part of benchmark_harness;', '// part of benchmark_harness;'); |
| 698 deltaBlue = deltaBlue.replaceFirst( | 721 deltaBlue = deltaBlue.replaceFirst( |
| 699 "import 'package:benchmark_harness/benchmark_harness.dart';", | 722 "import 'package:benchmark_harness/benchmark_harness.dart';", |
| 700 benchmarkBase); | 723 benchmarkBase); |
| 701 inputPre | 724 inputPre |
| 702 ..nodes.clear() | 725 ..nodes.clear() |
| 703 ..appendText(deltaBlue) | 726 ..appendText(deltaBlue) |
| 704 ..contentEditable = 'true'; | 727 ..contentEditable = 'true'; |
| 705 }); | 728 }); |
| 706 }); | 729 }); |
| 707 })); | 730 })); |
| 708 | 731 |
| 709 benchmarkGroup.append(buildTab('Richards', 'BENCHMARK_RICHARDS', (_) { | 732 benchmarkGroup.append(buildTab('Richards', 'BENCHMARK_RICHARDS', (_) { |
| 710 inputPre.contentEditable = 'false'; | 733 inputPre.contentEditable = 'false'; |
| 711 String richardsUri = query('link[rel="benchmark-Richards"]').href; | 734 LinkElement link = query('link[rel="benchmark-Richards"]'); |
| 712 String benchmarkBaseUri = query('link[rel="benchmark-base"]').href; | 735 String richardsUri = link.href; |
| 736 link = query('link[rel="benchmark-base"]'); |
| 737 String benchmarkBaseUri = link.href; |
| 713 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { | 738 HttpRequest.getString(benchmarkBaseUri).then((String benchmarkBase) { |
| 714 HttpRequest.getString(richardsUri).then((String richards) { | 739 HttpRequest.getString(richardsUri).then((String richards) { |
| 715 benchmarkBase = benchmarkBase.replaceFirst( | 740 benchmarkBase = benchmarkBase.replaceFirst( |
| 716 'part of benchmark_harness;', '// part of benchmark_harness;'); | 741 'part of benchmark_harness;', '// part of benchmark_harness;'); |
| 717 richards = richards.replaceFirst( | 742 richards = richards.replaceFirst( |
| 718 "import 'package:benchmark_harness/benchmark_harness.dart';", | 743 "import 'package:benchmark_harness/benchmark_harness.dart';", |
| 719 benchmarkBase); | 744 benchmarkBase); |
| 720 inputPre | 745 inputPre |
| 721 ..nodes.clear() | 746 ..nodes.clear() |
| 722 ..appendText(richards) | 747 ..appendText(richards) |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 return; | 856 return; |
| 832 } | 857 } |
| 833 } | 858 } |
| 834 } | 859 } |
| 835 outputDiv.appendText('${event.data}\n'); | 860 outputDiv.appendText('${event.data}\n'); |
| 836 }); | 861 }); |
| 837 | 862 |
| 838 observer = new MutationObserver(onMutation) | 863 observer = new MutationObserver(onMutation) |
| 839 ..observe(inputPre, childList: true, characterData: true, subtree: true); | 864 ..observe(inputPre, childList: true, characterData: true, subtree: true); |
| 840 | 865 |
| 841 window.setImmediate(() { | 866 scheduleMicrotask(() { |
| 842 inputPre.appendText(window.localStorage['currentSource']); | 867 inputPre.appendText(window.localStorage['currentSource']); |
| 843 }); | 868 }); |
| 844 | 869 |
| 845 // You cannot install event handlers on window.applicationCache | 870 // You cannot install event handlers on window.applicationCache |
| 846 // until the window has loaded. In dartium, that's later than this | 871 // until the window has loaded. In dartium, that's later than this |
| 847 // method is called. | 872 // method is called. |
| 848 window.onLoad.listen(onLoad); | 873 window.onLoad.listen(onLoad); |
| 849 | 874 |
| 850 // However, in dart2js, the window has already loaded, and onLoad is | 875 // However, in dart2js, the window has already loaded, and onLoad is |
| 851 // never called. | 876 // never called. |
| 852 onLoad(null); | 877 onLoad(null); |
| 853 } | 878 } |
| 854 | 879 |
| 855 void openSettings(MouseEvent event) { | 880 void openSettings(MouseEvent event) { |
| 856 event.preventDefault(); | 881 event.preventDefault(); |
| 857 | 882 |
| 858 var backdrop = new DivElement()..classes.add('modal-backdrop'); | 883 var backdrop = new DivElement()..classes.add('modal-backdrop'); |
| 859 document.body.append(backdrop); | 884 document.body.append(backdrop); |
| 860 | 885 |
| 861 void updateCodeFont(Event e) { | 886 void updateCodeFont(Event e) { |
| 862 codeFont = e.target.value; | 887 TextInputElement target = e.target; |
| 888 codeFont = target.value; |
| 863 inputPre.style.font = codeFont; | 889 inputPre.style.font = codeFont; |
| 864 backdrop.style.opacity = '0.0'; | 890 backdrop.style.opacity = '0.0'; |
| 865 } | 891 } |
| 866 | 892 |
| 867 void updateTheme(Event e) { | 893 void updateTheme(Event e) { |
| 868 var select = e.target; | 894 var select = e.target; |
| 869 String theme = select.queryAll('option')[select.selectedIndex].text; | 895 String theme = select.queryAll('option')[select.selectedIndex].text; |
| 870 window.localStorage['theme'] = theme; | 896 window.localStorage['theme'] = theme; |
| 871 currentTheme = Theme.named(theme); | 897 currentTheme = Theme.named(theme); |
| 872 | 898 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 890 | 916 |
| 891 body.nodes.clear(); | 917 body.nodes.clear(); |
| 892 | 918 |
| 893 var form = new FormElement(); | 919 var form = new FormElement(); |
| 894 var fieldSet = new FieldSetElement(); | 920 var fieldSet = new FieldSetElement(); |
| 895 body.append(form); | 921 body.append(form); |
| 896 form.append(fieldSet); | 922 form.append(fieldSet); |
| 897 | 923 |
| 898 buildCheckBox(String text, bool defaultValue, void action(Event e)) { | 924 buildCheckBox(String text, bool defaultValue, void action(Event e)) { |
| 899 var checkBox = new CheckboxInputElement() | 925 var checkBox = new CheckboxInputElement() |
| 900 ..defaultChecked = defaultValue | 926 // TODO(ahe): Used to be ..defaultChecked = defaultValue |
| 927 ..checked = defaultValue |
| 901 ..onChange.listen(action); | 928 ..onChange.listen(action); |
| 902 return new LabelElement() | 929 return new LabelElement() |
| 903 ..classes.add('checkbox') | 930 ..classes.add('checkbox') |
| 904 ..append(checkBox) | 931 ..append(checkBox) |
| 905 ..appendText(' $text'); | 932 ..appendText(' $text'); |
| 906 } | 933 } |
| 907 | 934 |
| 935 bool isChecked(CheckboxInputElement checkBox) => checkBox.checked; |
| 936 |
| 908 // TODO(ahe): Build abstraction for flags/options. | 937 // TODO(ahe): Build abstraction for flags/options. |
| 909 fieldSet.append( | 938 fieldSet.append( |
| 910 buildCheckBox( | 939 buildCheckBox( |
| 911 'Always run in Worker thread.', alwaysRunInWorker, | 940 'Always run in Worker thread.', alwaysRunInWorker, |
| 912 (Event e) { alwaysRunInWorker = e.target.checked; })); | 941 (Event e) { alwaysRunInWorker = isChecked(e.target); })); |
| 913 | 942 |
| 914 fieldSet.append( | 943 fieldSet.append( |
| 915 buildCheckBox( | 944 buildCheckBox( |
| 916 'Verbose compiler output.', verboseCompiler, | 945 'Verbose compiler output.', verboseCompiler, |
| 917 (Event e) { verboseCompiler = e.target.checked; })); | 946 (Event e) { verboseCompiler = isChecked(e.target); })); |
| 918 | 947 |
| 919 fieldSet.append( | 948 fieldSet.append( |
| 920 buildCheckBox( | 949 buildCheckBox( |
| 921 'Generate compact (minified) JavaScript.', minified, | 950 'Generate compact (minified) JavaScript.', minified, |
| 922 (Event e) { minified = e.target.checked; })); | 951 (Event e) { minified = isChecked(e.target); })); |
| 923 | 952 |
| 924 fieldSet.append( | 953 fieldSet.append( |
| 925 buildCheckBox( | 954 buildCheckBox( |
| 926 'Only analyze program.', onlyAnalyze, | 955 'Only analyze program.', onlyAnalyze, |
| 927 (Event e) { onlyAnalyze = e.target.checked; })); | 956 (Event e) { onlyAnalyze = isChecked(e.target); })); |
| 928 | 957 |
| 929 fieldSet.append(new LabelElement()..appendText('Code font:')); | 958 fieldSet.append(new LabelElement()..appendText('Code font:')); |
| 930 var textInput = new TextInputElement(); | 959 var textInput = new TextInputElement(); |
| 931 textInput.classes.add('input-block-level'); | 960 textInput.classes.add('input-block-level'); |
| 932 if (codeFont != null && codeFont != '') { | 961 if (codeFont != null && codeFont != '') { |
| 933 textInput.value = codeFont; | 962 textInput.value = codeFont; |
| 934 } | 963 } |
| 935 textInput.placeholder = 'Enter a size and font, for example, 11pt monospace'; | 964 textInput.placeholder = 'Enter a size and font, for example, 11pt monospace'; |
| 936 textInput.onChange.listen(updateCodeFont); | 965 textInput.onChange.listen(updateCodeFont); |
| 937 fieldSet.append(textInput); | 966 fieldSet.append(textInput); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 if (status == ApplicationCache.DOWNLOADING) return 'Downloading SDK'; | 1039 if (status == ApplicationCache.DOWNLOADING) return 'Downloading SDK'; |
| 1011 if (status == ApplicationCache.IDLE) return 'Try Dart! works offline'; | 1040 if (status == ApplicationCache.IDLE) return 'Try Dart! works offline'; |
| 1012 if (status == ApplicationCache.OBSOLETE) return 'OBSOLETE'; | 1041 if (status == ApplicationCache.OBSOLETE) return 'OBSOLETE'; |
| 1013 if (status == ApplicationCache.UNCACHED) return 'offline not available'; | 1042 if (status == ApplicationCache.UNCACHED) return 'offline not available'; |
| 1014 if (status == ApplicationCache.UPDATEREADY) return 'SDK downloaded'; | 1043 if (status == ApplicationCache.UPDATEREADY) return 'SDK downloaded'; |
| 1015 return '?'; | 1044 return '?'; |
| 1016 } | 1045 } |
| 1017 | 1046 |
| 1018 void updateCacheStatus() { | 1047 void updateCacheStatus() { |
| 1019 cacheStatusElement.nodes.clear(); | 1048 cacheStatusElement.nodes.clear(); |
| 1020 String status = window.applicationCache.status; | 1049 int status = window.applicationCache.status; |
| 1021 if (status == ApplicationCache.UPDATEREADY) { | 1050 if (status == ApplicationCache.UPDATEREADY) { |
| 1022 cacheStatusElement.appendText('New version of Try Dart! ready: '); | 1051 cacheStatusElement.appendText('New version of Try Dart! ready: '); |
| 1023 cacheStatusElement.append( | 1052 cacheStatusElement.append( |
| 1024 new AnchorElement(href: '#') | 1053 new AnchorElement(href: '#') |
| 1025 ..appendText('Load') | 1054 ..appendText('Load') |
| 1026 ..onClick.listen((event) { | 1055 ..onClick.listen((event) { |
| 1027 event.preventDefault(); | 1056 event.preventDefault(); |
| 1028 window.applicationCache.swapCache(); | 1057 window.applicationCache.swapCache(); |
| 1029 window.location.reload(); | 1058 window.location.reload(); |
| 1030 })); | 1059 })); |
| 1031 } else if (status == ApplicationCache.IDLE) { | 1060 } else if (status == ApplicationCache.IDLE) { |
| 1032 cacheStatusElement.appendText(cacheStatus()); | 1061 cacheStatusElement.appendText(cacheStatus()); |
| 1033 cacheStatusElement.classes.add('offlineyay'); | 1062 cacheStatusElement.classes.add('offlineyay'); |
| 1034 new Timer(const Duration(seconds: 10), () { | 1063 new Timer(const Duration(seconds: 10), () { |
| 1035 cacheStatusElement.style.display = 'none'; | 1064 cacheStatusElement.style.display = 'none'; |
| 1036 }); | 1065 }); |
| 1037 } else { | 1066 } else { |
| 1038 cacheStatusElement.appendText(cacheStatus()); | 1067 cacheStatusElement.appendText(cacheStatus()); |
| 1039 } | 1068 } |
| 1040 } | 1069 } |
| 1041 | 1070 |
| 1042 void compilerIsolate() { | 1071 void compilerIsolate(SendPort port) { |
| 1043 lazy.load().then((_) => port.receive(compile)); | 1072 // TODO(ahe): Restore when restoring deferred loading. |
| 1073 // lazy.load().then((_) => port.listen(compile)); |
| 1074 ReceivePort replyTo = new ReceivePort(); |
| 1075 port.send(replyTo.sendPort); |
| 1076 replyTo.listen((message) { |
| 1077 List list = message as List; |
| 1078 try { |
| 1079 compile(list[0], list[1]); |
| 1080 } catch (exception, stack) { |
| 1081 port.send('$exception\n$stack'); |
| 1082 } |
| 1083 }); |
| 1044 } | 1084 } |
| 1045 | 1085 |
| 1046 final String outputHelper = | 1086 final String outputHelper = |
| 1047 Url.createObjectUrl(new Blob([OUTPUT_HELPER], 'application/javascript')); | 1087 Url.createObjectUrl(new Blob([OUTPUT_HELPER], 'application/javascript')); |
| 1048 | 1088 |
| 1049 const String EXAMPLE_HELLO = r''' | 1089 const String EXAMPLE_HELLO = r''' |
| 1050 // Go ahead and modify this example. | 1090 // Go ahead and modify this example. |
| 1051 | 1091 |
| 1052 var greeting = "Hello, World!"; | 1092 var greeting = "Hello, World!"; |
| 1053 | 1093 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 } | 1309 } |
| 1270 | 1310 |
| 1271 .center { | 1311 .center { |
| 1272 display: block; | 1312 display: block; |
| 1273 margin: 0px auto; | 1313 margin: 0px auto; |
| 1274 text-align: center; | 1314 text-align: center; |
| 1275 } | 1315 } |
| 1276 """; | 1316 """; |
| 1277 | 1317 |
| 1278 '''; | 1318 '''; |
| OLD | NEW |