Chromium Code Reviews| 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * [CompilerTask] for loading libraries and setting up the import/export scopes. | 8 * [CompilerTask] for loading libraries and setting up the import/export scopes. |
| 9 * | |
| 10 * The library loader uses four different kinds of URIs in different parts of | |
| 11 * the loading process. | |
| 12 * | |
| 13 * ## User URI ## | |
| 14 * | |
| 15 * A 'user URI' is a URI provided by the user in code and as the main entry URI | |
| 16 * at the command line. These generally come in 3 versions: | |
| 17 * | |
| 18 * * A relative URI such as 'foo.dart', '../bar.dart', and 'baz/boz.dart'. | |
| 19 * | |
| 20 * * A dart URI such as 'dart:core' and 'dart:_js_helper'. | |
| 21 * | |
| 22 * * A package URI such as 'package:foo.dart' and 'package:bar/baz.dart'. | |
| 23 * | |
| 24 * A user URI can also be absolute, like 'file:///foo.dart' or | |
| 25 * 'http://example.com/bar.dart', but such URIs cannot necessarily be used for | |
| 26 * locating source files, since the scheme must be supported by the input | |
| 27 * provider. The standard input provider for dart2js only supports the 'file' | |
| 28 * scheme. | |
| 29 * | |
| 30 * ## Absolute URI ## | |
|
ahe
2013/01/24 10:00:57
I would call this "resolved".
Johnni Winther
2013/01/24 13:04:59
Done.
| |
| 31 * | |
| 32 * An 'absolute URI' is a (user) URI that has been resolved to an absolute URI | |
| 33 * based on the readable URI (see below) from which it was loaded. A URI with an | |
| 34 * explicit scheme (such as 'dart:', 'package:' or 'file:') is already absolute. | |
| 35 * A relative URI like for instance '../foo/bar.dart' is resolved into an | |
| 36 * absolute URI in one of three ways: | |
| 37 * | |
| 38 * * If provided as the main entry URI at the command line, the URI is resolved | |
| 39 * relative to the current working directory, say | |
| 40 * 'file:///current/working/dir/', and the absolute URI is therefore | |
| 41 * 'file:///current/working/foo/bar.dart'. | |
| 42 * | |
| 43 * * If the relative URI is provided in an import, export or part tag, and the | |
| 44 * readable URI of the enclosing compilation unit is a file URI, | |
| 45 * 'file://some/path/baz.dart', then the absolute URI is | |
| 46 * 'file://some/foo/bar.dart'. | |
| 47 * | |
| 48 * * If the relative URI is provided in an import, export or part tag, and the | |
| 49 * readable URI of the enclosing compilation unit is a package URI, | |
| 50 * 'package:some/path/baz.dart', then the absolute URI is | |
| 51 * 'package:some/foo/bar.dart'. | |
| 52 * | |
| 53 * The absolute URI thus preserves the scheme through resolution: A readable | |
| 54 * file URI results in an absolute file URI and a readable package URI results | |
| 55 * in an absolute package URI. Note that since a dart URI is not a readable URI, | |
| 56 * import, export or part tags within platform libraries are not interpreted as | |
| 57 * dart URIs but instead relative to the library source file location. | |
| 58 * | |
| 59 * The absolute URI of a library is also used as the canonical URI | |
| 60 * ([LibraryElement.canonicalUri]) by which we identify which libraries are | |
| 61 * identical. This means that libraries loaded through the 'package' scheme will | |
| 62 * resolve to the same library when loaded from within using relative URIs (see | |
| 63 * for instance the test 'standalone/package/package1_test.dart'). But loading a | |
| 64 * platform library using a relative URI will _not_ result in the same library | |
| 65 * as when loaded through the dart URI. | |
| 66 * | |
| 67 * ## Readable URI ## | |
|
ahe
2013/01/24 10:00:57
I don't understand why we need both "readable URIs
Johnni Winther
2013/01/24 13:04:59
Added a discussion of this.
| |
| 68 * | |
| 69 * A 'readable URI' is an absolute URI whose scheme is either 'package' or | |
| 70 * something supported by the input provider, normally 'file'. Dart URIs such as | |
| 71 * 'dart:core' and 'dart:_js_helper' are not readable themselves but are instead | |
| 72 * resolved into a readable URI using the library root URI provided from the | |
| 73 * command line and the list of platform libraries found in | |
| 74 * 'sdk/lib/_internal/libraries.dart'. This is done through the | |
| 75 * [Compiler.resolveAbsoluteUri] method which checks whether a library by that | |
| 76 * name exacts and in case of internal libraries whether access is granted. | |
|
ahe
2013/01/24 10:00:57
exacts -> exists
Johnni Winther
2013/01/24 13:04:59
Done.
| |
| 77 * | |
| 78 * ## Resource URI ## | |
| 79 * | |
| 80 * A 'resource URI' is an absolute URI with is scheme supported by the input | |
| 81 * provider. For the standard implementation this means a URI with the 'file' | |
| 82 * scheme. Readable URIs are converted into resource URIs as part of the | |
| 83 * [Compiler.readScript] method. In the standard implementation the package URIs | |
| 84 * are converted to file URIs using the package root URI provided on the | |
| 85 * command line as base. If the package root URI is | |
| 86 * 'file:///current/working/dir/' then the package URI 'package:../foo/bar.dart' | |
|
ahe
2013/01/24 10:00:57
This is a good example of something that shouldn't
Johnni Winther
2013/01/24 13:04:59
Changed the example since that was not crucial to
| |
| 87 * will be resolved to the resource URI 'file:///current/working/foo/bar.dart'. | |
| 88 * | |
| 9 */ | 89 */ |
| 10 abstract class LibraryLoader extends CompilerTask { | 90 abstract class LibraryLoader extends CompilerTask { |
| 11 LibraryLoader(Compiler compiler) : super(compiler); | 91 LibraryLoader(Compiler compiler) : super(compiler); |
| 12 | 92 |
| 13 /** | 93 /** |
| 14 * Loads the library located at [uri] and returns its [LibraryElement]. | 94 * Loads the library specified by the [absoluteUri] and returns its |
| 95 * [LibraryElement]. | |
| 15 * | 96 * |
| 16 * If the library is not already loaded, the method creates the | 97 * If the library is not already loaded, the method creates the |
| 17 * [LibraryElement] for the library and computes the import/export scope, | 98 * [LibraryElement] for the library and computes the import/export scope, |
| 18 * loading and computing the import/export scopes of all required libraries in | 99 * loading and computing the import/export scopes of all required libraries in |
| 19 * the process. The method handles cyclic dependency between libraries. | 100 * the process. The method handles cyclic dependency between libraries. |
| 20 * | 101 * |
| 21 * This is the main entry point for [LibraryLoader]. | 102 * This is the main entry point for [LibraryLoader]. |
| 22 */ | 103 */ |
| 23 LibraryElement loadLibrary(Uri uri, Node node, Uri canonicalUri); | 104 // TODO(johnniwinther): Remove [canonicalUri] together with |
| 105 // [Compiler.scanBuiltinLibrary]. | |
| 106 LibraryElement loadLibrary(Uri absoluteUri, Node node, Uri canonicalUri); | |
| 24 | 107 |
| 25 // TODO(johnniwinther): Remove this when patches don't need special parsing. | 108 // TODO(johnniwinther): Remove this when patches don't need special parsing. |
| 26 void registerLibraryFromTag(LibraryDependencyHandler handler, | 109 void registerLibraryFromTag(LibraryDependencyHandler handler, |
| 27 LibraryElement library, | 110 LibraryElement library, |
| 28 LibraryDependency tag); | 111 LibraryDependency tag); |
| 29 | 112 |
| 30 /** | 113 /** |
| 31 * Adds the elements in the export scope of [importedLibrary] to the import | 114 * Adds the elements in the export scope of [importedLibrary] to the import |
| 32 * scope of [importingLibrary]. | 115 * scope of [importingLibrary]. |
| 33 */ | 116 */ |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 */ | 209 */ |
| 127 class LibraryLoaderTask extends LibraryLoader { | 210 class LibraryLoaderTask extends LibraryLoader { |
| 128 LibraryLoaderTask(Compiler compiler) : super(compiler); | 211 LibraryLoaderTask(Compiler compiler) : super(compiler); |
| 129 String get name => 'LibraryLoader'; | 212 String get name => 'LibraryLoader'; |
| 130 | 213 |
| 131 final Map<String, LibraryElement> libraryNames = | 214 final Map<String, LibraryElement> libraryNames = |
| 132 new LinkedHashMap<String, LibraryElement>(); | 215 new LinkedHashMap<String, LibraryElement>(); |
| 133 | 216 |
| 134 LibraryDependencyHandler currentHandler; | 217 LibraryDependencyHandler currentHandler; |
| 135 | 218 |
| 136 LibraryElement loadLibrary(Uri uri, Node node, Uri canonicalUri) { | 219 LibraryElement loadLibrary(Uri absoluteUri, Node node, Uri canonicalUri) { |
| 137 return measure(() { | 220 return measure(() { |
| 138 assert(currentHandler == null); | 221 assert(currentHandler == null); |
| 139 currentHandler = new LibraryDependencyHandler(compiler); | 222 currentHandler = new LibraryDependencyHandler(compiler); |
| 140 LibraryElement library = | 223 LibraryElement library = |
| 141 createLibrary(currentHandler, uri, node, canonicalUri); | 224 createLibrary(currentHandler, null, absoluteUri, node, canonicalUri); |
| 142 currentHandler.computeExports(); | 225 currentHandler.computeExports(); |
| 143 currentHandler = null; | 226 currentHandler = null; |
| 144 return library; | 227 return library; |
| 145 }); | 228 }); |
| 146 } | 229 } |
| 147 | 230 |
| 148 /** | 231 /** |
| 149 * Processes the library tags in [library]. | 232 * Processes the library tags in [library]. |
| 150 * | 233 * |
| 151 * The imported/exported libraries are loaded and processed recursively but | 234 * The imported/exported libraries are loaded and processed recursively but |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 tagState = checkTag(TagState.LIBRARY, tag); | 269 tagState = checkTag(TagState.LIBRARY, tag); |
| 187 if (library.libraryTag != null) { | 270 if (library.libraryTag != null) { |
| 188 compiler.cancel("duplicated library declaration", node: tag); | 271 compiler.cancel("duplicated library declaration", node: tag); |
| 189 } else { | 272 } else { |
| 190 library.libraryTag = tag; | 273 library.libraryTag = tag; |
| 191 } | 274 } |
| 192 checkDuplicatedLibraryName(library); | 275 checkDuplicatedLibraryName(library); |
| 193 } else if (tag.isPart) { | 276 } else if (tag.isPart) { |
| 194 Part part = tag; | 277 Part part = tag; |
| 195 StringNode uri = part.uri; | 278 StringNode uri = part.uri; |
| 196 Uri resolved = base.resolve(uri.dartString.slowToString()); | 279 Uri absoluteUri = base.resolve(uri.dartString.slowToString()); |
| 197 tagState = checkTag(TagState.SOURCE, part); | 280 tagState = checkTag(TagState.SOURCE, part); |
| 198 scanPart(part, resolved, library); | 281 scanPart(part, absoluteUri, library); |
| 199 } else { | 282 } else { |
| 200 compiler.internalError("Unhandled library tag.", node: tag); | 283 compiler.internalError("Unhandled library tag.", node: tag); |
| 201 } | 284 } |
| 202 } | 285 } |
| 203 | 286 |
| 204 // Apply patch, if any. | 287 // Apply patch, if any. |
| 205 if (library.uri.scheme == 'dart') { | 288 if (library.isPlatformLibrary) { |
| 206 patchDartLibrary(handler, library, library.uri.path); | 289 patchDartLibrary(handler, library, library.canonicalUri.path); |
| 207 } | 290 } |
| 208 | 291 |
| 209 // Import dart:core if not already imported. | 292 // Import dart:core if not already imported. |
| 210 if (!importsDartCore && !isDartCore(library.uri)) { | 293 if (!importsDartCore && !isDartCore(library.canonicalUri)) { |
| 211 handler.registerDependency(library, null, loadCoreLibrary(handler)); | 294 handler.registerDependency(library, null, loadCoreLibrary(handler)); |
| 212 } | 295 } |
| 213 | 296 |
| 214 for (LibraryDependency tag in libraryDependencies.toLink()) { | 297 for (LibraryDependency tag in libraryDependencies.toLink()) { |
| 215 registerLibraryFromTag(handler, library, tag); | 298 registerLibraryFromTag(handler, library, tag); |
| 216 } | 299 } |
| 217 } | 300 } |
| 218 | 301 |
| 219 void checkDuplicatedLibraryName(LibraryElement library) { | 302 void checkDuplicatedLibraryName(LibraryElement library) { |
| 220 LibraryName tag = library.libraryTag; | 303 LibraryName tag = library.libraryTag; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 238 } | 321 } |
| 239 | 322 |
| 240 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core"; | 323 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core"; |
| 241 | 324 |
| 242 /** | 325 /** |
| 243 * Lazily loads and returns the [LibraryElement] for the dart:core library. | 326 * Lazily loads and returns the [LibraryElement] for the dart:core library. |
| 244 */ | 327 */ |
| 245 LibraryElement loadCoreLibrary(LibraryDependencyHandler handler) { | 328 LibraryElement loadCoreLibrary(LibraryDependencyHandler handler) { |
| 246 if (compiler.coreLibrary == null) { | 329 if (compiler.coreLibrary == null) { |
| 247 Uri coreUri = new Uri.fromComponents(scheme: 'dart', path: 'core'); | 330 Uri coreUri = new Uri.fromComponents(scheme: 'dart', path: 'core'); |
| 248 compiler.coreLibrary = createLibrary(handler, coreUri, null, coreUri); | 331 compiler.coreLibrary |
| 332 = createLibrary(handler, null, coreUri, null, coreUri); | |
| 249 } | 333 } |
| 250 return compiler.coreLibrary; | 334 return compiler.coreLibrary; |
| 251 } | 335 } |
| 252 | 336 |
| 253 void patchDartLibrary(LibraryDependencyHandler handler, | 337 void patchDartLibrary(LibraryDependencyHandler handler, |
| 254 LibraryElement library, String dartLibraryPath) { | 338 LibraryElement library, String dartLibraryPath) { |
| 255 if (library.isPatched) return; | 339 if (library.isPatched) return; |
| 256 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); | 340 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); |
| 257 if (patchUri != null) { | 341 if (patchUri != null) { |
| 258 compiler.patchParser.patchLibrary(handler, patchUri, library); | 342 compiler.patchParser.patchLibrary(handler, patchUri, library); |
| 259 } | 343 } |
| 260 } | 344 } |
| 261 | 345 |
| 262 /** | 346 /** |
| 263 * Handle a part tag in the scope of [library]. The [path] given is used as | 347 * Handle a part tag in the scope of [library]. The [absoluteUri] given is |
| 264 * is, any URI resolution should be done beforehand. | 348 * used as is, any URI resolution should be done beforehand. |
| 265 */ | 349 */ |
| 266 void scanPart(Part part, Uri path, LibraryElement library) { | 350 void scanPart(Part part, Uri absoluteUri, LibraryElement library) { |
| 267 if (!path.isAbsolute()) throw new ArgumentError(path); | 351 if (!absoluteUri.isAbsolute()) throw new ArgumentError(absoluteUri); |
| 268 Script sourceScript = compiler.readScript(path, part); | 352 Uri readableUri = compiler.resolveAbsoluteUri(library, absoluteUri, part); |
| 353 Script sourceScript = compiler.readScript(readableUri, part); | |
| 269 CompilationUnitElement unit = | 354 CompilationUnitElement unit = |
| 270 new CompilationUnitElementX(sourceScript, library); | 355 new CompilationUnitElementX(sourceScript, library); |
| 271 compiler.withCurrentElement(unit, () { | 356 compiler.withCurrentElement(unit, () { |
| 272 compiler.scanner.scan(unit); | 357 compiler.scanner.scan(unit); |
| 273 if (unit.partTag == null) { | 358 if (unit.partTag == null) { |
| 274 bool wasDiagnosticEmitted = false; | 359 bool wasDiagnosticEmitted = false; |
| 275 compiler.withCurrentElement(library, () { | 360 compiler.withCurrentElement(library, () { |
| 276 wasDiagnosticEmitted = | 361 wasDiagnosticEmitted = |
| 277 compiler.onDeprecatedFeature(part, 'missing part-of tag'); | 362 compiler.onDeprecatedFeature(part, 'missing part-of tag'); |
| 278 }); | 363 }); |
| 279 if (wasDiagnosticEmitted) { | 364 if (wasDiagnosticEmitted) { |
| 280 compiler.reportMessage( | 365 compiler.reportMessage( |
| 281 compiler.spanFromElement(unit), | 366 compiler.spanFromElement(unit), |
| 282 MessageKind.MISSING_PART_OF_TAG.error([]), | 367 MessageKind.MISSING_PART_OF_TAG.error([]), |
| 283 api.Diagnostic.INFO); | 368 api.Diagnostic.INFO); |
| 284 } | 369 } |
| 285 } | 370 } |
| 286 }); | 371 }); |
| 287 } | 372 } |
| 288 | 373 |
| 289 /** | 374 /** |
| 290 * Handle an import/export tag by loading the referenced library and | 375 * Handle an import/export tag by loading the referenced library and |
| 291 * registering its dependency in [handler] for the computation of the import/ | 376 * registering its dependency in [handler] for the computation of the import/ |
| 292 * export scope. | 377 * export scope. |
| 293 */ | 378 */ |
| 294 void registerLibraryFromTag(LibraryDependencyHandler handler, | 379 void registerLibraryFromTag(LibraryDependencyHandler handler, |
| 295 LibraryElement library, | 380 LibraryElement library, |
| 296 LibraryDependency tag) { | 381 LibraryDependency tag) { |
| 297 Uri base = library.entryCompilationUnit.script.uri; | 382 Uri base = library.entryCompilationUnit.script.uri; |
| 298 Uri resolved = base.resolve(tag.uri.dartString.slowToString()); | 383 Uri absoluteUri = base.resolve(tag.uri.dartString.slowToString()); |
| 299 LibraryElement loadedLibrary = | 384 LibraryElement loadedLibrary = |
| 300 createLibrary(handler, resolved, tag.uri, resolved); | 385 createLibrary(handler, library, absoluteUri, tag.uri, absoluteUri); |
| 301 handler.registerDependency(library, tag, loadedLibrary); | 386 handler.registerDependency(library, tag, loadedLibrary); |
| 302 | 387 |
| 303 if (!loadedLibrary.hasLibraryName()) { | 388 if (!loadedLibrary.hasLibraryName()) { |
| 304 compiler.withCurrentElement(library, () { | 389 compiler.withCurrentElement(library, () { |
| 305 compiler.reportError(tag == null ? null : tag.uri, | 390 compiler.reportError(tag == null ? null : tag.uri, |
| 306 'no library name found in ${loadedLibrary.uri}'); | 391 'no library name found in ${loadedLibrary.canonicalUri}'); |
| 307 }); | 392 }); |
| 308 } | 393 } |
| 309 } | 394 } |
| 310 | 395 |
| 311 /** | 396 /** |
| 312 * Create (or reuse) a library element for the library located at [uri]. | 397 * Create (or reuse) a library element for the library specified by the |
| 398 * [absoluteUri]. | |
| 399 * | |
| 313 * If a new library is created, the [handler] is notified. | 400 * If a new library is created, the [handler] is notified. |
| 314 */ | 401 */ |
| 402 // TODO(johnniwinther): Remove [canonicalUri] and make [absoluteUri] the | |
| 403 // canonical uri when [Compiler.scanBuiltinLibrary] is removed. | |
| 315 LibraryElement createLibrary(LibraryDependencyHandler handler, | 404 LibraryElement createLibrary(LibraryDependencyHandler handler, |
| 316 Uri uri, Node node, Uri canonicalUri) { | 405 LibraryElement importingLibrary, |
| 406 Uri absoluteUri, Node node, Uri canonicalUri) { | |
| 317 bool newLibrary = false; | 407 bool newLibrary = false; |
| 408 Uri readableUri = | |
| 409 compiler.resolveAbsoluteUri(importingLibrary, absoluteUri, node); | |
| 410 if (readableUri == null) return null; | |
| 318 LibraryElement createLibrary() { | 411 LibraryElement createLibrary() { |
| 319 newLibrary = true; | 412 newLibrary = true; |
| 320 Script script = compiler.readScript(uri, node); | 413 Script script = compiler.readScript(readableUri, node); |
| 321 LibraryElement element = new LibraryElementX(script, canonicalUri); | 414 LibraryElement element = new LibraryElementX(script, canonicalUri); |
| 322 handler.registerNewLibrary(element); | 415 handler.registerNewLibrary(element); |
| 323 native.maybeEnableNative(compiler, element, uri); | 416 native.maybeEnableNative(compiler, element); |
| 324 return element; | 417 return element; |
| 325 } | 418 } |
| 326 LibraryElement library; | 419 LibraryElement library; |
| 327 if (canonicalUri == null) { | 420 if (canonicalUri == null) { |
| 328 library = createLibrary(); | 421 library = createLibrary(); |
| 329 } else { | 422 } else { |
| 330 library = compiler.libraries.putIfAbsent(canonicalUri.toString(), | 423 library = compiler.libraries.putIfAbsent(canonicalUri.toString(), |
| 331 createLibrary); | 424 createLibrary); |
| 332 } | 425 } |
| 333 if (newLibrary) { | 426 if (newLibrary) { |
| 334 compiler.withCurrentElement(library, () { | 427 compiler.withCurrentElement(library, () { |
| 335 compiler.scanner.scanLibrary(library); | 428 compiler.scanner.scanLibrary(library); |
| 336 processLibraryTags(handler, library); | 429 processLibraryTags(handler, library); |
| 337 handler.registerLibraryExports(library); | 430 handler.registerLibraryExports(library); |
| 338 compiler.onLibraryScanned(library, uri); | 431 compiler.onLibraryScanned(library, absoluteUri); |
| 339 }); | 432 }); |
| 340 } | 433 } |
| 341 return library; | 434 return library; |
| 342 } | 435 } |
| 343 | 436 |
| 344 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by | 437 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by |
| 345 // [LibraryLoaderTask]. | 438 // [LibraryLoaderTask]. |
| 346 void importLibrary(LibraryElement importingLibrary, | 439 void importLibrary(LibraryElement importingLibrary, |
| 347 LibraryElement importedLibrary, | 440 LibraryElement importedLibrary, |
| 348 Import tag) { | 441 Import tag) { |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 } | 818 } |
| 726 | 819 |
| 727 /** | 820 /** |
| 728 * Registers all top-level entities of [library] as starting point for the | 821 * Registers all top-level entities of [library] as starting point for the |
| 729 * fixed-point computation of the import/export scopes. | 822 * fixed-point computation of the import/export scopes. |
| 730 */ | 823 */ |
| 731 void registerLibraryExports(LibraryElement library) { | 824 void registerLibraryExports(LibraryElement library) { |
| 732 nodeMap[library].registerInitialExports(); | 825 nodeMap[library].registerInitialExports(); |
| 733 } | 826 } |
| 734 } | 827 } |
| OLD | NEW |