Chromium Code Reviews| Index: lib/src/compiler.dart |
| diff --git a/lib/src/compiler.dart b/lib/src/compiler.dart |
| index e7af8f7f37b394537c560af6d83790f81a1c0622..0907c70c5362d33996bfce91de4faa938baa4a9e 100644 |
| --- a/lib/src/compiler.dart |
| +++ b/lib/src/compiler.dart |
| @@ -48,6 +48,8 @@ StreamSubscription setupLogger(Level level, printFn) { |
| class BatchCompiler extends AbstractCompiler { |
| JSGenerator _jsGen; |
| + LibraryElement _dartCore; |
| + String _runtimeOutputDir; |
| /// Already compiled sources, so we don't compile them again. |
| final _compiled = new HashSet<LibraryElement>(); |
| @@ -58,9 +60,12 @@ class BatchCompiler extends AbstractCompiler { |
| BatchCompiler(AnalysisContext context, CompilerOptions options, |
| {AnalysisErrorListener reporter}) |
| : super(context, options, reporter) { |
| + _inputBaseDir = options.inputBaseDir; |
| if (outputDir != null) { |
| _jsGen = new JSGenerator(this); |
| + _runtimeOutputDir = path.join(outputDir, 'dev_compiler', 'runtime'); |
| } |
| + _dartCore = context.typeProvider.objectType.element.library; |
| } |
| void reset() { |
| @@ -80,31 +85,39 @@ class BatchCompiler extends AbstractCompiler { |
| } |
| void compileFromUriString(String uriString) { |
| - compileFromUri(stringToUri(uriString)); |
| + _compileFromUri(stringToUri(uriString)); |
| } |
| - void compileFromUri(Uri uri) { |
| + void _compileFromUri(Uri uri) { |
| + if (!uri.isAbsolute) { |
| + throw new ArgumentError.value('$uri', 'uri', 'must be absolute'); |
| + } |
| var source = context.sourceFactory.forUri(Uri.encodeFull('$uri')); |
| - if (source == null) throw new ArgumentError.value( |
| - uri.toString(), 'uri', 'could not find source for'); |
| + if (source == null) { |
| + throw new ArgumentError.value('$uri', 'uri', 'could not find source for'); |
| + } |
| compileSource(source); |
| } |
| void compileSource(Source source) { |
| if (AnalysisEngine.isHtmlFileName(source.uri.path)) { |
| - compileHtml(source); |
| + _compileHtml(source); |
| return; |
| } |
| - |
| compileLibrary(context.computeLibraryElement(source)); |
| } |
| void compileLibrary(LibraryElement library) { |
| if (!_compiled.add(library)) return; |
| - if (!options.checkSdk && library.source.uri.scheme == 'dart') return; |
| + |
| + if (!options.checkSdk && library.source.uri.scheme == 'dart') { |
| + if (_jsGen != null) _copyDartRuntime(); |
| + return; |
| + } |
| // TODO(jmesserly): in incremental mode, we can skip the transitive |
| // compile of imports/exports. |
| + compileLibrary(_dartCore); // implicit dart:core dependency |
| library.importedLibraries.forEach(compileLibrary); |
| library.exportedLibraries.forEach(compileLibrary); |
| @@ -114,6 +127,15 @@ class BatchCompiler extends AbstractCompiler { |
| bool failureInLib = false; |
| for (var element in unitElements) { |
| var unit = context.resolveCompilationUnit(element.source, library); |
| + |
| + // TODO(jmesserly): this hack is to avoid compiling the same compilation |
| + // unit to JS twice. We mutate the AST, so it's not safe to run more than |
| + // once on the same unit. |
| + if (element.library == library) { |
| + if (unit.getProperty(_propertyName) == true) return; |
| + unit.setProperty(_propertyName, true); |
| + } |
| + |
| units.add(unit); |
| failureInLib = logErrors(element.source) || failureInLib; |
| checker.visitCompilationUnit(unit); |
| @@ -129,19 +151,22 @@ class BatchCompiler extends AbstractCompiler { |
| var unit = units.first; |
| var parts = units.skip(1).toList(); |
| - // TODO(jmesserly): this hack is to avoid compiling the same compilation |
| - // unit to JS twice. We mutate the AST, so it's not safe to run more than |
| - // once on the same unit. |
| - if (unit.getProperty(_propertyName) == true) return; |
| - unit.setProperty(_propertyName, true); |
| - |
| _jsGen.generateLibrary(new LibraryUnit(unit, parts)); |
| } |
| } |
| static const String _propertyName = 'dev_compiler.BatchCompiler.isCompiled'; |
|
vsm
2015/07/23 16:42:45
Perhaps rename _propertyName to _isCompiled?
Jennifer Messerly
2015/07/23 16:50:35
_propertyName is gone after I rebase against maste
|
| - void compileHtml(Source source) { |
| + void _copyDartRuntime() { |
| + for (var file in defaultRuntimeFiles) { |
| + var input = path.join(options.runtimeDir, file); |
| + var output = path.join(_runtimeOutputDir, file); |
| + new Directory(path.dirname(output)).createSync(recursive: true); |
| + new File(input).copySync(output); |
| + } |
| + } |
| + |
| + void _compileHtml(Source source) { |
| // TODO(jmesserly): reuse DartScriptsTask instead of copy/paste. |
| var contents = context.getContents(source); |
| var document = html.parse(contents.data, generateSpans: true); |
| @@ -149,6 +174,7 @@ class BatchCompiler extends AbstractCompiler { |
| var loadedLibs = new LinkedHashSet<Uri>(); |
| + var htmlOutDir = path.dirname(getOutputPath(source.uri)); |
| for (var script in scripts) { |
| Source scriptSource = null; |
| var srcAttr = script.attributes['src']; |
| @@ -171,19 +197,10 @@ class BatchCompiler extends AbstractCompiler { |
| if (scriptSource != null) { |
| var lib = context.computeLibraryElement(scriptSource); |
| compileLibrary(lib); |
| - script.replaceWith(_linkLibraries(lib, loadedLibs)); |
| + script.replaceWith(_linkLibraries(lib, loadedLibs, from: htmlOutDir)); |
| } |
| } |
| - // TODO(jmesserly): we need to clean this up so we aren't treating these |
| - // as a special case. |
| - for (var file in defaultRuntimeFiles) { |
| - var input = path.join(options.runtimeDir, file); |
| - var output = path.join(outputDir, runtimeFileOutput(file)); |
| - new Directory(path.dirname(output)).createSync(recursive: true); |
| - new File(input).copySync(output); |
| - } |
| - |
| new File(getOutputPath(source.uri)).openSync(mode: FileMode.WRITE) |
| ..writeStringSync(document.outerHtml) |
| ..writeStringSync('\n') |
| @@ -191,19 +208,30 @@ class BatchCompiler extends AbstractCompiler { |
| } |
| html.DocumentFragment _linkLibraries( |
| - LibraryElement mainLib, LinkedHashSet<Uri> loaded) { |
| + LibraryElement mainLib, LinkedHashSet<Uri> loaded, {String from}) { |
| + assert(from != null); |
| var alreadyLoaded = loaded.length; |
| _collectLibraries(mainLib, loaded); |
| var newLibs = loaded.skip(alreadyLoaded); |
| var df = new html.DocumentFragment(); |
| - for (var path in defaultRuntimeFiles) { |
| - df.append(html_codegen.libraryInclude(runtimeFileOutput(path))); |
| - } |
| + |
| for (var uri in newLibs) { |
| - if (uri.scheme == 'dart') continue; |
| - df.append(html_codegen.libraryInclude(getModulePath(uri))); |
| + if (uri.scheme == 'dart') { |
| + if (uri.path == 'core') { |
| + // TODO(jmesserly): it would be nice to not special case these. |
| + for (var file in defaultRuntimeFiles) { |
|
vsm
2015/07/23 16:42:45
Will this pick up dart:mirrors? I think core does
Jennifer Messerly
2015/07/23 16:50:35
dart:mirrors depends on dart:core, so we always hi
|
| + file = path.join(_runtimeOutputDir, file); |
| + df.append( |
| + html_codegen.libraryInclude(path.relative(file, from: from))); |
| + } |
| + } |
| + } else { |
| + var file = path.join(outputDir, getModulePath(uri)); |
| + df.append(html_codegen.libraryInclude(path.relative(file, from: from))); |
| + } |
| } |
| + |
| df.append(html_codegen.invokeMain(getModuleName(mainLib.source.uri))); |
| return df; |
| } |
| @@ -211,15 +239,13 @@ class BatchCompiler extends AbstractCompiler { |
| void _collectLibraries(LibraryElement lib, LinkedHashSet<Uri> loaded) { |
| var uri = lib.source.uri; |
| if (!loaded.add(uri)) return; |
| + _collectLibraries(_dartCore, loaded); |
| for (var l in lib.importedLibraries) _collectLibraries(l, loaded); |
| for (var l in lib.exportedLibraries) _collectLibraries(l, loaded); |
| // Move the item to the end of the list. |
| loaded.remove(uri); |
| loaded.add(uri); |
| } |
| - |
| - String runtimeFileOutput(String file) => |
| - path.join('dev_compiler', 'runtime', file); |
| } |
| abstract class AbstractCompiler { |
| @@ -249,7 +275,7 @@ abstract class AbstractCompiler { |
| Uri stringToUri(String uriString) { |
| var uri = uriString.startsWith('dart:') || uriString.startsWith('package:') |
| ? Uri.parse(uriString) |
| - : new Uri.file(uriString); |
| + : new Uri.file(path.absolute(uriString)); |
| return uri; |
| } |
| @@ -313,15 +339,15 @@ abstract class AbstractCompiler { |
| String getModuleName(Uri uri) { |
| var filepath = path.withoutExtension(uri.path); |
| if (uri.scheme == 'dart') { |
| - filepath = 'dart/$filepath'; |
| + return 'dart/$filepath'; |
| } else if (uri.scheme == 'file') { |
| - filepath = path.relative(filepath, from: inputBaseDir); |
| + return path.relative(filepath, from: inputBaseDir); |
| } else { |
| assert(uri.scheme == 'package'); |
| // filepath is good here, we want the output to start with a directory |
| // matching the package name. |
| + return filepath; |
| } |
| - return filepath; |
| } |
| /// Log any errors encountered when resolving [source] and return whether any |