Version 2.10.0-47.0.dev
Merge commit '7ec29a9b6d8bf015b92a4b28dc24494648ec2a39' into 'dev'
diff --git a/DEPS b/DEPS
index 39db623..8ddee13 100644
--- a/DEPS
+++ b/DEPS
@@ -132,7 +132,7 @@
"pub_semver_tag": "v1.4.4",
"quiver-dart_tag": "246e754fe45cecb6aa5f3f13b4ed61037ff0d784",
"resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
- "root_certificates_rev": "16ef64be64c7dfdff2b9f4b910726e635ccc519e",
+ "root_certificates_rev": "7e5ec82c99677a2e5b95ce296c4d68b0d3378ed8",
"rust_revision": "60960a260f7b5c695fd0717311d72ce62dd4eb43",
"shelf_static_rev": "v0.2.8",
"shelf_packages_handler_tag": "2.0.0",
diff --git a/pkg/_js_interop_checks/pubspec.yaml b/pkg/_js_interop_checks/pubspec.yaml
index 89f71c4..1463e1d 100644
--- a/pkg/_js_interop_checks/pubspec.yaml
+++ b/pkg/_js_interop_checks/pubspec.yaml
@@ -6,5 +6,7 @@
sdk: '>=2.7.0 <3.0.0'
dependencies:
- _fe_analyzer_shared: ../_fe_analyzer_shared
- kernel: ../kernel
+ _fe_analyzer_shared:
+ path: ../_fe_analyzer_shared
+ kernel:
+ path: ../kernel
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index c486755..92e70c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -24,19 +24,17 @@
/// there is a `return` statement at the end of the function body block.
final List<FunctionBody> functionBodiesThatDontComplete = [];
- /// The list of [SimpleIdentifier]s that were checked if they are definitely
- /// assigned, but were not.
- final List<AstNode> notDefinitelyAssignedNodes = [];
+ /// The list of references to variables, where a variable is read, and
+ /// is not definitely assigned.
+ final List<SimpleIdentifier> notDefinitelyAssigned = [];
- /// The list of [SimpleIdentifier]s representing variable references (reads,
- /// writes, or both) that occur when the corresponding variable has been
- /// definitely assigned.
- final List<AstNode> definitelyAssignedNodes = [];
+ /// The list of references to variables, where a variable is read, and
+ /// is definitely assigned.
+ final List<SimpleIdentifier> definitelyAssigned = [];
- /// The list of [SimpleIdentifier]s representing variable references (reads,
- /// writes, or both) that occur when the corresponding variable has been
- /// definitely unassigned.
- final List<AstNode> definitelyUnassignedNodes = [];
+ /// The list of references to variables, where a variable is written, and
+ /// is definitely unassigned.
+ final List<SimpleIdentifier> definitelyUnassigned = [];
/// For each top level or class level declaration, the assigned variables
/// information that was computed for it.
@@ -158,9 +156,9 @@
if (dataForTesting != null) {
if (isAssigned) {
- dataForTesting.definitelyAssignedNodes.add(node);
+ dataForTesting.definitelyAssigned.add(node);
} else {
- dataForTesting.notDefinitelyAssignedNodes.add(node);
+ dataForTesting.notDefinitelyAssigned.add(node);
}
}
@@ -174,7 +172,7 @@
var isUnassigned = flow.isUnassigned(element);
if (dataForTesting != null && isUnassigned) {
- dataForTesting.definitelyUnassignedNodes.add(node);
+ dataForTesting.definitelyUnassigned.add(node);
}
return isUnassigned;
diff --git a/pkg/analyzer/test/id_tests/definite_assignment_test.dart b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
index 4d75189..03d7c45 100644
--- a/pkg/analyzer/test/id_tests/definite_assignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
@@ -73,7 +73,7 @@
if (node is SimpleIdentifier && node.inGetterContext()) {
var element = node.staticElement;
if (element is LocalVariableElement || element is ParameterElement) {
- if (_flowResult.notDefinitelyAssignedNodes.contains(node)) {
+ if (_flowResult.notDefinitelyAssigned.contains(node)) {
return 'unassigned';
}
}
diff --git a/pkg/analyzer/test/id_tests/definite_unassignment_test.dart b/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
index 359b481..c0e1153 100644
--- a/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
@@ -73,7 +73,7 @@
if (node is SimpleIdentifier && node.inGetterContext()) {
var element = node.staticElement;
if (element is LocalVariableElement || element is ParameterElement) {
- if (_flowResult.definitelyUnassignedNodes.contains(node)) {
+ if (_flowResult.definitelyUnassigned.contains(node)) {
return 'unassigned';
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart b/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart
index 3ab33ad..eaac79c 100644
--- a/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart
@@ -438,15 +438,16 @@
var unitData = testingData.uriToFlowAnalysisData[result.uri];
if (assigned) {
- expect(unitData.definitelyAssignedNodes, contains(node));
+ expect(unitData.definitelyAssigned, contains(node));
} else {
- expect(unitData.definitelyAssignedNodes, isNot(contains(node)));
+ expect(unitData.notDefinitelyAssigned, contains(node));
+ expect(unitData.definitelyAssigned, isNot(contains(node)));
}
if (unassigned) {
- expect(unitData.definitelyUnassignedNodes, contains(node));
+ expect(unitData.definitelyUnassigned, contains(node));
} else {
- expect(unitData.definitelyUnassignedNodes, isNot(contains(node)));
+ expect(unitData.definitelyUnassigned, isNot(contains(node)));
}
}
}
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 33d1bed..2827fd4 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1432,11 +1432,12 @@
return thisType;
}
- void handleCondition(ir.Node node) {
+ TypeInformation handleCondition(ir.Node node) {
bool oldAccumulateIsChecks = _accumulateIsChecks;
_accumulateIsChecks = true;
- visit(node, conditionContext: true);
+ TypeInformation result = visit(node, conditionContext: true);
_accumulateIsChecks = oldAccumulateIsChecks;
+ return result;
}
void _potentiallyAddIsCheck(ir.IsExpression node) {
@@ -1500,6 +1501,8 @@
LocalState stateAfterOperandWhenFalse = _stateAfterWhenFalse;
_setStateAfter(
_state, stateAfterOperandWhenFalse, stateAfterOperandWhenTrue);
+ // TODO(sra): Improve precision on constant and bool-conversion-to-constant
+ // inputs.
return _types.boolType;
}
@@ -1508,11 +1511,11 @@
if (node.operator == '&&') {
LocalState stateBefore = _state;
_state = new LocalState.childPath(stateBefore);
- handleCondition(node.left);
+ TypeInformation leftInfo = handleCondition(node.left);
LocalState stateAfterLeftWhenTrue = _stateAfterWhenTrue;
LocalState stateAfterLeftWhenFalse = _stateAfterWhenFalse;
_state = new LocalState.childPath(stateAfterLeftWhenTrue);
- handleCondition(node.right);
+ TypeInformation rightInfo = handleCondition(node.right);
LocalState stateAfterRightWhenTrue = _stateAfterWhenTrue;
LocalState stateAfterRightWhenFalse = _stateAfterWhenFalse;
LocalState stateAfterWhenTrue = stateAfterRightWhenTrue;
@@ -1522,15 +1525,22 @@
LocalState after = stateBefore.mergeDiamondFlow(
_inferrer, stateAfterWhenTrue, stateAfterWhenFalse);
_setStateAfter(after, stateAfterWhenTrue, stateAfterWhenFalse);
+ // Constant-fold result.
+ if (_types.isLiteralFalse(leftInfo)) return leftInfo;
+ if (_types.isLiteralTrue(leftInfo)) {
+ if (_types.isLiteralFalse(rightInfo)) return rightInfo;
+ if (_types.isLiteralTrue(rightInfo)) return rightInfo;
+ }
+ // TODO(sra): Add a selector/mux node to improve precision.
return _types.boolType;
} else if (node.operator == '||') {
LocalState stateBefore = _state;
_state = new LocalState.childPath(stateBefore);
- handleCondition(node.left);
+ TypeInformation leftInfo = handleCondition(node.left);
LocalState stateAfterLeftWhenTrue = _stateAfterWhenTrue;
LocalState stateAfterLeftWhenFalse = _stateAfterWhenFalse;
_state = new LocalState.childPath(stateAfterLeftWhenFalse);
- handleCondition(node.right);
+ TypeInformation rightInfo = handleCondition(node.right);
LocalState stateAfterRightWhenTrue = _stateAfterWhenTrue;
LocalState stateAfterRightWhenFalse = _stateAfterWhenFalse;
LocalState stateAfterWhenTrue = new LocalState.childPath(stateBefore)
@@ -1540,6 +1550,13 @@
LocalState stateAfter = stateBefore.mergeDiamondFlow(
_inferrer, stateAfterWhenTrue, stateAfterWhenFalse);
_setStateAfter(stateAfter, stateAfterWhenTrue, stateAfterWhenFalse);
+ // Constant-fold result.
+ if (_types.isLiteralTrue(leftInfo)) return leftInfo;
+ if (_types.isLiteralFalse(leftInfo)) {
+ if (_types.isLiteralTrue(rightInfo)) return rightInfo;
+ if (_types.isLiteralFalse(rightInfo)) return rightInfo;
+ }
+ // TODO(sra): Add a selector/mux node to improve precision.
return _types.boolType;
}
failedAt(CURRENT_ELEMENT_SPANNABLE,
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 3042432..129b30b 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -508,7 +508,9 @@
// it is in the graph.
types.withMember(member, () => analyze(member));
});
+ metrics.elementsInGraph.add(_addedInGraph);
_reporter.log('Added $_addedInGraph elements in inferencing graph.');
+ metrics.allTypesCount.add(types.allTypes.length);
}
/// Returns the body node for [member].
@@ -1201,6 +1203,8 @@
final analyze = DurationMetric('time.analyze');
final refine1 = DurationMetric('time.refine1');
final refine2 = DurationMetric('time.refine2');
+ final elementsInGraph = CountMetric('count.elementsInGraph');
+ final allTypesCount = CountMetric('count.allTypes');
final exceededMaxChangeCount = CountMetric('count.exceededMaxChange');
final overallRefineCount = CountMetric('count.overallRefines');
@@ -1210,6 +1214,8 @@
analyze,
refine1,
refine2,
+ elementsInGraph,
+ allTypesCount,
exceededMaxChangeCount,
overallRefineCount
];
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index 1234917..865fbcc 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -4,6 +4,7 @@
import 'package:kernel/ast.dart' as ir;
import '../common.dart';
+import '../constants/values.dart' show BoolConstantValue;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../world.dart';
@@ -81,6 +82,9 @@
final Map<AbstractValue, TypeInformation> concreteTypes =
new Map<AbstractValue, TypeInformation>();
+ /// Cache of some primitive constant types.
+ final Map<Object, TypeInformation> primitiveConstantTypes = {};
+
/// List of [TypeInformation]s for calls inside method bodies.
final List<CallSiteTypeInformation> allocatedCalls =
<CallSiteTypeInformation>[];
@@ -102,8 +106,9 @@
allocatedMaps.values,
allocatedClosures,
concreteTypes.values,
+ primitiveConstantTypes.values,
allocatedCalls,
- allocatedTypes
+ allocatedTypes,
].expand((x) => x);
TypeSystem(this._closedWorld, this.strategy) {
@@ -283,8 +288,22 @@
}
TypeInformation boolLiteralType(bool value) {
- return new BoolLiteralTypeInformation(
- _abstractValueDomain, value, _abstractValueDomain.boolType);
+ return primitiveConstantTypes[value] ??= _boolLiteralType(value);
+ }
+
+ TypeInformation _boolLiteralType(bool value) {
+ AbstractValue abstractValue = _abstractValueDomain
+ .computeAbstractValueForConstant(BoolConstantValue(value));
+ return BoolLiteralTypeInformation(
+ _abstractValueDomain, value, abstractValue);
+ }
+
+ bool isLiteralTrue(TypeInformation info) {
+ return info is BoolLiteralTypeInformation && info.value == true;
+ }
+
+ bool isLiteralFalse(TypeInformation info) {
+ return info is BoolLiteralTypeInformation && info.value == false;
}
/// Returns the least upper bound between [firstType] and
diff --git a/pkg/compiler/test/inference/data/logical.dart b/pkg/compiler/test/inference/data/logical.dart
index 6503fd9f0..6f0c127 100644
--- a/pkg/compiler/test/inference/data/logical.dart
+++ b/pkg/compiler/test/inference/data/logical.dart
@@ -154,14 +154,14 @@
/// Return logical and of `true` && `true`.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnLogicalAndTrueTrue:[exact=JSBool]*/
+/*member: returnLogicalAndTrueTrue:Value([exact=JSBool], value: true)*/
returnLogicalAndTrueTrue() => true && true;
////////////////////////////////////////////////////////////////////////////////
/// Return logical and of `false` && `true`.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnLogicalAndFalseTrue:[exact=JSBool]*/
+/*member: returnLogicalAndFalseTrue:Value([exact=JSBool], value: false)*/
/// ignore: dead_code
returnLogicalAndFalseTrue() => false && true;
@@ -275,14 +275,14 @@
/// Return logical or of `false` || `true`.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnLogicalOrFalseTrue:[exact=JSBool]*/
+/*member: returnLogicalOrFalseTrue:Value([exact=JSBool], value: true)*/
returnLogicalOrFalseTrue() => false || true;
////////////////////////////////////////////////////////////////////////////////
/// Return logical or of `false` || `false`.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnLogicalOrFalseFalse:[exact=JSBool]*/
+/*member: returnLogicalOrFalseFalse:Value([exact=JSBool], value: false)*/
returnLogicalOrFalseFalse() => false || false;
////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml
index 3bdd2c5..85a9eac 100644
--- a/pkg/dart2native/pubspec.yaml
+++ b/pkg/dart2native/pubspec.yaml
@@ -11,6 +11,6 @@
dependencies:
args: ^1.4.0
+ path: any
dev_dependencies:
-
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 8768762..31bd2ba 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -209,9 +209,8 @@
// service intermediary which implements the VM service protocol and
// provides non-VM specific extensions (e.g., log caching, client
// synchronization).
- // TODO(bkonyi): Handle race condition made possible by Observatory
- // listening message being printed to console before DDS is started.
- // See https://github.com/dart-lang/sdk/issues/42727
+ // TODO(bkonyi): Remove once DevTools supports DDS.
+ // See https://github.com/flutter/flutter/issues/62507
launchDds = false;
_DebuggingSession debugSession;
if (launchDds) {
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 4b308e1..6713b64 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -11,6 +11,8 @@
args: '>=0.13.4 <2.0.0'
meta: ^1.0.0
dev_dependencies:
- expect: any
+ expect:
+ path: ../expect
+ front_end:
+ path: ../front_end
test: any
- testing: any
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 79222af..14eb334 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -155,7 +155,7 @@
hide: true),
_Option('system', 'The operating system to run tests on.',
abbr: 's',
- values: System.names,
+ values: ['all', ...System.names],
defaultsTo: Platform.operatingSystem,
hide: true),
_Option('sanitizer', 'Sanitizer in which to run the tests.',
@@ -228,6 +228,7 @@
_Option.bool('no-tree-shake', 'Disable kernel IR tree shaking.',
hide: true),
_Option.bool('list', 'List tests only, do not run them.'),
+ _Option.bool('find-configurations', 'Find matching configurations.'),
_Option.bool('list-configurations', 'Output list of configurations.'),
_Option.bool('list_status_files',
'List status files for test-suites. Do not run any test suites.',
@@ -406,21 +407,8 @@
return null;
}
- if (arguments.contains("--list-configurations")) {
- var testMatrixFile = "tools/bots/test_matrix.json";
- var testMatrix = TestMatrix.fromPath(testMatrixFile);
- for (var configuration in testMatrix.configurations
- .map((configuration) => configuration.name)
- .toList()
- ..sort()) {
- print(configuration);
- }
- return null;
- }
-
- var configuration = <String, dynamic>{};
-
- // Fill in configuration with arguments passed to the test script.
+ // Parse the command line arguments to a map.
+ var options = <String, dynamic>{};
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
@@ -458,7 +446,7 @@
} else {
// The argument does not start with "-" or "--" and is therefore not an
// option. Use it as a test selector pattern.
- var patterns = configuration.putIfAbsent("selectors", () => <String>[]);
+ var patterns = options.putIfAbsent("selectors", () => <String>[]);
// Allow passing in the full relative path to a test or directory and
// infer the selector from it. This lets users use tab completion on
@@ -492,7 +480,7 @@
// Multiple uses of a flag are an error, because there is no naturally
// correct way to handle conflicting options.
- if (configuration.containsKey(option.name)) {
+ if (options.containsKey(option.name)) {
_fail('Already have value for command line option "$command".');
}
@@ -503,12 +491,12 @@
_fail('Boolean flag "$command" does not take a value.');
}
- configuration[option.name] = true;
+ options[option.name] = true;
break;
case _OptionValueType.int:
try {
- configuration[option.name] = int.parse(value);
+ options[option.name] = int.parse(value);
} on FormatException {
_fail('Integer value expected for option "$command".');
}
@@ -535,17 +523,27 @@
// TODO(rnystrom): Store as a list instead of a comma-delimited
// string.
- configuration[option.name] = value;
+ options[option.name] = value;
break;
}
}
+ if (options.containsKey('find-configurations')) {
+ findConfigurations(options);
+ return null;
+ }
+
+ if (options.containsKey('list-configurations')) {
+ listConfigurations(options);
+ return null;
+ }
+
// If a named configuration was specified ensure no other options, which are
// implied by the named configuration, were specified.
- if (configuration['named_configuration'] is String) {
+ if (options['named_configuration'] is String) {
for (var optionName in _namedConfigurationOptions) {
- if (configuration.containsKey(optionName)) {
- var namedConfig = configuration['named_configuration'];
+ if (options.containsKey(optionName)) {
+ var namedConfig = options['named_configuration'];
_fail("The named configuration '$namedConfig' implies "
"'$optionName'. Try removing '$optionName'.");
}
@@ -554,26 +552,26 @@
// Apply default values for unspecified options.
for (var option in _options) {
- if (!configuration.containsKey(option.name)) {
- configuration[option.name] = option.defaultValue;
+ if (!options.containsKey(option.name)) {
+ options[option.name] = option.defaultValue;
}
}
// Fetch list of tests to run, if option is present.
- var testList = configuration['test_list'];
+ var testList = options['test_list'];
if (testList is String) {
- configuration['test_list_contents'] = File(testList).readAsLinesSync();
+ options['test_list_contents'] = File(testList).readAsLinesSync();
}
- var tests = configuration['tests'];
+ var tests = options['tests'];
if (tests is String) {
- if (configuration.containsKey('test_list_contents')) {
+ if (options.containsKey('test_list_contents')) {
_fail('--tests and --test-list cannot be used together');
}
- configuration['test_list_contents'] = LineSplitter.split(tests).toList();
+ options['test_list_contents'] = LineSplitter.split(tests).toList();
}
- return _createConfigurations(configuration);
+ return _createConfigurations(options);
}
/// Given a set of parsed option values, returns the list of command line
@@ -682,6 +680,12 @@
data['progress'] = 'verbose';
}
+ var systemName = data["system"] as String;
+ if (systemName == "all") {
+ _fail("Can only use '--system=all' with '--find-configurations'.");
+ }
+ var system = System.find(systemName);
+
var runtimeNames = data["runtime"] as String;
var runtimes = [
if (runtimeNames != null) ...runtimeNames.split(",").map(Runtime.find)
@@ -813,7 +817,6 @@
}
for (var sanitizerName in sanitizers.split(",")) {
var sanitizer = Sanitizer.find(sanitizerName);
- var system = System.find(data["system"] as String);
var configuration = Configuration("custom configuration",
architecture, compiler, mode, runtime, system,
nnbdMode: nnbdMode,
@@ -996,6 +999,101 @@
OptionParseException(this.message);
}
+/// Prints the names of the configurations in the test matrix that match the
+/// given filter options.
+///
+/// If any of the options `--system`, `--arch`, `--mode`, `--compiler`,
+/// `--nnbd`, or `--runtime` (or their abbreviations) are passed, then only
+/// configurations matching those are shown.
+void findConfigurations(Map<String, dynamic> options) {
+ var testMatrix = TestMatrix.fromPath('tools/bots/test_matrix.json');
+
+ // Default to only showing configurations for the current machine.
+ var systemOption = options['system'] as String;
+ var system = System.host;
+ if (systemOption == 'all') {
+ system = null;
+ } else if (systemOption != null) {
+ system = System.find(systemOption);
+ }
+
+ var architectureOption = options['arch'] as String;
+ var architectures = const [Architecture.x64];
+ if (architectureOption == 'all') {
+ architectures = null;
+ } else if (architectureOption != null) {
+ architectures =
+ architectureOption.split(',').map(Architecture.find).toList();
+ }
+
+ var mode = Mode.release;
+ if (options.containsKey('mode')) {
+ mode = Mode.find(options['mode'] as String);
+ }
+
+ Compiler compiler;
+ if (options.containsKey('compiler')) {
+ compiler = Compiler.find(options['compiler'] as String);
+ }
+
+ Runtime runtime;
+ if (options.containsKey('runtime')) {
+ runtime = Runtime.find(options['runtime'] as String);
+ }
+
+ NnbdMode nnbdMode;
+ if (options.containsKey('nnbd')) {
+ nnbdMode = NnbdMode.find(options['nnbd'] as String);
+ }
+
+ var names = <String>[];
+ for (var configuration in testMatrix.configurations) {
+ if (system != null && configuration.system != system) continue;
+ if (architectures != null &&
+ !architectures.contains(configuration.architecture)) {
+ continue;
+ }
+ if (mode != null && configuration.mode != mode) continue;
+ if (compiler != null && configuration.compiler != compiler) continue;
+ if (runtime != null && configuration.runtime != runtime) continue;
+ if (nnbdMode != null && configuration.nnbdMode != nnbdMode) continue;
+
+ names.add(configuration.name);
+ }
+
+ names.sort();
+
+ var filters = [
+ if (system != null) "system=$system",
+ if (architectures != null) "arch=${architectures.join(',')}",
+ if (mode != null) "mode=$mode",
+ if (compiler != null) "compiler=$compiler",
+ if (runtime != null) "runtime=$runtime",
+ if (nnbdMode != null) "nnbd=$nnbdMode",
+ ];
+
+ if (filters.isEmpty) {
+ print("All configurations:");
+ } else {
+ print("Configurations where ${filters.join(', ')}:");
+ }
+
+ for (var name in names) {
+ print("- $name");
+ }
+}
+
+/// Prints the names of the configurations in the test matrix.
+void listConfigurations(Map<String, dynamic> options) {
+ var testMatrix = TestMatrix.fromPath('tools/bots/test_matrix.json');
+
+ var names = testMatrix.configurations
+ .map((configuration) => configuration.name)
+ .toList();
+ names.sort();
+ names.forEach(print);
+}
+
/// Throws an [OptionParseException] with [message].
void _fail(String message) {
throw OptionParseException(message);
diff --git a/pkg/test_runner/lib/test_runner.dart b/pkg/test_runner/lib/test_runner.dart
index 065b840..e0843da 100644
--- a/pkg/test_runner/lib/test_runner.dart
+++ b/pkg/test_runner/lib/test_runner.dart
@@ -12,6 +12,7 @@
import 'package:smith/smith.dart';
import 'bot_results.dart';
+import 'src/options.dart';
const int deflakingCount = 5;
@@ -343,10 +344,7 @@
}
if (options["list-configurations"] as bool) {
- var process = await Process.start(
- "python", ["tools/test.py", "--list-configurations"],
- mode: ProcessStartMode.inheritStdio, runInShell: Platform.isWindows);
- exitCode = await process.exitCode;
+ listConfigurations({"system": "all"});
return;
}
diff --git a/runtime/bin/dart_embedder_api_impl.cc b/runtime/bin/dart_embedder_api_impl.cc
index ab0cbe0..88c641f 100644
--- a/runtime/bin/dart_embedder_api_impl.cc
+++ b/runtime/bin/dart_embedder_api_impl.cc
@@ -107,7 +107,8 @@
config.disable_auth_codes,
config.write_service_info_filename,
/*trace_loading=*/false, config.deterministic,
- /*enable_service_port_fallback=*/false)) {
+ /*enable_service_port_fallback=*/false,
+ /*wait_for_dds_to_advertise_service=*/false)) {
*error = Utils::StrDup(bin::VmService::GetErrorMessage());
return nullptr;
}
@@ -142,7 +143,8 @@
config.disable_auth_codes,
config.write_service_info_filename,
/*trace_loading=*/false, config.deterministic,
- /*enable_service_port_fallback=*/false)) {
+ /*enable_service_port_fallback=*/false,
+ /*wait_for_dds_to_advertise_service=*/false)) {
*error = Utils::StrDup(bin::VmService::GetErrorMessage());
return nullptr;
}
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 9457dcd..000855d 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -549,7 +549,10 @@
Options::vm_service_server_ip(), Options::vm_service_server_port(),
Options::vm_service_dev_mode(), Options::vm_service_auth_disabled(),
Options::vm_write_service_info_filename(), Options::trace_loading(),
- Options::deterministic(), Options::enable_service_port_fallback())) {
+ Options::deterministic(), Options::enable_service_port_fallback(),
+ // TODO(bkonyi): uncomment when DDS is re-enabled.
+ // See https://github.com/flutter/flutter/issues/62507
+ /*!Options::disable_dart_dev()*/ false)) {
*error = Utils::StrDup(VmService::GetErrorMessage());
return NULL;
}
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index c288359..9513513 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -149,7 +149,8 @@
/*dev_mode=*/false, /*auth_disabled=*/true,
/*write_service_info_filename*/ "",
/*trace_loading=*/false, /*deterministic=*/true,
- /*enable_service_port_fallback=*/false)) {
+ /*enable_service_port_fallback=*/false,
+ /*wait_for_dds_to_advertise_service*/ false)) {
*error = Utils::StrDup(bin::VmService::GetErrorMessage());
return nullptr;
}
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 0a1896a..47b7992 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -118,7 +118,8 @@
const char* write_service_info_filename,
bool trace_loading,
bool deterministic,
- bool enable_service_port_fallback) {
+ bool enable_service_port_fallback,
+ bool wait_for_dds_to_advertise_service) {
Dart_Isolate isolate = Dart_CurrentIsolate();
ASSERT(isolate != NULL);
SetServerAddress("");
@@ -189,6 +190,12 @@
write_service_info_filename);
SHUTDOWN_ON_ERROR(result);
}
+
+ result = Dart_SetField(library,
+ DartUtils::NewString("_waitForDdsToAdvertiseService"),
+ Dart_NewBoolean(wait_for_dds_to_advertise_service));
+ SHUTDOWN_ON_ERROR(result);
+
// Are we running on Windows?
#if defined(HOST_OS_WINDOWS)
Dart_Handle is_windows = Dart_True();
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 4b5838b..3371f27 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -21,7 +21,8 @@
const char* write_service_info_filename,
bool trace_loading,
bool deterministic,
- bool enable_service_port_fallback);
+ bool enable_service_port_fallback,
+ bool wait_for_dds_to_advertise_service);
static void SetNativeResolver();
diff --git a/sdk/lib/_internal/vm/bin/vmservice_io.dart b/sdk/lib/_internal/vm/bin/vmservice_io.dart
index e84c8f8..5718d46 100644
--- a/sdk/lib/_internal/vm/bin/vmservice_io.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_io.dart
@@ -37,6 +37,8 @@
var _signalSubscription;
@pragma("vm:entry-point")
bool _enableServicePortFallback = false;
+@pragma("vm:entry-point")
+bool _waitForDdsToAdvertiseService = false;
// HTTP server.
Server? server;
@@ -78,6 +80,12 @@
_shutdown();
}
+Future<void> ddsConnectedCallback() async {
+ if (_waitForDdsToAdvertiseService) {
+ await server!.outputConnectionInformation();
+ }
+}
+
Future<Uri> createTempDirCallback(String base) async {
final temp = await Directory.systemTemp.createTemp(base);
// Underneath the temporary directory, create a directory with the
@@ -245,6 +253,7 @@
// Set embedder hooks.
VMServiceEmbedderHooks.cleanup = cleanupCallback;
VMServiceEmbedderHooks.createTempDir = createTempDirCallback;
+ VMServiceEmbedderHooks.ddsConnected = ddsConnectedCallback;
VMServiceEmbedderHooks.deleteDir = deleteDirCallback;
VMServiceEmbedderHooks.writeFile = writeFileCallback;
VMServiceEmbedderHooks.writeStreamFile = writeStreamFileCallback;
diff --git a/sdk/lib/_internal/vm/bin/vmservice_server.dart b/sdk/lib/_internal/vm/bin/vmservice_server.dart
index 68e18a3..09ec391 100644
--- a/sdk/lib/_internal/vm/bin/vmservice_server.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_server.dart
@@ -477,11 +477,21 @@
}
final server = _server!;
server.listen(_requestHandler, cancelOnError: true);
+ if (!_waitForDdsToAdvertiseService) {
+ await outputConnectionInformation();
+ }
+ // Server is up and running.
+ _notifyServerState(serverAddress.toString());
+ onServerAddressChange('$serverAddress');
+ return this;
+ }
+
+ Future<void> outputConnectionInformation() async {
serverPrint('Observatory listening on $serverAddress');
if (Platform.isFuchsia) {
// Create a file with the port number.
final tmp = Directory.systemTemp.path;
- final path = '$tmp/dart.services/${server.port}';
+ final path = '$tmp/dart.services/${_server!.port}';
serverPrint('Creating $path');
File(path)..createSync(recursive: true);
}
@@ -490,10 +500,6 @@
serviceInfoFilenameLocal.isNotEmpty) {
await _dumpServiceInfoToFile(serviceInfoFilenameLocal);
}
- // Server is up and running.
- _notifyServerState(serverAddress.toString());
- onServerAddressChange('$serverAddress');
- return this;
}
Future<void> cleanup(bool force) {
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index 840a6e0..c404a78 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -139,6 +139,9 @@
/// Called when the server should be stopped.
typedef Future ServerStopCallback();
+/// Called when DDS has connected.
+typedef Future<void> DdsConnectedCallback();
+
/// Called when the service is exiting.
typedef Future CleanupCallback();
@@ -177,6 +180,7 @@
class VMServiceEmbedderHooks {
static ServerStartCallback? serverStart;
static ServerStopCallback? serverStop;
+ static DdsConnectedCallback? ddsConnected;
static CleanupCallback? cleanup;
static CreateTempDirCallback? createTempDir;
static DeleteDirCallback? deleteDir;
@@ -245,6 +249,7 @@
}
acceptNewWebSocketConnections(false);
_ddsUri = Uri.parse(uri);
+ await VMServiceEmbedderHooks?.ddsConnected!();
return encodeSuccess(message);
}
diff --git a/tools/VERSION b/tools/VERSION
index 85b59ea..8f56a69 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 46
+PRERELEASE 47
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/package_deps/.gitignore b/tools/package_deps/.gitignore
new file mode 100644
index 0000000..3d64647
--- /dev/null
+++ b/tools/package_deps/.gitignore
@@ -0,0 +1,9 @@
+# Files and directories created by pub
+.dart_tool/
+.packages
+
+# Conventional directory for build outputs
+build/
+
+# Directory created by dartdoc
+doc/api/
diff --git a/tools/package_deps/README.md b/tools/package_deps/README.md
new file mode 100644
index 0000000..45b49b6
--- /dev/null
+++ b/tools/package_deps/README.md
@@ -0,0 +1 @@
+A tool to validate pubspec files in pkg/.
diff --git a/tools/package_deps/bin/package_deps.dart b/tools/package_deps/bin/package_deps.dart
new file mode 100644
index 0000000..97eb5d1
--- /dev/null
+++ b/tools/package_deps/bin/package_deps.dart
@@ -0,0 +1,353 @@
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+import 'package:yaml/yaml.dart' as yaml;
+
+// TODO(devoncarew): Use bold ansi chars for emphasis.
+
+// TODO(devoncarew): Validate that publishable packages don't use relative sdk
+// paths in their pubspecs.
+
+// TODO(devoncarew): Find unused entries in the DEPS file.
+const validateDEPS = false;
+
+void main(List<String> arguments) {
+ // validate the cwd
+ if (!FileSystemEntity.isFileSync('DEPS') ||
+ !FileSystemEntity.isDirectorySync('pkg')) {
+ print('Please run this tool from the root of the Dart repo.');
+ exit(1);
+ }
+
+ // TODO(devoncarew): Support manually added directories (outside of pkg/).
+
+ // locate all packages
+ final packages = <Package>[];
+ for (var entity in Directory('pkg').listSync()) {
+ if (entity is Directory) {
+ var package = Package(entity.path);
+ if (package.hasPubspec) {
+ packages.add(package);
+ }
+ }
+ }
+
+ packages.sort();
+
+ var validateFailure = false;
+
+ // For each, validate the pubspec contents.
+ for (var package in packages) {
+ print('validating ${package.dir}'
+ '${package.publishable ? ' [publishable]' : ''}');
+
+ if (!package.validate()) {
+ validateFailure = true;
+ }
+
+ print('');
+ }
+
+ // Read and display info about the sdk DEPS file.
+ if (validateDEPS) {
+ print('SDK DEPS');
+ var sdkDeps = SdkDeps(File('DEPS'));
+ sdkDeps.parse();
+ print('');
+ print('packages:');
+ for (var pkg in sdkDeps.pkgs) {
+ print(' package:$pkg');
+ }
+
+ print('');
+ print('tested packages:');
+ for (var pkg in sdkDeps.testedPkgs) {
+ print(' package:$pkg');
+ }
+ }
+
+ if (validateFailure) {
+ exit(1);
+ }
+}
+
+class Package implements Comparable<Package> {
+ final String dir;
+
+ Package(this.dir) {
+ _parsePubspec();
+ }
+
+ String get dirName => path.basename(dir);
+ final Set<String> _regularDependencies = {};
+ final Set<String> _devDependencies = {};
+ String _packageName;
+
+ String get packageName => _packageName;
+ Set<String> _declaredDependencies;
+ Set<String> _declaredDevDependencies;
+
+ List<String> get regularDependencies => _regularDependencies.toList()..sort();
+
+ List<String> get devDependencies => _devDependencies.toList()..sort();
+
+ bool _publishToNone;
+ bool get publishable => !_publishToNone;
+
+ @override
+ String toString() => 'Package $dirName';
+
+ bool get hasPubspec =>
+ FileSystemEntity.isFileSync(path.join(dir, 'pubspec.yaml'));
+
+ @override
+ int compareTo(Package other) {
+ return dirName.compareTo(other.dirName);
+ }
+
+ bool validate() {
+ _parseImports();
+ return _validatePubspecDeps();
+ }
+
+ void _parseImports() {
+ final files = <File>[];
+
+ _collectDartFiles(Directory(dir), files);
+
+ for (var file in files) {
+ //print(' ${file.path}');
+
+ var importedPackages = <String>{};
+
+ for (var import in _collectImports(file)) {
+ try {
+ var uri = Uri.parse(import);
+ if (uri.hasScheme && uri.scheme == 'package') {
+ var packageName = path.split(uri.path).first;
+ importedPackages.add(packageName);
+ }
+ } on FormatException {
+ // ignore
+ }
+ }
+
+ var topLevelDir = _topLevelDir(file);
+
+ if ({'bin', 'lib'}.contains(topLevelDir)) {
+ _regularDependencies.addAll(importedPackages);
+ } else {
+ _devDependencies.addAll(importedPackages);
+ }
+ }
+ }
+
+ void _parsePubspec() {
+ var pubspec = File(path.join(dir, 'pubspec.yaml'));
+ var doc = yaml.loadYamlDocument(pubspec.readAsStringSync());
+ dynamic docContents = doc.contents.value;
+ _packageName = docContents['name'];
+ _publishToNone = docContents['publish_to'] == 'none';
+
+ if (docContents['dependencies'] != null) {
+ _declaredDependencies =
+ Set<String>.from(docContents['dependencies'].keys);
+ } else {
+ _declaredDependencies = {};
+ }
+ if (docContents['dev_dependencies'] != null) {
+ _declaredDevDependencies =
+ Set<String>.from(docContents['dev_dependencies'].keys);
+ } else {
+ _declaredDevDependencies = {};
+ }
+ }
+
+ bool _validatePubspecDeps() {
+ var fail = false;
+
+ if (dirName != packageName) {
+ print(' Package name is different from the directory name.');
+ fail = true;
+ }
+
+ var deps = regularDependencies;
+ deps.remove(packageName);
+
+ var devdeps = devDependencies;
+ devdeps.remove(packageName);
+
+ // if (deps.isNotEmpty) {
+ // print(' deps : ${deps}');
+ // }
+ // if (devdeps.isNotEmpty) {
+ // print(' dev deps: ${devdeps}');
+ // }
+
+ var undeclaredRegularUses = Set<String>.from(deps)
+ ..removeAll(_declaredDependencies);
+ if (undeclaredRegularUses.isNotEmpty) {
+ print(' ${_printSet(undeclaredRegularUses)} used in lib/ but not '
+ "declared in 'dependencies:'.");
+ fail = true;
+ }
+
+ var undeclaredDevUses = Set<String>.from(devdeps)
+ ..removeAll(_declaredDependencies)
+ ..removeAll(_declaredDevDependencies);
+ if (undeclaredDevUses.isNotEmpty) {
+ print(' ${_printSet(undeclaredDevUses)} used in dev dirs but not '
+ "declared in 'dev_dependencies:'.");
+ fail = true;
+ }
+
+ var extraRegularDeclarations = Set<String>.from(_declaredDependencies)
+ ..removeAll(deps);
+ if (extraRegularDeclarations.isNotEmpty) {
+ print(' ${_printSet(extraRegularDeclarations)} declared in '
+ "'dependencies:' but not used in lib/.");
+ fail = true;
+ }
+
+ var extraDevDeclarations = Set<String>.from(_declaredDevDependencies)
+ ..removeAll(devdeps);
+ // Remove package:pedantic as it is often declared as a dev dependency in
+ // order to bring in its analysis_options.yaml file.
+ extraDevDeclarations.remove('pedantic');
+ if (extraDevDeclarations.isNotEmpty) {
+ print(' ${_printSet(extraDevDeclarations)} declared in '
+ "'dev_dependencies:' but not used in dev dirs.");
+ fail = true;
+ }
+
+ // Look for things declared in deps, not used in lib/, but that are used in
+ // dev dirs.
+ var misplacedDeps =
+ extraRegularDeclarations.intersection(Set.from(devdeps));
+ if (misplacedDeps.isNotEmpty) {
+ print(" ${_printSet(misplacedDeps)} declared in 'dependencies:' but "
+ 'only used in dev dirs.');
+ fail = true;
+ }
+
+ if (!fail) {
+ print(' No issues.');
+ }
+
+ return !fail;
+ }
+
+ void _collectDartFiles(Directory dir, List<File> files) {
+ for (var entity in dir.listSync(followLinks: false)) {
+ if (entity is Directory) {
+ var name = path.basename(entity.path);
+
+ // Skip 'pkg/analyzer_cli/test/data'.
+ // Skip 'pkg/front_end/test/id_testing/data/'.
+ // Skip 'pkg/front_end/test/language_versioning/data/'.
+ if (name == 'data' && path.split(entity.parent.path).contains('test')) {
+ continue;
+ }
+
+ // Skip 'pkg/analysis_server/test/mock_packages'.
+ if (name == 'mock_packages') {
+ continue;
+ }
+
+ // Skip 'pkg/front_end/testcases'.
+ if (name == 'testcases') {
+ continue;
+ }
+
+ if (!name.startsWith('.')) {
+ _collectDartFiles(entity, files);
+ }
+ } else if (entity is File && entity.path.endsWith('.dart')) {
+ files.add(entity);
+ }
+ }
+ }
+
+ // look for both kinds of quotes
+ static RegExp importRegex1 = RegExp(r"^(import|export)\s+\'(\S+)\'");
+ static RegExp importRegex2 = RegExp(r'^(import|export)\s+"(\S+)"');
+
+ List<String> _collectImports(File file) {
+ var results = <String>[];
+
+ for (var line in file.readAsLinesSync()) {
+ // Check for a few tokens that should stop our parse.
+ if (line.startsWith('class ') ||
+ line.startsWith('typedef ') ||
+ line.startsWith('mixin ') ||
+ line.startsWith('enum ') ||
+ line.startsWith('extension ') ||
+ line.startsWith('void ') ||
+ line.startsWith('Future ') ||
+ line.startsWith('final ') ||
+ line.startsWith('const ')) {
+ break;
+ }
+
+ var match = importRegex1.firstMatch(line);
+ if (match != null) {
+ results.add(match.group(2));
+ continue;
+ }
+
+ match = importRegex2.firstMatch(line);
+ if (match != null) {
+ results.add(match.group(2));
+ continue;
+ }
+ }
+
+ return results;
+ }
+
+ String _topLevelDir(File file) {
+ var relativePath = path.relative(file.path, from: dir);
+ return path.split(relativePath).first;
+ }
+}
+
+String _printSet(Set<String> value) {
+ var list = value.toList()..sort();
+ list = list.map((item) => 'package:$item').toList();
+ if (list.length > 1) {
+ return list.sublist(0, list.length - 1).join(', ') + ' and ' + list.last;
+ } else {
+ return list.join(', ');
+ }
+}
+
+class SdkDeps {
+ final File file;
+
+ List<String> pkgs = [];
+ List<String> testedPkgs = [];
+
+ SdkDeps(this.file);
+
+ void parse() {
+ // Var("dart_root") + "/third_party/pkg/dart2js_info":
+ final pkgRegExp = RegExp(r'"/third_party/pkg/(\S+)"');
+
+ // Var("dart_root") + "/third_party/pkg_tested/dart_style":
+ final testedPkgRegExp = RegExp(r'"/third_party/pkg_tested/(\S+)"');
+
+ for (var line in file.readAsLinesSync()) {
+ var pkgDep = pkgRegExp.firstMatch(line);
+ var testedPkgDep = testedPkgRegExp.firstMatch(line);
+
+ if (pkgDep != null) {
+ pkgs.add(pkgDep.group(1));
+ } else if (testedPkgDep != null) {
+ testedPkgs.add(testedPkgDep.group(1));
+ }
+ }
+
+ pkgs.sort();
+ testedPkgs.sort();
+ }
+}
diff --git a/tools/package_deps/pubspec.yaml b/tools/package_deps/pubspec.yaml
new file mode 100644
index 0000000..f581f76
--- /dev/null
+++ b/tools/package_deps/pubspec.yaml
@@ -0,0 +1,15 @@
+name: package_deps
+description: A tool to validate pubspec files in pkg/.
+
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
+
+environment:
+ sdk: '>=2.8.1 <3.0.0'
+
+dependencies:
+ path: any
+ yaml: any
+
+dev_dependencies:
+ pedantic: ^1.9.0