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 import 'dart:convert'; |
9 | 9 |
10 import 'package:package_config/packages.dart'; | 10 import 'package:package_config/packages.dart'; |
11 import 'package:package_config/packages_file.dart' as pkgs; | 11 import 'package:package_config/packages_file.dart' as pkgs; |
12 import 'package:package_config/src/packages_impl.dart' | 12 import 'package:package_config/src/packages_impl.dart' |
13 show MapPackages, NonFilePackagesDirectoryPackages; | 13 show MapPackages, NonFilePackagesDirectoryPackages; |
14 import 'package:package_config/src/util.dart' show checkValidPackageUri; | 14 import 'package:package_config/src/util.dart' show checkValidPackageUri; |
15 | 15 |
16 import '../compiler_new.dart' as api; | 16 import '../compiler_new.dart' as api; |
| 17 import 'common/tasks.dart' show GenericTask; |
17 import 'common.dart'; | 18 import 'common.dart'; |
18 import 'common/tasks.dart' show GenericTask; | |
19 import 'compiler.dart'; | 19 import 'compiler.dart'; |
20 import 'diagnostics/messages.dart' show Message; | 20 import 'diagnostics/messages.dart' show Message; |
21 import 'elements/elements.dart' as elements; | 21 import 'elements/elements.dart' as elements; |
22 import 'environment.dart'; | 22 import 'environment.dart'; |
23 import 'io/source_file.dart'; | 23 import 'io/source_file.dart'; |
24 import 'options.dart' show CompilerOptions; | 24 import 'options.dart' show CompilerOptions; |
25 import 'platform_configuration.dart' as platform_configuration; | 25 import 'platform_configuration.dart' as platform_configuration; |
| 26 import 'resolved_uri_translator.dart'; |
26 import 'script.dart'; | 27 import 'script.dart'; |
27 | 28 |
28 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the | 29 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the |
29 /// sources. | 30 /// sources. |
30 class CompilerImpl extends Compiler { | 31 class CompilerImpl extends Compiler { |
31 api.CompilerInput provider; | 32 api.CompilerInput provider; |
32 api.CompilerDiagnostics handler; | 33 api.CompilerDiagnostics handler; |
33 Packages packages; | 34 Packages packages; |
34 bool mockableLibraryUsed = false; | |
35 | 35 |
36 /// A mapping of the dart: library-names to their location. | 36 bool get mockableLibraryUsed => resolvedUriTranslator.isSet |
37 /// | 37 ? resolvedUriTranslator.mockableLibraryUsed |
38 /// Initialized in [setupSdk]. | 38 : false; |
39 Map<String, Uri> sdkLibraries; | 39 |
| 40 ForwardingResolvedUriTranslator resolvedUriTranslator; |
40 | 41 |
41 GenericTask userHandlerTask; | 42 GenericTask userHandlerTask; |
42 GenericTask userProviderTask; | 43 GenericTask userProviderTask; |
43 GenericTask userPackagesDiscoveryTask; | 44 GenericTask userPackagesDiscoveryTask; |
44 | 45 |
45 Uri get libraryRoot => options.platformConfigUri.resolve("."); | 46 Uri get libraryRoot => options.platformConfigUri.resolve("."); |
46 | 47 |
47 CompilerImpl(this.provider, api.CompilerOutput outputProvider, this.handler, | 48 CompilerImpl(this.provider, api.CompilerOutput outputProvider, this.handler, |
48 CompilerOptions options) | 49 CompilerOptions options) |
49 : super( | 50 : resolvedUriTranslator = new ForwardingResolvedUriTranslator(), |
| 51 super( |
50 options: options, | 52 options: options, |
51 outputProvider: outputProvider, | 53 outputProvider: outputProvider, |
52 environment: new _Environment(options.environment)) { | 54 environment: new _Environment(options.environment)) { |
53 _Environment env = environment; | 55 _Environment env = environment; |
54 env.compiler = this; | 56 env.compiler = this; |
55 tasks.addAll([ | 57 tasks.addAll([ |
56 userHandlerTask = new GenericTask('Diagnostic handler', this), | 58 userHandlerTask = new GenericTask('Diagnostic handler', this), |
57 userProviderTask = new GenericTask('Input provider', this), | 59 userProviderTask = new GenericTask('Input provider', this), |
58 userPackagesDiscoveryTask = new GenericTask('Package discovery', this), | 60 userPackagesDiscoveryTask = new GenericTask('Package discovery', this), |
59 ]); | 61 ]); |
60 } | 62 } |
61 | 63 |
62 void log(message) { | 64 void log(message) { |
63 callUserHandler( | 65 callUserHandler( |
64 null, null, null, null, message, api.Diagnostic.VERBOSE_INFO); | 66 null, null, null, null, message, api.Diagnostic.VERBOSE_INFO); |
65 } | 67 } |
66 | 68 |
67 /// See [Compiler.translateResolvedUri]. | |
68 Uri translateResolvedUri(elements.LibraryElement importingLibrary, | |
69 Uri resolvedUri, Spannable spannable) { | |
70 if (resolvedUri.scheme == 'dart') { | |
71 return translateDartUri(importingLibrary, resolvedUri, spannable); | |
72 } | |
73 return resolvedUri; | |
74 } | |
75 | |
76 /** | 69 /** |
77 * Reads the script designated by [readableUri]. | 70 * Reads the script designated by [readableUri]. |
78 */ | 71 */ |
79 Future<Script> readScript(Uri readableUri, [Spannable node]) { | 72 Future<Script> readScript(Uri readableUri, [Spannable node]) { |
80 if (!readableUri.isAbsolute) { | 73 if (!readableUri.isAbsolute) { |
81 if (node == null) node = NO_LOCATION_SPANNABLE; | 74 if (node == null) node = NO_LOCATION_SPANNABLE; |
82 reporter.internalError( | 75 reporter.internalError( |
83 node, 'Relative uri $readableUri provided to readScript(Uri).'); | 76 node, 'Relative uri $readableUri provided to readScript(Uri).'); |
84 } | 77 } |
85 | 78 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 } | 135 } |
143 | 136 |
144 /** | 137 /** |
145 * Translates a readable URI into a resource URI. | 138 * Translates a readable URI into a resource URI. |
146 * | 139 * |
147 * See [LibraryLoader] for terminology on URIs. | 140 * See [LibraryLoader] for terminology on URIs. |
148 */ | 141 */ |
149 Uri translateUri(Spannable node, Uri uri) => | 142 Uri translateUri(Spannable node, Uri uri) => |
150 uri.scheme == 'package' ? translatePackageUri(node, uri) : uri; | 143 uri.scheme == 'package' ? translatePackageUri(node, uri) : uri; |
151 | 144 |
152 /// Translates "resolvedUri" with scheme "dart" to a [uri] resolved relative | |
153 /// to `options.platformConfigUri` according to the information in the file at | |
154 /// `options.platformConfigUri`. | |
155 /// | |
156 /// Returns null and emits an error if the library could not be found or | |
157 /// imported into [importingLibrary]. | |
158 /// | |
159 /// Internal libraries (whose name starts with '_') can be only resolved if | |
160 /// [importingLibrary] is a platform or patch library. | |
161 Uri translateDartUri(elements.LibraryElement importingLibrary, | |
162 Uri resolvedUri, Spannable spannable) { | |
163 Uri location = lookupLibraryUri(resolvedUri.path); | |
164 | |
165 if (location == null) { | |
166 reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_FOUND, | |
167 {'resolvedUri': resolvedUri}); | |
168 return null; | |
169 } | |
170 | |
171 if (resolvedUri.path.startsWith('_')) { | |
172 bool allowInternalLibraryAccess = importingLibrary != null && | |
173 (importingLibrary.isPlatformLibrary || | |
174 importingLibrary.isPatch || | |
175 importingLibrary.canonicalUri.path | |
176 .contains('sdk/tests/compiler/dart2js_native')); | |
177 | |
178 if (!allowInternalLibraryAccess) { | |
179 if (importingLibrary != null) { | |
180 reporter.reportErrorMessage( | |
181 spannable, MessageKind.INTERNAL_LIBRARY_FROM, { | |
182 'resolvedUri': resolvedUri, | |
183 'importingUri': importingLibrary.canonicalUri | |
184 }); | |
185 } else { | |
186 reporter.reportErrorMessage(spannable, MessageKind.INTERNAL_LIBRARY, | |
187 {'resolvedUri': resolvedUri}); | |
188 registerDisallowedLibraryUse(resolvedUri); | |
189 } | |
190 return null; | |
191 } | |
192 } | |
193 | |
194 if (location.scheme == "unsupported") { | |
195 reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_SUPPORTED, | |
196 {'resolvedUri': resolvedUri}); | |
197 registerDisallowedLibraryUse(resolvedUri); | |
198 return null; | |
199 } | |
200 | |
201 if (resolvedUri.path == 'html' || resolvedUri.path == 'io') { | |
202 // TODO(ahe): Get rid of mockableLibraryUsed when test.dart | |
203 // supports this use case better. | |
204 mockableLibraryUsed = true; | |
205 } | |
206 return location; | |
207 } | |
208 | |
209 Uri translatePackageUri(Spannable node, Uri uri) { | 145 Uri translatePackageUri(Spannable node, Uri uri) { |
210 try { | 146 try { |
211 checkValidPackageUri(uri); | 147 checkValidPackageUri(uri); |
212 } on ArgumentError catch (e) { | 148 } on ArgumentError catch (e) { |
213 reporter.reportErrorMessage(node, MessageKind.INVALID_PACKAGE_URI, | 149 reporter.reportErrorMessage(node, MessageKind.INVALID_PACKAGE_URI, |
214 {'uri': uri, 'exception': e.message}); | 150 {'uri': uri, 'exception': e.message}); |
215 return null; | 151 return null; |
216 } | 152 } |
217 return packages.resolve(uri, notFound: (Uri notFound) { | 153 return packages.resolve(uri, notFound: (Uri notFound) { |
218 reporter.reportErrorMessage( | 154 reporter.reportErrorMessage( |
219 node, MessageKind.LIBRARY_NOT_FOUND, {'resolvedUri': uri}); | 155 node, MessageKind.LIBRARY_NOT_FOUND, {'resolvedUri': uri}); |
220 return null; | 156 return null; |
221 }); | 157 }); |
222 } | 158 } |
223 | 159 |
224 Future<elements.LibraryElement> analyzeUri(Uri uri, | 160 Future<elements.LibraryElement> analyzeUri(Uri uri, |
225 {bool skipLibraryWithPartOfTag: true}) { | 161 {bool skipLibraryWithPartOfTag: true}) { |
226 List<Future> setupFutures = new List<Future>(); | 162 List<Future> setupFutures = new List<Future>(); |
227 if (sdkLibraries == null) { | 163 if (resolvedUriTranslator.isNotSet) { |
228 setupFutures.add(setupSdk()); | 164 setupFutures.add(setupSdk()); |
229 } | 165 } |
230 if (packages == null) { | 166 if (packages == null) { |
231 setupFutures.add(setupPackages(uri)); | 167 setupFutures.add(setupPackages(uri)); |
232 } | 168 } |
233 return Future.wait(setupFutures).then((_) { | 169 return Future.wait(setupFutures).then((_) { |
234 return super | 170 return super |
235 .analyzeUri(uri, skipLibraryWithPartOfTag: skipLibraryWithPartOfTag); | 171 .analyzeUri(uri, skipLibraryWithPartOfTag: skipLibraryWithPartOfTag); |
236 }); | 172 }); |
237 } | 173 } |
(...skipping 28 matching lines...) Expand all Loading... |
266 } else { | 202 } else { |
267 return callUserPackagesDiscovery(uri).then((p) { | 203 return callUserPackagesDiscovery(uri).then((p) { |
268 packages = p; | 204 packages = p; |
269 }); | 205 }); |
270 } | 206 } |
271 } | 207 } |
272 return new Future.value(); | 208 return new Future.value(); |
273 } | 209 } |
274 | 210 |
275 Future<Null> setupSdk() { | 211 Future<Null> setupSdk() { |
276 if (sdkLibraries == null) { | 212 if (resolvedUriTranslator.isNotSet) { |
277 return platform_configuration | 213 return platform_configuration |
278 .load(options.platformConfigUri, provider) | 214 .load(options.platformConfigUri, provider) |
279 .then((Map<String, Uri> mapping) { | 215 .then((Map<String, Uri> mapping) { |
280 sdkLibraries = mapping; | 216 resolvedUriTranslator.resolvedUriTranslator = |
| 217 new ResolvedUriTranslator(mapping, reporter); |
281 }); | 218 }); |
282 } else { | 219 } else { |
283 // The incremental compiler sets up the sdk before run. | 220 // The incremental compiler sets up the sdk before run. |
284 // Therefore this will be called a second time. | 221 // Therefore this will be called a second time. |
285 return new Future.value(null); | 222 return new Future.value(null); |
286 } | 223 } |
287 } | 224 } |
288 | 225 |
289 Future<bool> run(Uri uri) { | 226 Future<bool> run(Uri uri) { |
290 log('Using platform configuration at ${options.platformConfigUri}'); | 227 log('Using platform configuration at ${options.platformConfigUri}'); |
291 | 228 |
292 return Future.wait([setupSdk(), setupPackages(uri)]).then((_) { | 229 return Future.wait([setupSdk(), setupPackages(uri)]).then((_) { |
293 assert(sdkLibraries != null); | 230 assert(resolvedUriTranslator.isSet); |
294 assert(packages != null); | 231 assert(packages != null); |
295 | 232 |
296 return super.run(uri).then((bool success) { | 233 return super.run(uri).then((bool success) { |
297 int cumulated = 0; | 234 int cumulated = 0; |
298 for (final task in tasks) { | 235 for (final task in tasks) { |
299 int elapsed = task.timing; | 236 int elapsed = task.timing; |
300 if (elapsed != 0) { | 237 if (elapsed != 0) { |
301 cumulated += elapsed; | 238 cumulated += elapsed; |
302 log('${task.name} took ${elapsed}msec'); | 239 log('${task.name} took ${elapsed}msec'); |
303 for (String subtask in task.subtasks) { | 240 for (String subtask in task.subtasks) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 | 285 |
349 Future callUserProvider(Uri uri) { | 286 Future callUserProvider(Uri uri) { |
350 return userProviderTask.measure(() => provider.readFromUri(uri)); | 287 return userProviderTask.measure(() => provider.readFromUri(uri)); |
351 } | 288 } |
352 | 289 |
353 Future<Packages> callUserPackagesDiscovery(Uri uri) { | 290 Future<Packages> callUserPackagesDiscovery(Uri uri) { |
354 return userPackagesDiscoveryTask | 291 return userPackagesDiscoveryTask |
355 .measure(() => options.packagesDiscoveryProvider(uri)); | 292 .measure(() => options.packagesDiscoveryProvider(uri)); |
356 } | 293 } |
357 | 294 |
358 Uri lookupLibraryUri(String libraryName) { | |
359 assert(invariant(NO_LOCATION_SPANNABLE, sdkLibraries != null, | |
360 message: "setupSdk() has not been run")); | |
361 return sdkLibraries[libraryName]; | |
362 } | |
363 | |
364 Uri resolvePatchUri(String libraryName) { | 295 Uri resolvePatchUri(String libraryName) { |
365 return backend.resolvePatchUri(libraryName, options.platformConfigUri); | 296 return backend.resolvePatchUri(libraryName, options.platformConfigUri); |
366 } | 297 } |
367 } | 298 } |
368 | 299 |
369 class _Environment implements Environment { | 300 class _Environment implements Environment { |
370 final Map<String, String> definitions; | 301 final Map<String, String> definitions; |
371 | 302 |
372 // TODO(sigmund): break the circularity here: Compiler needs an environment to | 303 // TODO(sigmund): break the circularity here: Compiler needs an environment to |
373 // intialize the library loader, but the environment here needs to know about | 304 // initialize the library loader, but the environment here needs to know about |
374 // how the sdk is set up and about whether the backend supports mirrors. | 305 // how the sdk is set up and about whether the backend supports mirrors. |
375 CompilerImpl compiler; | 306 CompilerImpl compiler; |
376 | 307 |
377 _Environment(this.definitions); | 308 _Environment(this.definitions); |
378 | 309 |
379 String valueOf(String name) { | 310 String valueOf(String name) { |
380 assert(invariant(NO_LOCATION_SPANNABLE, compiler.sdkLibraries != null, | 311 assert(invariant( |
| 312 NO_LOCATION_SPANNABLE, compiler.resolvedUriTranslator != null, |
381 message: "setupSdk() has not been run")); | 313 message: "setupSdk() has not been run")); |
382 | 314 |
383 var result = definitions[name]; | 315 var result = definitions[name]; |
384 if (result != null || definitions.containsKey(name)) return result; | 316 if (result != null || definitions.containsKey(name)) return result; |
385 if (!name.startsWith(_dartLibraryEnvironmentPrefix)) return null; | 317 if (!name.startsWith(_dartLibraryEnvironmentPrefix)) return null; |
386 | 318 |
387 String libraryName = name.substring(_dartLibraryEnvironmentPrefix.length); | 319 String libraryName = name.substring(_dartLibraryEnvironmentPrefix.length); |
388 | 320 |
389 // Private libraries are not exposed to the users. | 321 // Private libraries are not exposed to the users. |
390 if (libraryName.startsWith("_")) return null; | 322 if (libraryName.startsWith("_")) return null; |
391 | 323 |
392 if (compiler.sdkLibraries.containsKey(libraryName)) { | 324 if (compiler.resolvedUriTranslator.sdkLibraries.containsKey(libraryName)) { |
393 // Dart2js always "supports" importing 'dart:mirrors' but will abort | 325 // Dart2js always "supports" importing 'dart:mirrors' but will abort |
394 // the compilation at a later point if the backend doesn't support | 326 // the compilation at a later point if the backend doesn't support |
395 // mirrors. In this case 'mirrors' should not be in the environment. | 327 // mirrors. In this case 'mirrors' should not be in the environment. |
396 if (libraryName == 'mirrors') { | 328 if (libraryName == 'mirrors') { |
397 return compiler.backend.supportsReflection ? "true" : null; | 329 return compiler.backend.supportsReflection ? "true" : null; |
398 } | 330 } |
399 return "true"; | 331 return "true"; |
400 } | 332 } |
401 return null; | 333 return null; |
402 } | 334 } |
403 } | 335 } |
404 | 336 |
405 /// For every 'dart:' library, a corresponding environment variable is set | 337 /// For every 'dart:' library, a corresponding environment variable is set |
406 /// to "true". The environment variable's name is the concatenation of | 338 /// to "true". The environment variable's name is the concatenation of |
407 /// this prefix and the name (without the 'dart:'. | 339 /// this prefix and the name (without the 'dart:'. |
408 /// | 340 /// |
409 /// For example 'dart:html' has the environment variable 'dart.library.html' set | 341 /// For example 'dart:html' has the environment variable 'dart.library.html' set |
410 /// to "true". | 342 /// to "true". |
411 const String _dartLibraryEnvironmentPrefix = 'dart.library.'; | 343 const String _dartLibraryEnvironmentPrefix = 'dart.library.'; |
OLD | NEW |