blob: 5d44cf6b57c4e369a0437efaf2e7f4c4fa358f14 [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library dart2js.cmdline;
import 'dart:async' show EventSink, Future;
import 'dart:convert' show UTF8, LineSplitter;
import 'dart:io' show exit, File, FileMode, Platform, stdin, stderr;
import 'package:package_config/discovery.dart' show findPackages;
import '../compiler_new.dart' as api;
import 'commandline_options.dart';
import 'common/names.dart' show Uris;
import 'filenames.dart';
import 'io/source_file.dart';
import 'null_compiler_output.dart';
import 'options.dart' show CompilerOptions;
import 'source_file_provider.dart';
import 'util/command_line.dart';
import 'util/uri_extras.dart';
import 'util/util.dart' show stackTraceFilePrefix;
const String LIBRARY_ROOT = '../../../../../sdk';
const String OUTPUT_LANGUAGE_DART = 'Dart';
* A string to identify the revision or build.
* This ID is displayed if the compiler crashes and in verbose mode, and is
* an aid in reproducing bug reports.
* The actual string is rewritten by a wrapper script when included in the sdk.
String BUILD_ID = null;
* The data passed to the [HandleOption] callback is either a single
* string argument, or the arguments iterator for multiple arguments
* handlers.
typedef void HandleOption(data);
class OptionHandler {
final String pattern;
final HandleOption handle;
final bool multipleArguments;
OptionHandler(this.pattern, this.handle, {this.multipleArguments: false});
* Extract the parameter of an option.
* For example, in ['--out=fisk.js'] and ['-ohest.js'], the parameters
* are ['fisk.js'] and ['hest.js'], respectively.
String extractParameter(String argument, {bool isOptionalArgument: false}) {
// m[0] is the entire match (which will be equal to argument). m[1]
// is something like "-o" or "--out=", and m[2] is the parameter.
Match m = new RegExp('^(-[a-z]|--.+=)(.*)').firstMatch(argument);
if (m == null) {
if (isOptionalArgument) return null;
helpAndFail('Unknown option "$argument".');
return m[2];
String extractPath(String argument, {bool isDirectory: true}) {
String path = nativeToUriPath(extractParameter(argument));
return !path.endsWith("/") && isDirectory ? "$path/" : path;
void parseCommandLine(List<OptionHandler> handlers, List<String> argv) {
// TODO(ahe): Use ../../args/args.dart for parsing options instead.
var patterns = <String>[];
for (OptionHandler handler in handlers) {
var pattern = new RegExp('^(${patterns.join(")\$|^(")})\$');
Iterator<String> arguments = argv.iterator;
while (arguments.moveNext()) {
String argument = arguments.current;
Match match = pattern.firstMatch(argument);
assert(match.groupCount == handlers.length);
for (int i = 0; i < handlers.length; i++) {
if (match[i + 1] != null) {
OptionHandler handler = handlers[i];
if (handler.multipleArguments) {
} else {
continue OUTER;
throw 'Internal error: "$argument" did not match';
FormattingDiagnosticHandler diagnosticHandler;
Future<api.CompilationResult> compile(List<String> argv) {
stackTraceFilePrefix = '$currentDirectory';
Uri libraryRoot = currentDirectory;
Uri out = currentDirectory.resolve('out.js');
Uri sourceMapOut = currentDirectory.resolve('');
List<Uri> resolutionInputs;
List<String> bazelPaths;
Uri packageConfig = null;
Uri packageRoot = null;
List<String> options = new List<String>();
List<String> explicitOutputArguments = <String>[];
bool wantHelp = false;
bool wantVersion = false;
bool analyzeOnly = false;
bool analyzeAll = false;
bool resolveOnly = false;
Uri resolutionOutput = currentDirectory.resolve('');
bool allowNativeExtensions = false;
bool trustTypeAnnotations = false;
bool checkedMode = false;
List<String> hints = <String>[];
bool verbose;
bool throwOnError;
int throwOnErrorCount;
bool showWarnings;
bool showHints;
bool enableColors;
// List of provided options that imply that output is expected.
List<String> optionsImplyCompilation = <String>[];
bool hasDisallowUnsafeEval = false;
Map<String, dynamic> environment = new Map<String, dynamic>();
void passThrough(String argument) => options.add(argument);
void ignoreOption(String argument) {}
if (BUILD_ID != null) {
void setLibraryRoot(String argument) {
libraryRoot = currentDirectory.resolve(extractPath(argument));
void setPackageRoot(String argument) {
packageRoot = currentDirectory.resolve(extractPath(argument));
void setPackageConfig(String argument) {
packageConfig =
currentDirectory.resolve(extractPath(argument, isDirectory: false));
void setOutput(Iterator<String> arguments) {
String path;
if (arguments.current == '-o') {
if (!arguments.moveNext()) {
helpAndFail('Error: Missing file after -o option.');
path = arguments.current;
} else {
path = extractParameter(arguments.current);
resolutionOutput = out = currentDirectory.resolve(nativeToUriPath(path));
sourceMapOut = Uri.parse('$');
void setOutputType(String argument) {
if (argument == '--output-type=dart' ||
argument == '--output-type=dart-multi') {
"--output-type=dart is no longer supported. It was deprecated "
"since Dart 1.11 and removed in Dart 1.19.");
void setResolutionInput(String argument) {
resolutionInputs = <Uri>[];
String parts = extractParameter(argument);
for (String part in parts.split(',')) {
void setBazelPaths(String argument) {
String paths = extractParameter(argument);
bazelPaths = <String>[]..addAll(paths.split(','));
void setResolveOnly(String argument) {
resolveOnly = true;
String getDepsOutput(Map<Uri, SourceFile> sourceFiles) {
var filenames = => '$uri').toList();
return filenames.join("\n");
implyCompilation(String argument) {
setStrip(String argument) {
helpAndFail("Option '--force-strip' is not in use now that"
"--output-type=dart is no longer supported.");
void setAnalyzeOnly(String argument) {
analyzeOnly = true;
void setAnalyzeAll(String argument) {
analyzeAll = true;
void setAllowNativeExtensions(String argument) {
allowNativeExtensions = true;
void setVerbose(_) {
verbose = true;
void setTrustTypeAnnotations(String argument) {
trustTypeAnnotations = true;
void setTrustJSInteropTypeAnnotations(String argument) {
void setTrustPrimitives(String argument) {
void setCheckedMode(String argument) {
checkedMode = true;
void addInEnvironment(String argument) {
int eqIndex = argument.indexOf('=');
String name = argument.substring(2, eqIndex);
String value = argument.substring(eqIndex + 1);
environment[name] = value;
void setCategories(String argument) {
List<String> categories = extractParameter(argument).split(',');
if (categories.contains('all')) {
categories = ["Client", "Server"];
} else {
for (String category in categories) {
if (!["Client", "Server"].contains(category)) {
fail('Unsupported library category "$category", '
'supported categories are: Client, Server, all');
void handleThrowOnError(String argument) {
throwOnError = true;
String parameter = extractParameter(argument, isOptionalArgument: true);
if (parameter != null) {
var count = int.parse(parameter);
throwOnErrorCount = count;
void handleShortOptions(String argument) {
var shortOptions = argument.substring(1).split("");
for (var shortOption in shortOptions) {
switch (shortOption) {
case 'v':
case 'h':
case '?':
wantHelp = true;
case 'c':
case 'm':
throw 'Internal error: "$shortOption" did not match';
List<String> arguments = <String>[];
List<OptionHandler> handlers = <OptionHandler>[
new OptionHandler('-[chvm?]+', handleShortOptions),
new OptionHandler('--throw-on-error(?:=[0-9]+)?', handleThrowOnError),
new OptionHandler(Flags.suppressWarnings, (_) {
showWarnings = false;
new OptionHandler(Flags.fatalWarnings, passThrough),
new OptionHandler(Flags.suppressHints, (_) {
showHints = false;
// TODO(sigmund): remove entirely after Dart 1.20
new OptionHandler(
new OptionHandler(Flags.useKernel, passThrough),
new OptionHandler(Flags.noFrequencyBasedMinification, passThrough),
new OptionHandler(Flags.verbose, setVerbose),
new OptionHandler(Flags.version, (_) => wantVersion = true),
new OptionHandler('--library-root=.+', setLibraryRoot),
new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
new OptionHandler(Flags.allowMockCompilation, passThrough),
new OptionHandler(Flags.fastStartup, passThrough),
new OptionHandler(Flags.genericMethodSyntax, ignoreOption),
new OptionHandler(Flags.initializingFormalAccess, ignoreOption),
new OptionHandler('${Flags.minify}|-m', implyCompilation),
new OptionHandler(Flags.preserveUris, passThrough),
new OptionHandler('--force-strip=.*', setStrip),
new OptionHandler(Flags.disableDiagnosticColors, (_) {
enableColors = false;
new OptionHandler(Flags.enableDiagnosticColors, (_) {
enableColors = true;
new OptionHandler('--enable[_-]checked[_-]mode|--checked',
(_) => setCheckedMode(Flags.enableCheckedMode)),
new OptionHandler(Flags.trustTypeAnnotations,
(_) => setTrustTypeAnnotations(Flags.trustTypeAnnotations)),
new OptionHandler(Flags.trustPrimitives,
(_) => setTrustPrimitives(Flags.trustPrimitives)),
new OptionHandler(
(_) => setTrustJSInteropTypeAnnotations(
new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
new OptionHandler('--packages=.+', setPackageConfig),
new OptionHandler('--package-root=.+|-p.+', setPackageRoot),
new OptionHandler(Flags.analyzeAll, setAnalyzeAll),
new OptionHandler(Flags.analyzeOnly, setAnalyzeOnly),
new OptionHandler(Flags.noSourceMaps, passThrough),
new OptionHandler(Option.resolutionInput, setResolutionInput),
new OptionHandler(Option.bazelPaths, setBazelPaths),
new OptionHandler(Flags.resolveOnly, setResolveOnly),
new OptionHandler(Flags.analyzeSignaturesOnly, setAnalyzeOnly),
new OptionHandler(Flags.disableNativeLiveTypeAnalysis, passThrough),
new OptionHandler('--categories=.*', setCategories),
new OptionHandler(Flags.disableInlining, implyCompilation),
new OptionHandler(Flags.disableTypeInference, implyCompilation),
new OptionHandler(Flags.terse, passThrough),
new OptionHandler('--deferred-map=.+', implyCompilation),
new OptionHandler(Flags.dumpInfo, implyCompilation),
new OptionHandler(
'--disallow-unsafe-eval', (_) => hasDisallowUnsafeEval = true),
new OptionHandler(Option.showPackageWarnings, passThrough),
new OptionHandler(Flags.useContentSecurityPolicy, passThrough),
new OptionHandler(Flags.enableExperimentalMirrors, passThrough),
new OptionHandler(Flags.enableAssertMessage, passThrough),
// TODO(floitsch): remove conditional directives flag.
// We don't provide the info-message yet, since we haven't publicly
// launched the feature yet.
new OptionHandler(Flags.conditionalDirectives, (_) {}),
new OptionHandler('--enable-async', (_) {
hints.add("Option '--enable-async' is no longer needed. "
"Async-await is supported by default.");
new OptionHandler('--enable-null-aware-operators', (_) {
hints.add("Option '--enable-null-aware-operators' is no longer needed. "
"Null aware operators are supported by default.");
new OptionHandler('--enable-enum', (_) {
hints.add("Option '--enable-enum' is no longer needed. "
"Enums are supported by default.");
new OptionHandler(Flags.allowNativeExtensions, setAllowNativeExtensions),
new OptionHandler(Flags.generateCodeWithCompileTimeErrors, passThrough),
new OptionHandler(Flags.useMultiSourceInfo, passThrough),
new OptionHandler(Flags.useNewSourceInfo, passThrough),
new OptionHandler(Flags.testMode, passThrough),
// The following three options must come last.
new OptionHandler('-D.+=.*', addInEnvironment),
new OptionHandler('-.*', (String argument) {
helpAndFail("Unknown option '$argument'.");
new OptionHandler('.*', (String argument) {
parseCommandLine(handlers, argv);
// TODO(johnniwinther): Measure time for reading files.
SourceFileProvider inputProvider;
if (bazelPaths != null) {
inputProvider = new BazelInputProvider(bazelPaths);
} else {
inputProvider = new CompilerSourceFileProvider();
diagnosticHandler = new FormattingDiagnosticHandler(inputProvider);
if (verbose != null) {
diagnosticHandler.verbose = verbose;
if (throwOnError != null) {
diagnosticHandler.throwOnError = throwOnError;
if (throwOnErrorCount != null) {
diagnosticHandler.throwOnErrorCount = throwOnErrorCount;
if (showWarnings != null) {
diagnosticHandler.showWarnings = showWarnings;
if (showHints != null) {
diagnosticHandler.showHints = showHints;
if (enableColors != null) {
diagnosticHandler.enableColors = enableColors;
for (String hint in hints) {, api.Diagnostic.HINT);
if (wantHelp || wantVersion) {
helpAndExit(wantHelp, wantVersion, diagnosticHandler.verbose);
if (hasDisallowUnsafeEval) {
String precompiledName = relativize(
helpAndFail("Option '--disallow-unsafe-eval' has been removed."
" Instead, the compiler generates a file named"
" '$precompiledName'.");
if (arguments.isEmpty) {
helpAndFail('No Dart file specified.');
if (arguments.length > 1) {
var extra = arguments.sublist(1);
helpAndFail('Extra arguments: ${extra.join(" ")}');
if (checkedMode && trustTypeAnnotations) {
helpAndFail("Option '${Flags.trustTypeAnnotations}' may not be used in "
"checked mode.");
if (packageRoot != null && packageConfig != null) {
helpAndFail("Cannot specify both '--package-root' and '--packages.");
List<String> optionsImplyOutput = <String>[]
if (resolveOnly && !optionsImplyCompilation.isEmpty) {
"Options $optionsImplyCompilation indicate that compilation is "
"expected, but compilation is turned off by the option "
} else if ((analyzeOnly || analyzeAll) && !optionsImplyOutput.isEmpty) {
if (analyzeAll && !analyzeOnly) {
"Option '${Flags.analyzeAll}' implies '${Flags.analyzeOnly}'.",
"Options $optionsImplyOutput indicate that output is expected, "
"but compilation is turned off by the option '${Flags.analyzeOnly}'.",
if (resolveOnly) {
if (resolutionInputs != null &&
resolutionInputs.contains(resolutionOutput)) {
helpAndFail("Resolution input '${resolutionOutput}' can't be used as "
"resolution output. Use the '--out' option to specify another "
"resolution output.");
analyzeOnly = analyzeAll = true;
} else if (analyzeAll) {
analyzeOnly = true;
if (!analyzeOnly) {
if (allowNativeExtensions) {
helpAndFail("Option '${Flags.allowNativeExtensions}' is only supported "
"in combination with the '${Flags.analyzeOnly}' option.");
RandomAccessFileOutputProvider outputProvider =
new RandomAccessFileOutputProvider(out, sourceMapOut,
onFailure: fail,
resolutionOutput: resolveOnly ? resolutionOutput : null);
api.CompilationResult compilationDone(api.CompilationResult result) {
if (analyzeOnly) return result;
if (!result.isSuccess) {
fail('Compilation failed.');
Uri.parse('$out.deps'), getDepsOutput(inputProvider.sourceFiles));
.info('Compiled ${inputProvider.dartCharactersRead} characters Dart '
'-> ${outputProvider.totalCharactersWritten} characters '
'JavaScript in '
'${relativize(currentDirectory, out, Platform.isWindows)}');
if (diagnosticHandler.verbose) {
String input = uriPathToNative(arguments[0]);
print('Dart file ($input) compiled to JavaScript.');
print('Wrote the following files:');
for (String filename in outputProvider.allOutputFiles) {
print(" $filename");
} else if (explicitOutputArguments.isNotEmpty) {
String input = uriPathToNative(arguments[0]);
String output = relativize(currentDirectory, out, Platform.isWindows);
print('Dart file ($input) compiled to JavaScript: $output');
return result;
Uri script = currentDirectory.resolve(arguments[0]);
CompilerOptions compilerOptions = new CompilerOptions.parse(
entryPoint: script,
libraryRoot: libraryRoot,
packageRoot: packageRoot,
packageConfig: packageConfig,
packagesDiscoveryProvider: findPackages,
resolutionInputs: resolutionInputs,
resolutionOutput: resolveOnly ? resolutionOutput : null,
options: options,
environment: environment);
return compileFunc(
compilerOptions, inputProvider, diagnosticHandler, outputProvider)
class AbortLeg {
final message;
toString() => 'Aborted due to --throw-on-error: $message';
void writeString(Uri uri, String text) {
if (!enableWriteString) return;
if (uri.scheme != 'file') {
fail('Unhandled scheme ${uri.scheme}.');
var file = new File(uri.toFilePath()).openSync(mode: FileMode.WRITE);
void fail(String message) {
if (diagnosticHandler != null) {, null, -1, -1, message, api.Diagnostic.ERROR);
} else {
print('Error: $message');
Future<api.CompilationResult> compilerMain(List<String> arguments) {
var root = uriPathToNative("/$LIBRARY_ROOT");
arguments = <String>['--library-root=${Platform.script.toFilePath()}$root']
return compile(arguments);
void help() {
// This message should be no longer than 20 lines. The default
// terminal size normally 80x24. Two lines are used for the prompts
// before and after running the compiler. Another two lines may be
// used to print an error message.
Usage: dart2js [options] dartfile
Compiles Dart to JavaScript.
Common options:
-o <file> Generate the output into <file>.
-c Insert runtime type checks and enable assertions (checked mode).
-m Generate minified output.
-h Display this message (add -v for information about all options).''');
void verboseHelp() {
Usage: dart2js [options] dartfile
Compiles Dart to JavaScript.
Supported options:
-o <file>, --out=<file>
Generate the output into <file>.
-c, --enable-checked-mode, --checked
Insert runtime type checks and enable assertions (checked mode).
-m, --minify
Generate minified output.
-h, /h, /?, --help
Display this message (add -v for information about all options).
-v, --verbose
Display verbose information.
Define an environment variable.
Display version information.
-p<path>, --package-root=<path>
Where to find packages, that is, "package:..." imports. This option cannot
be used with --packages.
Path to the package resolution configuration file, which supplies a mapping
of package names to paths. This option cannot be used with --package-root.
Analyze all code. Without this option, the compiler only analyzes
code that is reachable from [main]. This option implies --analyze-only.
Analyze but do not generate code.
Skip analysis of method bodies and field initializers. This option implies
Do not display any warnings.
Treat warnings as compilation errors.
Do not display any hints.
Add colors to diagnostic messages.
Emit diagnostics without suggestions for how to get rid of the diagnosed
Show warnings and hints generated from packages.
Preserve the source URIs in the reflection data. Without this flag the
`uri` getter for `LibraryMirror`s is mangled in minified mode.
Disables dynamic generation of code in the generated output. This is
necessary to satisfy CSP restrictions (see
Do not generate a source map file.
The following options are only used for compiler development and may
be removed in a future version:
Throw an exception if a compile-time error is detected.
Where to find the Dart platform libraries.
Do not generate a call to main if either of the following
libraries are used: dart:dom, dart:html dart:io.
Disable the optimization that removes unused native types from dart:html
and related libraries.
A comma separated list of allowed library categories. The default
is "Client". Possible categories can be seen by providing an
unsupported category, for example, --categories=help. To enable
all categories, use --categories=all.
Generates a json file with a mapping from each deferred import to a list of
the part.js files that will be loaded.
Generates an file with information about the generated code.
You can inspect the generated file with the viewer at:
Generates output even if the program contains compile-time errors. Use the
exit code to determine if compilation failed.
Experimental. Disabled the new frequency based minifying namer and use the
old namer instead.
void helpAndExit(bool wantHelp, bool wantVersion, bool verbose) {
if (wantVersion) {
var version = (BUILD_ID == null) ? '<non-SDK build>' : BUILD_ID;
print('Dart-to-JavaScript compiler (dart2js) version: $version');
if (wantHelp) {
if (verbose) {
} else {
void helpAndFail(String message) {
void main(List<String> arguments) {
// Since the sdk/bin/dart2js script adds its own arguments in front of
// user-supplied arguments we search for '--batch' at the end of the list.
if (arguments.length > 0 && arguments.last == "--batch") {
batchMain(arguments.sublist(0, arguments.length - 1));
typedef void ExitFunc(int exitCode);
typedef Future<api.CompilationResult> CompileFunc(
CompilerOptions compilerOptions,
api.CompilerInput compilerInput,
api.CompilerDiagnostics compilerDiagnostics,
api.CompilerOutput compilerOutput);
ExitFunc exitFunc = exit;
CompileFunc compileFunc = api.compile;
/// If `true` a '.deps' file will be generated after compilation.
/// Set this to `false` in end-to-end tests to avoid generating '.deps' files.
bool enableWriteString = true;
Future<api.CompilationResult> internalMain(List<String> arguments) {
Future onError(exception, trace) {
// If we are already trying to exit, just continue exiting.
if (exception == _EXIT_SIGNAL) throw exception;
try {
print('The compiler crashed: $exception');
} catch (ignored) {
print('The compiler crashed: error while printing exception');
try {
if (trace != null) {
} finally {
exitFunc(253); // 253 is recognized as a crash by our test scripts.
return new Future.error(exception, trace);
try {
return compilerMain(arguments).catchError(onError);
} catch (exception, trace) {
return onError(exception, trace);
class _ExitSignal {
const _ExitSignal();
const _EXIT_SIGNAL = const _ExitSignal();
void batchMain(List<String> batchArguments) {
int exitCode;
exitFunc = (errorCode) {
// Since we only throw another part of the compiler might intercept our
// exception and try to exit with a different code.
if (exitCode == 0) {
exitCode = errorCode;
var stream = stdin.transform(UTF8.decoder).transform(new LineSplitter());
var subscription;
subscription = stream.listen((line) {
new Future.sync(() {
exitCode = 0;
if (line == null) exit(0);
List<String> args = <String>[];
args.addAll(splitLine(line, windows: Platform.isWindows));
return internalMain(args);
}).catchError((exception, trace) {
if (!identical(exception, _EXIT_SIGNAL)) {
exitCode = 253;
}).whenComplete(() {
// The testing framework waits for a status line on stdout and
// stderr before moving to the next test.
if (exitCode == 0) {
print(">>> TEST OK");
} else if (exitCode == 253) {
print(">>> TEST CRASH");
} else {
print(">>> TEST FAIL");
stderr.writeln(">>> EOF STDERR");
// TODO(johnniwinther): Add corresponding options to the test script and change
// these to use 'bool.fromEnvironment'.
Platform.environment['USE_SERIALIZED_DART_CORE'] == 'true';
Platform.environment['SERIALIZED_COMPILATION'] == 'true';
/// Mock URI used only in testing when [USE_SERIALIZED_DART_CORE] or
final Uri _SERIALIZED_DART_CORE_URI = Uri.parse('');
final Uri _SERIALIZED_TEST_URI = Uri.parse('');
void _useSerializedDataForDartCore(CompileFunc oldCompileFunc) {
/// Run the [oldCompileFunc] with [serializedData] added as resolution input.
Future<api.CompilationResult> compileWithSerializedData(
CompilerOptions compilerOptions,
api.CompilerInput compilerInput,
api.CompilerDiagnostics compilerDiagnostics,
api.CompilerOutput compilerOutput,
List<_SerializedData> serializedData,
{bool compileOnly: false}) {
api.CompilerInput input = compilerInput;
CompilerOptions options = compilerOptions;
if (serializedData != null && serializedData.isNotEmpty) {
Map<Uri, String> dataMap = <Uri, String>{};
for (_SerializedData data in serializedData) {
dataMap[data.uri] =;
input = new _CompilerInput(input, dataMap);
List<Uri> resolutionInputs = dataMap.keys.toList();
if (compilerOptions.resolutionInputs != null) {
for (Uri uri in compilerOptions.resolutionInputs) {
if (!dataMap.containsKey(uri)) {
options = CompilerOptions.copy(options,
resolutionInputs: resolutionInputs, compileOnly: compileOnly);
return oldCompileFunc(options, input, compilerDiagnostics, compilerOutput);
/// Serialize [entryPoint] using [serializedData] if provided.
Future<api.CompilationResult> serialize(
Uri entryPoint,
Uri serializedUri,
CompilerOptions compilerOptions,
api.CompilerInput compilerInput,
api.CompilerDiagnostics compilerDiagnostics,
api.CompilerOutput compilerOutput,
[List<_SerializedData> serializedData]) {
CompilerOptions options = CompilerOptions.copy(compilerOptions,
entryPoint: entryPoint,
resolutionOutput: serializedUri,
analyzeAll: true,
analyzeOnly: true,
resolveOnly: true);
return compileWithSerializedData(options, compilerInput,
compilerDiagnostics, compilerOutput, serializedData);
// Local cache for the serialized data for dart:core.
_SerializedData serializedDartCore;
/// Serialize the entry point using serialized data from dart:core and run
/// [oldCompileFunc] using serialized data for whole program.
Future<api.CompilationResult> compileFromSerializedData(
CompilerOptions compilerOptions,
api.CompilerInput compilerInput,
api.CompilerDiagnostics compilerDiagnostics,
api.CompilerOutput compilerOutput) async {
_CompilerOutput output = new _CompilerOutput(_SERIALIZED_TEST_URI);
api.CompilationResult result = await serialize(
if (!result.isSuccess) {
return result;
return compileWithSerializedData(
[serializedDartCore, output.serializedData],
compileOnly: true);
/// Compiles the entry point using the serialized data from dart:core.
Future<api.CompilationResult> compileWithSerializedDartCoreData(
CompilerOptions compilerOptions,
api.CompilerInput compilerInput,
api.CompilerDiagnostics compilerDiagnostics,
api.CompilerOutput compilerOutput) async {
return compileWithSerializedData(compilerOptions, compilerInput,
compilerDiagnostics, compilerOutput, [serializedDartCore]);
/// Serialize dart:core data into [serializedDartCore] and setup the
/// [compileFunc] to run the compiler using this data.
Future<api.CompilationResult> generateSerializedDataForDartCore(
CompilerOptions compilerOptions,
api.CompilerInput compilerInput,
api.CompilerDiagnostics compilerDiagnostics,
api.CompilerOutput compilerOutput) async {
_CompilerOutput output = new _CompilerOutput(_SERIALIZED_DART_CORE_URI);
await serialize(Uris.dart_core, output.uri, compilerOptions, compilerInput,
compilerDiagnostics, output);
serializedDartCore = output.serializedData;
compileFunc = compileFromSerializedData;
} else {
compileFunc = compileWithSerializedDartCoreData;
return compileFunc(
compilerOptions, compilerInput, compilerDiagnostics, compilerOutput);
compileFunc = generateSerializedDataForDartCore;
class _CompilerInput implements api.CompilerInput {
final api.CompilerInput _input;
final Map<Uri, String> _data;
_CompilerInput(this._input, this._data);
Future readFromUri(Uri uri) {
String data = _data[uri];
if (data != null) {
return new Future.value(data);
return _input.readFromUri(uri);
class _SerializedData {
final Uri uri;
final String data;
class _CompilerOutput extends NullCompilerOutput {
final Uri uri;
_BufferedOutputSink sink;
api.OutputSink createOutputSink(
String name, String extension, api.OutputType type) {
if (name == '' && extension == 'data') {
return sink = new _BufferedOutputSink();
return super.createOutputSink(name, extension, type);
_SerializedData get serializedData {
return new _SerializedData(uri,;
class _BufferedOutputSink implements api.OutputSink {
StringBuffer sb = new StringBuffer();
void add(String event) {
void close() {
// Do nothing.