Chromium Code Reviews| 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('dart2js'); | 5 #library('dart2js'); |
| 6 | 6 |
| 7 #import('dart:io'); | 7 #import('dart:io'); |
| 8 #import('dart:uri'); | 8 #import('dart:uri'); |
| 9 #import('dart:utf'); | 9 #import('dart:utf'); |
| 10 | 10 |
| 11 #import('../compiler.dart', prefix: 'api'); | 11 #import('../compiler.dart', prefix: 'api'); |
| 12 #import('colors.dart', prefix: 'colors'); | 12 #import('colors.dart', prefix: 'colors'); |
| 13 #import('source_file.dart'); | 13 #import('source_file.dart'); |
| 14 #import('filenames.dart'); | 14 #import('filenames.dart'); |
| 15 #import('util/uri_extras.dart'); | 15 #import('util/uri_extras.dart'); |
| 16 | 16 |
| 17 final String LIBRARY_ROOT = '../../../..'; | 17 final String LIBRARY_ROOT = '../../../..'; |
| 18 | 18 |
| 19 typedef void HandleOption(String option); | |
| 20 | |
| 21 class OptionHandler { | |
| 22 String pattern; | |
| 23 HandleOption handle; | |
| 24 | |
| 25 OptionHandler(this.pattern, this.handle); | |
| 26 } | |
| 27 | |
| 28 String extractParameter(String argument) { | |
| 29 return argument.substring(argument.indexOf('=') + 1); | |
| 30 } | |
| 31 | |
| 32 void parseCommandLine(List<OptionHandler> handlers, List<String> argv) { | |
| 33 var patterns = <String>[]; | |
| 34 for (OptionHandler handler in handlers) { | |
| 35 patterns.add(handler.pattern); | |
| 36 } | |
| 37 var pattern = new RegExp('^(${Strings.join(patterns, ")|(")})\$'); | |
| 38 assert(pattern.groupCount() == handlers.length); | |
| 39 OUTER: for (String argument in argv) { | |
| 40 Match match = pattern.firstMatch(argument); | |
| 41 for (int i = 0; i < handlers.length; i++) { | |
| 42 if (match[i + 1] !== null) { | |
| 43 handlers[i].handle(argument); | |
| 44 continue OUTER; | |
| 45 } | |
| 46 } | |
| 47 throw 'Internal error: "$argument" did not match'; | |
| 48 } | |
| 49 } | |
| 50 | |
| 19 void compile(List<String> argv) { | 51 void compile(List<String> argv) { |
| 20 Uri cwd = getCurrentDirectory(); | 52 Uri cwd = getCurrentDirectory(); |
| 21 bool throwOnError = false; | 53 bool throwOnError = false; |
| 22 bool showWarnings = true; | 54 bool showWarnings = true; |
| 23 bool verbose = false; | 55 bool verbose = false; |
| 24 Uri libraryRoot = cwd; | 56 Uri libraryRoot = cwd; |
| 25 Uri out = cwd.resolve('out.js'); | 57 Uri out = cwd.resolve('out.js'); |
| 26 List<String> options = new List<String>(); | 58 List<String> options = new List<String>(); |
| 27 | 59 |
| 60 passThrough(String argument) => options.add(argument); | |
| 61 | |
| 28 List<String> arguments = <String>[]; | 62 List<String> arguments = <String>[]; |
| 29 for (String argument in argv) { | 63 List<OptionHandler> handlers = <OptionHandler>[ |
| 30 if ('--throw-on-error' == argument) { | 64 new OptionHandler('--throw-on-error', (_) => throwOnError = true), |
| 31 throwOnError = true; | 65 new OptionHandler('--suppress-warnings', (_) => showWarnings = false), |
| 32 } else if ('--suppress-warnings' == argument) { | 66 new OptionHandler('--verbose', (_) => verbose = true), |
| 33 showWarnings = false; | 67 new OptionHandler('--library-root=.*', (String argument) { |
| 34 } else if ('--verbose' == argument) { | 68 String path = nativeToUriPath(extractParameter(argument)); |
| 35 verbose = true; | |
| 36 } else if (argument.startsWith('--library-root=')) { | |
| 37 String path = | |
| 38 nativeToUriPath(argument.substring(argument.indexOf('=') + 1)); | |
| 39 if (!path.endsWith("/")) path = "$path/"; | 69 if (!path.endsWith("/")) path = "$path/"; |
| 40 libraryRoot = cwd.resolve(path); | 70 libraryRoot = cwd.resolve(path); |
| 41 } else if (argument.startsWith('--out=')) { | 71 }), |
| 42 String path = | 72 new OptionHandler('--out=.*', (String argument) { |
| 43 nativeToUriPath(argument.substring(argument.indexOf('=') + 1)); | 73 out = cwd.resolve(nativeToUriPath(extractParameter(argument))); |
| 44 out = cwd.resolve(path); | 74 }), |
| 45 } else if ('--allow-mock-compilation' == argument) { | 75 new OptionHandler('--allow-mock-compilation', passThrough), |
| 46 options.add(argument); | 76 new OptionHandler('--no-colors', (_) => colors.enabled = false), |
| 47 } else if ('--no-colors' == argument) { | 77 new OptionHandler('--enable-checked-mode|--checked|-c', |
| 48 colors.enabled = false; | 78 (_) => passThrough('--enable_checked_mode')), |
| 49 } else if ('--enable-checked-mode' == argument) { | 79 new OptionHandler('--help', (_) => helpAndExit()), |
| 50 options.add(argument); | 80 // The following two options must come last. |
| 51 } else if (argument.startsWith('-')) { | 81 new OptionHandler('-.*', (String argument) { |
| 52 fail('Unknown option $argument.'); | 82 fail('Error: unknown option "$argument".'); |
| 53 } else { | 83 }), |
| 84 new OptionHandler('.*', (String argument) { | |
| 54 arguments.add(nativeToUriPath(argument)); | 85 arguments.add(nativeToUriPath(argument)); |
| 55 } | 86 }) |
| 56 } | 87 ]; |
| 88 | |
| 89 parseCommandLine(handlers, argv); | |
| 90 | |
| 57 if (arguments.isEmpty()) { | 91 if (arguments.isEmpty()) { |
| 58 fail('No file to compile.'); | 92 helpAndFail('Error: no file to compile.'); |
| 59 } | 93 } |
| 60 if (arguments.length > 1) { | 94 if (arguments.length > 1) { |
| 61 var extra = arguments.getRange(1, arguments.length - 1); | 95 var extra = arguments.getRange(1, arguments.length - 1); |
| 62 fail('Extra arguments: $extra.'); | 96 helpAndFail('Error: extra arguments: ${Strings.join(extra, " ")}'); |
| 63 } | 97 } |
| 64 | 98 |
| 65 Map<String, SourceFile> sourceFiles = <SourceFile>{}; | 99 Map<String, SourceFile> sourceFiles = <SourceFile>{}; |
| 66 int dartBytesRead = 0; | 100 int dartBytesRead = 0; |
| 67 | 101 |
| 68 Future<String> provider(Uri uri) { | 102 Future<String> provider(Uri uri) { |
| 69 if (uri.scheme != 'file') { | 103 if (uri.scheme != 'file') { |
| 70 throw new IllegalArgumentException(uri); | 104 throw new IllegalArgumentException(uri); |
| 71 } | 105 } |
| 72 String source = readAll(uriPathToNative(uri.path)); | 106 String source = readAll(uriPathToNative(uri.path)); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 97 if (fatal && throwOnError) throw new AbortLeg(message); | 131 if (fatal && throwOnError) throw new AbortLeg(message); |
| 98 } | 132 } |
| 99 | 133 |
| 100 Uri uri = cwd.resolve(arguments[0]); | 134 Uri uri = cwd.resolve(arguments[0]); |
| 101 info('compiling $uri'); | 135 info('compiling $uri'); |
| 102 | 136 |
| 103 // TODO(ahe): We expect the future to be complete and call value | 137 // TODO(ahe): We expect the future to be complete and call value |
| 104 // directly. In effect, we don't support truly asynchronous API. | 138 // directly. In effect, we don't support truly asynchronous API. |
| 105 String code = api.compile(uri, libraryRoot, provider, handler, options).value; | 139 String code = api.compile(uri, libraryRoot, provider, handler, options).value; |
| 106 if (code === null) { | 140 if (code === null) { |
| 107 fail('Compilation failed.'); | 141 fail('Error: compilation failed.'); |
| 108 } | 142 } |
| 109 writeString(out, code); | 143 writeString(out, code); |
| 110 int jsBytesWritten = code.length; | 144 int jsBytesWritten = code.length; |
| 111 info('compiled $dartBytesRead bytes Dart -> $jsBytesWritten bytes JS ' | 145 info('compiled $dartBytesRead bytes Dart -> $jsBytesWritten bytes JS ' |
| 112 + 'in ${relativize(cwd, out)}'); | 146 + 'in ${relativize(cwd, out)}'); |
| 113 } | 147 } |
| 114 | 148 |
| 115 class AbortLeg { | 149 class AbortLeg { |
| 116 final message; | 150 final message; |
| 117 AbortLeg(this.message); | 151 AbortLeg(this.message); |
| 118 toString() => 'Aborted due to --throw-on-error: $message'; | 152 toString() => 'Aborted due to --throw-on-error: $message'; |
| 119 } | 153 } |
| 120 | 154 |
| 121 void writeString(Uri uri, String text) { | 155 void writeString(Uri uri, String text) { |
| 122 if (uri.scheme != 'file') { | 156 if (uri.scheme != 'file') { |
| 123 fail('Unhandled scheme ${uri.scheme}.'); | 157 fail('Error: unhandled scheme ${uri.scheme}.'); |
| 124 } | 158 } |
| 125 var file = new File(uriPathToNative(uri.path)).openSync(FileMode.WRITE); | 159 var file = new File(uriPathToNative(uri.path)).openSync(FileMode.WRITE); |
| 126 file.writeStringSync(text); | 160 file.writeStringSync(text); |
| 127 file.closeSync(); | 161 file.closeSync(); |
| 128 } | 162 } |
| 129 | 163 |
| 130 String readAll(String filename) { | 164 String readAll(String filename) { |
| 131 var file = (new File(filename)).openSync(FileMode.READ); | 165 var file = (new File(filename)).openSync(FileMode.READ); |
| 132 var length = file.lengthSync(); | 166 var length = file.lengthSync(); |
| 133 var buffer = new List<int>(length); | 167 var buffer = new List<int>(length); |
| 134 var bytes = file.readListSync(buffer, 0, length); | 168 var bytes = file.readListSync(buffer, 0, length); |
| 135 file.closeSync(); | 169 file.closeSync(); |
| 136 return new String.fromCharCodes(new Utf8Decoder(buffer).decodeRest()); | 170 return new String.fromCharCodes(new Utf8Decoder(buffer).decodeRest()); |
| 137 } | 171 } |
| 138 | 172 |
| 139 void fail(String message) { | 173 void fail(String message) { |
| 140 print(message); | 174 print(message); |
| 141 exit(1); | 175 exit(1); |
| 142 } | 176 } |
| 143 | 177 |
| 144 void compilerMain(Options options) { | 178 void compilerMain(Options options) { |
| 145 var root = uriPathToNative("/$LIBRARY_ROOT"); | 179 var root = uriPathToNative("/$LIBRARY_ROOT"); |
| 146 List<String> argv = ['--library-root=${options.script}$root']; | 180 List<String> argv = ['--library-root=${options.script}$root']; |
| 147 argv.addAll(options.arguments); | 181 argv.addAll(options.arguments); |
| 148 compile(argv); | 182 compile(argv); |
| 149 } | 183 } |
| 150 | 184 |
| 185 void help() { | |
| 186 // This message should be no longer than 22 lines. The default | |
| 187 // terminal size normally 80x24. Two lines are used for the prompts | |
| 188 // before and after running the compiler. | |
| 189 print(''' | |
| 190 dart2js [OPTIONS...] DART-FILE | |
| 191 | |
| 192 A Dart to JavaScript compiler. | |
| 193 | |
| 194 By default, the compiled JavaScript code is saved to a file named | |
| 195 out.js in the current directory. | |
| 196 | |
| 197 Common options: | |
| 198 | |
| 199 --help Display this message. | |
| 200 | |
| 201 --out=FILE Save the output to FILE (default is out.js). | |
|
sethladd
2012/05/09 18:08:12
I believe the new dart.js file that Kasper updated
| |
| 202 | |
| 203 --checked Turn on checked mode in generated JavaScript code. | |
| 204 '''); | |
| 205 } | |
| 206 | |
| 207 void helpAndExit() { | |
| 208 help(); | |
| 209 exit(0); | |
| 210 } | |
| 211 | |
| 212 void helpAndFail(String message) { | |
| 213 help(); | |
| 214 fail(message); | |
| 215 } | |
| 216 | |
| 151 void main() { | 217 void main() { |
| 152 try { | 218 try { |
| 153 compilerMain(new Options()); | 219 compilerMain(new Options()); |
| 154 } catch (var exception, var trace) { | 220 } catch (var exception, var trace) { |
| 155 try { | 221 try { |
| 156 print('Internal error: $exception'); | 222 print('Internal error: $exception'); |
| 157 } catch (var ignored) { | 223 } catch (var ignored) { |
| 158 print('Internal error: error while printing exception'); | 224 print('Internal error: error while printing exception'); |
| 159 } | 225 } |
| 160 try { | 226 try { |
| 161 print(trace); | 227 print(trace); |
| 162 } finally { | 228 } finally { |
| 163 exit(253); // 253 is recognized as a crash by our test scripts. | 229 exit(253); // 253 is recognized as a crash by our test scripts. |
| 164 } | 230 } |
| 165 } | 231 } |
| 166 } | 232 } |
| OLD | NEW |