OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 library dart2js_incremental; | |
6 | |
7 import 'dart:async' show | |
8 EventSink, | |
9 Future; | |
10 | |
11 import 'dart:developer' show | |
12 UserTag; | |
13 | |
14 import 'package:compiler/src/apiimpl.dart' show | |
15 CompilerImpl; | |
16 | |
17 import 'package:compiler/compiler_new.dart' show | |
18 CompilerDiagnostics, | |
19 CompilerInput, | |
20 CompilerOutput, | |
21 Diagnostic; | |
22 | |
23 import 'package:compiler/src/options.dart' show | |
24 CompilerOptions; | |
25 | |
26 import 'package:compiler/src/null_compiler_output.dart' show | |
27 NullCompilerOutput; | |
28 | |
29 import 'package:compiler/src/js_backend/js_backend.dart' show | |
30 JavaScriptBackend; | |
31 | |
32 import 'package:compiler/src/js_emitter/full_emitter/emitter.dart' | |
33 as full show Emitter; | |
34 | |
35 import 'package:compiler/src/elements/elements.dart' show | |
36 LibraryElement; | |
37 | |
38 import 'library_updater.dart' show | |
39 IncrementalCompilerContext, | |
40 LibraryUpdater, | |
41 Logger; | |
42 | |
43 import 'package:compiler/src/js/js.dart' as jsAst; | |
44 | |
45 part 'caching_compiler.dart'; | |
46 | |
47 const List<String> INCREMENTAL_OPTIONS = const <String>[ | |
48 '--disable-type-inference', | |
49 '--incremental-support', | |
50 '--generate-code-with-compile-time-errors', | |
51 '--no-source-maps', // TODO(ahe): Remove this. | |
52 ]; | |
53 | |
54 class IncrementalCompiler { | |
55 final Uri libraryRoot; | |
56 final Uri packageRoot; | |
57 final Uri packageConfig; | |
58 final CompilerInput inputProvider; | |
59 final CompilerDiagnostics diagnosticHandler; | |
60 final List<String> options; | |
61 final CompilerOutput outputProvider; | |
62 final Map<String, dynamic> environment; | |
63 final List<String> _updates = <String>[]; | |
64 final IncrementalCompilerContext _context = new IncrementalCompilerContext(); | |
65 | |
66 CompilerImpl _compiler; | |
67 | |
68 IncrementalCompiler({ | |
69 this.libraryRoot, | |
70 this.packageRoot, | |
71 this.packageConfig, | |
72 this.inputProvider, | |
73 this.diagnosticHandler, | |
74 this.options, | |
75 this.outputProvider, | |
76 this.environment}) { | |
77 if (libraryRoot == null) { | |
78 throw new ArgumentError('libraryRoot is null.'); | |
79 } | |
80 if (inputProvider == null) { | |
81 throw new ArgumentError('inputProvider is null.'); | |
82 } | |
83 if (outputProvider == null) { | |
84 throw new ArgumentError('outputProvider is null.'); | |
85 } | |
86 if (diagnosticHandler == null) { | |
87 throw new ArgumentError('diagnosticHandler is null.'); | |
88 } | |
89 _context.incrementalCompiler = this; | |
90 } | |
91 | |
92 LibraryElement get mainApp => _compiler.mainApp; | |
93 | |
94 CompilerImpl get compiler => _compiler; | |
95 | |
96 Future<bool> compile(Uri script) { | |
97 return _reuseCompiler(null).then((CompilerImpl compiler) { | |
98 _compiler = compiler; | |
99 return compiler.run(script); | |
100 }); | |
101 } | |
102 | |
103 Future<CompilerImpl> _reuseCompiler( | |
104 Future<bool> reuseLibrary(LibraryElement library)) { | |
105 List<String> options = this.options == null | |
106 ? <String> [] : new List<String>.from(this.options); | |
107 options.addAll(INCREMENTAL_OPTIONS); | |
108 return reuseCompiler( | |
109 cachedCompiler: _compiler, | |
110 libraryRoot: libraryRoot, | |
111 packageRoot: packageRoot, | |
112 packageConfig: packageConfig, | |
113 inputProvider: inputProvider, | |
114 diagnosticHandler: diagnosticHandler, | |
115 options: options, | |
116 outputProvider: outputProvider, | |
117 environment: environment, | |
118 reuseLibrary: reuseLibrary); | |
119 } | |
120 | |
121 Future<String> compileUpdates( | |
122 Map<Uri, Uri> updatedFiles, | |
123 {Logger logTime, | |
124 Logger logVerbose}) { | |
125 if (logTime == null) { | |
126 logTime = (_) {}; | |
127 } | |
128 if (logVerbose == null) { | |
129 logVerbose = (_) {}; | |
130 } | |
131 Future mappingInputProvider(Uri uri) { | |
132 Uri updatedFile = updatedFiles[uri]; | |
133 return inputProvider.readFromUri(updatedFile == null ? uri : updatedFile); | |
134 } | |
135 LibraryUpdater updater = new LibraryUpdater( | |
136 _compiler, | |
137 mappingInputProvider, | |
138 logTime, | |
139 logVerbose, | |
140 _context); | |
141 _context.registerUriWithUpdates(updatedFiles.keys); | |
142 Future<CompilerImpl> future = _reuseCompiler(updater.reuseLibrary); | |
143 return future.then((CompilerImpl compiler) { | |
144 _compiler = compiler; | |
145 if (compiler.compilationFailed) { | |
146 return null; | |
147 } else { | |
148 String update = updater.computeUpdateJs(); | |
149 _updates.add(update); | |
150 return update; | |
151 } | |
152 }); | |
153 } | |
154 | |
155 String allUpdates() { | |
156 jsAst.Node updates = jsAst.js.escapedString(_updates.join("")); | |
157 | |
158 JavaScriptBackend backend = _compiler.backend; | |
159 | |
160 jsAst.FunctionDeclaration mainRunner = jsAst.js.statement(r""" | |
161 function dartMainRunner(main, args) { | |
162 #helper.patch(#updates + "\n//# sourceURL=initial_patch.js\n"); | |
163 return main(args); | |
164 }""", {'updates': updates, 'helper': backend.namer.accessIncrementalHelper}); | |
165 | |
166 return jsAst.prettyPrint(mainRunner, _compiler).getText(); | |
167 } | |
168 } | |
169 | |
170 class IncrementalCompilationFailed { | |
171 final String reason; | |
172 | |
173 const IncrementalCompilationFailed(this.reason); | |
174 | |
175 String toString() => "Can't incrementally compile program.\n\n$reason"; | |
176 } | |
OLD | NEW |