| Index: utils/kernel-service/kernel-service.dart
|
| diff --git a/utils/kernel-service/kernel-service.dart b/utils/kernel-service/kernel-service.dart
|
| index 957613bee19664e17fb17e0e295639227e5dc70a..0df8cbef8dfc462592d82aa66292943a09b99e56 100644
|
| --- a/utils/kernel-service/kernel-service.dart
|
| +++ b/utils/kernel-service/kernel-service.dart
|
| @@ -20,21 +20,98 @@
|
| ///
|
| library runtime.tools.kernel_service;
|
|
|
| -import 'dart:async';
|
| -import 'dart:io' hide FileSystemEntity;
|
| +import 'dart:async' show Future;
|
| +import 'dart:io' show File, Platform hide FileSystemEntity;
|
| import 'dart:isolate';
|
| +import 'dart:typed_data' show Uint8List;
|
|
|
| import 'package:front_end/file_system.dart';
|
| +import 'package:front_end/front_end.dart';
|
| import 'package:front_end/memory_file_system.dart';
|
| import 'package:front_end/physical_file_system.dart';
|
| -import 'package:front_end/src/fasta/vm.dart'
|
| - show CompilationResult, Status, parseScriptInFileSystem;
|
| +import 'package:front_end/src/fasta/kernel/utils.dart';
|
| import 'package:front_end/src/testing/hybrid_file_system.dart';
|
| +import 'package:kernel/kernel.dart' show Program;
|
| +import 'package:kernel/target/targets.dart' show TargetFlags;
|
| +import 'package:kernel/target/vm_fasta.dart' show VmFastaTarget;
|
|
|
| const bool verbose = const bool.fromEnvironment('DFE_VERBOSE');
|
|
|
| const bool strongMode = const bool.fromEnvironment('DFE_STRONG_MODE');
|
|
|
| +/// CODE REVIEW NOTE: this came from fasta.dart, moved here because it is
|
| +/// specific to the kernel-service and nothing else.
|
| +Future<CompilationResult> _parseScriptInFileSystem(
|
| + Uri script, FileSystem fileSystem,
|
| + {bool verbose: false, bool strongMode: false}) async {
|
| + final Uri packagesUri = (Platform.packageConfig != null)
|
| + ? Uri.parse(Platform.packageConfig)
|
| + : await _findPackagesFile(fileSystem, script);
|
| + if (packagesUri == null) {
|
| + throw "Could not find .packages";
|
| + }
|
| +
|
| + final Uri patchedSdk = Uri.base
|
| + .resolveUri(new Uri.file(Platform.resolvedExecutable))
|
| + .resolveUri(new Uri.directory("patched_sdk"));
|
| +
|
| + if (verbose) {
|
| + print("""DFE: Requesting compilation {
|
| + scriptUri: ${script}
|
| + packagesUri: ${packagesUri}
|
| + patchedSdk: ${patchedSdk}
|
| +}""");
|
| + }
|
| +
|
| + try {
|
| + var errors = <String>[];
|
| + var options = new CompilerOptions()
|
| + ..strongMode = strongMode
|
| + ..fileSystem = fileSystem
|
| + ..target = new VmFastaTarget(new TargetFlags(strongMode: strongMode))
|
| + ..packagesFileUri = packagesUri
|
| + // TODO(sigmund): use outline.dill when the mixin transformer is modular.
|
| + ..sdkSummary = patchedSdk.resolve('platform.dill')
|
| + ..verbose = verbose
|
| + ..onError = (CompilationError e) => errors.add(e.message);
|
| +
|
| + Program program = await kernelForProgram(script, options);
|
| + if (errors.isNotEmpty) return new CompilationResult.errors(errors);
|
| +
|
| + // We serialize the program excluding platform.dill because the VM has these
|
| + // sources built-in. Everything loaded as a summary in [kernelForProgram] is
|
| + // marked `external`, so we can use that bit to decide what to excluce.
|
| + return new CompilationResult.ok(
|
| +
|
| + /// CODE REVIEW NOTE: this is a change: we used to call the
|
| + /// LibraryFilteringBinaryBuilder. [serializeProgram] uses
|
| + /// LimitedBinaryBuilder instead (which not only excludes code, but also
|
| + /// string tables from excluded libraries).
|
| + serializeProgram(program, filter: (lib) => !lib.isExternal));
|
| + } catch (err, stack) {
|
| + return new CompilationResult.crash(err, stack);
|
| + }
|
| +}
|
| +
|
| +/// This duplicates functionality from the Loader which we can't easily
|
| +/// access from here.
|
| +// TODO(sigmund): delete, this should be supported by the default options in
|
| +// package:front_end.
|
| +Future<Uri> _findPackagesFile(FileSystem fileSystem, Uri base) async {
|
| + var dir = new File.fromUri(base).parent;
|
| + while (true) {
|
| + final packagesFile = dir.uri.resolve(".packages");
|
| + if (await fileSystem.entityForUri(packagesFile).exists()) {
|
| + return packagesFile;
|
| + }
|
| + if (dir.parent.path == dir.path) {
|
| + break;
|
| + }
|
| + dir = dir.parent;
|
| + }
|
| + return null;
|
| +}
|
| +
|
| Future<CompilationResult> _processLoadRequestImpl(
|
| String inputFilePathOrUri, FileSystem fileSystem) {
|
| Uri scriptUri = Uri.parse(inputFilePathOrUri);
|
| @@ -50,10 +127,10 @@ Future<CompilationResult> _processLoadRequestImpl(
|
|
|
| if (!scriptUri.isScheme('file')) {
|
| // TODO(vegorov): Reuse loader code to support other schemes.
|
| - return new Future<CompilationResult>.value(new CompilationResult.error(
|
| - "Expected 'file' scheme for a script uri: got ${scriptUri.scheme}"));
|
| + return new Future<CompilationResult>.value(new CompilationResult.errors(
|
| + ["Expected 'file' scheme for a script uri: got ${scriptUri.scheme}"]));
|
| }
|
| - return parseScriptInFileSystem(scriptUri, fileSystem,
|
| + return _parseScriptInFileSystem(scriptUri, fileSystem,
|
| verbose: verbose, strongMode: strongMode);
|
| }
|
|
|
| @@ -146,3 +223,91 @@ main([args]) {
|
| return new RawReceivePort()..handler = _processLoadRequest;
|
| }
|
| }
|
| +
|
| +/// CODE REVIEW NOTE: this came from fasta/vm.dart, also moved here because it
|
| +/// is specific to the kernel-service and nothing else.
|
| +
|
| +/// Compilation status codes.
|
| +///
|
| +/// Note: The [index] property of these constants must match
|
| +/// `Dart_KernelCompilationStatus` in
|
| +/// [dart_api.h](../../../../runtime/include/dart_api.h).
|
| +enum Status {
|
| + /// Compilation was successful.
|
| + ok,
|
| +
|
| + /// Compilation failed with a compile time error.
|
| + error,
|
| +
|
| + /// Compiler crashed.
|
| + crash,
|
| +}
|
| +
|
| +abstract class CompilationResult {
|
| + CompilationResult._();
|
| +
|
| + factory CompilationResult.ok(Uint8List bytes) = _CompilationOk;
|
| +
|
| + factory CompilationResult.errors(List<String> errors) = _CompilationError;
|
| +
|
| + factory CompilationResult.crash(Object exception, StackTrace stack) =
|
| + _CompilationCrash;
|
| +
|
| + Status get status;
|
| +
|
| + get payload;
|
| +
|
| + List toResponse() => [status.index, payload];
|
| +}
|
| +
|
| +class _CompilationOk extends CompilationResult {
|
| + final Uint8List bytes;
|
| +
|
| + _CompilationOk(this.bytes) : super._();
|
| +
|
| + @override
|
| + Status get status => Status.ok;
|
| +
|
| + @override
|
| + get payload => bytes;
|
| +
|
| + String toString() => "_CompilationOk(${bytes.length} bytes)";
|
| +}
|
| +
|
| +abstract class _CompilationFail extends CompilationResult {
|
| + _CompilationFail() : super._();
|
| +
|
| + String get errorString;
|
| +
|
| + @override
|
| + get payload => errorString;
|
| +}
|
| +
|
| +class _CompilationError extends _CompilationFail {
|
| + final List<String> errors;
|
| +
|
| + _CompilationError(this.errors);
|
| +
|
| + @override
|
| + Status get status => Status.error;
|
| +
|
| + @override
|
| + String get errorString => errors.take(10).join('\n');
|
| +
|
| + String toString() => "_CompilationError(${errorString})";
|
| +}
|
| +
|
| +class _CompilationCrash extends _CompilationFail {
|
| + final Object exception;
|
| + final StackTrace stack;
|
| +
|
| + _CompilationCrash(this.exception, this.stack);
|
| +
|
| + @override
|
| + Status get status => Status.crash;
|
| +
|
| + @override
|
| + String get errorString => "${exception}\n${stack}";
|
| +
|
| + String toString() => "_CompilationCrash(${errorString})";
|
| +}
|
|
|