blob: 2b5acacc4e9572b9794cf29a355ce06e03d553fb [file] [log] [blame]
#!/usr/bin/env dart
// Copyright (c) 2018, 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.
//
// Compiles code with DDC and runs the resulting code with either node or
// chrome.
//
// The first script supplied should be the one with `main()`.
//
// Saves the output in the same directory as the sources for convenient
// inspection, modification or rerunning the code.
import 'dart:async';
import 'dart:io';
import 'package:args/args.dart' show ArgParser;
import 'package:path/path.dart' as path;
// TODO(vsm): Remove this once we stop ignoring. It's off here, but
// configurable for manual testing.
const ignoreWhitelistedErrors = false;
void main(List<String> args) {
// Parse flags.
var parser = new ArgParser()
..addFlag('kernel',
abbr: 'k', help: 'Compile with the new kernel-based front end.')
..addFlag('debug',
abbr: 'd',
help: 'Use current source instead of built SDK.',
defaultsTo: false)
..addOption('runtime',
abbr: 'r',
help: 'Platform to run on (node|d8|chrome). Default is node.',
allowed: ['node', 'd8', 'chrome'],
defaultsTo: 'node')
..addOption('binary', abbr: 'b', help: 'Runtime binary path.');
var options = parser.parse(args);
if (options.rest.length != 1) {
throw 'Expected a single dart entrypoint.';
}
var entry = options.rest.first;
var libRoot = path.dirname(entry);
var basename = path.basenameWithoutExtension(entry);
var debug = options['debug'] as bool;
var kernel = options['kernel'] as bool;
var binary = options['binary'] as String;
var dartBinary = Platform.resolvedExecutable;
var dartPath = path.dirname(dartBinary);
var dartSdk = path.dirname(dartPath);
var toolPath = Platform.script.normalizePath().toFilePath();
var ddcPath = path.dirname(path.dirname(toolPath));
ProcessResult runDdc(String command, List<String> args) {
if (debug) {
// Use unbuilt script. This only works from a source checkout.
args.insertAll(0, [
'--preview-dart-2',
'--enable-asserts',
path.join(ddcPath, 'bin', '${command}.dart')
]);
command = dartBinary;
} else {
// Use built snapshot.
command = path.join(dartPath, command);
}
return Process.runSync(command, args);
}
String mod;
bool chrome = false;
bool node = false;
bool d8 = false;
switch (options['runtime']) {
case 'node':
node = true;
mod = 'common';
break;
case 'd8':
d8 = true;
mod = 'es6';
break;
case 'chrome':
chrome = true;
mod = 'amd';
break;
}
String sdkJsPath;
String requirePath;
String ddcSdk;
if (debug) {
var sdkRoot = path.dirname(path.dirname(ddcPath));
var buildDir = path.join(sdkRoot, Platform.isMacOS ? 'xcodebuild' : 'out');
var genDir = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc');
sdkJsPath = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc',
kernel ? 'kernel' : 'js', mod);
requirePath = path.join(sdkRoot, 'third_party', 'requirejs');
ddcSdk = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc',
kernel ? path.join('kernel', 'ddc_sdk.dill') : 'ddc_sdk.sum');
} else {
var suffix = kernel ? path.join('kernel', mod) : mod;
sdkJsPath = path.join(dartSdk, 'lib', 'dev_compiler', suffix);
requirePath = sdkJsPath;
ddcSdk = path.join(
dartSdk, 'lib', '_internal', kernel ? 'ddc_sdk.dill' : 'ddc_sdk.sum');
}
ProcessResult result;
if (kernel) {
result = runDdc('dartdevk', [
'--modules=$mod',
'--dart-sdk-summary=$ddcSdk',
'-o',
'$libRoot/$basename.js',
entry
]);
} else {
result = runDdc('dartdevc', [
'--modules=$mod',
'--dart-sdk-summary=$ddcSdk',
'--library-root=$libRoot',
'-o',
'$libRoot/$basename.js',
entry
]);
}
print(result.stdout);
if (result.exitCode != 0) {
print(result.stderr);
exit(result.exitCode);
}
if (chrome) {
String chromeBinary;
if (binary != null) {
chromeBinary = binary;
} else if (Platform.isWindows) {
chromeBinary =
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe';
} else if (Platform.isMacOS) {
chromeBinary =
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
} else {
// Assume Linux
chromeBinary = 'google-chrome';
}
var html = """
<script src='$requirePath/require.js'></script>
<script>
require.config({
baseUrl: '$libRoot',
paths: {
'dart_sdk': '$sdkJsPath/dart_sdk'
},
waitSeconds: 15
});
require(['dart_sdk', '$basename'],
function(sdk, app) {
'use strict';
sdk._debugger.registerDevtoolsFormatter();
sdk.dart.ignoreWhitelistedErrors($ignoreWhitelistedErrors);
app.$basename.main();
});
</script>
""";
var htmlFile = '$libRoot/$basename.html';
new File(htmlFile).writeAsStringSync(html);
var tmp = path.join(Directory.systemTemp.path, 'ddc');
result = Process.runSync(chromeBinary,
['--auto-open-devtools-for-tabs', '--user-data-dir=$tmp', htmlFile]);
} else if (node) {
var nodePath = '$sdkJsPath:$libRoot';
var runjs = '''
let source_maps;
try {
source_maps = require('source-map-support');
source_maps.install();
} catch(e) {
}
let sdk = require(\"dart_sdk\");
let main = require(\"./$basename\").$basename.main;
sdk.dart.ignoreWhitelistedErrors($ignoreWhitelistedErrors);
try {
sdk._isolate_helper.startRootIsolate(main, []);
} catch(e) {
if (!source_maps) {
console.log('For Dart source maps: npm install source-map-support');
}
console.error(e);
process.exit(1);
}
''';
var nodeFile = '$libRoot/$basename.run.js';
new File(nodeFile).writeAsStringSync(runjs);
var nodeBinary = binary ?? 'node';
result = Process
.runSync(nodeBinary, [nodeFile], environment: {'NODE_PATH': nodePath});
stdout
..write(result.stdout)
..flush();
} else if (d8) {
var runjs = '''
import { dart, _isolate_helper } from '$sdkJsPath/dart_sdk.js';
import { $basename } from '$basename.js';
let main = $basename.main;
dart.ignoreWhitelistedErrors($ignoreWhitelistedErrors);
try {
_isolate_helper.startRootIsolate(() => {}, []);
main();
} catch(e) {
console.error(e);
}
''';
var d8File = '$libRoot/$basename.d8.js';
new File(d8File).writeAsStringSync(runjs);
var d8Binary = binary ?? 'd8';
result = Process.runSync(binary, ['--module', d8File]);
stdout
..write(result.stdout)
..flush();
}
if (result.exitCode != 0) {
print(result.stderr);
exit(result.exitCode);
}
}