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 |