OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library compiler_isolate; | |
6 | |
7 import 'dart:async'; | |
8 import 'dart:html'; | |
9 import 'dart:isolate'; | |
10 import 'dart:convert' show JSON; | |
11 | |
12 import 'compilation.dart' show PRIVATE_SCHEME; | |
13 | |
14 import 'package:compiler/compiler.dart' as compiler; | |
15 | |
16 import 'package:compiler/src/old_to_new_api.dart' show | |
17 LegacyCompilerDiagnostics, LegacyCompilerInput; | |
18 | |
19 import 'package:dart2js_incremental/dart2js_incremental.dart' show | |
20 reuseCompiler, OutputProvider; | |
21 | |
22 import 'package:compiler/src/compiler.dart' show | |
23 Compiler; | |
24 | |
25 const bool THROW_ON_ERROR = false; | |
26 | |
27 final cachedSources = new Map<Uri, Future<String>>(); | |
28 | |
29 Uri sdkLocation; | |
30 List options = []; | |
31 | |
32 var communicateViaBlobs; | |
33 | |
34 var cachedCompiler; | |
35 | |
36 void notifyDartHtml(SendPort port) { | |
37 // Notify the controlling isolate (Try Dart UI) that the program imports | |
38 // dart:html. This is used to determine how to run the program: in an iframe | |
39 // or in a worker. | |
40 port.send('dart:html'); | |
41 } | |
42 | |
43 compile(source, SendPort replyTo) { | |
44 if (sdkLocation == null) { | |
45 // The first message received gives us the URI of this web app. | |
46 if (source.endsWith('/sdk.json')) { | |
47 var request = new HttpRequest(); | |
48 request.open('GET', source, async: false); | |
49 request.send(null); | |
50 if (request.status != 200) { | |
51 throw 'SDK not found at $source'; | |
52 } | |
53 sdkLocation = Uri.parse('sdk:/sdk/'); | |
54 JSON.decode(request.responseText).forEach((file, content) { | |
55 cachedSources[Uri.parse(file)] = new Future<String>.value(content); | |
56 }); | |
57 } else { | |
58 sdkLocation = Uri.parse(source); | |
59 } | |
60 replyTo.send(null); | |
61 return; | |
62 } | |
63 if (source is List) { | |
64 String messageType = (source.length > 0) ? source[0] : null; | |
65 var data = (source.length > 1) ? source[1] : null; | |
66 if (messageType == 'options') { | |
67 options = data as List; | |
68 } if (messageType == 'communicateViaBlobs') { | |
69 communicateViaBlobs = data as bool; | |
70 } | |
71 return; | |
72 } | |
73 int charactersRead = 0; | |
74 Future<String> inputProvider(Uri uri) { | |
75 Future<String> future; | |
76 if (uri.scheme == 'sdk') { | |
77 if (uri.path.endsWith('/lib/html/dart2js/html_dart2js.dart')) { | |
78 notifyDartHtml(replyTo); | |
79 } | |
80 future = cachedSources[uri]; | |
81 } else if (uri.scheme == 'http' || uri.scheme == 'https') { | |
82 future = | |
83 cachedSources.putIfAbsent(uri, () => HttpRequest.getString('$uri')); | |
84 } else if ('$uri' == '$PRIVATE_SCHEME:/main.dart') { | |
85 future = new Future<String>.value(source); | |
86 } else if (uri.scheme == PRIVATE_SCHEME) { | |
87 future = HttpRequest.getString('project${uri.path}'); | |
88 } | |
89 if (future == null) { | |
90 future = new Future<String>.error('$uri: Not found'); | |
91 } | |
92 return future.then((String value) { | |
93 charactersRead += value.length; | |
94 return value; | |
95 }).catchError((Event event) { | |
96 var target = event.target; | |
97 if (target is HttpRequest) { | |
98 throw '$uri: ${target.statusText}'; | |
99 } else { | |
100 throw event; | |
101 } | |
102 }, test: (error) => error is Event); | |
103 } | |
104 void handler(Uri uri, int begin, int end, | |
105 String message, compiler.Diagnostic kind) { | |
106 replyTo.send(['diagnostic', { 'uri': '$uri', | |
107 'begin': begin, | |
108 'end': end, | |
109 'message': message, | |
110 'kind': kind.name }]); | |
111 if (THROW_ON_ERROR && kind == compiler.Diagnostic.ERROR) { | |
112 throw new Exception('Throw on error'); | |
113 } | |
114 } | |
115 Stopwatch compilationTimer = new Stopwatch()..start(); | |
116 OutputProvider outputProvider = new OutputProvider(); | |
117 reuseCompiler( | |
118 diagnosticHandler: new LegacyCompilerDiagnostics(handler), | |
119 inputProvider: new LegacyCompilerInput(inputProvider), | |
120 outputProvider: outputProvider, | |
121 options: options, | |
122 cachedCompiler: cachedCompiler, | |
123 libraryRoot: sdkLocation, | |
124 packageRoot: Uri.base.resolve('/packages/'), | |
125 packagesAreImmutable: true).then((Compiler newCompiler) { | |
126 cachedCompiler = newCompiler; | |
127 return cachedCompiler.run(Uri.parse('$PRIVATE_SCHEME:/main.dart')); | |
128 }).then((success) { | |
129 compilationTimer.stop(); | |
130 print('Compilation took ${compilationTimer.elapsed}'); | |
131 if (cachedCompiler.libraryLoader | |
132 .lookupLibrary(Uri.parse('dart:html')) != null) { | |
133 notifyDartHtml(replyTo); | |
134 } | |
135 String js = outputProvider['.js']; | |
136 if (js == null) { | |
137 if (!options.contains('--analyze-only')) replyTo.send('failed'); | |
138 } else { | |
139 var url; | |
140 handler(null, 0, 0, | |
141 'Compiled ${source.length}/${charactersRead} characters Dart' | |
142 ' -> ${js.length} characters.', | |
143 compiler.Diagnostic.VERBOSE_INFO); | |
144 if (communicateViaBlobs) { | |
145 try { | |
146 // At least Safari and Firefox do not support creating an | |
147 // object URL from a web worker. MDN claims that it will be | |
148 // supported in Firefox 21. | |
149 url = Url.createObjectUrl(new Blob([js], 'application/javascript')); | |
150 } catch (_) { | |
151 // Ignored. | |
152 } | |
153 } else { | |
154 url = null; | |
155 } | |
156 if (url != null) { | |
157 replyTo.send(['url', url]); | |
158 } else { | |
159 replyTo.send(['code', js]); | |
160 } | |
161 } | |
162 }).catchError((e, trace) { | |
163 replyTo.send(['crash', '$e, $trace']); | |
164 }).whenComplete(() { | |
165 replyTo.send('done'); | |
166 }); | |
167 } | |
168 | |
169 void main(List<String> arguments, SendPort port) { | |
170 ReceivePort replyTo = new ReceivePort(); | |
171 port.send(replyTo.sendPort); | |
172 replyTo.listen((message) { | |
173 try { | |
174 List list = message as List; | |
175 compile(list[0], list[1]); | |
176 } catch (exception, stack) { | |
177 port.send('$exception\n$stack'); | |
178 } | |
179 }); | |
180 } | |
OLD | NEW |