Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(733)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart2js.dart

Issue 80793002: Check compiler exitCode. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 dart2js.cmdline; 5 library dart2js.cmdline;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io' 8 import 'dart:io'
9 show exit, File, FileMode, Platform, RandomAccessFile; 9 show exit, File, FileMode, Platform, RandomAccessFile;
10 import 'dart:math' as math; 10 import 'dart:math' as math;
(...skipping 27 matching lines...) Expand all
38 typedef void HandleOption(data); 38 typedef void HandleOption(data);
39 39
40 class OptionHandler { 40 class OptionHandler {
41 final String pattern; 41 final String pattern;
42 final HandleOption handle; 42 final HandleOption handle;
43 final bool multipleArguments; 43 final bool multipleArguments;
44 44
45 OptionHandler(this.pattern, this.handle, {this.multipleArguments: false}); 45 OptionHandler(this.pattern, this.handle, {this.multipleArguments: false});
46 } 46 }
47 47
48 /** 48 class _Dart2Js {
ahe 2013/11/21 12:44:53 If you think it makes sense to create a class here
49 * Extract the parameter of an option. 49 final exitFunc;
50 * 50 final compileFunc;
51 * For example, in ['--out=fisk.js'] and ['-ohest.js'], the parameters 51
52 * are ['fisk.js'] and ['hest.js'], respectively. 52 _Dart2Js(this.exitFunc, this.compileFunc);
53 */ 53
54 String extractParameter(String argument) { 54 /**
55 // m[0] is the entire match (which will be equal to argument). m[1] 55 * Extract the parameter of an option.
56 // is something like "-o" or "--out=", and m[2] is the parameter. 56 *
57 Match m = new RegExp('^(-[a-z]|--.+=)(.*)').firstMatch(argument); 57 * For example, in ['--out=fisk.js'] and ['-ohest.js'], the parameters
58 if (m == null) helpAndFail('Error: Unknown option "$argument".'); 58 * are ['fisk.js'] and ['hest.js'], respectively.
59 return m[2]; 59 */
60 String extractParameter(String argument) {
61 // m[0] is the entire match (which will be equal to argument). m[1]
62 // is something like "-o" or "--out=", and m[2] is the parameter.
63 Match m = new RegExp('^(-[a-z]|--.+=)(.*)').firstMatch(argument);
64 if (m == null) helpAndFail('Error: Unknown option "$argument".');
65 return m[2];
66 }
67
68 String extractPath(String argument) {
69 String path = nativeToUriPath(extractParameter(argument));
70 return path.endsWith("/") ? path : "$path/";
71 }
72
73 void parseCommandLine(List<OptionHandler> handlers, List<String> argv) {
74 // TODO(ahe): Use ../../args/args.dart for parsing options instead.
75 var patterns = <String>[];
76 for (OptionHandler handler in handlers) {
77 patterns.add(handler.pattern);
78 }
79 var pattern = new RegExp('^(${patterns.join(")\$|(")})\$');
80
81 Iterator<String> arguments = argv.iterator;
82 OUTER: while (arguments.moveNext()) {
83 String argument = arguments.current;
84 Match match = pattern.firstMatch(argument);
85 assert(match.groupCount == handlers.length);
86 for (int i = 0; i < handlers.length; i++) {
87 if (match[i + 1] != null) {
88 OptionHandler handler = handlers[i];
89 if (handler.multipleArguments) {
90 handler.handle(arguments);
91 } else {
92 handler.handle(argument);
93 }
94 continue OUTER;
95 }
96 }
97 throw 'Internal error: "$argument" did not match';
98 }
99 }
100
101 FormattingDiagnosticHandler diagnosticHandler;
102
103 Future compile(List<String> argv) {
104 bool isWindows = (Platform.operatingSystem == 'windows');
105 stackTraceFilePrefix = '$currentDirectory';
106 Uri libraryRoot = currentDirectory;
107 Uri out = currentDirectory.resolve('out.js');
108 Uri sourceMapOut = currentDirectory.resolve('out.js.map');
109 Uri packageRoot = null;
110 List<String> options = new List<String>();
111 bool explicitOut = false;
112 bool wantHelp = false;
113 bool wantVersion = false;
114 String outputLanguage = 'JavaScript';
115 bool stripArgumentSet = false;
116 bool analyzeOnly = false;
117 bool hasDisallowUnsafeEval = false;
118 // TODO(johnniwinther): Measure time for reading files.
119 SourceFileProvider inputProvider = new CompilerSourceFileProvider();
120 diagnosticHandler = new FormattingDiagnosticHandler(inputProvider);
121 Map<String, dynamic> environment = new Map<String, dynamic>();
122
123 passThrough(String argument) => options.add(argument);
124
125 if (BUILD_ID != null) {
126 passThrough("--build-id=$BUILD_ID");
127 }
128
129 setLibraryRoot(String argument) {
130 libraryRoot = currentDirectory.resolve(extractPath(argument));
131 }
132
133 setPackageRoot(String argument) {
134 packageRoot = currentDirectory.resolve(extractPath(argument));
135 }
136
137 setOutput(Iterator<String> arguments) {
138 String path;
139 if (arguments.current == '-o') {
140 if (!arguments.moveNext()) {
141 helpAndFail('Error: Missing file after -o option.');
142 }
143 path = arguments.current;
144 } else {
145 path = extractParameter(arguments.current);
146 }
147 explicitOut = true;
148 out = currentDirectory.resolve(nativeToUriPath(path));
149 sourceMapOut = Uri.parse('$out.map');
150 }
151
152 setOutputType(String argument) {
153 if (argument == '--output-type=dart') {
154 outputLanguage = OUTPUT_LANGUAGE_DART;
155 if (!explicitOut) {
156 out = currentDirectory.resolve('out.dart');
157 sourceMapOut = currentDirectory.resolve('out.dart.map');
158 }
159 }
160 passThrough(argument);
161 }
162
163 String getDepsOutput(Map<String, SourceFile> sourceFiles) {
164 var filenames = new List.from(sourceFiles.keys);
165 filenames.sort();
166 return filenames.join("\n");
167 }
168
169 setStrip(String argument) {
170 stripArgumentSet = true;
171 passThrough(argument);
172 }
173
174 setAnalyzeOnly(String argument) {
175 analyzeOnly = true;
176 passThrough(argument);
177 }
178
179 setVerbose(_) {
180 diagnosticHandler.verbose = true;
181 passThrough('--verbose');
182 }
183
184 addInEnvironment(String argument) {
185 int eqIndex = argument.indexOf('=');
186 String name = argument.substring(2, eqIndex);
187 String value = argument.substring(eqIndex + 1);
188 environment[name] = value;
189 }
190
191 setCategories(String argument) {
192 List<String> categories = extractParameter(argument).split(',');
193 Set<String> allowedCategories =
194 LIBRARIES.values.map((x) => x.category).toSet();
195 allowedCategories.remove('Shared');
196 allowedCategories.remove('Internal');
197 List<String> allowedCategoriesList =
198 new List<String>.from(allowedCategories);
199 allowedCategoriesList.sort();
200 if (categories.contains('all')) {
201 categories = allowedCategoriesList;
202 } else {
203 String allowedCategoriesString = allowedCategoriesList.join(', ');
204 for (String category in categories) {
205 if (!allowedCategories.contains(category)) {
206 fail('Error: unsupported library category "$category", '
207 'supported categories are: $allowedCategoriesString');
208 }
209 }
210 }
211 passThrough('--categories=${categories.join(",")}');
212 }
213
214 checkGlobalName(String argument) {
215 String globalName = extractParameter(argument);
216 if (!new RegExp(r'^\$[a-z]*$').hasMatch(globalName)) {
217 fail('Error: "$globalName" must match "\\\$[a-z]*"');
218 }
219 passThrough(argument);
220 }
221
222 handleShortOptions(String argument) {
223 var shortOptions = argument.substring(1).split("");
224 for (var shortOption in shortOptions) {
225 switch (shortOption) {
226 case 'v':
227 setVerbose(null);
228 break;
229 case 'h':
230 case '?':
231 wantHelp = true;
232 break;
233 case 'c':
234 passThrough('--enable-checked-mode');
235 break;
236 default:
237 throw 'Internal error: "$shortOption" did not match';
238 }
239 }
240 }
241
242 Uri computePrecompiledUri() {
243 String extension = 'precompiled.js';
244 String outPath = out.path;
245 if (outPath.endsWith('.js')) {
246 outPath = outPath.substring(0, outPath.length - 3);
247 return out.resolve('$outPath.$extension');
248 } else {
249 return out.resolve(extension);
250 }
251 }
252
253 List<String> arguments = <String>[];
254 List<OptionHandler> handlers = <OptionHandler>[
255 new OptionHandler('-[chv?]+', handleShortOptions),
256 new OptionHandler('--throw-on-error',
257 (_) => diagnosticHandler.throwOnError = true),
258 new OptionHandler('--suppress-warnings',
259 (_) => diagnosticHandler.showWarnings = false),
260 new OptionHandler('--suppress-hints',
261 (_) => diagnosticHandler.showHints = false),
262 new OptionHandler('--output-type=dart|--output-type=js', setOutputType),
263 new OptionHandler('--verbose', setVerbose),
264 new OptionHandler('--version', (_) => wantVersion = true),
265 new OptionHandler('--library-root=.+', setLibraryRoot),
266 new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
267 new OptionHandler('--allow-mock-compilation', passThrough),
268 new OptionHandler('--minify', passThrough),
269 new OptionHandler('--force-strip=.*', setStrip),
270 new OptionHandler('--disable-diagnostic-colors',
271 (_) => diagnosticHandler.enableColors = false),
272 new OptionHandler('--enable-diagnostic-colors',
273 (_) => diagnosticHandler.enableColors = true),
274 new OptionHandler('--enable[_-]checked[_-]mode|--checked',
275 (_) => passThrough('--enable-checked-mode')),
276 new OptionHandler('--enable-concrete-type-inference',
277 (_) => passThrough('--enable-concrete-type-inference')),
278 new OptionHandler('--trust-type-annotations',
279 (_) => passThrough('--trust-type-annotations')),
280 new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
281 new OptionHandler('--package-root=.+|-p.+', setPackageRoot),
282 new OptionHandler('--analyze-all', passThrough),
283 new OptionHandler('--analyze-only', setAnalyzeOnly),
284 new OptionHandler('--analyze-signatures-only', passThrough),
285 new OptionHandler('--disable-native-live-type-analysis', passThrough),
286 new OptionHandler('--categories=.*', setCategories),
287 new OptionHandler('--global-js-name=.*', checkGlobalName),
288 new OptionHandler('--disable-type-inference', passThrough),
289 new OptionHandler('--terse', passThrough),
290 new OptionHandler('--disallow-unsafe-eval',
291 (_) => hasDisallowUnsafeEval = true),
292 new OptionHandler('-D.+=.*', addInEnvironment),
293
294 // The following two options must come last.
295 new OptionHandler('-.*', (String argument) {
296 helpAndFail('Error: Unknown option "$argument".');
297 }),
298 new OptionHandler('.*', (String argument) {
299 arguments.add(nativeToUriPath(argument));
300 })
301 ];
302
303 parseCommandLine(handlers, argv);
304 if (wantHelp || wantVersion) {
305 helpAndExit(wantHelp, wantVersion, diagnosticHandler.verbose);
306 }
307
308 if (hasDisallowUnsafeEval) {
309 String precompiledName =
310 relativize(currentDirectory, computePrecompiledUri(), isWindows);
311 helpAndFail("Error: option '--disallow-unsafe-eval' has been removed."
312 " Instead, the compiler generates a file named"
313 " '$precompiledName'.");
314 }
315
316 if (outputLanguage != OUTPUT_LANGUAGE_DART && stripArgumentSet) {
317 helpAndFail('Error: --force-strip may only be used with '
318 '--output-type=dart');
319 }
320 if (arguments.isEmpty) {
321 helpAndFail('Error: No Dart file specified.');
322 }
323 if (arguments.length > 1) {
324 var extra = arguments.sublist(1);
325 helpAndFail('Error: Extra arguments: ${extra.join(" ")}');
326 }
327
328 Uri uri = currentDirectory.resolve(arguments[0]);
329 if (packageRoot == null) {
330 packageRoot = uri.resolve('./packages/');
331 }
332
333 diagnosticHandler.info('package root is $packageRoot');
334
335 int totalCharactersWritten = 0;
336
337 options.add('--source-map=$sourceMapOut');
338
339 compilationDone(String code) {
340 if (analyzeOnly) return;
341 if (code == null) {
342 fail('Error: Compilation failed.');
343 }
344 writeString(Uri.parse('$out.deps'),
345 getDepsOutput(inputProvider.sourceFiles));
346 diagnosticHandler.info(
347 'compiled ${inputProvider.dartCharactersRead} characters Dart '
348 '-> $totalCharactersWritten characters $outputLanguage '
349 'in ${relativize(currentDirectory, out, isWindows)}');
350 if (!explicitOut) {
351 String input = uriPathToNative(arguments[0]);
352 String output = relativize(currentDirectory, out, isWindows);
353 print('Dart file ($input) compiled to $outputLanguage: $output');
354 }
355 }
356
357 EventSink<String> outputProvider(String name, String extension) {
358 Uri uri;
359 String sourceMapFileName;
360 bool isPrimaryOutput = false;
361 if (name == '') {
362 if (extension == 'js' || extension == 'dart') {
363 isPrimaryOutput = true;
364 uri = out;
365 sourceMapFileName =
366 sourceMapOut.path.substring(sourceMapOut.path.lastIndexOf('/') + 1 );
367 } else if (extension == 'precompiled.js') {
368 uri = computePrecompiledUri();
369 diagnosticHandler.info(
370 "File ($uri) is compatible with header"
371 " \"Content-Security-Policy: script-src 'self'\"");
372 } else if (extension == 'js.map' || extension == 'dart.map') {
373 uri = sourceMapOut;
374 } else {
375 fail('Error: Unknown extension: $extension');
376 }
377 } else {
378 uri = out.resolve('$name.$extension');
379 }
380
381 if (uri.scheme != 'file') {
382 fail('Error: Unhandled scheme ${uri.scheme} in $uri.');
383 }
384
385 RandomAccessFile output =
386 new File(uriPathToNative(uri.path)).openSync(mode: FileMode.WRITE);
387 int charactersWritten = 0;
388
389 writeStringSync(String data) {
390 // Write the data in chunks of 8kb, otherwise we risk running OOM
391 int chunkSize = 8*1024;
392
393 int offset = 0;
394 while (offset < data.length) {
395 output.writeStringSync(
396 data.substring(offset, math.min(offset + chunkSize, data.length))) ;
397 offset += chunkSize;
398 }
399 charactersWritten += data.length;
400 }
401
402 onDone() {
403 if (sourceMapFileName != null) {
404 // Using # is the new proposed standard. @ caused problems in Internet
405 // Explorer due to "Conditional Compilation Statements" in JScript,
406 // see:
407 // http://msdn.microsoft.com/en-us/library/7kx09ct1(v=vs.80).aspx
408 // About source maps, see:
409 // https://docs.google.com/a/google.com/document/d/1U1RGAehQwRypUTovF1 KRlpiOFze0b-_2gc6fAH0KY0k/edit
410 // TODO(http://dartbug.com/11914): Remove @ line.
411 String sourceMapTag = '''
412
413 //# sourceMappingURL=$sourceMapFileName
414 //@ sourceMappingURL=$sourceMapFileName
415 ''';
416 writeStringSync(sourceMapTag);
417 }
418 output.closeSync();
419 if (isPrimaryOutput) {
420 totalCharactersWritten += charactersWritten;
421 }
422 }
423
424 return new EventSinkWrapper(writeStringSync, onDone);
425 }
426
427 return compileFunc(uri, libraryRoot, packageRoot,
428 inputProvider, diagnosticHandler,
429 options, outputProvider, environment)
430 .then(compilationDone);
431 }
432
433 void writeString(Uri uri, String text) {
434 if (uri.scheme != 'file') {
435 fail('Error: Unhandled scheme ${uri.scheme}.');
436 }
437 var file = new File(uriPathToNative(uri.path)).openSync(mode: FileMode.WRITE );
438 file.writeStringSync(text);
439 file.closeSync();
440 }
441
442 void fail(String message) {
443 if (diagnosticHandler != null) {
444 diagnosticHandler.diagnosticHandler(
445 null, -1, -1, message, api.Diagnostic.ERROR);
446 } else {
447 print(message);
448 }
449 exitFunc(1);
450 }
451
452 Future compilerMain(List<String> arguments) {
453 var root = uriPathToNative("/$LIBRARY_ROOT");
454 arguments = <String>['--library-root=${Platform.script.toFilePath()}$root']
455 ..addAll(arguments);
456 return compile(arguments);
457 }
458
459 void helpAndExit(bool wantHelp, bool wantVersion, bool verbose) {
460 if (wantVersion) {
461 var version = (BUILD_ID == null)
462 ? '<non-SDK build>'
463 : BUILD_ID;
464 print('Dart-to-JavaScript compiler (dart2js) version: $version');
465 }
466 if (wantHelp) {
467 if (verbose) {
468 verboseHelp();
469 } else {
470 help();
471 }
472 }
473 exitFunc(0);
474 }
475
476 void helpAndFail(String message) {
477 help();
478 print('');
479 fail(message);
480 }
60 } 481 }
61 482
62 String extractPath(String argument) {
63 String path = nativeToUriPath(extractParameter(argument));
64 return path.endsWith("/") ? path : "$path/";
65 }
66
67 void parseCommandLine(List<OptionHandler> handlers, List<String> argv) {
68 // TODO(ahe): Use ../../args/args.dart for parsing options instead.
69 var patterns = <String>[];
70 for (OptionHandler handler in handlers) {
71 patterns.add(handler.pattern);
72 }
73 var pattern = new RegExp('^(${patterns.join(")\$|(")})\$');
74
75 Iterator<String> arguments = argv.iterator;
76 OUTER: while (arguments.moveNext()) {
77 String argument = arguments.current;
78 Match match = pattern.firstMatch(argument);
79 assert(match.groupCount == handlers.length);
80 for (int i = 0; i < handlers.length; i++) {
81 if (match[i + 1] != null) {
82 OptionHandler handler = handlers[i];
83 if (handler.multipleArguments) {
84 handler.handle(arguments);
85 } else {
86 handler.handle(argument);
87 }
88 continue OUTER;
89 }
90 }
91 throw 'Internal error: "$argument" did not match';
92 }
93 }
94
95 FormattingDiagnosticHandler diagnosticHandler;
96
97 Future compile(List<String> argv) {
98 bool isWindows = (Platform.operatingSystem == 'windows');
99 stackTraceFilePrefix = '$currentDirectory';
100 Uri libraryRoot = currentDirectory;
101 Uri out = currentDirectory.resolve('out.js');
102 Uri sourceMapOut = currentDirectory.resolve('out.js.map');
103 Uri packageRoot = null;
104 List<String> options = new List<String>();
105 bool explicitOut = false;
106 bool wantHelp = false;
107 bool wantVersion = false;
108 String outputLanguage = 'JavaScript';
109 bool stripArgumentSet = false;
110 bool analyzeOnly = false;
111 bool hasDisallowUnsafeEval = false;
112 // TODO(johnniwinther): Measure time for reading files.
113 SourceFileProvider inputProvider = new CompilerSourceFileProvider();
114 diagnosticHandler = new FormattingDiagnosticHandler(inputProvider);
115 Map<String, dynamic> environment = new Map<String, dynamic>();
116
117 passThrough(String argument) => options.add(argument);
118
119 if (BUILD_ID != null) {
120 passThrough("--build-id=$BUILD_ID");
121 }
122
123 setLibraryRoot(String argument) {
124 libraryRoot = currentDirectory.resolve(extractPath(argument));
125 }
126
127 setPackageRoot(String argument) {
128 packageRoot = currentDirectory.resolve(extractPath(argument));
129 }
130
131 setOutput(Iterator<String> arguments) {
132 String path;
133 if (arguments.current == '-o') {
134 if (!arguments.moveNext()) {
135 helpAndFail('Error: Missing file after -o option.');
136 }
137 path = arguments.current;
138 } else {
139 path = extractParameter(arguments.current);
140 }
141 explicitOut = true;
142 out = currentDirectory.resolve(nativeToUriPath(path));
143 sourceMapOut = Uri.parse('$out.map');
144 }
145
146 setOutputType(String argument) {
147 if (argument == '--output-type=dart') {
148 outputLanguage = OUTPUT_LANGUAGE_DART;
149 if (!explicitOut) {
150 out = currentDirectory.resolve('out.dart');
151 sourceMapOut = currentDirectory.resolve('out.dart.map');
152 }
153 }
154 passThrough(argument);
155 }
156
157 String getDepsOutput(Map<String, SourceFile> sourceFiles) {
158 var filenames = new List.from(sourceFiles.keys);
159 filenames.sort();
160 return filenames.join("\n");
161 }
162
163 setStrip(String argument) {
164 stripArgumentSet = true;
165 passThrough(argument);
166 }
167
168 setAnalyzeOnly(String argument) {
169 analyzeOnly = true;
170 passThrough(argument);
171 }
172
173 setVerbose(_) {
174 diagnosticHandler.verbose = true;
175 passThrough('--verbose');
176 }
177
178 addInEnvironment(String argument) {
179 int eqIndex = argument.indexOf('=');
180 String name = argument.substring(2, eqIndex);
181 String value = argument.substring(eqIndex + 1);
182 environment[name] = value;
183 }
184
185 setCategories(String argument) {
186 List<String> categories = extractParameter(argument).split(',');
187 Set<String> allowedCategories =
188 LIBRARIES.values.map((x) => x.category).toSet();
189 allowedCategories.remove('Shared');
190 allowedCategories.remove('Internal');
191 List<String> allowedCategoriesList =
192 new List<String>.from(allowedCategories);
193 allowedCategoriesList.sort();
194 if (categories.contains('all')) {
195 categories = allowedCategoriesList;
196 } else {
197 String allowedCategoriesString = allowedCategoriesList.join(', ');
198 for (String category in categories) {
199 if (!allowedCategories.contains(category)) {
200 fail('Error: unsupported library category "$category", '
201 'supported categories are: $allowedCategoriesString');
202 }
203 }
204 }
205 passThrough('--categories=${categories.join(",")}');
206 }
207
208 checkGlobalName(String argument) {
209 String globalName = extractParameter(argument);
210 if (!new RegExp(r'^\$[a-z]*$').hasMatch(globalName)) {
211 fail('Error: "$globalName" must match "\\\$[a-z]*"');
212 }
213 passThrough(argument);
214 }
215
216 handleShortOptions(String argument) {
217 var shortOptions = argument.substring(1).split("");
218 for (var shortOption in shortOptions) {
219 switch (shortOption) {
220 case 'v':
221 setVerbose(null);
222 break;
223 case 'h':
224 case '?':
225 wantHelp = true;
226 break;
227 case 'c':
228 passThrough('--enable-checked-mode');
229 break;
230 default:
231 throw 'Internal error: "$shortOption" did not match';
232 }
233 }
234 }
235
236 Uri computePrecompiledUri() {
237 String extension = 'precompiled.js';
238 String outPath = out.path;
239 if (outPath.endsWith('.js')) {
240 outPath = outPath.substring(0, outPath.length - 3);
241 return out.resolve('$outPath.$extension');
242 } else {
243 return out.resolve(extension);
244 }
245 }
246
247 List<String> arguments = <String>[];
248 List<OptionHandler> handlers = <OptionHandler>[
249 new OptionHandler('-[chv?]+', handleShortOptions),
250 new OptionHandler('--throw-on-error',
251 (_) => diagnosticHandler.throwOnError = true),
252 new OptionHandler('--suppress-warnings',
253 (_) => diagnosticHandler.showWarnings = false),
254 new OptionHandler('--suppress-hints',
255 (_) => diagnosticHandler.showHints = false),
256 new OptionHandler('--output-type=dart|--output-type=js', setOutputType),
257 new OptionHandler('--verbose', setVerbose),
258 new OptionHandler('--version', (_) => wantVersion = true),
259 new OptionHandler('--library-root=.+', setLibraryRoot),
260 new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
261 new OptionHandler('--allow-mock-compilation', passThrough),
262 new OptionHandler('--minify', passThrough),
263 new OptionHandler('--force-strip=.*', setStrip),
264 new OptionHandler('--disable-diagnostic-colors',
265 (_) => diagnosticHandler.enableColors = false),
266 new OptionHandler('--enable-diagnostic-colors',
267 (_) => diagnosticHandler.enableColors = true),
268 new OptionHandler('--enable[_-]checked[_-]mode|--checked',
269 (_) => passThrough('--enable-checked-mode')),
270 new OptionHandler('--enable-concrete-type-inference',
271 (_) => passThrough('--enable-concrete-type-inference')),
272 new OptionHandler('--trust-type-annotations',
273 (_) => passThrough('--trust-type-annotations')),
274 new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
275 new OptionHandler('--package-root=.+|-p.+', setPackageRoot),
276 new OptionHandler('--analyze-all', passThrough),
277 new OptionHandler('--analyze-only', setAnalyzeOnly),
278 new OptionHandler('--analyze-signatures-only', passThrough),
279 new OptionHandler('--disable-native-live-type-analysis', passThrough),
280 new OptionHandler('--categories=.*', setCategories),
281 new OptionHandler('--global-js-name=.*', checkGlobalName),
282 new OptionHandler('--disable-type-inference', passThrough),
283 new OptionHandler('--terse', passThrough),
284 new OptionHandler('--disallow-unsafe-eval',
285 (_) => hasDisallowUnsafeEval = true),
286 new OptionHandler('-D.+=.*', addInEnvironment),
287
288 // The following two options must come last.
289 new OptionHandler('-.*', (String argument) {
290 helpAndFail('Error: Unknown option "$argument".');
291 }),
292 new OptionHandler('.*', (String argument) {
293 arguments.add(nativeToUriPath(argument));
294 })
295 ];
296
297 parseCommandLine(handlers, argv);
298 if (wantHelp || wantVersion) {
299 helpAndExit(wantHelp, wantVersion, diagnosticHandler.verbose);
300 }
301
302 if (hasDisallowUnsafeEval) {
303 String precompiledName =
304 relativize(currentDirectory, computePrecompiledUri(), isWindows);
305 helpAndFail("Error: option '--disallow-unsafe-eval' has been removed."
306 " Instead, the compiler generates a file named"
307 " '$precompiledName'.");
308 }
309
310 if (outputLanguage != OUTPUT_LANGUAGE_DART && stripArgumentSet) {
311 helpAndFail('Error: --force-strip may only be used with '
312 '--output-type=dart');
313 }
314 if (arguments.isEmpty) {
315 helpAndFail('Error: No Dart file specified.');
316 }
317 if (arguments.length > 1) {
318 var extra = arguments.sublist(1);
319 helpAndFail('Error: Extra arguments: ${extra.join(" ")}');
320 }
321
322 Uri uri = currentDirectory.resolve(arguments[0]);
323 if (packageRoot == null) {
324 packageRoot = uri.resolve('./packages/');
325 }
326
327 diagnosticHandler.info('package root is $packageRoot');
328
329 int totalCharactersWritten = 0;
330
331 options.add('--source-map=$sourceMapOut');
332
333 compilationDone(String code) {
334 if (analyzeOnly) return;
335 if (code == null) {
336 fail('Error: Compilation failed.');
337 }
338 writeString(Uri.parse('$out.deps'),
339 getDepsOutput(inputProvider.sourceFiles));
340 diagnosticHandler.info(
341 'compiled ${inputProvider.dartCharactersRead} characters Dart '
342 '-> $totalCharactersWritten characters $outputLanguage '
343 'in ${relativize(currentDirectory, out, isWindows)}');
344 if (!explicitOut) {
345 String input = uriPathToNative(arguments[0]);
346 String output = relativize(currentDirectory, out, isWindows);
347 print('Dart file ($input) compiled to $outputLanguage: $output');
348 }
349 }
350
351 EventSink<String> outputProvider(String name, String extension) {
352 Uri uri;
353 String sourceMapFileName;
354 bool isPrimaryOutput = false;
355 if (name == '') {
356 if (extension == 'js' || extension == 'dart') {
357 isPrimaryOutput = true;
358 uri = out;
359 sourceMapFileName =
360 sourceMapOut.path.substring(sourceMapOut.path.lastIndexOf('/') + 1);
361 } else if (extension == 'precompiled.js') {
362 uri = computePrecompiledUri();
363 diagnosticHandler.info(
364 "File ($uri) is compatible with header"
365 " \"Content-Security-Policy: script-src 'self'\"");
366 } else if (extension == 'js.map' || extension == 'dart.map') {
367 uri = sourceMapOut;
368 } else {
369 fail('Error: Unknown extension: $extension');
370 }
371 } else {
372 uri = out.resolve('$name.$extension');
373 }
374
375 if (uri.scheme != 'file') {
376 fail('Error: Unhandled scheme ${uri.scheme} in $uri.');
377 }
378
379 RandomAccessFile output =
380 new File(uriPathToNative(uri.path)).openSync(mode: FileMode.WRITE);
381 int charactersWritten = 0;
382
383 writeStringSync(String data) {
384 // Write the data in chunks of 8kb, otherwise we risk running OOM
385 int chunkSize = 8*1024;
386
387 int offset = 0;
388 while (offset < data.length) {
389 output.writeStringSync(
390 data.substring(offset, math.min(offset + chunkSize, data.length)));
391 offset += chunkSize;
392 }
393 charactersWritten += data.length;
394 }
395
396 onDone() {
397 if (sourceMapFileName != null) {
398 // Using # is the new proposed standard. @ caused problems in Internet
399 // Explorer due to "Conditional Compilation Statements" in JScript,
400 // see:
401 // http://msdn.microsoft.com/en-us/library/7kx09ct1(v=vs.80).aspx
402 // About source maps, see:
403 // https://docs.google.com/a/google.com/document/d/1U1RGAehQwRypUTovF1KR lpiOFze0b-_2gc6fAH0KY0k/edit
404 // TODO(http://dartbug.com/11914): Remove @ line.
405 String sourceMapTag = '''
406
407 //# sourceMappingURL=$sourceMapFileName
408 //@ sourceMappingURL=$sourceMapFileName
409 ''';
410 writeStringSync(sourceMapTag);
411 }
412 output.closeSync();
413 if (isPrimaryOutput) {
414 totalCharactersWritten += charactersWritten;
415 }
416 }
417
418 return new EventSinkWrapper(writeStringSync, onDone);
419 }
420
421 return api.compile(uri, libraryRoot, packageRoot,
422 inputProvider, diagnosticHandler,
423 options, outputProvider, environment)
424 .then(compilationDone);
425 }
426
427 class EventSinkWrapper extends EventSink<String> { 483 class EventSinkWrapper extends EventSink<String> {
428 var onAdd, onClose; 484 var onAdd, onClose;
429 485
430 EventSinkWrapper(this.onAdd, this.onClose); 486 EventSinkWrapper(this.onAdd, this.onClose);
431 487
432 void add(String data) => onAdd(data); 488 void add(String data) => onAdd(data);
433 489
434 void addError(error, [StackTrace stackTrace]) => throw error; 490 void addError(error, [StackTrace stackTrace]) => throw error;
435 491
436 void close() => onClose(); 492 void close() => onClose();
437 } 493 }
438 494
439 class AbortLeg { 495 class AbortLeg {
440 final message; 496 final message;
441 AbortLeg(this.message); 497 AbortLeg(this.message);
442 toString() => 'Aborted due to --throw-on-error: $message'; 498 toString() => 'Aborted due to --throw-on-error: $message';
443 } 499 }
444 500
445 void writeString(Uri uri, String text) {
446 if (uri.scheme != 'file') {
447 fail('Error: Unhandled scheme ${uri.scheme}.');
448 }
449 var file = new File(uriPathToNative(uri.path)).openSync(mode: FileMode.WRITE);
450 file.writeStringSync(text);
451 file.closeSync();
452 }
453
454 void fail(String message) {
455 if (diagnosticHandler != null) {
456 diagnosticHandler.diagnosticHandler(
457 null, -1, -1, message, api.Diagnostic.ERROR);
458 } else {
459 print(message);
460 }
461 exit(1);
462 }
463
464 Future compilerMain(List<String> arguments) {
465 var root = uriPathToNative("/$LIBRARY_ROOT");
466 arguments = <String>['--library-root=${Platform.script.toFilePath()}$root']
467 ..addAll(arguments);
468 return compile(arguments);
469 }
470
471 void help() { 501 void help() {
472 // This message should be no longer than 20 lines. The default 502 // This message should be no longer than 20 lines. The default
473 // terminal size normally 80x24. Two lines are used for the prompts 503 // terminal size normally 80x24. Two lines are used for the prompts
474 // before and after running the compiler. Another two lines may be 504 // before and after running the compiler. Another two lines may be
475 // used to print an error message. 505 // used to print an error message.
476 print(''' 506 print('''
477 Usage: dart2js [options] dartfile 507 Usage: dart2js [options] dartfile
478 508
479 Compiles Dart to JavaScript. 509 Compiles Dart to JavaScript.
480 510
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 all categories, use --categories=all. 601 all categories, use --categories=all.
572 602
573 --global-js-name=<name> 603 --global-js-name=<name>
574 By default, dart2js generates JavaScript output that uses a global 604 By default, dart2js generates JavaScript output that uses a global
575 variable named "$". The name of this global can be overridden 605 variable named "$". The name of this global can be overridden
576 with this option. The name must match the regular expression "\$[a-z]*". 606 with this option. The name must match the regular expression "\$[a-z]*".
577 607
578 '''.trim()); 608 '''.trim());
579 } 609 }
580 610
581 void helpAndExit(bool wantHelp, bool wantVersion, bool verbose) { 611 Future internalMain(Function exitFunc, Function compileFunc,
582 if (wantVersion) { 612 List<String> arguments) {
583 var version = (BUILD_ID == null) 613 var dart2js = new _Dart2Js(exitFunc, compileFunc);
584 ? '<non-SDK build>' 614
585 : BUILD_ID; 615 onError(exception, trace) {
586 print('Dart-to-JavaScript compiler (dart2js) version: $version'); 616 if (exception is CompilerCrashedException) {
ahe 2013/11/21 12:44:53 This looks like a break down of the API to me. Co
587 } 617 // Error and stack trace already reported.
588 if (wantHelp) { 618 exitFunc(253); // 253 is recognized as a crash by our test scripts.
589 if (verbose) {
590 verboseHelp();
591 } else { 619 } else {
592 help(); 620 try {
621 print('Internal error: $exception');
622 } catch (ignored) {
623 print('Internal error: error while printing exception');
624 }
625
626 try {
627 if (trace != null) {
628 print(trace);
629 }
630 } finally {
631 exitFunc(253); // 253 is recognized as a crash by our test scripts.
632 }
593 } 633 }
594 } 634 }
595 exit(0);
596 }
597 635
598 void helpAndFail(String message) { 636 try {
599 help(); 637 return dart2js.compilerMain(arguments).catchError(onError);
600 print(''); 638 } catch (exception, trace) {
601 fail(message); 639 onError(exception, trace);
640 return new Future.value();
641 }
602 } 642 }
603 643
604 void main(List<String> arguments) { 644 void main(List<String> arguments) {
605 runZoned(() => compilerMain(arguments), onError: (exception, trace) { 645 internalMain(exit, api.compile, arguments);
606 try {
607 print('Internal error: $exception');
608 } catch (ignored) {
609 print('Internal error: error while printing exception');
610 }
611
612 try {
613 if (trace != null) {
614 print(trace);
615 }
616 } finally {
617 exit(253); // 253 is recognized as a crash by our test scripts.
618 }
619 });
620 } 646 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/compiler.dart ('k') | sdk/lib/_internal/compiler/implementation/util/util.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698