Add hook to use single-root in fasta scripts and make use of it when creating
the dart2js platform files.
The main use-case right now is in compile-platform, but the way it is implemented
makes this available to any fasta tool.
This also adds resolveInputUri so we don't incorrectly treat supported URIs as file:* Uris.
Fixes https://github.com/dart-lang/sdk/issues/32633
Change-Id: I0ea3b1128352e72957b35823c6a1749ee418768b
Reviewed-on: https://dart-review.googlesource.com/56282
Reviewed-by: Zach Anderson <zra@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
Commit-Queue: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart b/pkg/front_end/lib/src/scheme_based_file_system.dart
similarity index 94%
rename from pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart
rename to pkg/front_end/lib/src/scheme_based_file_system.dart
index c992ea7..c2b3981 100644
--- a/pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart
+++ b/pkg/front_end/lib/src/scheme_based_file_system.dart
@@ -2,7 +2,7 @@
// 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.
-import 'file_system.dart';
+import 'api_prototype/file_system.dart';
/// A [FileSystem] that delegates to other file systems based on the URI scheme.
class SchemeBasedFileSystem implements FileSystem {
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 4ba2dc2..86c698f 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -20,6 +20,7 @@
dev_dependencies:
analyzer: '>=0.31.0 <0.33.0'
args: '>=0.13.0 <2.0.0'
+ build_integration: ^0.0.1
dart_style: '^1.0.7'
json_rpc_2: ^2.0.4
mockito: ^2.0.2
diff --git a/pkg/front_end/test/scheme_based_file_system_test.dart b/pkg/front_end/test/scheme_based_file_system_test.dart
index be40f65..e6b374b 100644
--- a/pkg/front_end/test/scheme_based_file_system_test.dart
+++ b/pkg/front_end/test/scheme_based_file_system_test.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:front_end/src/api_prototype/file_system.dart';
-import 'package:front_end/src/api_prototype/scheme_based_file_system.dart';
+import 'package:front_end/src/scheme_based_file_system.dart';
import 'package:test/test.dart';
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index daceb3cd..8408682 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -6,9 +6,17 @@
import 'dart:io' show exit;
+import 'package:build_integration/file_system/single_root.dart'
+ show SingleRootFileSystem;
+
import 'package:front_end/src/api_prototype/compiler_options.dart'
show CompilerOptions;
+import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;
+
+import 'package:front_end/src/api_prototype/standard_file_system.dart'
+ show StandardFileSystem;
+
import 'package:front_end/src/base/processed_options.dart'
show ProcessedOptions;
@@ -29,10 +37,13 @@
import 'package:front_end/src/fasta/severity.dart' show Severity;
+import 'package:front_end/src/scheme_based_file_system.dart'
+ show SchemeBasedFileSystem;
+
import 'package:kernel/target/targets.dart'
show Target, getTarget, TargetFlags, targets;
-Uri resolveFile(String path) => Uri.base.resolveUri(new Uri.file(path));
+import 'resolve_input_uri.dart' show resolveInputUri;
class CommandLineProblem {
final Message message;
@@ -159,7 +170,9 @@
"but expected one of: 'true', 'false', 'yes', or 'no'.");
}
} else if (valueSpecification == Uri) {
- parsedValue = resolveFile(value);
+ // TODO(ahe): resolve Uris lazily, so that schemes provided by
+ // other flags can be used for parsed command-line arguments too.
+ parsedValue = resolveInputUri(value);
} else if (valueSpecification == String) {
parsedValue = value;
} else if (valueSpecification is String) {
@@ -210,6 +223,8 @@
"--packages": Uri,
"--platform": Uri,
"--sdk": Uri,
+ "--single-root-scheme": String,
+ "--single-root-base": Uri,
"--strong": "--strong-mode",
"--strong-mode": false,
"--sync-async": true,
@@ -279,6 +294,24 @@
final bool compileSdk = options.containsKey("--compile-sdk");
+ final String singleRootScheme = options["--single-root-scheme"];
+ final Uri singleRootBase = options["--single-root-base"];
+
+ FileSystem fileSystem = StandardFileSystem.instance;
+ List<String> extraSchemes = const [];
+ if (singleRootScheme != null) {
+ extraSchemes = [singleRootScheme];
+ fileSystem = new SchemeBasedFileSystem({
+ 'file': fileSystem,
+ 'data': fileSystem,
+ // TODO(askesc): remove also when fixing StandardFileSystem (empty schemes
+ // should have been handled elsewhere).
+ '': fileSystem,
+ singleRootScheme: new SingleRootFileSystem(
+ singleRootScheme, singleRootBase, fileSystem),
+ });
+ }
+
if (programName == "compile_platform") {
if (arguments.length != 4) {
return throw new CommandLineProblem.deprecated(
@@ -296,8 +329,10 @@
return new ProcessedOptions(
new CompilerOptions()
..sdkSummary = options["--platform"]
- ..librariesSpecificationUri = resolveFile(arguments[1])
+ ..librariesSpecificationUri =
+ resolveInputUri(arguments[1], extraSchemes: extraSchemes)
..setExitCodeOnProblem = true
+ ..fileSystem = fileSystem
..packagesFileUri = packages
..strongMode = strongMode
..target = target
@@ -308,12 +343,13 @@
..verbose = verbose
..verify = verify,
<Uri>[Uri.parse(arguments[0])],
- resolveFile(arguments[2]));
+ resolveInputUri(arguments[2], extraSchemes: extraSchemes));
} else if (arguments.isEmpty) {
return throw new CommandLineProblem.deprecated("No Dart file specified.");
}
- final Uri defaultOutput = resolveFile("${arguments.first}.dill");
+ final Uri defaultOutput =
+ resolveInputUri("${arguments.first}.dill", extraSchemes: extraSchemes);
final Uri output = options["-o"] ?? options["--output"] ?? defaultOutput;
@@ -326,6 +362,7 @@
CompilerOptions compilerOptions = new CompilerOptions()
..compileSdk = compileSdk
+ ..fileSystem = fileSystem
..sdkRoot = sdk
..sdkSummary = platform
..packagesFileUri = packages
@@ -343,7 +380,7 @@
List<Uri> inputs = <Uri>[];
if (areRestArgumentsInputs) {
for (String argument in arguments) {
- inputs.add(resolveFile(argument));
+ inputs.add(resolveInputUri(argument, extraSchemes: extraSchemes));
}
}
return new ProcessedOptions(compilerOptions, inputs, output);
diff --git a/pkg/front_end/tool/_fasta/resolve_input_uri.dart b/pkg/front_end/tool/_fasta/resolve_input_uri.dart
new file mode 100644
index 0000000..f0b49d5
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/resolve_input_uri.dart
@@ -0,0 +1,19 @@
+// 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.
+
+/// Resolve [string] as a [Uri]. If the input [string] starts with a supported
+/// scheme, it is resolved as a Uri of that scheme, otherwise the [string]
+/// is treated as a file system (possibly relative) path.
+///
+/// Three schemes are always supported by default: `dart`, `package`, and
+/// `data`. Additional supported schemes can be specified via [extraSchemes].
+Uri resolveInputUri(String string, {List<String> extraSchemes: const []}) {
+ if (string.startsWith('dart:')) return Uri.parse(string);
+ if (string.startsWith('data:')) return Uri.parse(string);
+ if (string.startsWith('package:')) return Uri.parse(string);
+ for (var scheme in extraSchemes) {
+ if (string.startsWith('$scheme:')) return Uri.parse(string);
+ }
+ return Uri.base.resolveUri(new Uri.file(string));
+}
diff --git a/pkg/front_end/tool/_fasta/resolve_input_uri_test.dart b/pkg/front_end/tool/_fasta/resolve_input_uri_test.dart
new file mode 100644
index 0000000..7020ffc
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/resolve_input_uri_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+import 'package:test/test.dart';
+
+import 'resolve_input_uri.dart';
+
+main() {
+ test('data URI scheme is supported by default', () {
+ expect(resolveInputUri('data:,foo').scheme, 'data');
+ });
+
+ test('internal dart schemes are recognized by default', () {
+ expect(resolveInputUri('dart:foo').scheme, 'dart');
+ expect(resolveInputUri('package:foo').scheme, 'package');
+ });
+
+ test('unknown schemes are not recognized by default', () {
+ expect(resolveInputUri('test:foo').scheme, 'file');
+ expect(resolveInputUri('org-dartlang-foo:bar').scheme, 'file');
+ });
+
+ test('more schemes can be supported', () {
+ expect(resolveInputUri('test:foo', extraSchemes: ['test']).scheme, 'test');
+ expect(
+ resolveInputUri('org-dartlang-foo:bar',
+ extraSchemes: ['org-dartlang-foo']).scheme,
+ 'org-dartlang-foo');
+ });
+}
diff --git a/utils/compile_platform.gni b/utils/compile_platform.gni
index 68ade10..4601662 100644
--- a/utils/compile_platform.gni
+++ b/utils/compile_platform.gni
@@ -17,6 +17,14 @@
assert(defined(invoker.sources), "Need 'sources' in $target_name")
assert(defined(invoker.outputs), "Need 'outputs' in $target_name")
assert(defined(invoker.args), "Need 'args' in $target_name")
+ if (defined(invoker.single_root_scheme)) {
+ assert(defined(invoker.single_root_base),
+ "Need 'single_root_base' in $target_name")
+ }
+ if (defined(invoker.single_root_base)) {
+ assert(defined(invoker.single_root_scheme),
+ "Need 'single_root_scheme' in $target_name")
+ }
assert(!defined(invoker.script), "Remove 'script' from $target_name")
assert(!defined(invoker.depfile), "Remove 'depfile' from $target_name")
@@ -35,7 +43,15 @@
action(target_name) {
script = "$_dart_root/tools/compile_platform.py"
- sources = invoker.sources
+ # Note: invoker.sources contains a library-specification URI. It's not
+ # listed as a source of the action because it may be written using a custom
+ # URI when this template is invoked with a single_root_scheme.
+ #
+ # The compile_platform script, however, generates a deps file which includes
+ # the corresponding library-specification file URI, so we rely on that to
+ # track the required dependencies.
+ # TODO(sigmund): replace "sources" with a "library_specification_uri"
+ # argument to make this clearer.
outputs = invoker.outputs
@@ -74,7 +90,17 @@
}
args += invoker.args
- args += rebase_path(sources, root_build_dir)
+ if (defined(invoker.single_root_scheme)) {
+ args += ["--single-root-scheme=" + invoker.single_root_scheme]
+ }
+ if (defined(invoker.single_root_base)) {
+ args += ["--single-root-base=" + invoker.single_root_base]
+ }
+ if (defined(invoker.single_root_scheme)) {
+ args += invoker.sources
+ } else {
+ args += rebase_path(invoker.sources, root_build_dir)
+ }
args += rebase_path(outputs, root_build_dir)
}
}
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index fbc9258..428a2e0 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -76,8 +76,10 @@
}
compile_platform("compile_dart2js_platform") {
+ single_root_scheme = "org-dartlang-sdk"
+ single_root_base = "../../"
sources = [
- "../../sdk/lib/libraries.json",
+ "org-dartlang-sdk:///sdk/lib/libraries.json",
]
outputs = [
@@ -92,8 +94,10 @@
}
compile_platform("compile_dart2js_platform_strong") {
+ single_root_scheme = "org-dartlang-sdk"
+ single_root_base = "../../"
sources = [
- "../../sdk/lib/libraries.json",
+ "org-dartlang-sdk:///sdk/lib/libraries.json",
]
outputs = [
@@ -109,8 +113,10 @@
}
compile_platform("compile_dart2js_server_platform") {
+ single_root_scheme = "org-dartlang-sdk"
+ single_root_base = "../../"
sources = [
- "../../sdk/lib/libraries.json",
+ "org-dartlang-sdk:///sdk/lib/libraries.json",
]
outputs = [
@@ -125,8 +131,10 @@
}
compile_platform("compile_dart2js_server_platform_strong") {
+ single_root_scheme = "org-dartlang-sdk"
+ single_root_base = "../../"
sources = [
- "../../sdk/lib/libraries.json",
+ "org-dartlang-sdk:///sdk/lib/libraries.json",
]
outputs = [