OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 leg_apiimpl; | 5 library leg_apiimpl; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; |
8 | 9 |
9 import '../compiler.dart' as api; | 10 import '../compiler.dart' as api; |
10 import 'dart2jslib.dart' as leg; | 11 import 'dart2jslib.dart' as leg; |
11 import 'tree/tree.dart' as tree; | 12 import 'tree/tree.dart' as tree; |
12 import 'elements/elements.dart' as elements; | 13 import 'elements/elements.dart' as elements; |
13 import 'package:_internal/libraries.dart' hide LIBRARIES; | 14 import 'package:_internal/libraries.dart' hide LIBRARIES; |
14 import 'package:_internal/libraries.dart' as library_info show LIBRARIES; | 15 import 'package:_internal/libraries.dart' as library_info show LIBRARIES; |
15 import 'io/source_file.dart'; | 16 import 'io/source_file.dart'; |
| 17 import 'package:package_config/packages.dart'; |
| 18 import 'package:package_config/packages_file.dart' as pkgs; |
| 19 import 'package:package_config/src/packages_impl.dart' |
| 20 show NonFilePackagesDirectoryPackages, MapPackages; |
| 21 import 'package:package_config/src/util.dart' show checkValidPackageUri; |
16 | 22 |
17 const bool forceIncrementalSupport = | 23 const bool forceIncrementalSupport = |
18 const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT'); | 24 const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT'); |
19 | 25 |
20 class Compiler extends leg.Compiler { | 26 class Compiler extends leg.Compiler { |
21 api.CompilerInputProvider provider; | 27 api.CompilerInputProvider provider; |
22 api.DiagnosticHandler handler; | 28 api.DiagnosticHandler handler; |
23 final Uri libraryRoot; | 29 final Uri libraryRoot; |
| 30 final Uri packageConfig; |
24 final Uri packageRoot; | 31 final Uri packageRoot; |
| 32 final api.PackagesDiscoveryProvider packagesDiscoveryProvider; |
| 33 Packages packages; |
25 List<String> options; | 34 List<String> options; |
26 Map<String, dynamic> environment; | 35 Map<String, dynamic> environment; |
27 bool mockableLibraryUsed = false; | 36 bool mockableLibraryUsed = false; |
28 final Set<String> allowedLibraryCategories; | 37 final Set<String> allowedLibraryCategories; |
29 | 38 |
30 leg.GenericTask userHandlerTask; | 39 leg.GenericTask userHandlerTask; |
31 leg.GenericTask userProviderTask; | 40 leg.GenericTask userProviderTask; |
| 41 leg.GenericTask userPackagesDiscoveryTask; |
32 | 42 |
33 Compiler(this.provider, | 43 Compiler(this.provider, |
34 api.CompilerOutputProvider outputProvider, | 44 api.CompilerOutputProvider outputProvider, |
35 this.handler, | 45 this.handler, |
36 this.libraryRoot, | 46 this.libraryRoot, |
37 this.packageRoot, | 47 this.packageRoot, |
38 List<String> options, | 48 List<String> options, |
39 this.environment) | 49 this.environment, |
| 50 [this.packageConfig, |
| 51 this.packagesDiscoveryProvider]) |
40 : this.options = options, | 52 : this.options = options, |
41 this.allowedLibraryCategories = getAllowedLibraryCategories(options), | 53 this.allowedLibraryCategories = getAllowedLibraryCategories(options), |
42 super( | 54 super( |
43 outputProvider: outputProvider, | 55 outputProvider: outputProvider, |
44 enableTypeAssertions: hasOption(options, '--enable-checked-mode'), | 56 enableTypeAssertions: hasOption(options, '--enable-checked-mode'), |
45 enableUserAssertions: hasOption(options, '--enable-checked-mode'), | 57 enableUserAssertions: hasOption(options, '--enable-checked-mode'), |
46 trustTypeAnnotations: | 58 trustTypeAnnotations: |
47 hasOption(options, '--trust-type-annotations'), | 59 hasOption(options, '--trust-type-annotations'), |
48 trustPrimitives: | 60 trustPrimitives: |
49 hasOption(options, '--trust-primitives'), | 61 hasOption(options, '--trust-primitives'), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 generateCodeWithCompileTimeErrors: | 101 generateCodeWithCompileTimeErrors: |
90 hasOption(options, '--generate-code-with-compile-time-errors'), | 102 hasOption(options, '--generate-code-with-compile-time-errors'), |
91 testMode: hasOption(options, '--test-mode'), | 103 testMode: hasOption(options, '--test-mode'), |
92 allowNativeExtensions: | 104 allowNativeExtensions: |
93 hasOption(options, '--allow-native-extensions'), | 105 hasOption(options, '--allow-native-extensions'), |
94 enableNullAwareOperators: | 106 enableNullAwareOperators: |
95 hasOption(options, '--enable-null-aware-operators')) { | 107 hasOption(options, '--enable-null-aware-operators')) { |
96 tasks.addAll([ | 108 tasks.addAll([ |
97 userHandlerTask = new leg.GenericTask('Diagnostic handler', this), | 109 userHandlerTask = new leg.GenericTask('Diagnostic handler', this), |
98 userProviderTask = new leg.GenericTask('Input provider', this), | 110 userProviderTask = new leg.GenericTask('Input provider', this), |
| 111 userPackagesDiscoveryTask = |
| 112 new leg.GenericTask('Package discovery', this), |
99 ]); | 113 ]); |
100 if (libraryRoot == null) { | 114 if (libraryRoot == null) { |
101 throw new ArgumentError("[libraryRoot] is null."); | 115 throw new ArgumentError("[libraryRoot] is null."); |
102 } | 116 } |
103 if (!libraryRoot.path.endsWith("/")) { | 117 if (!libraryRoot.path.endsWith("/")) { |
104 throw new ArgumentError("[libraryRoot] must end with a /."); | 118 throw new ArgumentError("[libraryRoot] must end with a /."); |
105 } | 119 } |
106 if (packageRoot == null) { | 120 if (packageRoot != null && packageConfig != null) { |
107 throw new ArgumentError("[packageRoot] is null."); | 121 throw new ArgumentError("Only one of [packageRoot] or [packageConfig] " |
| 122 "may be given."); |
108 } | 123 } |
109 if (!packageRoot.path.endsWith("/")) { | 124 if (packageRoot != null && !packageRoot.path.endsWith("/")) { |
110 throw new ArgumentError("[packageRoot] must end with a /."); | 125 throw new ArgumentError("[packageRoot] must end with a /."); |
111 } | 126 } |
112 if (!analyzeOnly) { | 127 if (!analyzeOnly) { |
113 if (allowNativeExtensions) { | 128 if (allowNativeExtensions) { |
114 throw new ArgumentError( | 129 throw new ArgumentError( |
115 "--allow-native-extensions is only supported in combination with " | 130 "--allow-native-extensions is only supported in combination with " |
116 "--analyze-only"); | 131 "--analyze-only"); |
117 } | 132 } |
118 } | 133 } |
119 } | 134 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 result.add('Internal'); | 168 result.add('Internal'); |
154 return new Set<String>.from(result); | 169 return new Set<String>.from(result); |
155 } | 170 } |
156 | 171 |
157 static bool hasOption(List<String> options, String option) { | 172 static bool hasOption(List<String> options, String option) { |
158 return options.indexOf(option) >= 0; | 173 return options.indexOf(option) >= 0; |
159 } | 174 } |
160 | 175 |
161 // TODO(johnniwinther): Merge better with [translateDartUri] when | 176 // TODO(johnniwinther): Merge better with [translateDartUri] when |
162 // [scanBuiltinLibrary] is removed. | 177 // [scanBuiltinLibrary] is removed. |
163 String lookupLibraryPath(String dartLibraryName) { | 178 String lookupLibraryPath(LibraryInfo info) { |
164 LibraryInfo info = lookupLibraryInfo(dartLibraryName); | |
165 if (info == null) return null; | 179 if (info == null) return null; |
166 if (!info.isDart2jsLibrary) return null; | 180 if (!info.isDart2jsLibrary) return null; |
167 if (!allowedLibraryCategories.contains(info.category)) return null; | 181 if (!allowedLibraryCategories.contains(info.category)) return null; |
168 String path = info.dart2jsPath; | 182 String path = info.dart2jsPath; |
169 if (path == null) { | 183 if (path == null) { |
170 path = info.path; | 184 path = info.path; |
171 } | 185 } |
172 return "lib/$path"; | 186 return "lib/$path"; |
173 } | 187 } |
174 | 188 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 withCurrentElement(element, () { | 232 withCurrentElement(element, () { |
219 reportError( | 233 reportError( |
220 node, | 234 node, |
221 leg.MessageKind.READ_SCRIPT_ERROR, | 235 leg.MessageKind.READ_SCRIPT_ERROR, |
222 {'uri': readableUri, 'exception': exception}); | 236 {'uri': readableUri, 'exception': exception}); |
223 }); | 237 }); |
224 } | 238 } |
225 } | 239 } |
226 | 240 |
227 Uri resourceUri = translateUri(node, readableUri); | 241 Uri resourceUri = translateUri(node, readableUri); |
| 242 if (resourceUri == null) return synthesizeScript(node, readableUri); |
228 if (resourceUri.scheme == 'dart-ext') { | 243 if (resourceUri.scheme == 'dart-ext') { |
229 if (!allowNativeExtensions) { | 244 if (!allowNativeExtensions) { |
230 withCurrentElement(element, () { | 245 withCurrentElement(element, () { |
231 reportError(node, leg.MessageKind.DART_EXT_NOT_SUPPORTED); | 246 reportError(node, leg.MessageKind.DART_EXT_NOT_SUPPORTED); |
232 }); | 247 }); |
233 } | 248 } |
234 return synthesizeScript(node, readableUri); | 249 return synthesizeScript(node, readableUri); |
235 } | 250 } |
236 | 251 |
237 // TODO(johnniwinther): Wrap the result from [provider] in a specialized | 252 // TODO(johnniwinther): Wrap the result from [provider] in a specialized |
(...skipping 15 matching lines...) Expand all Loading... |
253 // relative URIs mentioned in the script. See the comment on | 268 // relative URIs mentioned in the script. See the comment on |
254 // [LibraryLoader] for more details. | 269 // [LibraryLoader] for more details. |
255 return new leg.Script(readableUri, resourceUri, sourceFile); | 270 return new leg.Script(readableUri, resourceUri, sourceFile); |
256 }).catchError((error) { | 271 }).catchError((error) { |
257 reportReadError(error); | 272 reportReadError(error); |
258 return synthesizeScript(node, readableUri); | 273 return synthesizeScript(node, readableUri); |
259 }); | 274 }); |
260 } | 275 } |
261 | 276 |
262 Future<leg.Script> synthesizeScript(leg.Spannable node, Uri readableUri) { | 277 Future<leg.Script> synthesizeScript(leg.Spannable node, Uri readableUri) { |
263 Uri resourceUri = translateUri(node, readableUri); | |
264 return new Future.value( | 278 return new Future.value( |
265 new leg.Script( | 279 new leg.Script( |
266 readableUri, resourceUri, | 280 readableUri, readableUri, |
267 new StringSourceFile.fromUri( | 281 new StringSourceFile.fromUri( |
268 resourceUri, | 282 readableUri, |
269 "// Synthetic source file generated for '$readableUri'."), | 283 "// Synthetic source file generated for '$readableUri'."), |
270 isSynthesized: true)); | 284 isSynthesized: true)); |
271 } | 285 } |
272 | 286 |
273 /** | 287 /** |
274 * Translates a readable URI into a resource URI. | 288 * Translates a readable URI into a resource URI. |
275 * | 289 * |
276 * See [LibraryLoader] for terminology on URIs. | 290 * See [LibraryLoader] for terminology on URIs. |
277 */ | 291 */ |
278 Uri translateUri(leg.Spannable node, Uri readableUri) { | 292 Uri translateUri(leg.Spannable node, Uri readableUri) { |
279 switch (readableUri.scheme) { | 293 switch (readableUri.scheme) { |
280 case 'package': return translatePackageUri(node, readableUri); | 294 case 'package': return translatePackageUri(node, readableUri); |
281 default: return readableUri; | 295 default: return readableUri; |
282 } | 296 } |
283 } | 297 } |
284 | 298 |
285 Uri translateDartUri(elements.LibraryElement importingLibrary, | 299 Uri translateDartUri(elements.LibraryElement importingLibrary, |
286 Uri resolvedUri, tree.Node node) { | 300 Uri resolvedUri, tree.Node node) { |
287 LibraryInfo libraryInfo = lookupLibraryInfo(resolvedUri.path); | 301 LibraryInfo libraryInfo = lookupLibraryInfo(resolvedUri.path); |
288 String path = lookupLibraryPath(resolvedUri.path); | 302 String path = lookupLibraryPath(libraryInfo); |
289 if (libraryInfo != null && | 303 if (libraryInfo != null && |
290 libraryInfo.category == "Internal") { | 304 libraryInfo.category == "Internal") { |
291 bool allowInternalLibraryAccess = false; | 305 bool allowInternalLibraryAccess = false; |
292 if (importingLibrary != null) { | 306 if (importingLibrary != null) { |
293 if (importingLibrary.isPlatformLibrary || importingLibrary.isPatch) { | 307 if (importingLibrary.isPlatformLibrary || importingLibrary.isPatch) { |
294 allowInternalLibraryAccess = true; | 308 allowInternalLibraryAccess = true; |
295 } else if (importingLibrary.canonicalUri.path.contains( | 309 } else if (importingLibrary.canonicalUri.path.contains( |
296 'sdk/tests/compiler/dart2js_native')) { | 310 'sdk/tests/compiler/dart2js_native')) { |
297 allowInternalLibraryAccess = true; | 311 allowInternalLibraryAccess = true; |
298 } | 312 } |
(...skipping 27 matching lines...) Expand all Loading... |
326 return libraryRoot.resolve(path); | 340 return libraryRoot.resolve(path); |
327 } | 341 } |
328 | 342 |
329 Uri resolvePatchUri(String dartLibraryPath) { | 343 Uri resolvePatchUri(String dartLibraryPath) { |
330 String patchPath = lookupPatchPath(dartLibraryPath); | 344 String patchPath = lookupPatchPath(dartLibraryPath); |
331 if (patchPath == null) return null; | 345 if (patchPath == null) return null; |
332 return libraryRoot.resolve(patchPath); | 346 return libraryRoot.resolve(patchPath); |
333 } | 347 } |
334 | 348 |
335 Uri translatePackageUri(leg.Spannable node, Uri uri) { | 349 Uri translatePackageUri(leg.Spannable node, Uri uri) { |
336 return packageRoot.resolve(uri.path); | 350 try { |
| 351 checkValidPackageUri(uri); |
| 352 } on ArgumentError catch (e) { |
| 353 reportError( |
| 354 node, |
| 355 leg.MessageKind.INVALID_PACKAGE_URI, |
| 356 {'uri': uri, 'exception': e.message}); |
| 357 return null; |
| 358 } |
| 359 return packages.resolve(uri, |
| 360 notFound: (Uri notFound) { |
| 361 reportError( |
| 362 node, |
| 363 leg.MessageKind.LIBRARY_NOT_FOUND, |
| 364 {'resolvedUri': uri} |
| 365 ); |
| 366 return null; |
| 367 }); |
337 } | 368 } |
338 | 369 |
339 Future<bool> run(Uri uri) { | 370 Future setupPackages(Uri uri) async { |
| 371 if (packageRoot != null) { |
| 372 // Use "non-file" packages because the file version requires a [Directory] |
| 373 // and we can't depend on 'dart:io' classes. |
| 374 packages = new NonFilePackagesDirectoryPackages(packageRoot); |
| 375 } else if (packageConfig != null) { |
| 376 var packageConfigContents = await provider(packageConfig); |
| 377 if (packageConfigContents is String) { |
| 378 packageConfigContents = UTF8.encode(packageConfigContents); |
| 379 } |
| 380 packages = |
| 381 new MapPackages(pkgs.parse(packageConfigContents, packageConfig)); |
| 382 } else { |
| 383 if (packagesDiscoveryProvider == null) { |
| 384 packages = Packages.noPackages; |
| 385 } else { |
| 386 packages = await callUserPackagesDiscovery(uri); |
| 387 } |
| 388 } |
| 389 } |
| 390 |
| 391 Future<bool> run(Uri uri) async { |
340 log('Allowed library categories: $allowedLibraryCategories'); | 392 log('Allowed library categories: $allowedLibraryCategories'); |
341 return super.run(uri).then((bool success) { | 393 |
342 int cumulated = 0; | 394 await setupPackages(uri); |
343 for (final task in tasks) { | 395 assert(packages != null); |
344 int elapsed = task.timing; | 396 |
345 if (elapsed != 0) { | 397 bool success = await super.run(uri); |
346 cumulated += elapsed; | 398 int cumulated = 0; |
347 log('${task.name} took ${elapsed}msec'); | 399 for (final task in tasks) { |
348 } | 400 int elapsed = task.timing; |
| 401 if (elapsed != 0) { |
| 402 cumulated += elapsed; |
| 403 log('${task.name} took ${elapsed}msec'); |
349 } | 404 } |
350 int total = totalCompileTime.elapsedMilliseconds; | 405 } |
351 log('Total compile-time ${total}msec;' | 406 int total = totalCompileTime.elapsedMilliseconds; |
352 ' unaccounted ${total - cumulated}msec'); | 407 log('Total compile-time ${total}msec;' |
353 return success; | 408 ' unaccounted ${total - cumulated}msec'); |
354 }); | 409 return success; |
355 } | 410 } |
356 | 411 |
357 void reportDiagnostic(leg.Spannable node, | 412 void reportDiagnostic(leg.Spannable node, |
358 leg.Message message, | 413 leg.Message message, |
359 api.Diagnostic kind) { | 414 api.Diagnostic kind) { |
360 leg.SourceSpan span = spanFromSpannable(node); | 415 leg.SourceSpan span = spanFromSpannable(node); |
361 if (identical(kind, api.Diagnostic.ERROR) | 416 if (identical(kind, api.Diagnostic.ERROR) |
362 || identical(kind, api.Diagnostic.CRASH) | 417 || identical(kind, api.Diagnostic.CRASH) |
363 || (fatalWarnings && identical(kind, api.Diagnostic.WARNING))) { | 418 || (fatalWarnings && identical(kind, api.Diagnostic.WARNING))) { |
364 compilationFailed = true; | 419 compilationFailed = true; |
365 } | 420 } |
366 // [:span.uri:] might be [:null:] in case of a [Script] with no [uri]. For | 421 // [:span.uri:] might be [:null:] in case of a [Script] with no [uri]. For |
367 // instance in the [Types] constructor in typechecker.dart. | 422 // instance in the [Types] constructor in typechecker.dart. |
368 if (span == null || span.uri == null) { | 423 if (span == null || span.uri == null) { |
369 callUserHandler(null, null, null, '$message', kind); | 424 callUserHandler(null, null, null, '$message', kind); |
370 } else { | 425 } else { |
371 callUserHandler( | 426 callUserHandler(span.uri, span.begin, span.end, '$message', kind); |
372 translateUri(null, span.uri), span.begin, span.end, '$message', kind); | |
373 } | 427 } |
374 } | 428 } |
375 | 429 |
376 bool get isMockCompilation { | 430 bool get isMockCompilation { |
377 return mockableLibraryUsed | 431 return mockableLibraryUsed |
378 && (options.indexOf('--allow-mock-compilation') != -1); | 432 && (options.indexOf('--allow-mock-compilation') != -1); |
379 } | 433 } |
380 | 434 |
381 void callUserHandler(Uri uri, int begin, int end, | 435 void callUserHandler(Uri uri, int begin, int end, |
382 String message, api.Diagnostic kind) { | 436 String message, api.Diagnostic kind) { |
(...skipping 10 matching lines...) Expand all Loading... |
393 | 447 |
394 Future callUserProvider(Uri uri) { | 448 Future callUserProvider(Uri uri) { |
395 try { | 449 try { |
396 return userProviderTask.measure(() => provider(uri)); | 450 return userProviderTask.measure(() => provider(uri)); |
397 } catch (ex, s) { | 451 } catch (ex, s) { |
398 diagnoseCrashInUserCode('Uncaught exception in input provider', ex, s); | 452 diagnoseCrashInUserCode('Uncaught exception in input provider', ex, s); |
399 rethrow; | 453 rethrow; |
400 } | 454 } |
401 } | 455 } |
402 | 456 |
| 457 Future<Packages> callUserPackagesDiscovery(Uri uri) { |
| 458 try { |
| 459 return userPackagesDiscoveryTask.measure( |
| 460 () => packagesDiscoveryProvider(uri)); |
| 461 } catch (ex, s) { |
| 462 diagnoseCrashInUserCode('Uncaught exception in package discovery', ex, s); |
| 463 rethrow; |
| 464 } |
| 465 } |
| 466 |
403 void diagnoseCrashInUserCode(String message, exception, stackTrace) { | 467 void diagnoseCrashInUserCode(String message, exception, stackTrace) { |
404 hasCrashed = true; | 468 hasCrashed = true; |
405 print('$message: ${tryToString(exception)}'); | 469 print('$message: ${tryToString(exception)}'); |
406 print(tryToString(stackTrace)); | 470 print(tryToString(stackTrace)); |
407 } | 471 } |
408 | 472 |
409 fromEnvironment(String name) => environment[name]; | 473 fromEnvironment(String name) => environment[name]; |
410 | 474 |
411 LibraryInfo lookupLibraryInfo(String libraryName) { | 475 LibraryInfo lookupLibraryInfo(String libraryName) { |
412 return library_info.LIBRARIES[libraryName]; | 476 return library_info.LIBRARIES[libraryName]; |
413 } | 477 } |
414 } | 478 } |
OLD | NEW |