Version 2.18.0-113.0.dev
Merge commit '44f85834256ea00ebad401b54934f18028ff3101' into 'dev'
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index 54a7d17..d65c266 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:collection';
import 'package:kernel/kernel.dart';
@@ -55,7 +53,7 @@
if (type is InterfaceType) {
var name = '${type.classNode.name}$nullability';
var typeArgs = type.typeArguments;
- if (typeArgs == null) return name;
+ if (typeArgs.isEmpty) return name;
if (typeArgs.every((p) => p == const DynamicType())) return name;
return "${name}Of${typeArgs.map(_typeString).join("\$")}";
}
@@ -67,7 +65,7 @@
if (type is TypedefType) {
var name = '${type.typedefNode.name}$nullability';
var typeArgs = type.typeArguments;
- if (typeArgs == null) return name;
+ if (typeArgs.isEmpty) return name;
if (typeArgs.every((p) => p == const DynamicType())) return name;
return "${name}Of${typeArgs.map(_typeString).join("\$")}";
}
@@ -110,7 +108,7 @@
/// Holds JS type generators keyed by their underlying DartType.
final typeContainer = ModuleItemContainer<DartType>.asObject('T',
- keyToString: (DartType t) => escapeIdentifier(_typeString(t)));
+ keyToString: (DartType t) => escapeIdentifier(_typeString(t))!);
final js_ast.Expression Function(String, [List<Object>]) _runtimeCall;
@@ -151,8 +149,8 @@
js_ast.Statement _dischargeFreeType(DartType type) {
typeContainer.setNoEmit(type);
- var init = typeContainer[type];
- var id = _unboundTypeIds[type];
+ var init = typeContainer[type]!;
+ var id = _unboundTypeIds[type]!;
// TODO(vsm): Change back to `let`.
// See https://github.com/dart-lang/sdk/issues/40380.
return js.statement('var # = () => ((# = #)());', [
@@ -167,7 +165,8 @@
///
/// If [formals] is present, only emit the definitions which depend on the
/// formals.
- List<js_ast.Statement> dischargeFreeTypes([Iterable<TypeParameter> formals]) {
+ List<js_ast.Statement> dischargeFreeTypes(
+ [Iterable<TypeParameter>? formals]) {
var decls = <js_ast.Statement>[];
var types = formals == null
? typeContainer.keys.where((p) => freeTypeParameters(p).isNotEmpty)
@@ -175,7 +174,7 @@
for (var t in types) {
var stmt = _dischargeFreeType(t);
- if (stmt != null) decls.add(stmt);
+ decls.add(stmt);
}
return decls;
}
@@ -221,7 +220,7 @@
// TODO(40273) Remove prepended text when we have a better way to hide
// these names from debug tools.
_unboundTypeIds[type] =
- js_ast.TemporaryId(escapeIdentifier('__t\$${_typeString(type)}'));
+ js_ast.TemporaryId(escapeIdentifier('__t\$${_typeString(type)}')!);
}
for (var free in freeVariables) {
diff --git a/pkg/dev_compiler/test/modular_suite.dart b/pkg/dev_compiler/test/modular_suite.dart
index 1d540ba..1a53fcd 100644
--- a/pkg/dev_compiler/test/modular_suite.dart
+++ b/pkg/dev_compiler/test/modular_suite.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
/// Test the modular compilation pipeline of ddc.
///
/// This is a shell that runs multiple tests, one per folder under `data/`.
@@ -18,9 +16,9 @@
String packageConfigJsonPath = '.dart_tool/package_config.json';
Uri sdkRoot = Platform.script.resolve('../../../');
Uri packageConfigUri = sdkRoot.resolve(packageConfigJsonPath);
-Options _options;
-String _dartdevcScript;
-String _kernelWorkerScript;
+late Options _options;
+late String _dartdevcScript;
+late String _kernelWorkerScript;
void main(List<String> args) async {
_options = Options.parse(args);
@@ -89,8 +87,7 @@
extraArgs = [
'--libraries-file',
'$rootScheme:///sdk/lib/libraries.json',
- '--enable-experiment',
- 'non-nullable',
+ '--no-sound-null-safety',
];
assert(transitiveDependencies.isEmpty);
} else {
@@ -175,8 +172,7 @@
'--compile-sdk',
'--libraries-file',
'$rootScheme:///sdk/lib/libraries.json',
- '--enable-experiment',
- 'non-nullable',
+ '--no-sound-null-safety',
];
assert(transitiveDependencies.isEmpty);
} else {
@@ -319,7 +315,7 @@
String _sourceToImportUri(Module module, String rootScheme, Uri relativeUri) {
if (module.isPackage) {
- var basePath = module.packageBase.path;
+ var basePath = module.packageBase!.path;
var packageRelativePath = basePath == './'
? relativeUri.path
: relativeUri.path.substring(basePath.length);
diff --git a/pkg/dev_compiler/test/modular_suite_nnbd.dart b/pkg/dev_compiler/test/modular_suite_nnbd.dart
index 4a19cfb..c5c0567 100644
--- a/pkg/dev_compiler/test/modular_suite_nnbd.dart
+++ b/pkg/dev_compiler/test/modular_suite_nnbd.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
/// Test the modular compilation pipeline of ddc.
///
/// This is a shell that runs multiple tests, one per folder under `data/`.
@@ -18,9 +16,9 @@
String packageConfigJsonPath = '.dart_tool/package_config.json';
Uri sdkRoot = Platform.script.resolve('../../../');
Uri packageConfigUri = sdkRoot.resolve(packageConfigJsonPath);
-Options _options;
-String _dartdevcScript;
-String _kernelWorkerScript;
+late Options _options;
+late String _dartdevcScript;
+late String _kernelWorkerScript;
void main(List<String> args) async {
_options = Options.parse(args);
@@ -120,10 +118,7 @@
.where((m) => !m.isSdk)
.expand((m) => ['--input-summary', '${toUri(m, dillId)}']),
...sources.expand((String uri) => ['--source', uri]),
- // TODO(40266) After unfork of dart:_runtime only need experiment when
- // compiling SDK. For now always use the Null Safety experiment.
- '--enable-experiment',
- 'non-nullable',
+ '--sound-null-safety',
...flags.expand((String flag) => ['--enable-experiment', flag]),
];
@@ -206,10 +201,7 @@
rootScheme,
...sources,
...extraArgs,
- // TODO(40266) After unfork of dart:_runtime only need experiment when
- // compiling SDK. For now always use the Null Safety experiment.
- '--enable-experiment',
- 'non-nullable',
+ '--sound-null-safety',
for (String flag in flags) '--enable-experiment=$flag',
...transitiveDependencies
.where((m) => !m.isSdk)
@@ -323,7 +315,7 @@
String _sourceToImportUri(Module module, String rootScheme, Uri relativeUri) {
if (module.isPackage) {
- var basePath = module.packageBase.path;
+ var basePath = module.packageBase!.path;
var packageRelativePath = basePath == './'
? relativeUri.path
: relativeUri.path.substring(basePath.length);
diff --git a/pkg/test_runner/bin/http_server.dart b/pkg/test_runner/bin/http_server.dart
index b034e72..a6eeacc 100644
--- a/pkg/test_runner/bin/http_server.dart
+++ b/pkg/test_runner/bin/http_server.dart
@@ -2,10 +2,10 @@
// 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:args/args.dart';
import 'package:test_runner/src/configuration.dart';
import 'package:test_runner/src/testing_servers.dart';
import 'package:test_runner/src/utils.dart';
-import 'package:test_runner/src/vendored_pkg/args/args.dart';
void main(List<String> arguments) {
var parser = ArgParser();
@@ -30,7 +30,7 @@
var args = parser.parse(arguments);
if (args['help'] as bool) {
- print(parser.getUsage());
+ print(parser.usage);
} else {
var servers = TestingServers(
args['build-directory'] as String,
diff --git a/pkg/test_runner/lib/src/vendored_pkg/README.txt b/pkg/test_runner/lib/src/vendored_pkg/README.txt
deleted file mode 100644
index 0d4c1a7..0000000
--- a/pkg/test_runner/lib/src/vendored_pkg/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-The files in this folder are copies of libraries in the pkg directory. We have
-copies here to prevent a bootstrapping issue when running the test.dart binary
-in case breaking changes are made to the language in future revisions, we can
-still test with a known stable version.
diff --git a/pkg/test_runner/lib/src/vendored_pkg/args/args.dart b/pkg/test_runner/lib/src/vendored_pkg/args/args.dart
deleted file mode 100644
index d36be63..0000000
--- a/pkg/test_runner/lib/src/vendored_pkg/args/args.dart
+++ /dev/null
@@ -1,384 +0,0 @@
-// 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.
-
-/// This library lets you define parsers for parsing raw command-line arguments
-/// into a set of options and values using [GNU][] and [POSIX][] style options.
-///
-/// ## Defining options ##
-///
-/// To use this library, you create an [ArgParser] object which will contain
-/// the set of options you support:
-///
-/// var parser = new ArgParser();
-///
-/// Then you define a set of options on that parser using [addOption()] and
-/// [addFlag()]. The minimal way to create an option is:
-///
-/// parser.addOption('name');
-///
-/// This creates an option named "name". Options must be given a value on the
-/// command line. If you have a simple on/off flag, you can instead use:
-///
-/// parser.addFlag('name');
-///
-/// Flag options will, by default, accept a 'no-' prefix to negate the option.
-/// This can be disabled like so:
-///
-/// parser.addFlag('name', negatable: false);
-///
-/// (From here on out "option" will refer to both "regular" options and flags.
-/// In cases where the distinction matters, we'll use "non-flag option".)
-///
-/// Options may have an optional single-character abbreviation:
-///
-/// parser.addOption('mode', abbr: 'm');
-/// parser.addFlag('verbose', abbr: 'v');
-///
-/// They may also specify a default value. The default value will be used if the
-/// option isn't provided:
-///
-/// parser.addOption('mode', defaultsTo: 'debug');
-/// parser.addFlag('verbose', defaultsTo: false);
-///
-/// The default value for non-flag options can be any [String]. For flags, it
-/// must be a [bool].
-///
-/// To validate non-flag options, you may provide an allowed set of values. When
-/// you do, it will throw a [FormatException] when you parse the arguments if
-/// the value for an option is not in the allowed set:
-///
-/// parser.addOption('mode', allowed: ['debug', 'release']);
-///
-/// You can provide a callback when you define an option. When you later parse
-/// a set of arguments, the callback for that option will be invoked with the
-/// value provided for it:
-///
-/// parser.addOption('mode', callback: (mode) => print('Got mode $mode));
-/// parser.addFlag('verbose', callback: (verbose) {
-/// if (verbose) print('Verbose');
-/// });
-///
-/// The callback for each option will *always* be called when you parse a set of
-/// arguments. If the option isn't provided in the args, the callback will be
-/// passed the default value, or `null` if there is none set.
-///
-/// ## Parsing arguments ##
-///
-/// Once you have an [ArgParser] set up with some options and flags, you use it
-/// by calling [ArgParser.parse()] with a set of arguments:
-///
-/// var results = parser.parse(['some', 'command', 'line', 'args']);
-///
-/// These will usually come from `new Options().arguments`, but you can pass in
-/// any list of strings. It returns an instance of [ArgResults]. This is a
-/// map-like object that will return the value of any parsed option.
-///
-/// var parser = new ArgParser();
-/// parser.addOption('mode');
-/// parser.addFlag('verbose', defaultsTo: true);
-/// var results = parser.parse('['--mode', 'debug', 'something', 'else']);
-///
-/// print(results['mode']); // debug
-/// print(results['verbose']); // true
-///
-/// The [parse()] method will stop as soon as it reaches `--` or anything that
-/// it doesn't recognize as an option, flag, or option value. If there are still
-/// arguments left, they will be provided to you in
-/// [ArgResults.rest].
-///
-/// print(results.rest); // ['something', 'else']
-///
-/// ## Specifying options ##
-///
-/// To actually pass in options and flags on the command line, use GNU or POSIX
-/// style. If you define an option like:
-///
-/// parser.addOption('name', abbr: 'n');
-///
-/// Then a value for it can be specified on the command line using any of:
-///
-/// --name=somevalue
-/// --name somevalue
-/// -nsomevalue
-/// -n somevalue
-///
-/// Given this flag:
-///
-/// parser.addFlag('name', abbr: 'n');
-///
-/// You can set it on using one of:
-///
-/// --name
-/// -n
-///
-/// Or set it off using:
-///
-/// --no-name
-///
-/// Multiple flag abbreviation can also be collapsed into a single argument. If
-/// you define:
-///
-/// parser.addFlag('verbose', abbr: 'v');
-/// parser.addFlag('french', abbr: 'f');
-/// parser.addFlag('iambic-pentameter', abbr: 'i');
-///
-/// Then all three flags could be set using:
-///
-/// -vfi
-///
-/// By default, an option has only a single value, with later option values
-/// overriding earlier ones; for example:
-///
-/// var parser = new ArgParser();
-/// parser.addOption('mode');
-/// var results = parser.parse(['--mode', 'on', '--mode', 'off']);
-/// print(results['mode']); // prints 'off'
-///
-/// If you need multiple values, set the `allowMultiple` flag. In that
-/// case the option can occur multiple times and when parsing arguments a
-/// List of values will be returned:
-///
-/// var parser = new ArgParser();
-/// parser.addOption('mode', allowMultiple: true);
-/// var results = parser.parse(['--mode', 'on', '--mode', 'off']);
-/// print(results['mode']); // prints '[on, off]'
-///
-/// ## Defining commands ##
-///
-/// In addition to *options*, you can also define *commands*. A command is a
-/// named argument that has its own set of options. For example, when you run:
-///
-/// $ git commit -a
-///
-/// The executable is `git`, the command is `commit`, and the `-a` option is an
-/// option passed to the command. You can add a command like so:
-///
-/// var parser = new ArgParser();
-/// var command = parser.addCommand("commit");
-/// command.addFlag('all', abbr: 'a');
-///
-/// It returns another [ArgParser] which you can use to define options and
-/// subcommands on that command. When an argument list is parsed, you can then
-/// determine which command was entered and what options were provided for it.
-///
-/// var results = parser.parse(['commit', '-a']);
-/// print(results.command.name); // "commit"
-/// print(results.command['a']); // true
-///
-/// ## Displaying usage ##
-///
-/// This library can also be used to automatically generate nice usage help
-/// text like you get when you run a program with `--help`. To use this, you
-/// will also want to provide some help text when you create your options. To
-/// define help text for the entire option, do:
-///
-/// parser.addOption('mode', help: 'The compiler configuration',
-/// allowed: ['debug', 'release']);
-/// parser.addFlag('verbose', help: 'Show additional diagnostic info');
-///
-/// For non-flag options, you can also provide detailed help for each expected
-/// value using a map:
-///
-/// parser.addOption('arch', help: 'The architecture to compile for',
-/// allowedHelp: {
-/// 'ia32': 'Intel x86',
-/// 'arm': 'ARM Holding 32-bit chip'
-/// });
-///
-/// If you define a set of options like the above, then calling this:
-///
-/// print(parser.getUsage());
-///
-/// Will display something like:
-///
-/// --mode The compiler configuration
-/// [debug, release]
-///
-/// --[no-]verbose Show additional diagnostic info
-/// --arch The architecture to compile for
-///
-/// [arm] ARM Holding 32-bit chip
-/// [ia32] Intel x86
-///
-/// To assist the formatting of the usage help, single line help text will
-/// be followed by a single new line. Options with multi-line help text
-/// will be followed by two new lines. This provides spatial diversity between
-/// options.
-///
-/// [posix]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
-/// [gnu]: http://www.gnu.org/prep/standards/standards.html#Command_002dLine-Interfaces
-library args;
-
-import 'src/parser.dart';
-import 'src/usage.dart';
-
-/// A class for taking a list of raw command line arguments and parsing out
-/// options and flags from them.
-class ArgParser {
- /// The options that have been defined for this parser.
- final Map<String, Option> options = <String, Option>{};
-
- /// The commands that have been defined for this parser.
- final Map<String, ArgParser> commands = <String, ArgParser>{};
-
- /// Creates a new ArgParser.
- ArgParser();
-
- /// Defines a command. A command is a named argument which may in turn
- /// define its own options and subcommands. Returns an [ArgParser] that can
- /// be used to define the command's options.
- ArgParser addCommand(String name) {
- // Make sure the name isn't in use.
- if (commands.containsKey(name)) {
- throw ArgumentError('Duplicate command "$name".');
- }
-
- var command = ArgParser();
- commands[name] = command;
- return command;
- }
-
- /// Defines a flag. Throws an [ArgumentError] if:
- ///
- /// * There is already an option named [name].
- /// * There is already an option using abbreviation [abbr].
- void addFlag(String name,
- {String abbr,
- String help,
- bool defaultsTo = false,
- bool negatable = true,
- void callback(bool value)}) {
- _addOption(name, abbr, help, null, null, defaultsTo,
- callback == null ? null : (value) => callback(value as bool),
- isFlag: true, negatable: negatable);
- }
-
- /// Defines a value-taking option. Throws an [ArgumentError] if:
- ///
- /// * There is already an option with name [name].
- /// * There is already an option using abbreviation [abbr].
- void addOption(String name,
- {String abbr,
- String help,
- List<String> allowed,
- Map<String, String> allowedHelp,
- String defaultsTo,
- void callback(dynamic value),
- bool allowMultiple = false}) {
- _addOption(name, abbr, help, allowed, allowedHelp, defaultsTo, callback,
- isFlag: false, allowMultiple: allowMultiple);
- }
-
- void _addOption(
- String name,
- String abbr,
- String help,
- List<String> allowed,
- Map<String, String> allowedHelp,
- dynamic defaultsTo,
- void callback(dynamic value),
- {bool isFlag,
- bool negatable = false,
- bool allowMultiple = false}) {
- // Make sure the name isn't in use.
- if (options.containsKey(name)) {
- throw ArgumentError('Duplicate option "$name".');
- }
-
- // Make sure the abbreviation isn't too long or in use.
- if (abbr != null) {
- if (abbr.length > 1) {
- throw ArgumentError(
- 'Abbreviation "$abbr" is longer than one character.');
- }
-
- var existing = findByAbbreviation(abbr);
- if (existing != null) {
- throw ArgumentError(
- 'Abbreviation "$abbr" is already used by "${existing.name}".');
- }
- }
-
- options[name] = Option(
- name, abbr, help, allowed, allowedHelp, defaultsTo, callback,
- isFlag: isFlag, negatable: negatable, allowMultiple: allowMultiple);
- }
-
- /// Parses [args], a list of command-line arguments, matches them against the
- /// flags and options defined by this parser, and returns the result.
- ArgResults parse(List<String> args) =>
- Parser(null, this, args.toList()).parse();
-
- /// Generates a string displaying usage information for the defined options.
- /// This is basically the help text shown on the command line.
- String getUsage() => Usage(this).generate();
-
- /// Get the default value for an option. Useful after parsing to test
- /// if the user specified something other than the default.
- dynamic getDefault(String option) {
- if (!options.containsKey(option)) {
- throw ArgumentError('No option named $option');
- }
- return options[option].defaultValue;
- }
-
- /// Finds the option whose abbreviation is [abbr], or `null` if no option has
- /// that abbreviation.
- Option findByAbbreviation(String abbr) {
- return options.values.firstWhere((option) => option.abbreviation == abbr,
- orElse: () => null);
- }
-}
-
-/// A command-line option. Includes both flags and options which take a value.
-class Option {
- final String name;
- final String abbreviation;
- final List allowed;
- final dynamic defaultValue;
- final Function callback;
- final String help;
- final Map<String, String> allowedHelp;
- final bool isFlag;
- final bool negatable;
- final bool allowMultiple;
-
- Option(this.name, this.abbreviation, this.help, this.allowed,
- this.allowedHelp, this.defaultValue, this.callback,
- {this.isFlag, this.negatable, this.allowMultiple = false});
-}
-
-/// The results of parsing a series of command line arguments using
-/// [ArgParser.parse()]. Includes the parsed options and any remaining unparsed
-/// command line arguments.
-class ArgResults {
- final Map<String, dynamic> _options;
-
- /// If these are the results for parsing a command's options, this will be
- /// the name of the command. For top-level results, this returns `null`.
- final String name;
-
- /// The command that was selected, or `null` if none was. This will contain
- /// the options that were selected for that command.
- final ArgResults command;
-
- /// The remaining command-line arguments that were not parsed as options or
- /// flags. If `--` was used to separate the options from the remaining
- /// arguments, it will not be included in this list.
- final List<String> rest;
-
- /// Creates a new [ArgResults].
- ArgResults(this._options, this.name, this.command, this.rest);
-
- /// Gets the parsed command-line option named [name].
- dynamic operator [](String name) {
- if (!_options.containsKey(name)) {
- throw ArgumentError('Could not find an option named "$name".');
- }
-
- return _options[name];
- }
-
- List<String> get options => _options.keys.toList();
-}
diff --git a/pkg/test_runner/lib/src/vendored_pkg/args/src/parser.dart b/pkg/test_runner/lib/src/vendored_pkg/args/src/parser.dart
deleted file mode 100644
index 990dbf7..0000000
--- a/pkg/test_runner/lib/src/vendored_pkg/args/src/parser.dart
+++ /dev/null
@@ -1,265 +0,0 @@
-// 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 args.src.parser;
-
-import '../args.dart';
-
-final _SOLO_OPT = RegExp(r'^-([a-zA-Z0-9])$');
-final _ABBR_OPT = RegExp(r'^-([a-zA-Z0-9]+)(.*)$');
-final _LONG_OPT = RegExp(r'^--([a-zA-Z\-_0-9]+)(=(.*))?$');
-
-/// The actual parsing class. Unlike [ArgParser] which is really more an "arg
-/// grammar", this is the class that does the parsing and holds the mutable
-/// state required during a parse.
-class Parser {
- /// If parser is parsing a command's options, this will be the name of the
- /// command. For top-level results, this returns `null`.
- final String commandName;
-
- /// The parser for the supercommand of this command parser, or `null` if this
- /// is the top-level parser.
- final Parser parent;
-
- /// The grammar being parsed.
- final ArgParser grammar;
-
- /// The arguments being parsed.
- final List<String> args;
-
- /// The accumulated parsed options.
- final Map<String, dynamic> results = {};
-
- Parser(this.commandName, this.grammar, this.args, [this.parent]);
-
- /// The current argument being parsed.
- String get current => args[0];
-
- /// Parses the arguments. This can only be called once.
- ArgResults parse() {
- ArgResults commandResults;
-
- // Initialize flags to their defaults.
- grammar.options.forEach((name, option) {
- if (option.allowMultiple) {
- results[name] = [];
- } else {
- results[name] = option.defaultValue;
- }
- });
-
- // Parse the args.
- while (args.isNotEmpty) {
- if (current == '--') {
- // Reached the argument terminator, so stop here.
- args.removeAt(0);
- break;
- }
-
- // Try to parse the current argument as a command. This happens before
- // options so that commands can have option-like names.
- var command = grammar.commands[current];
- if (command != null) {
- var commandName = args.removeAt(0);
- var commandParser = Parser(commandName, command, args, this);
- commandResults = commandParser.parse();
- continue;
- }
-
- // Try to parse the current argument as an option. Note that the order
- // here matters.
- if (parseSoloOption()) continue;
- if (parseAbbreviation(this)) continue;
- if (parseLongOption()) continue;
-
- // If we got here, the argument doesn't look like an option, so stop.
- break;
- }
-
- // Set unspecified multivalued arguments to their default value,
- // if any, and invoke the callbacks.
- grammar.options.forEach((name, option) {
- if (option.allowMultiple &&
- results[name].length == 0 &&
- option.defaultValue != null) {
- results[name].add(option.defaultValue);
- }
- if (option.callback != null) option.callback(results[name]);
- });
-
- // Add in the leftover arguments we didn't parse to the innermost command.
- var rest = args.toList();
- args.clear();
- return ArgResults(results, commandName, commandResults, rest);
- }
-
- /// Pulls the value for [option] from the second argument in [args]. Validates
- /// that there is a valid value there.
- void readNextArgAsValue(Option option) {
- // Take the option argument from the next command line arg.
- validate(args.isNotEmpty, 'Missing argument for "${option.name}".');
-
- // Make sure it isn't an option itself.
- validate(!_ABBR_OPT.hasMatch(current) && !_LONG_OPT.hasMatch(current),
- 'Missing argument for "${option.name}".');
-
- setOption(results, option, current);
- args.removeAt(0);
- }
-
- /// Tries to parse the current argument as a "solo" option, which is a single
- /// hyphen followed by a single letter. We treat this differently than
- /// collapsed abbreviations (like "-abc") to handle the possible value that
- /// may follow it.
- bool parseSoloOption() {
- var soloOpt = _SOLO_OPT.firstMatch(current);
- if (soloOpt == null) return false;
-
- var option = grammar.findByAbbreviation(soloOpt[1]);
- if (option == null) {
- // Walk up to the parent command if possible.
- validate(
- parent != null, 'Could not find an option or flag "-${soloOpt[1]}".');
- return parent.parseSoloOption();
- }
-
- args.removeAt(0);
-
- if (option.isFlag) {
- setOption(results, option, true);
- } else {
- readNextArgAsValue(option);
- }
-
- return true;
- }
-
- /// Tries to parse the current argument as a series of collapsed abbreviations
- /// (like "-abc") or a single abbreviation with the value directly attached
- /// to it (like "-mrelease").
- bool parseAbbreviation(Parser innermostCommand) {
- var abbrOpt = _ABBR_OPT.firstMatch(current);
- if (abbrOpt == null) return false;
-
- // If the first character is the abbreviation for a non-flag option, then
- // the rest is the value.
- var c = abbrOpt[1].substring(0, 1);
- var first = grammar.findByAbbreviation(c);
- if (first == null) {
- // Walk up to the parent command if possible.
- validate(
- parent != null, 'Could not find an option with short name "-$c".');
- return parent.parseAbbreviation(innermostCommand);
- } else if (!first.isFlag) {
- // The first character is a non-flag option, so the rest must be the
- // value.
- var value = '${abbrOpt[1].substring(1)}${abbrOpt[2]}';
- setOption(results, first, value);
- } else {
- // If we got some non-flag characters, then it must be a value, but
- // if we got here, it's a flag, which is wrong.
- validate(
- abbrOpt[2] == '',
- 'Option "-$c" is a flag and cannot handle value '
- '"${abbrOpt[1].substring(1)}${abbrOpt[2]}".');
-
- // Not an option, so all characters should be flags.
- // We use "innermostCommand" here so that if a parent command parses the
- // *first* letter, subcommands can still be found to parse the other
- // letters.
- for (var i = 0; i < abbrOpt[1].length; i++) {
- var c = abbrOpt[1].substring(i, i + 1);
- innermostCommand.parseShortFlag(c);
- }
- }
-
- args.removeAt(0);
- return true;
- }
-
- void parseShortFlag(String c) {
- var option = grammar.findByAbbreviation(c);
- if (option == null) {
- // Walk up to the parent command if possible.
- validate(
- parent != null, 'Could not find an option with short name "-$c".');
- parent.parseShortFlag(c);
- return;
- }
-
- // In a list of short options, only the first can be a non-flag. If
- // we get here we've checked that already.
- validate(
- option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".');
-
- setOption(results, option, true);
- }
-
- /// Tries to parse the current argument as a long-form named option, which
- /// may include a value like "--mode=release" or "--mode release".
- bool parseLongOption() {
- var longOpt = _LONG_OPT.firstMatch(current);
- if (longOpt == null) return false;
-
- var name = longOpt[1];
- var option = grammar.options[name];
- if (option != null) {
- args.removeAt(0);
- if (option.isFlag) {
- validate(longOpt[3] == null,
- 'Flag option "$name" should not be given a value.');
-
- setOption(results, option, true);
- } else if (longOpt[3] != null) {
- // We have a value like --foo=bar.
- setOption(results, option, longOpt[3]);
- } else {
- // Option like --foo, so look for the value as the next arg.
- readNextArgAsValue(option);
- }
- } else if (name.startsWith('no-')) {
- // See if it's a negated flag.
- name = name.substring('no-'.length);
- option = grammar.options[name];
- if (option == null) {
- // Walk up to the parent command if possible.
- validate(parent != null, 'Could not find an option named "$name".');
- return parent.parseLongOption();
- }
-
- args.removeAt(0);
- validate(option.isFlag, 'Cannot negate non-flag option "$name".');
- validate(option.negatable, 'Cannot negate option "$name".');
-
- setOption(results, option, false);
- } else {
- // Walk up to the parent command if possible.
- validate(parent != null, 'Could not find an option named "$name".');
- return parent.parseLongOption();
- }
-
- return true;
- }
-
- /// Called during parsing to validate the arguments. Throws a
- /// [FormatException] if [condition] is `false`.
- void validate(bool condition, String message) {
- if (!condition) throw FormatException(message);
- }
-
- /// Validates and stores [value] as the value for [option].
- void setOption(Map results, Option option, dynamic value) {
- // See if it's one of the allowed values.
- if (option.allowed != null) {
- validate(option.allowed.any((allow) => allow == value),
- '"$value" is not an allowed value for option "${option.name}".');
- }
-
- if (option.allowMultiple) {
- results[option.name].add(value);
- } else {
- results[option.name] = value;
- }
- }
-}
diff --git a/pkg/test_runner/lib/src/vendored_pkg/args/src/usage.dart b/pkg/test_runner/lib/src/vendored_pkg/args/src/usage.dart
deleted file mode 100644
index 60d4a9e..0000000
--- a/pkg/test_runner/lib/src/vendored_pkg/args/src/usage.dart
+++ /dev/null
@@ -1,228 +0,0 @@
-// 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 args.src.usage;
-
-import 'dart:math';
-
-import '../args.dart';
-
-/// Takes an [ArgParser] and generates a string of usage (i.e. help) text for its
-/// defined options. Internally, it works like a tabular printer. The output is
-/// divided into three horizontal columns, like so:
-///
-/// -h, --help Prints the usage information
-/// | | | |
-///
-/// It builds the usage text up one column at a time and handles padding with
-/// spaces and wrapping to the next line to keep the cells correctly lined up.
-class Usage {
- static const numColumns = 3; // Abbreviation, long name, help.
-
- /// The parser this is generating usage for.
- final ArgParser args;
-
- /// The working buffer for the generated usage text.
- StringBuffer buffer;
-
- /// The column that the "cursor" is currently on. If the next call to
- /// [write()] is not for this column, it will correctly handle advancing to
- /// the next column (and possibly the next row).
- int currentColumn = 0;
-
- /// The width in characters of each column.
- List<int> columnWidths;
-
- /// The number of sequential lines of text that have been written to the last
- /// column (which shows help info). We track this so that help text that spans
- /// multiple lines can be padded with a blank line after it for separation.
- /// Meanwhile, sequential options with single-line help will be compacted next
- /// to each other.
- int numHelpLines = 0;
-
- /// How many newlines need to be rendered before the next bit of text can be
- /// written. We do this lazily so that the last bit of usage doesn't have
- /// dangling newlines. We only write newlines right *before* we write some
- /// real content.
- int newlinesNeeded = 0;
-
- Usage(this.args);
-
- /// Generates a string displaying usage information for the defined options.
- /// This is basically the help text shown on the command line.
- String generate() {
- buffer = StringBuffer();
-
- calculateColumnWidths();
-
- args.options.forEach((name, option) {
- write(0, getAbbreviation(option));
- write(1, getLongOption(option));
-
- if (option.help != null) write(2, option.help);
-
- if (option.allowedHelp != null) {
- var allowedNames = option.allowedHelp.keys.toList();
- allowedNames.sort();
- newline();
- for (var name in allowedNames) {
- write(1, getAllowedTitle(name));
- write(2, option.allowedHelp[name]);
- }
- newline();
- } else if (option.allowed != null) {
- write(2, buildAllowedList(option));
- } else if (option.defaultValue != null) {
- if (option.isFlag && option.defaultValue == true) {
- write(2, '(defaults to on)');
- } else if (!option.isFlag) {
- write(2, '(defaults to "${option.defaultValue}")');
- }
- }
-
- // If any given option displays more than one line of text on the right
- // column (i.e. help, default value, allowed options, etc.) then put a
- // blank line after it. This gives space where it's useful while still
- // keeping simple one-line options clumped together.
- if (numHelpLines > 1) newline();
- });
-
- return buffer.toString();
- }
-
- String getAbbreviation(Option option) {
- if (option.abbreviation != null) {
- return '-${option.abbreviation}, ';
- } else {
- return '';
- }
- }
-
- String getLongOption(Option option) {
- if (option.negatable) {
- return '--[no-]${option.name}';
- } else {
- return '--${option.name}';
- }
- }
-
- String getAllowedTitle(String allowed) {
- return ' [$allowed]';
- }
-
- void calculateColumnWidths() {
- var abbr = 0;
- var title = 0;
- args.options.forEach((name, option) {
- // Make room in the first column if there are abbreviations.
- abbr = max(abbr, getAbbreviation(option).length);
-
- // Make room for the option.
- title = max(title, getLongOption(option).length);
-
- // Make room for the allowed help.
- if (option.allowedHelp != null) {
- for (var allowed in option.allowedHelp.keys) {
- title = max(title, getAllowedTitle(allowed).length);
- }
- }
- });
-
- // Leave a gutter between the columns.
- title += 4;
- columnWidths = [abbr, title];
- }
-
- void newline() {
- newlinesNeeded++;
- currentColumn = 0;
- numHelpLines = 0;
- }
-
- void write(int column, String text) {
- var lines = text.split('\n');
-
- // Strip leading and trailing empty lines.
- while (lines.isNotEmpty && lines[0].trim() == '') {
- lines.removeRange(0, 1);
- }
-
- while (lines.isNotEmpty && lines[lines.length - 1].trim() == '') {
- lines.removeLast();
- }
-
- for (var line in lines) {
- writeLine(column, line);
- }
- }
-
- void writeLine(int column, String text) {
- // Write any pending newlines.
- while (newlinesNeeded > 0) {
- buffer.writeln('');
- newlinesNeeded--;
- }
-
- // Advance until we are at the right column (which may mean wrapping around
- // to the next line.
- while (currentColumn != column) {
- if (currentColumn < numColumns - 1) {
- buffer.write(padRight('', columnWidths[currentColumn]));
- } else {
- buffer.writeln('');
- }
- currentColumn = (currentColumn + 1) % numColumns;
- }
-
- if (column < columnWidths.length) {
- // Fixed-size column, so pad it.
- buffer.write(padRight(text, columnWidths[column]));
- } else {
- // The last column, so just write it.
- buffer.write(text);
- }
-
- // Advance to the next column.
- currentColumn = (currentColumn + 1) % numColumns;
-
- // If we reached the last column, we need to wrap to the next line.
- if (column == numColumns - 1) newlinesNeeded++;
-
- // Keep track of how many consecutive lines we've written in the last
- // column.
- if (column == numColumns - 1) {
- numHelpLines++;
- } else {
- numHelpLines = 0;
- }
- }
-
- String buildAllowedList(Option option) {
- var allowedBuffer = StringBuffer();
- allowedBuffer.write('[');
- var first = true;
- for (var allowed in option.allowed) {
- if (!first) allowedBuffer.write(', ');
- allowedBuffer.write(allowed);
- if (allowed == option.defaultValue) {
- allowedBuffer.write(' (default)');
- }
- first = false;
- }
- allowedBuffer.write(']');
- return allowedBuffer.toString();
- }
-}
-
-/// Pads [source] to [length] by adding spaces at the end.
-String padRight(String source, int length) {
- var result = StringBuffer();
- result.write(source);
-
- while (result.length < length) {
- result.write(' ');
- }
-
- return result.toString();
-}
diff --git a/pkg/test_runner/tool/convert_multitest.dart b/pkg/test_runner/tool/convert_multitest.dart
index 0647876..0bc1a3a 100644
--- a/pkg/test_runner/tool/convert_multitest.dart
+++ b/pkg/test_runner/tool/convert_multitest.dart
@@ -10,13 +10,13 @@
import 'dart:convert';
import 'dart:io';
+import 'package:args/args.dart';
import 'package:path/path.dart';
import 'package:test_runner/src/multitest.dart';
import 'package:test_runner/src/path.dart';
import 'package:test_runner/src/static_error.dart';
import 'package:test_runner/src/test_file.dart';
import 'package:test_runner/src/update_errors.dart';
-import 'package:test_runner/src/vendored_pkg/args/args.dart';
import 'update_static_error_tests.dart' show runAnalyzer, runCfe;
@@ -247,13 +247,13 @@
var parser = ArgParser();
parser.addFlag("verbose", abbr: "v", help: "print additional information");
parser.addFlag("write", abbr: "w", help: "write output to input file");
- parser.addOption("enable-experiment",
- help: "Enable one or more experimental features", allowMultiple: true);
+ parser.addMultiOption("enable-experiment",
+ help: "Enable one or more experimental features");
var results = parser.parse(arguments);
if (results.rest.isEmpty) {
print("Usage: convert_multi_test.dart [-v] [-w] <input files>");
- print(parser.getUsage());
+ print(parser.usage);
exitCode = 1;
return;
}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_late.dart b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart
new file mode 100644
index 0000000..048ae94
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2022, 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.
+
+// @dart=2.16
+
+import 'dart:ffi';
+
+class Foo implements Finalizable {}
+
+void main() {
+ late Foo foo;
+ // Generates a reachability fence between the constructor call and assignment.
+ // That reachability fence should not trigger a late initialization error.
+ foo = Foo();
+ print(foo);
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_late.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart.expect
new file mode 100644
index 0000000..45321de
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart.expect
@@ -0,0 +1,22 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class Foo extends core::Object implements ffi::Finalizable {
+ synthetic constructor •() → self::Foo
+ : super core::Object::•()
+ ;
+}
+static method main() → void {
+ late self::Foo foo;
+ foo = block {
+ final self::Foo :expressionValueWrappedFinalizable = new self::Foo::•();
+ _in::reachabilityFence(foo);
+ } =>:expressionValueWrappedFinalizable;
+ core::print(foo);
+ _in::reachabilityFence(foo);
+}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 6bbd861..abfc8a7 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2095,28 +2095,35 @@
return Fragment();
}
-Fragment StreamingFlowGraphBuilder::BuildVariableGet(TokenPosition* position) {
+Fragment StreamingFlowGraphBuilder::BuildVariableGet(
+ TokenPosition* position,
+ bool allow_late_uninitialized) {
const TokenPosition pos = ReadPosition();
if (position != nullptr) *position = pos;
intptr_t variable_kernel_position = ReadUInt(); // read kernel position.
ReadUInt(); // read relative variable index.
SkipOptionalDartType(); // read promoted type.
- return BuildVariableGetImpl(variable_kernel_position, pos);
+ return BuildVariableGetImpl(variable_kernel_position, pos,
+ allow_late_uninitialized);
}
-Fragment StreamingFlowGraphBuilder::BuildVariableGet(uint8_t payload,
- TokenPosition* position) {
+Fragment StreamingFlowGraphBuilder::BuildVariableGet(
+ uint8_t payload,
+ TokenPosition* position,
+ bool allow_late_uninitialized) {
const TokenPosition pos = ReadPosition();
if (position != nullptr) *position = pos;
intptr_t variable_kernel_position = ReadUInt(); // read kernel position.
- return BuildVariableGetImpl(variable_kernel_position, pos);
+ return BuildVariableGetImpl(variable_kernel_position, pos,
+ allow_late_uninitialized);
}
Fragment StreamingFlowGraphBuilder::BuildVariableGetImpl(
intptr_t variable_kernel_position,
- TokenPosition position) {
+ TokenPosition position,
+ bool allow_late_uninitialized) {
LocalVariable* variable = LookupVariable(variable_kernel_position);
- if (!variable->is_late()) {
+ if (!variable->is_late() || allow_late_uninitialized) {
return LoadLocal(variable);
}
@@ -3479,6 +3486,8 @@
switch (recognized_kind) {
case MethodRecognizer::kNativeEffect:
return BuildNativeEffect();
+ case MethodRecognizer::kReachabilityFence:
+ return BuildReachabilityFence();
case MethodRecognizer::kFfiAsFunctionInternal:
return BuildFfiAsFunctionInternal();
case MethodRecognizer::kFfiNativeCallbackFunction:
@@ -5722,6 +5731,45 @@
return code;
}
+Fragment StreamingFlowGraphBuilder::BuildReachabilityFence() {
+ const intptr_t argc = ReadUInt(); // Read argument count.
+ ASSERT(argc == 1); // LoadField, can be late.
+ const intptr_t list_length = ReadListLength(); // Read types list length.
+ ASSERT(list_length == 0);
+
+ const intptr_t positional_count = ReadListLength();
+ ASSERT(positional_count == 1);
+
+ // The CFE transform only generates a subset of argument expressions:
+ // either variable get or `this`.
+ uint8_t payload = 0;
+ Tag tag = ReadTag(&payload);
+ TokenPosition* position = nullptr;
+ const bool allow_late_uninitialized = true;
+ Fragment code;
+ switch (tag) {
+ case kVariableGet:
+ code = BuildVariableGet(position, allow_late_uninitialized);
+ break;
+ case kSpecializedVariableGet:
+ code = BuildVariableGet(payload, position, allow_late_uninitialized);
+ break;
+ case kThisExpression:
+ code = BuildThisExpression(position);
+ break;
+ default:
+ // The transformation should not be generating anything else.
+ FATAL1("Unexpected tag %i", tag);
+ }
+
+ const intptr_t named_args_len = ReadListLength();
+ ASSERT(named_args_len == 0);
+
+ code <<= new (Z) ReachabilityFenceInstr(Pop());
+ code += NullConstant(); // Return type is void.
+ return code;
+}
+
static void ReportIfNotNull(const char* error) {
if (error != nullptr) {
const auto& language_error = Error::Handle(
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index cd5ccb6..4547f0e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -274,10 +274,14 @@
Fragment BuildArgumentsFromActualArguments(Array* argument_names);
Fragment BuildInvalidExpression(TokenPosition* position);
- Fragment BuildVariableGet(TokenPosition* position);
- Fragment BuildVariableGet(uint8_t payload, TokenPosition* position);
+ Fragment BuildVariableGet(TokenPosition* position,
+ bool allow_late_uninitialized = false);
+ Fragment BuildVariableGet(uint8_t payload,
+ TokenPosition* position,
+ bool allow_late_uninitialized = false);
Fragment BuildVariableGetImpl(intptr_t variable_kernel_position,
- TokenPosition position);
+ TokenPosition position,
+ bool allow_late_uninitialized = false);
Fragment BuildVariableSet(TokenPosition* position);
Fragment BuildVariableSet(uint8_t payload, TokenPosition* position);
Fragment BuildVariableSetImpl(TokenPosition position,
@@ -368,6 +372,10 @@
// Build flow graph for '_nativeEffect'.
Fragment BuildNativeEffect();
+ // Build the call-site manually, to avoid doing initialization checks
+ // for late fields.
+ Fragment BuildReachabilityFence();
+
// Build flow graph for '_loadAbiSpecificInt' and
// '_loadAbiSpecificIntAtIndex', '_storeAbiSpecificInt', and
// '_storeAbiSpecificIntAtIndex' call sites.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index d516d3f..fe6b416 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -955,7 +955,6 @@
case MethodRecognizer::kCopyRangeFromUint8ListToOneByteString:
case MethodRecognizer::kImmutableLinkedHashBase_setIndexStoreRelease:
case MethodRecognizer::kFfiAbi:
- case MethodRecognizer::kReachabilityFence:
case MethodRecognizer::kUtf8DecoderScan:
case MethodRecognizer::kHas63BitSmis:
case MethodRecognizer::kExtensionStreamHasListener:
@@ -1293,12 +1292,6 @@
body += Utf8Scan();
body += Box(kUnboxedIntPtr);
break;
- case MethodRecognizer::kReachabilityFence:
- ASSERT_EQUAL(function.NumParameters(), 1);
- body += LoadLocal(parsed_function_->RawParameterVariable(0));
- body += ReachabilityFence();
- body += NullConstant();
- break;
case MethodRecognizer::kFfiAbi:
ASSERT_EQUAL(function.NumParameters(), 0);
body += IntConstant(static_cast<int64_t>(compiler::ffi::TargetAbi()));
diff --git a/tests/language/vm/regress_49005_test.dart b/tests/language/vm/regress_49005_test.dart
new file mode 100644
index 0000000..619aa12
--- /dev/null
+++ b/tests/language/vm/regress_49005_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, 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 'dart:ffi';
+
+class Foo implements Finalizable {}
+
+void main() {
+ late Foo foo;
+ foo = Foo();
+ print(foo);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 7d7058c..b892b81 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 112
+PRERELEASE 113
PRERELEASE_PATCH 0
\ No newline at end of file