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 source_file_provider; | 5 library source_file_provider; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 import 'dart:math' as math; | 10 import 'dart:math' as math; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 } | 49 } |
50 } | 50 } |
51 | 51 |
52 Future<List<int>> _readFromFile(Uri resourceUri) { | 52 Future<List<int>> _readFromFile(Uri resourceUri) { |
53 assert(resourceUri.scheme == 'file'); | 53 assert(resourceUri.scheme == 'file'); |
54 List<int> source; | 54 List<int> source; |
55 try { | 55 try { |
56 source = readAll(resourceUri.toFilePath()); | 56 source = readAll(resourceUri.toFilePath()); |
57 } on FileSystemException catch (ex) { | 57 } on FileSystemException catch (ex) { |
58 OSError ose = ex.osError; | 58 OSError ose = ex.osError; |
59 String detail = (ose != null && ose.message != null) | 59 String detail = |
60 ? ' (${ose.message})' | 60 (ose != null && ose.message != null) ? ' (${ose.message})' : ''; |
61 : ''; | |
62 return new Future.error( | 61 return new Future.error( |
63 "Error reading '${relativize(cwd, resourceUri, isWindows)}'" | 62 "Error reading '${relativize(cwd, resourceUri, isWindows)}'" |
64 "$detail"); | 63 "$detail"); |
65 } | 64 } |
66 dartCharactersRead += source.length; | 65 dartCharactersRead += source.length; |
67 sourceFiles[resourceUri] = | 66 sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile( |
68 new CachingUtf8BytesSourceFile( | 67 resourceUri, relativizeUri(resourceUri), source); |
69 resourceUri, relativizeUri(resourceUri), source); | |
70 return new Future.value(source); | 68 return new Future.value(source); |
71 } | 69 } |
72 | 70 |
73 Future<List<int>> _readFromHttp(Uri resourceUri) { | 71 Future<List<int>> _readFromHttp(Uri resourceUri) { |
74 assert(resourceUri.scheme == 'http'); | 72 assert(resourceUri.scheme == 'http'); |
75 HttpClient client = new HttpClient(); | 73 HttpClient client = new HttpClient(); |
76 return client.getUrl(resourceUri) | 74 return client |
| 75 .getUrl(resourceUri) |
77 .then((HttpClientRequest request) => request.close()) | 76 .then((HttpClientRequest request) => request.close()) |
78 .then((HttpClientResponse response) { | 77 .then((HttpClientResponse response) { |
79 if (response.statusCode != HttpStatus.OK) { | 78 if (response.statusCode != HttpStatus.OK) { |
80 String msg = 'Failure getting $resourceUri: ' | 79 String msg = 'Failure getting $resourceUri: ' |
81 '${response.statusCode} ${response.reasonPhrase}'; | 80 '${response.statusCode} ${response.reasonPhrase}'; |
82 throw msg; | 81 throw msg; |
83 } | 82 } |
84 return response.toList(); | 83 return response.toList(); |
85 }) | 84 }).then((List<List<int>> splitContent) { |
86 .then((List<List<int>> splitContent) { | 85 int totalLength = splitContent.fold(0, (int old, List list) { |
87 int totalLength = splitContent.fold(0, (int old, List list) { | 86 return old + list.length; |
88 return old + list.length; | 87 }); |
89 }); | 88 Uint8List result = new Uint8List(totalLength); |
90 Uint8List result = new Uint8List(totalLength); | 89 int offset = 0; |
91 int offset = 0; | 90 for (List<int> contentPart in splitContent) { |
92 for (List<int> contentPart in splitContent) { | 91 result.setRange(offset, offset + contentPart.length, contentPart); |
93 result.setRange( | 92 offset += contentPart.length; |
94 offset, offset + contentPart.length, contentPart); | 93 } |
95 offset += contentPart.length; | 94 dartCharactersRead += totalLength; |
96 } | 95 sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile( |
97 dartCharactersRead += totalLength; | 96 resourceUri, resourceUri.toString(), result); |
98 sourceFiles[resourceUri] = | 97 return result; |
99 new CachingUtf8BytesSourceFile( | 98 }); |
100 resourceUri, resourceUri.toString(), result); | |
101 return result; | |
102 }); | |
103 } | 99 } |
104 | 100 |
105 // TODO(johnniwinther): Remove this when no longer needed for the old compiler | 101 // TODO(johnniwinther): Remove this when no longer needed for the old compiler |
106 // API. | 102 // API. |
107 Future/*<List<int> | String>*/ call(Uri resourceUri); | 103 Future/*<List<int> | String>*/ call(Uri resourceUri); |
108 | 104 |
109 relativizeUri(Uri uri) => relativize(cwd, uri, isWindows); | 105 relativizeUri(Uri uri) => relativize(cwd, uri, isWindows); |
110 | 106 |
111 SourceFile getSourceFile(Uri resourceUri) { | 107 SourceFile getSourceFile(Uri resourceUri) { |
112 return sourceFiles[resourceUri]; | 108 return sourceFiles[resourceUri]; |
(...skipping 20 matching lines...) Expand all Loading... |
133 int throwOnErrorCount = 0; | 129 int throwOnErrorCount = 0; |
134 api.Diagnostic lastKind = null; | 130 api.Diagnostic lastKind = null; |
135 int fatalCount = 0; | 131 int fatalCount = 0; |
136 | 132 |
137 final int FATAL = api.Diagnostic.CRASH.ordinal | api.Diagnostic.ERROR.ordinal; | 133 final int FATAL = api.Diagnostic.CRASH.ordinal | api.Diagnostic.ERROR.ordinal; |
138 final int INFO = | 134 final int INFO = |
139 api.Diagnostic.INFO.ordinal | api.Diagnostic.VERBOSE_INFO.ordinal; | 135 api.Diagnostic.INFO.ordinal | api.Diagnostic.VERBOSE_INFO.ordinal; |
140 | 136 |
141 FormattingDiagnosticHandler([SourceFileProvider provider]) | 137 FormattingDiagnosticHandler([SourceFileProvider provider]) |
142 : this.provider = | 138 : this.provider = |
143 (provider == null) ? new CompilerSourceFileProvider() : provider; | 139 (provider == null) ? new CompilerSourceFileProvider() : provider; |
144 | 140 |
145 void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) { | 141 void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) { |
146 if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return; | 142 if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return; |
147 if (enableColors) { | 143 if (enableColors) { |
148 print('${colors.green("Info:")} $message'); | 144 print('${colors.green("Info:")} $message'); |
149 } else { | 145 } else { |
150 print('Info: $message'); | 146 print('Info: $message'); |
151 } | 147 } |
152 } | 148 } |
153 | 149 |
(...skipping 10 matching lines...) Expand all Loading... |
164 return 'Internal Error: $message'; | 160 return 'Internal Error: $message'; |
165 case api.Diagnostic.INFO: | 161 case api.Diagnostic.INFO: |
166 case api.Diagnostic.VERBOSE_INFO: | 162 case api.Diagnostic.VERBOSE_INFO: |
167 return 'Info: $message'; | 163 return 'Info: $message'; |
168 } | 164 } |
169 throw 'Unexpected diagnostic kind: $kind (${kind.ordinal})'; | 165 throw 'Unexpected diagnostic kind: $kind (${kind.ordinal})'; |
170 } | 166 } |
171 | 167 |
172 @override | 168 @override |
173 void report(var code, Uri uri, int begin, int end, String message, | 169 void report(var code, Uri uri, int begin, int end, String message, |
174 api.Diagnostic kind) { | 170 api.Diagnostic kind) { |
175 // TODO(ahe): Remove this when source map is handled differently. | 171 // TODO(ahe): Remove this when source map is handled differently. |
176 if (identical(kind.name, 'source map')) return; | 172 if (identical(kind.name, 'source map')) return; |
177 | 173 |
178 if (isAborting) return; | 174 if (isAborting) return; |
179 isAborting = (kind == api.Diagnostic.CRASH); | 175 isAborting = (kind == api.Diagnostic.CRASH); |
180 | 176 |
181 bool fatal = (kind.ordinal & FATAL) != 0; | 177 bool fatal = (kind.ordinal & FATAL) != 0; |
182 bool isInfo = (kind.ordinal & INFO) != 0; | 178 bool isInfo = (kind.ordinal & INFO) != 0; |
183 if (isInfo && uri == null && kind != api.Diagnostic.INFO) { | 179 if (isInfo && uri == null && kind != api.Diagnostic.INFO) { |
184 info(message, kind); | 180 info(message, kind); |
(...skipping 27 matching lines...) Expand all Loading... |
212 throw 'Unknown kind: $kind (${kind.ordinal})'; | 208 throw 'Unknown kind: $kind (${kind.ordinal})'; |
213 } | 209 } |
214 if (!enableColors) { | 210 if (!enableColors) { |
215 color = (x) => x; | 211 color = (x) => x; |
216 } | 212 } |
217 if (uri == null) { | 213 if (uri == null) { |
218 print('${color(message)}'); | 214 print('${color(message)}'); |
219 } else { | 215 } else { |
220 SourceFile file = provider.sourceFiles[uri]; | 216 SourceFile file = provider.sourceFiles[uri]; |
221 if (file != null) { | 217 if (file != null) { |
222 print(file.getLocationMessage( | 218 print(file.getLocationMessage(color(message), begin, end, |
223 color(message), begin, end, colorize: color)); | 219 colorize: color)); |
224 } else { | 220 } else { |
225 String position = end - begin > 0 ? '@$begin+${end - begin}' : ''; | 221 String position = end - begin > 0 ? '@$begin+${end - begin}' : ''; |
226 print('${provider.relativizeUri(uri)}$position:\n' | 222 print('${provider.relativizeUri(uri)}$position:\n' |
227 '${color(message)}'); | 223 '${color(message)}'); |
228 } | 224 } |
229 } | 225 } |
230 if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) { | 226 if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) { |
231 isAborting = true; | 227 isAborting = true; |
232 throw new AbortLeg(message); | 228 throw new AbortLeg(message); |
233 } | 229 } |
234 } | 230 } |
235 | 231 |
236 // TODO(johnniwinther): Remove this when no longer needed for the old compiler | 232 // TODO(johnniwinther): Remove this when no longer needed for the old compiler |
237 // API. | 233 // API. |
238 void call(Uri uri, int begin, int end, String message, api.Diagnostic kind) { | 234 void call(Uri uri, int begin, int end, String message, api.Diagnostic kind) { |
239 return report(null, uri, begin, end, message, kind); | 235 return report(null, uri, begin, end, message, kind); |
240 } | 236 } |
241 } | 237 } |
242 | 238 |
243 typedef void MessageCallback(String message); | 239 typedef void MessageCallback(String message); |
244 | 240 |
245 class RandomAccessFileOutputProvider { | 241 class RandomAccessFileOutputProvider { |
246 final Uri out; | 242 final Uri out; |
247 final Uri sourceMapOut; | 243 final Uri sourceMapOut; |
248 final MessageCallback onInfo; | 244 final MessageCallback onInfo; |
249 final MessageCallback onFailure; | 245 final MessageCallback onFailure; |
250 | 246 |
251 int totalCharactersWritten = 0; | 247 int totalCharactersWritten = 0; |
252 List<String> allOutputFiles = new List<String>(); | 248 List<String> allOutputFiles = new List<String>(); |
253 | 249 |
254 RandomAccessFileOutputProvider(this.out, | 250 RandomAccessFileOutputProvider(this.out, this.sourceMapOut, |
255 this.sourceMapOut, | 251 {this.onInfo, this.onFailure}); |
256 {this.onInfo, | |
257 this.onFailure}); | |
258 | 252 |
259 static Uri computePrecompiledUri(Uri out) { | 253 static Uri computePrecompiledUri(Uri out) { |
260 String extension = 'precompiled.js'; | 254 String extension = 'precompiled.js'; |
261 String outPath = out.path; | 255 String outPath = out.path; |
262 if (outPath.endsWith('.js')) { | 256 if (outPath.endsWith('.js')) { |
263 outPath = outPath.substring(0, outPath.length - 3); | 257 outPath = outPath.substring(0, outPath.length - 3); |
264 return out.resolve('$outPath.$extension'); | 258 return out.resolve('$outPath.$extension'); |
265 } else { | 259 } else { |
266 return out.resolve(extension); | 260 return out.resolve(extension); |
267 } | 261 } |
268 } | 262 } |
269 | 263 |
270 EventSink<String> call(String name, String extension) { | 264 EventSink<String> call(String name, String extension) { |
271 Uri uri; | 265 Uri uri; |
272 bool isPrimaryOutput = false; | 266 bool isPrimaryOutput = false; |
273 // TODO (johnniwinther, sigurdm): Make a better interface for | 267 // TODO (johnniwinther, sigurdm): Make a better interface for |
274 // output-providers. | 268 // output-providers. |
275 if (extension == "deferred_map") { | 269 if (extension == "deferred_map") { |
276 uri = out.resolve(name); | 270 uri = out.resolve(name); |
277 } else if (name == '') { | 271 } else if (name == '') { |
278 if (extension == 'js' || extension == 'dart') { | 272 if (extension == 'js' || extension == 'dart') { |
279 isPrimaryOutput = true; | 273 isPrimaryOutput = true; |
280 uri = out; | 274 uri = out; |
281 } else if (extension == 'precompiled.js') { | 275 } else if (extension == 'precompiled.js') { |
282 uri = computePrecompiledUri(out); | 276 uri = computePrecompiledUri(out); |
283 onInfo("File ($uri) is compatible with header" | 277 onInfo("File ($uri) is compatible with header" |
284 " \"Content-Security-Policy: script-src 'self'\""); | 278 " \"Content-Security-Policy: script-src 'self'\""); |
285 } else if (extension == 'js.map' || extension == 'dart.map') { | 279 } else if (extension == 'js.map' || extension == 'dart.map') { |
286 uri = sourceMapOut; | 280 uri = sourceMapOut; |
287 } else if (extension == "info.json") { | 281 } else if (extension == "info.json") { |
288 String outName = out.path.substring(out.path.lastIndexOf('/') + 1); | 282 String outName = out.path.substring(out.path.lastIndexOf('/') + 1); |
289 uri = out.resolve('$outName.$extension'); | 283 uri = out.resolve('$outName.$extension'); |
290 } else { | 284 } else { |
291 onFailure('Unknown extension: $extension'); | 285 onFailure('Unknown extension: $extension'); |
292 } | 286 } |
293 } else { | 287 } else { |
294 uri = out.resolve('$name.$extension'); | 288 uri = out.resolve('$name.$extension'); |
295 } | 289 } |
296 | 290 |
297 if (uri.scheme != 'file') { | 291 if (uri.scheme != 'file') { |
298 onFailure('Unhandled scheme ${uri.scheme} in $uri.'); | 292 onFailure('Unhandled scheme ${uri.scheme} in $uri.'); |
299 } | 293 } |
300 | 294 |
301 RandomAccessFile output; | 295 RandomAccessFile output; |
302 try { | 296 try { |
303 output = new File(uri.toFilePath()).openSync(mode: FileMode.WRITE); | 297 output = new File(uri.toFilePath()).openSync(mode: FileMode.WRITE); |
304 } on FileSystemException catch(e) { | 298 } on FileSystemException catch (e) { |
305 onFailure('$e'); | 299 onFailure('$e'); |
306 } | 300 } |
307 | 301 |
308 allOutputFiles.add(relativize(currentDirectory, uri, Platform.isWindows)); | 302 allOutputFiles.add(relativize(currentDirectory, uri, Platform.isWindows)); |
309 | 303 |
310 int charactersWritten = 0; | 304 int charactersWritten = 0; |
311 | 305 |
312 writeStringSync(String data) { | 306 writeStringSync(String data) { |
313 // Write the data in chunks of 8kb, otherwise we risk running OOM. | 307 // Write the data in chunks of 8kb, otherwise we risk running OOM. |
314 int chunkSize = 8*1024; | 308 int chunkSize = 8 * 1024; |
315 | 309 |
316 int offset = 0; | 310 int offset = 0; |
317 while (offset < data.length) { | 311 while (offset < data.length) { |
318 output.writeStringSync( | 312 output.writeStringSync( |
319 data.substring(offset, math.min(offset + chunkSize, data.length))); | 313 data.substring(offset, math.min(offset + chunkSize, data.length))); |
320 offset += chunkSize; | 314 offset += chunkSize; |
321 } | 315 } |
322 charactersWritten += data.length; | 316 charactersWritten += data.length; |
323 } | 317 } |
324 | 318 |
(...skipping 12 matching lines...) Expand all Loading... |
337 var onAdd, onClose; | 331 var onAdd, onClose; |
338 | 332 |
339 EventSinkWrapper(this.onAdd, this.onClose); | 333 EventSinkWrapper(this.onAdd, this.onClose); |
340 | 334 |
341 void add(String data) => onAdd(data); | 335 void add(String data) => onAdd(data); |
342 | 336 |
343 void addError(error, [StackTrace stackTrace]) => throw error; | 337 void addError(error, [StackTrace stackTrace]) => throw error; |
344 | 338 |
345 void close() => onClose(); | 339 void close() => onClose(); |
346 } | 340 } |
OLD | NEW |