| Index: pkg/dev_compiler/web/web_command.dart
|
| diff --git a/pkg/dev_compiler/web/web_command.dart b/pkg/dev_compiler/web/web_command.dart
|
| index 5f6514a9b789711f31bc79a99c4919d4e2dfd3c9..68b216a7ddb01eb71f9c96ac9432e6d73ec33653 100644
|
| --- a/pkg/dev_compiler/web/web_command.dart
|
| +++ b/pkg/dev_compiler/web/web_command.dart
|
| @@ -5,9 +5,15 @@
|
| library dev_compiler.web.web_command;
|
|
|
| import 'dart:async';
|
| +import 'dart:convert';
|
| import 'dart:html' show HttpRequest;
|
| -import 'dart:convert' show BASE64;
|
|
|
| +import 'package:analyzer/dart/element/element.dart'
|
| + show
|
| + LibraryElement,
|
| + ImportElement,
|
| + ShowElementCombinator,
|
| + HideElementCombinator;
|
| import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver;
|
| import 'package:analyzer/file_system/memory_file_system.dart'
|
| show MemoryResourceProvider;
|
| @@ -20,6 +26,7 @@ import 'package:analyzer/src/summary/package_bundle_reader.dart'
|
| InSummaryUriResolver,
|
| InputPackagesResultProvider,
|
| InSummarySource;
|
| +import 'package:analyzer/src/dart/resolver/scope.dart' show Scope;
|
| import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
|
|
|
| import 'package:args/command_runner.dart';
|
| @@ -30,6 +37,7 @@ import 'package:dev_compiler/src/compiler/compiler.dart'
|
|
|
| import 'package:dev_compiler/src/compiler/module_builder.dart';
|
| import 'package:js/js.dart';
|
| +import 'package:path/path.dart' as path;
|
|
|
| typedef void MessageHandler(Object message);
|
|
|
| @@ -40,8 +48,8 @@ class CompileResult {
|
| {String code, List<String> errors, bool isValid});
|
| }
|
|
|
| -typedef CompileResult CompileModule(
|
| - String code, String libraryName, String fileName);
|
| +typedef CompileModule(String imports, String body, String libraryName,
|
| + String existingLibrary, String fileName);
|
|
|
| /// The command for invoking the modular compiler.
|
| class WebCompileCommand extends Command {
|
| @@ -102,7 +110,8 @@ class WebCompileCommand extends Command {
|
| var summaryBundle = new PackageBundle.fromBuffer(bytes);
|
| summaryDataStore.addBundle(url, summaryBundle);
|
| }
|
| - var summaryResolver = new InSummaryUriResolver(resourceProvider, summaryDataStore);
|
| + var summaryResolver =
|
| + new InSummaryUriResolver(resourceProvider, summaryDataStore);
|
|
|
| var fileResolvers = [summaryResolver, resourceUriResolver];
|
|
|
| @@ -112,24 +121,85 @@ class WebCompileCommand extends Command {
|
| fileResolvers: fileResolvers,
|
| resourceProvider: resourceProvider);
|
|
|
| - (compiler.context as AnalysisContextImpl).resultProvider =
|
| + var context = compiler.context as AnalysisContextImpl;
|
| + context.resultProvider =
|
| new InputPackagesResultProvider(compiler.context, summaryDataStore);
|
|
|
| var compilerOptions = new CompilerOptions.fromArguments(argResults);
|
|
|
| - CompileModule compileFn =
|
| - (String sourceCode, String libraryName, String fileName) {
|
| + CompileModule compileFn = (String imports, String body, String libraryName,
|
| + String existingLibrary, String fileName) {
|
| // Create a new virtual File that contains the given Dart source.
|
| - resourceProvider.newFile("/$fileName", sourceCode);
|
| + String sourceCode;
|
| + if (existingLibrary == null) {
|
| + sourceCode = imports + body;
|
| + } else {
|
| + var dir = path.dirname(existingLibrary);
|
| + // Need to pull in all the imports from the existing library and
|
| + // re-export all privates as privates in this library.
|
| + var source = context.sourceFactory.forUri(existingLibrary);
|
| + if (source == null) {
|
| + throw "Unable to load source for library $existingLibrary";
|
| + }
|
| +
|
| + LibraryElement libraryElement = context.computeLibraryElement(source);
|
| + if (libraryElement == null) {
|
| + throw "Unable to get library element.";
|
| + }
|
| + var sb = new StringBuffer(imports);
|
| + sb.write('\n');
|
| +
|
| + // TODO(jacobr): we need to add a proper Analyzer flag specifing that
|
| + // cross-library privates should be in scope instead of this hack.
|
| + // We set the private name prefix for scope resolution to an invalid
|
| + // character code so that the analyzer ignores normal Dart private
|
| + // scoping rules for top level names allowing REPL users to access
|
| + // privates in arbitrary libraries. The downside of this scheme is it is
|
| + // possible to get errors if privates in the current library and
|
| + // imported libraries happen to have exactly the same name.
|
| + Scope.PRIVATE_NAME_PREFIX = -1;
|
| +
|
| + // We emulate running code in the context of an existing library by
|
| + // importing that library and all libraries it imports.
|
| + sb.write('import ${JSON.encode(existingLibrary)};\n');
|
| +
|
| + for (ImportElement importElement in libraryElement.imports) {
|
| + if (importElement.uri == null) continue;
|
| + var uri = importElement.uri;
|
| + // dart: and package: uris are not relative but the path package
|
| + // thinks they are. We have to provide absolute uris as our library
|
| + // has a different directory than the library we are pretending to be.
|
| + if (path.isRelative(uri) &&
|
| + !uri.startsWith('package:') &&
|
| + !uri.startsWith('dart:')) {
|
| + uri = path.normalize(path.join(dir, uri));
|
| + }
|
| + sb.write('import ${JSON.encode(uri)}');
|
| + if (importElement.prefix != null)
|
| + sb.write(' as ${importElement.prefix.name}');
|
| + for (var combinator in importElement.combinators) {
|
| + if (combinator is ShowElementCombinator) {
|
| + sb.write(' show ${combinator.shownNames.join(', ')}');
|
| + } else if (combinator is HideElementCombinator) {
|
| + sb.write(' hide ${combinator.hiddenNames.join(', ')}');
|
| + } else {
|
| + throw 'Unexpected element combinator';
|
| + }
|
| + }
|
| + sb.write(';\n');
|
| + }
|
| + sb.write(body);
|
| + sourceCode = sb.toString();
|
| + }
|
| + resourceProvider.newFile(fileName, sourceCode);
|
|
|
| - var unit = new BuildUnit(
|
| - libraryName, "", ["file:///$fileName"], _moduleForLibrary);
|
| + var unit = new BuildUnit(libraryName, "", [fileName], _moduleForLibrary);
|
|
|
| JSModuleFile module = compiler.compile(unit, compilerOptions);
|
|
|
| var moduleCode = module.isValid
|
| ? module
|
| - .getCode(ModuleFormat.legacy, false, unit.name, unit.name + '.map')
|
| + .getCode(ModuleFormat.legacy, true, unit.name, unit.name + '.map')
|
| .code
|
| : '';
|
|
|
|
|