Version 2.17.0-275.0.dev
Merge commit '837ee17b43aa2b5601cad637b9348cc8fd848d99' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce5d29a..7cfff32 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,24 @@
- Add `ref=` and `[]=` methods to the `StructPointer` and `UnionPointer`
extensions. They copy a compound instance into a native memory region.
+- Add `AbiSpecificInteger`s for common C types:
+ - `char`
+ - `unsigned char`
+ - `signed char`
+ - `short`
+ - `unsigned short`
+ - `int`
+ - `unsigned int`
+ - `long`
+ - `unsigned long`
+ - `long long`
+ - `unsigned long long`
+ - `uintptr_t`
+ - `size_t`
+ - `wchar_t`
+- Add `NativeFinalizer` which can potentially detect when objects are
+ "garbage collected". `NativeFinalizer`s run native code where `dart:core`'s
+ `Finalizer`s run Dart code on finalization.
#### `dart:html`
@@ -172,6 +190,11 @@
error with an existing stack trace, instead of creating
a new stack trace.
+#### `dart:ffi`
+
+- Add `Abi` and `AbiSpecificInteger`. These enable specifying integers which
+ have different sizes/signs per ABI (hardware and OS combination).
+
#### `dart:io`
- **Security advisory**
@@ -608,6 +631,10 @@
Code catching the class should move to catching `Error` instead
(or, for integers, check first for whether it's dividing by zero).
+#### `dart:ffi`
+
+- Add `Bool` native type.
+
#### `dart:io`
- **Breaking change** [#46875](https://github.com/dart-lang/sdk/issues/46875):
@@ -912,8 +939,9 @@
#### `dart:ffi`
-- Adds the `DynamicLibrary.providesSymbol` function to check whether a symbol is
+- Add the `DynamicLibrary.providesSymbol` function to check whether a symbol is
available in a dynamic library.
+- Add `Union` native type for interacting with unions in native memory.
#### `dart:html`
@@ -1210,6 +1238,11 @@
- Added `serverWebSocketUri` property to `ServiceProtocolInfo`.
+#### `dart:ffi`
+
+- Add `Packed` for interacting with packed structs in native memory.
+- Add `Array` for interacting with structs with inline arrays.
+
### Dart VM
### Tools
@@ -1350,6 +1383,26 @@
- Add `Set.unmodifiable()` constructor, which allows users to create
unmodifiable `Set` instances.
+#### `dart:ffi`
+
+- **Breaking change** [#44621][]: Invocations with a generic `T` of `sizeOf<T>`,
+ `Pointer<T>.elementAt()`, `Pointer<T extends Struct>.ref`, and
+ `Pointer<T extends Struct>[]` are being deprecated in the current stable
+ release (2.12), and are planned to be fully removed in the following stable
+ release (2.13). Consequently, `allocate` in `package:ffi` will no longer be
+ able to invoke `sizeOf<T>` generically, and will be deprecated as well.
+ Instead, the `Allocator` it is introduced to `dart:ffi`, and also requires a
+ constant `T` on invocations. For migration notes see the breaking change
+ request.
+
+- **Breaking change** [#44622][]: Subtypes of `Struct` without any native member
+ are being deprecated in the current stable release (2.12), and are planned to
+ be fully removed in the following stable release (2.13). Migrate opaque types
+ to extend `Opaque` rather than `Struct`.
+
+[#44621]: https://github.com/dart-lang/sdk/issues/44621
+[#44622]: https://github.com/dart-lang/sdk/issues/44622
+
#### `dart:io`
- `HttpRequest` now correctly follows HTTP 308 redirects
@@ -1385,26 +1438,6 @@
[#42312]: https://github.com/dart-lang/sdk/issues/42312
-### Foreign Function Interface (`dart:ffi`)
-
-- **Breaking change** [#44621][]: Invocations with a generic `T` of `sizeOf<T>`,
- `Pointer<T>.elementAt()`, `Pointer<T extends Struct>.ref`, and
- `Pointer<T extends Struct>[]` are being deprecated in the current stable
- release (2.12), and are planned to be fully removed in the following stable
- release (2.13). Consequently, `allocate` in `package:ffi` will no longer be
- able to invoke `sizeOf<T>` generically, and will be deprecated as well.
- Instead, the `Allocator` it is introduced to `dart:ffi`, and also requires a
- constant `T` on invocations. For migration notes see the breaking change
- request.
-
-- **Breaking change** [#44622][]: Subtypes of `Struct` without any native member
- are being deprecated in the current stable release (2.12), and are planned to
- be fully removed in the following stable release (2.13). Migrate opaque types
- to extend `Opaque` rather than `Struct`.
-
-[#44621]: https://github.com/dart-lang/sdk/issues/44621
-[#44622]: https://github.com/dart-lang/sdk/issues/44622
-
### Dart2JS
- Remove `--no-defer-class-types` and `--no-new-deferred-split`.
@@ -2028,6 +2061,19 @@
parameter provided in the constructor. This will be used by tooling to allow
for better filtering of timeline events.
+#### `dart:ffi`
+
+- **Breaking change**: Changed `Pointer.asFunction()` and
+ `DynamicLibrary.lookupFunction()` to extension methods. Invoking them
+ dynamically previously already threw an exception, so the runtime behavior
+ stays the same. However, the extension methods are only visible if `dart:ffi`
+ is imported directly. This breaks code where `dart:ffi` is not directly
+ imported. To fix, add:
+
+ ```dart
+ import 'dart:ffi';
+ ```
+
#### `dart:html`
- **Breaking change** [#39627][]: Changed the return type of several HTML native
@@ -2167,19 +2213,6 @@
- `Dart_IsNonNullableType()`
- `Dart_IsNullableType()`
-### Foreign Function Interface (`dart:ffi`)
-
-- **Breaking change**: Changed `Pointer.asFunction()` and
- `DynamicLibrary.lookupFunction()` to extension methods. Invoking them
- dynamically previously already threw an exception, so the runtime behavior
- stays the same. However, the extension methods are only visible if `dart:ffi`
- is imported directly. This breaks code where `dart:ffi` is not directly
- imported. To fix, add:
-
- ```dart
- import 'dart:ffi';
- ```
-
### Tools
#### Dart Dev Compiler (DDC)
@@ -2561,18 +2594,7 @@
- Added optional `parent` parameter to `TimelineTask` constructor to allow for
linking of asynchronous timeline events in the DevTools timeline view.
-#### `dart:io`
-
-- Added `enableTimelineLogging` property to `HttpClient` which, when enabled,
- will post HTTP connection and request information to the developer timeline
- for all `HttpClient` instances.
-
-### Dart VM
-
-- Added a new tool for AOT compiling Dart programs to native, self-contained
- executables. See https://dart.dev/tools/dart2native for additional details.
-
-### Foreign Function Interface (`dart:ffi`)
+#### `dart:ffi`
- **Breaking change**: The API now makes use of static extension members. Static
extension members enable the `dart:ffi` API to be more precise with types, and
@@ -2592,6 +2614,17 @@
- The dartanalyzer (commandline and IDEs) now reports `dart:ffi` static errors.
- Callbacks are now supported in AOT (ahead-of-time) compiled code.
+#### `dart:io`
+
+- Added `enableTimelineLogging` property to `HttpClient` which, when enabled,
+ will post HTTP connection and request information to the developer timeline
+ for all `HttpClient` instances.
+
+### Dart VM
+
+- Added a new tool for AOT compiling Dart programs to native, self-contained
+ executables. See https://dart.dev/tools/dart2native for additional details.
+
### Dart for the Web
#### Dart Dev Compiler (DDC)
diff --git a/DEPS b/DEPS
index fa7dad3..e1d4793 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
# co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
# hashes. It requires access to the dart-build-access group, which EngProd
# has.
- "co19_rev": "7baaec7cf49188b92ceed2af98beb1caf8939756",
+ "co19_rev": "6604c07f70757e9d081f64a08ab36f5b9aeaf937",
# This line prevents conflicts when both packages are rolled simultaneously.
"co19_2_rev": "b2034a17609472e374623f3dbe0efd9f5cb258af",
@@ -141,7 +141,7 @@
"pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
"process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
"protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
- "pub_rev": "a3a102a549388a6dbfecc9252fabb618f9a2f5f7",
+ "pub_rev": "a949b329b1b51f5f3973a790e0a0a45897d837de",
"pub_semver_rev": "ea6c54019948dc03042c595ce9413e17aaf7aa38",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
@@ -150,7 +150,7 @@
"shelf_proxy_tag": "ccd311f64d8689e7a145d703ba267975d6df9e28", # 1.0.0
"shelf_rev": "78ac724a7944700340a3cef28c84bccbe62e9367",
"shelf_web_socket_rev": "24fb8a04befa75a94ac63a27047b231d1a22aab4",
- "source_map_stack_trace_rev": "80709f2d2fe5086ab50d744a28a2d26ea4384a1b",
+ "source_map_stack_trace_rev": "8eabd96b1811e30a11d3c54c9b4afae4fb72e98f",
"source_maps-0.9.4_rev": "38524",
"source_maps_rev": "6499ee3adac8d469e2953e2e8ba4bdb4c2fbef90",
"source_span_rev": "dc189b455d823e2919667f6c5dcb41ab7483bce0",
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
index e94c61e..fddd932 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
@@ -25,16 +25,16 @@
macroDeclarations
.forEach((String macroImport, Map<String, List<String>> macroClasses) {
imports.writeln('import \'$macroImport\';');
+ constructorEntries.writeln("Uri.parse('$macroImport'): {");
macroClasses.forEach((String macroName, List<String> constructorNames) {
- constructorEntries
- .writeln("MacroClassIdentifierImpl(Uri.parse('$macroImport'), "
- "'$macroName'): {");
+ constructorEntries.writeln("'$macroName': {");
for (String constructor in constructorNames) {
constructorEntries.writeln("'$constructor': "
"$macroName.${constructor.isEmpty ? 'new' : constructor},");
}
constructorEntries.writeln('},');
});
+ constructorEntries.writeln("}");
});
return template
.replaceFirst(_importMarker, imports.toString())
@@ -169,8 +169,8 @@
sendResult(serializer);
}
-/// Maps macro identifiers to constructors.
-final _macroConstructors = <MacroClassIdentifierImpl, Map<String, Macro Function()>>{
+/// Maps libraries by uri to macros by name, and then constructors by name.
+final _macroConstructors = <Uri, Map<String, Map<String, Macro Function()>>>{
$_macroConstructorEntriesMarker
};
@@ -181,15 +181,21 @@
Future<SerializableResponse> _instantiateMacro(
InstantiateMacroRequest request) async {
try {
- var constructors = _macroConstructors[request.macroClass];
- if (constructors == null) {
- throw new ArgumentError('Unrecognized macro class \${request.macroClass}');
+ var classes = _macroConstructors[request.library];
+ if (classes == null) {
+ throw new ArgumentError('Unrecognized macro library \${request.library}');
}
- var constructor = constructors[request.constructorName];
+ var constructors = classes[request.name];
+ if (constructors == null) {
+ throw new ArgumentError(
+ 'Unrecognized macro class \${request.name} for library '
+ '\${request.library}');
+ }
+ var constructor = constructors[request.constructor];
if (constructor == null) {
throw new ArgumentError(
- 'Unrecognized constructor name "\${request.constructorName}" for '
- 'macro class "\${request.macroClass}".');
+ 'Unrecognized constructor name "\${request.constructor}" for '
+ 'macro class "\${request.name}".');
}
var instance = Function.apply(constructor, request.arguments.positional, {
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
index f178c40..8a8e8f2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'api.dart';
+// ignore: unused_import
import 'bootstrap.dart'; // For doc comments only.
import 'executor/serialization.dart';
@@ -14,32 +15,15 @@
/// during macro discovery and expansion, and unifies how augmentation libraries
/// are produced.
abstract class MacroExecutor {
- /// Invoked when an implementation discovers a new macro definition in a
- /// [library] with [name], and prepares this executor to run the macro.
- ///
- /// May be invoked more than once for the same macro, which will cause the
- /// macro to be re-loaded. Previous [MacroClassIdentifier]s and
- /// [MacroInstanceIdentifier]s given for this macro will be invalid after
- /// that point and should be discarded.
- ///
- /// The [precompiledKernelUri] if passed must point to a kernel program for
- /// the given macro. A bootstrap Dart program can be generated with the
- /// [bootstrapMacroIsolate] function, and the result should be compiled to
- /// kernel and passed here.
- ///
- /// Some implementations may require [precompiledKernelUri] to be passed, and
- /// will throw an [UnsupportedError] if it is not.
- ///
- /// Throws an exception if the macro fails to load.
- Future<MacroClassIdentifier> loadMacro(Uri library, String name,
- {Uri? precompiledKernelUri});
-
- /// Creates an instance of [macroClass] in the executor, and returns an
- /// identifier for that instance.
+ /// Creates an instance of the macro [name] from [library] in the executor,
+ /// and returns an identifier for that instance.
///
/// Throws an exception if an instance is not created.
+ ///
+ /// Instances may be re-used throughout a single build, but should be
+ /// re-created on subsequent builds (even incremental ones).
Future<MacroInstanceIdentifier> instantiateMacro(
- MacroClassIdentifier macroClass, String constructor, Arguments arguments);
+ Uri library, String name, String constructor, Arguments arguments);
/// Runs the type phase for [macro] on a given [declaration].
///
@@ -93,7 +77,7 @@
/// Tell the executor to shut down and clean up any resources it may have
/// allocated.
- void close();
+ Future<void> close();
}
/// The arguments passed to a macro constructor.
@@ -266,12 +250,6 @@
topLevelMember,
}
-/// An opaque identifier for a macro class, retrieved by
-/// [MacroExecutor.loadMacro].
-///
-/// Used to execute or reload this macro in the future.
-abstract class MacroClassIdentifier implements Serializable {}
-
/// An opaque identifier for an instance of a macro class, retrieved by
/// [MacroExecutor.instantiateMacro].
///
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
index 5609883..2e3c5d2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
@@ -392,21 +392,11 @@
@override
Future<MacroInstanceIdentifier> instantiateMacro(
- MacroClassIdentifier macroClass,
- String constructor,
- Arguments arguments) =>
+ Uri library, String name, String constructor, Arguments arguments) =>
_sendRequest((zoneId) => new InstantiateMacroRequest(
- macroClass, constructor, arguments, RemoteInstance.uniqueId,
+ library, name, constructor, arguments, RemoteInstance.uniqueId,
serializationZoneId: zoneId));
- /// These calls are handled by the higher level executor.
- @override
- Future<MacroClassIdentifier> loadMacro(Uri library, String name,
- {Uri? precompiledKernelUri}) =>
- throw new StateError(
- 'This executor should be wrapped in a MultiMacroExecutor which will '
- 'handle load requests.');
-
/// Sends [serializer.result] to [sendPort], possibly wrapping it in a
/// [TransferableTypedData] object.
void sendResult(Serializer serializer);
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/isolated_executor.dart
index ae15038..35facb9 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/isolated_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/isolated_executor.dart
@@ -6,30 +6,26 @@
import 'dart:isolate';
import 'dart:typed_data';
-import '../executor/multi_executor.dart';
import '../executor/executor_base.dart';
import '../executor/serialization.dart';
import '../executor.dart';
-/// Returns a [MacroExecutor] which loads macros into isolates using precompiled
-/// kernel files and communicates with that isolate using [serializationMode].
+/// Spawns a [MacroExecutor] as an isolate by passing [uriToSpawn] to
+/// [Isolate.spawnUri], and communicating using [serializationMode].
///
-/// The [serializationMode] must be a `server` variant, and any precompiled
-/// programs must use the corresponding `client` variant.
+/// The [uriToSpawn] can be any valid Uri for [Isolate.spawnUri].
+///
+/// Both [arguments] and [packageConfigUri] will be forwarded to
+/// [Isolate.spawnUri] if provided.
+///
+/// The [serializationMode] must be a `server` variant, and [uriToSpawn] must
+/// use the corresponding `client` variant.
///
/// This is the only public api exposed by this library.
-Future<MacroExecutor> start(SerializationMode serializationMode) async =>
- new MultiMacroExecutor((Uri library, String name,
- {Uri? precompiledKernelUri}) {
- if (precompiledKernelUri == null) {
- throw new UnsupportedError(
- 'This environment requires a non-null `precompiledKernelUri` to be '
- 'passed when loading macros.');
- }
-
- return _SingleIsolatedMacroExecutor.start(
- library, name, precompiledKernelUri, serializationMode);
- });
+Future<MacroExecutor> start(SerializationMode serializationMode, Uri uriToSpawn,
+ {List<String> arguments = const [], Uri? packageConfigUri}) async =>
+ _SingleIsolatedMacroExecutor.start(
+ uriToSpawn, serializationMode, arguments, packageConfigUri);
/// Actual implementation of the isolate based macro executor.
class _SingleIsolatedMacroExecutor extends ExternalMacroExecutorBase {
@@ -48,11 +44,15 @@
: super(
messageStream: messageStream, serializationMode: serializationMode);
- static Future<_SingleIsolatedMacroExecutor> start(Uri library, String name,
- Uri precompiledKernelUri, SerializationMode serializationMode) async {
+ static Future<_SingleIsolatedMacroExecutor> start(
+ Uri uriToSpawn,
+ SerializationMode serializationMode,
+ List<String> arguments,
+ Uri? packageConfig) async {
ReceivePort receivePort = new ReceivePort();
- Isolate isolate =
- await Isolate.spawnUri(precompiledKernelUri, [], receivePort.sendPort);
+ Isolate isolate = await Isolate.spawnUri(
+ uriToSpawn, arguments, receivePort.sendPort,
+ packageConfig: packageConfig);
Completer<SendPort> sendPortCompleter = new Completer();
StreamController<Object> messageStreamController =
new StreamController(sync: true);
@@ -79,7 +79,7 @@
}
@override
- void close() => onClose();
+ Future<void> close() => new Future.sync(onClose);
/// Sends the [Serializer.result] to [sendPort], possibly wrapping it in a
/// [TransferableTypedData] object.
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/multi_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/multi_executor.dart
index 654669d..e5b11af 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/multi_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/multi_executor.dart
@@ -7,29 +7,91 @@
import '../api.dart';
import '../executor/augmentation_library.dart';
import '../executor/introspection_impls.dart';
-import '../executor/response_impls.dart';
import '../executor.dart';
/// A [MacroExecutor] implementation which delegates most work to other
/// executors which are spawned through a provided callback.
class MultiMacroExecutor extends MacroExecutor with AugmentationLibraryBuilder {
- /// Individual executors indexed by [MacroClassIdentifier] or
- /// [MacroInstanceIdentifier].
- final _executors = <Object, MacroExecutor>{};
+ /// Executors by [MacroInstanceIdentifier].
+ ///
+ /// Using an expando means we don't have to worry about cleaning up instances
+ /// for executors that were shut down.
+ final Expando<ExecutorFactoryToken> _instanceExecutors = new Expando();
- /// The function to spawn an actual macro executor for a given [loadMacro]
- /// request.
- final Future<MacroExecutor> Function(Uri library, String name,
- {Uri? precompiledKernelUri}) _spawnExecutor;
+ /// Registered factories for starting up a new macro executor for a library.
+ final Map<Uri, ExecutorFactoryToken> _libraryExecutorFactories = {};
- MultiMacroExecutor(this._spawnExecutor);
+ /// All known registered executor factories.
+ final Set<ExecutorFactoryToken> _executorFactoryTokens = {};
- @override
- void close() {
- for (MacroExecutor executor in _executors.values) {
- executor.close();
+ /// Whether or not an executor factory for [library] is currently registered.
+ bool libraryIsRegistered(Uri library) =>
+ _libraryExecutorFactories.containsKey(library);
+
+ /// Registers a [factory] which can produce a [MacroExecutor] that can be
+ /// used to run any macro defined in [libraries].
+ ///
+ /// Throws an [ArgumentError] if a library in [libraries] already has a
+ /// factory registered.
+ ///
+ /// Returns a token which can be used to shut down any executors spawned in
+ /// this way via [unregisterExecutorFactory].
+ ExecutorFactoryToken registerExecutorFactory(
+ FutureOr<MacroExecutor> Function() factory, Set<Uri> libraries) {
+ ExecutorFactoryToken token = new ExecutorFactoryToken._(factory, libraries);
+ _executorFactoryTokens.add(token);
+ for (Uri library in libraries) {
+ if (_libraryExecutorFactories.containsKey(library)) {
+ throw new ArgumentError(
+ 'Attempted to register a macro executor factory for library '
+ '$library which already has one assigned.');
+ }
+ _libraryExecutorFactories[library] = token;
}
- _executors.clear();
+ return token;
+ }
+
+ /// Unregisters [token] for all [libraries].
+ ///
+ /// If [libraries] is not passed (or `null`), then the token is unregistered
+ /// for all libraries.
+ ///
+ /// If no libraries are registered for [token] after this call, then the
+ /// executor mapped to [token] will be shut down and the token will be freed.
+ ///
+ /// This should be called whenever the executors might be stale, or as an
+ /// optimization to shut them down when they are known to be not used any
+ /// longer.
+ Future<void> unregisterExecutorFactory(ExecutorFactoryToken token,
+ {Set<Uri>? libraries}) async {
+ bool shouldClose;
+ if (libraries == null) {
+ libraries = token._libraries;
+ shouldClose = true;
+ } else {
+ token._libraries.removeAll(libraries);
+ shouldClose = token._libraries.isEmpty;
+ }
+
+ for (Uri library in libraries) {
+ _libraryExecutorFactories.remove(library);
+ }
+
+ if (shouldClose) {
+ _executorFactoryTokens.remove(token);
+ token._libraries.clear();
+ await token._close();
+ }
+ }
+
+ /// Shuts down all executors, but does not clear [_libraryExecutorFactories]
+ /// or [_executorFactoryTokens].
+ @override
+ Future<void> close() {
+ Future done = Future.wait([
+ for (ExecutorFactoryToken token in _executorFactoryTokens) token._close(),
+ ]);
+ return done;
}
@override
@@ -39,8 +101,9 @@
IdentifierResolver identifierResolver,
TypeResolver typeResolver,
ClassIntrospector classIntrospector) =>
- _executors[macro]!.executeDeclarationsPhase(macro, declaration,
- identifierResolver, typeResolver, classIntrospector);
+ _instanceExecutors[macro]!._withInstance((executor) =>
+ executor.executeDeclarationsPhase(macro, declaration,
+ identifierResolver, typeResolver, classIntrospector));
@override
Future<MacroExecutionResult> executeDefinitionsPhase(
@@ -51,43 +114,75 @@
ClassIntrospector classIntrospector,
TypeDeclarationResolver typeDeclarationResolver,
TypeInferrer typeInferrer) =>
- _executors[macro]!.executeDefinitionsPhase(
- macro,
- declaration,
- identifierResolver,
- typeResolver,
- classIntrospector,
- typeDeclarationResolver,
- typeInferrer);
+ _instanceExecutors[macro]!._withInstance((executor) =>
+ executor.executeDefinitionsPhase(
+ macro,
+ declaration,
+ identifierResolver,
+ typeResolver,
+ classIntrospector,
+ typeDeclarationResolver,
+ typeInferrer));
@override
Future<MacroExecutionResult> executeTypesPhase(MacroInstanceIdentifier macro,
DeclarationImpl declaration, IdentifierResolver identifierResolver) =>
- _executors[macro]!
- .executeTypesPhase(macro, declaration, identifierResolver);
+ _instanceExecutors[macro]!._withInstance((executor) =>
+ executor.executeTypesPhase(macro, declaration, identifierResolver));
@override
Future<MacroInstanceIdentifier> instantiateMacro(
- MacroClassIdentifier macroClass,
- String constructor,
- Arguments arguments) async {
- MacroExecutor executor = _executors[macroClass]!;
- MacroInstanceIdentifier instance =
- await executor.instantiateMacro(macroClass, constructor, arguments);
- _executors[instance] = executor;
- return instance;
+ Uri library, String name, String constructor, Arguments arguments) {
+ ExecutorFactoryToken? token = _libraryExecutorFactories[library];
+ if (token == null) {
+ throw new ArgumentError(
+ 'No executor registered to run macros from $library');
+ }
+ return token._withInstance((executor) async {
+ MacroInstanceIdentifier instance = await executor.instantiateMacro(
+ library, name, constructor, arguments);
+ _instanceExecutors[instance] = token;
+ return instance;
+ });
+ }
+}
+
+/// A token to track registered [MacroExecutor] factories.
+///
+/// Used to unregister them later on, and also handles bookkeeping for the
+/// factory and actual instances.
+class ExecutorFactoryToken {
+ final FutureOr<MacroExecutor> Function() _factory;
+ FutureOr<MacroExecutor>? _instance;
+ final Set<Uri> _libraries;
+
+ ExecutorFactoryToken._(this._factory, this._libraries);
+
+ /// Runs [callback] with an actual instance once available.
+ ///
+ /// This will spin up an instance if one is not currently running.
+ Future<T> _withInstance<T>(Future<T> Function(MacroExecutor) callback) {
+ FutureOr<MacroExecutor>? instance = _instance;
+ if (instance == null) {
+ instance = _instance = _factory();
+ }
+ if (instance is Future<MacroExecutor>) {
+ return instance.then(callback);
+ } else {
+ return callback(instance);
+ }
}
- @override
- Future<MacroClassIdentifier> loadMacro(Uri library, String name,
- {Uri? precompiledKernelUri}) async {
- MacroClassIdentifier identifier =
- new MacroClassIdentifierImpl(library, name);
- _executors.remove(identifier)?.close();
-
- MacroExecutor executor = await _spawnExecutor(library, name,
- precompiledKernelUri: precompiledKernelUri);
- _executors[identifier] = executor;
- return identifier;
+ /// Closes [_instance] if non-null, and sets it to `null`.
+ Future<void> _close() async {
+ FutureOr<MacroExecutor>? instance = _instance;
+ _instance = null;
+ if (instance != null) {
+ if (instance is Future<MacroExecutor>) {
+ await (await instance).close();
+ } else {
+ await instance.close();
+ }
+ }
}
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
index 07b02f0..7205ecd 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
@@ -10,39 +10,29 @@
import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart';
import '../executor/message_grouper.dart';
-import '../executor/multi_executor.dart';
import '../executor/executor_base.dart';
import '../executor/serialization.dart';
import '../executor.dart';
-/// Returns a [MacroExecutor] which loads macros as separate processes using
-/// precompiled binaries and communicates with that program using
-/// [serializationMode].
+/// Spawns a [MacroExecutor] as a separate process, by running [program] with
+/// [arguments], and communicating using [serializationMode].
///
-/// The [serializationMode] must be a `server` variant, and any precompiled
-/// programs spawned must use the corresponding `client` variant.
+/// The [serializationMode] must be a `server` variant, and [program] must use
+/// the corresponding `client` variant.
///
/// This is the only public api exposed by this library.
Future<MacroExecutor> start(SerializationMode serializationMode,
- CommunicationChannel communicationChannel) async =>
- new MultiMacroExecutor((Uri library, String name,
- {Uri? precompiledKernelUri}) {
- // TODO: We actually assume this is a full precompiled AOT binary, and
- // not a kernel file. We launch it directly using `Process.start`.
- if (precompiledKernelUri == null) {
- throw new UnsupportedError(
- 'This environment requires a non-null `precompiledKernelUri` to be '
- 'passed when loading macros.');
- }
- switch (communicationChannel) {
- case CommunicationChannel.stdio:
- return _SingleProcessMacroExecutor.startWithStdio(library, name,
- serializationMode, precompiledKernelUri.toFilePath());
- case CommunicationChannel.socket:
- return _SingleProcessMacroExecutor.startWithSocket(library, name,
- serializationMode, precompiledKernelUri.toFilePath());
- }
- });
+ CommunicationChannel communicationChannel, String program,
+ [List<String> arguments = const []]) {
+ switch (communicationChannel) {
+ case CommunicationChannel.stdio:
+ return _SingleProcessMacroExecutor.startWithStdio(
+ serializationMode, program, arguments);
+ case CommunicationChannel.socket:
+ return _SingleProcessMacroExecutor.startWithSocket(
+ serializationMode, program, arguments);
+ }
+}
/// Actual implementation of the separate process based macro executor.
class _SingleProcessMacroExecutor extends ExternalMacroExecutorBase {
@@ -62,10 +52,9 @@
messageStream: messageStream, serializationMode: serializationMode);
static Future<_SingleProcessMacroExecutor> startWithSocket(
- Uri library,
- String name,
SerializationMode serializationMode,
- String programPath) async {
+ String programPath,
+ List<String> arguments) async {
late ServerSocket serverSocket;
// Try an ipv6 address loopback first, and fall back on ipv4.
try {
@@ -74,6 +63,7 @@
serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
}
Process process = await Process.start(programPath, [
+ ...arguments,
serverSocket.address.address,
serverSocket.port.toString(),
]);
@@ -116,11 +106,10 @@
}
static Future<_SingleProcessMacroExecutor> startWithStdio(
- Uri library,
- String name,
SerializationMode serializationMode,
- String programPath) async {
- Process process = await Process.start(programPath, []);
+ String programPath,
+ List<String> arguments) async {
+ Process process = await Process.start(programPath, arguments);
process.stderr
.transform(const Utf8Decoder())
.listen((content) => throw new RemoteException(content));
@@ -150,7 +139,7 @@
}
@override
- void close() => onClose();
+ Future<void> close() => new Future.sync(onClose);
/// Sends the [Serializer.result] to [stdin].
///
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/protocol.dart
index b868726..d763d12 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/protocol.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/protocol.dart
@@ -96,9 +96,6 @@
deserializer.moveNext();
error = deserializer.expectString();
break;
- case MessageType.macroClassIdentifier:
- response = new MacroClassIdentifierImpl.deserialize(deserializer);
- break;
case MessageType.macroInstanceIdentifier:
response = new MacroInstanceIdentifierImpl.deserialize(deserializer);
break;
@@ -219,34 +216,38 @@
/// A request to instantiate a macro instance.
class InstantiateMacroRequest extends Request {
- final MacroClassIdentifier macroClass;
- final String constructorName;
+ final Uri library;
+ final String name;
+ final String constructor;
final Arguments arguments;
/// The ID to assign to the identifier, this needs to come from the requesting
/// side so that it is unique.
final int instanceId;
- InstantiateMacroRequest(
- this.macroClass, this.constructorName, this.arguments, this.instanceId,
+ InstantiateMacroRequest(this.library, this.name, this.constructor,
+ this.arguments, this.instanceId,
{required int serializationZoneId})
: super(serializationZoneId: serializationZoneId);
InstantiateMacroRequest.deserialize(
Deserializer deserializer, int serializationZoneId)
- : macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
- constructorName = (deserializer..moveNext()).expectString(),
+ : library = (deserializer..moveNext()).expectUri(),
+ name = (deserializer..moveNext()).expectString(),
+ constructor = (deserializer..moveNext()).expectString(),
arguments = new Arguments.deserialize(deserializer),
instanceId = (deserializer..moveNext()).expectInt(),
super.deserialize(deserializer, serializationZoneId);
@override
void serialize(Serializer serializer) {
- serializer.addInt(MessageType.instantiateMacroRequest.index);
- macroClass.serialize(serializer);
- serializer.addString(constructorName);
- arguments.serialize(serializer);
- serializer.addInt(instanceId);
+ serializer
+ ..addInt(MessageType.instantiateMacroRequest.index)
+ ..addUri(library)
+ ..addString(name)
+ ..addString(constructor)
+ ..addSerializable(arguments)
+ ..addInt(instanceId);
super.serialize(serializer);
}
}
@@ -845,7 +846,6 @@
isSubtypeOfRequest,
loadMacroRequest,
remoteInstance,
- macroClassIdentifier,
macroInstanceIdentifier,
macroExecutionResult,
namedStaticType,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
index eedc0bc..89fb92e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
@@ -7,22 +7,6 @@
import 'serialization.dart';
import 'serialization_extensions.dart';
-/// Implementation of [MacroClassIdentifier].
-class MacroClassIdentifierImpl implements MacroClassIdentifier {
- final String id;
-
- MacroClassIdentifierImpl(Uri library, String name) : id = '$library#$name';
-
- MacroClassIdentifierImpl.deserialize(Deserializer deserializer)
- : id = (deserializer..moveNext()).expectString();
-
- void serialize(Serializer serializer) => serializer.addString(id);
-
- operator ==(other) => other is MacroClassIdentifierImpl && id == other.id;
-
- int get hashCode => id.hashCode;
-}
-
/// Implementation of [MacroInstanceIdentifier].
class MacroInstanceIdentifierImpl implements MacroInstanceIdentifier {
/// Unique identifier for this instance, passed in from the server.
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
index 8cf9207..c51175a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
@@ -67,6 +67,8 @@
}
}
+ Uri expectUri() => Uri.parse(expectString());
+
/// Helper method to read a list of [RemoteInstance]s.
List<T> _expectRemoteInstanceList<T extends RemoteInstance>() {
expectList();
@@ -413,6 +415,13 @@
}
}
+extension Helpers on Serializer {
+ void addUri(Uri uri) => addString('$uri');
+
+ void addSerializable(Serializable serializable) =>
+ serializable.serialize(this);
+}
+
enum _CodePartKind {
string,
code,
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
index f29fc9f..04fe99d 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
@@ -7,6 +7,7 @@
import 'id.dart';
import 'id_generation.dart';
import '../util/colors.dart' as colors;
+import '../util/options.dart';
const String cfeMarker = 'cfe';
const String cfeWithNnbdMarker = '$cfeMarker:nnbd';
@@ -504,9 +505,10 @@
/// Checks [compiledData] against the expected data in [expectedMaps] derived
/// from [code].
Future<TestResult<T>> checkCode<T>(
+ MarkerOptions markerOptions,
+ String marker,
String modeName,
- Uri mainFileUri,
- Map<Uri, AnnotatedCode> code,
+ TestData testData,
MemberAnnotations<IdValue> expectedMaps,
CompiledData<T> compiledData,
DataInterpreter<T> dataInterpreter,
@@ -514,6 +516,9 @@
bool fatalErrors: true,
bool succinct: false,
required void onFailure(String message)}) async {
+ String testName = testData.name;
+ Map<Uri, AnnotatedCode> code = testData.code;
+
bool hasFailure = false;
Set<Uri> neededDiffs = new Set<Uri>();
@@ -630,12 +635,18 @@
hasFailure = true;
}
if (hasFailure && fatalErrors) {
- onFailure('Errors found.');
+ onFailure(generateErrorMessage(
+ markerOptions,
+ mismatches: {
+ testName: {marker}
+ },
+ ));
}
return new TestResult<T>(dataInterpreter, compiledData, hasFailure);
}
-typedef Future<Map<String, TestResult<T>>> RunTestFunction<T>(TestData testData,
+typedef Future<Map<String, TestResult<T>>> RunTestFunction<T>(
+ MarkerOptions markerOptions, TestData testData,
{required bool testAfterFailures,
required bool verbose,
required bool succinct,
@@ -657,8 +668,37 @@
]);
}
+/// Description of a tester for a specific marker.
+///
+/// A tester is the runnable dart script used to run the tests for a certain
+/// configurations. For instance
+/// `pkg/front_end/test/id_tests/constant_test.dart` is used to run the test
+/// data in `pkg/_fe_analyzer_shared/test/constants/data/` using the front end
+/// and `pkg/analyzer/test/id_tests/constant_test.dart` is used to run the same
+/// test data using the analyzer.
+class MarkerTester {
+ /// The marker supported by this tester, for instance 'cfe' for front end
+ /// testing.
+ final String marker;
+
+ /// The path of the tester relative to the sdk repo root, for instance
+ /// `pkg/front_end/test/id_tests/constant_test.dart`.
+ final String path;
+
+ /// The resolved file uri for the test.
+ final Uri uri;
+
+ MarkerTester(this.marker, this.path, this.uri);
+
+ @override
+ String toString() => 'MarkerTester($marker,$path,$uri)';
+}
+
+/// A model of the testers defined in a `marker.options` file, located in the
+/// data folder for id tests.
class MarkerOptions {
- final Map<String, Uri> markers;
+ /// The supported markers and their corresponding testers.
+ final Map<String, MarkerTester> markers;
MarkerOptions.internal(this.markers);
@@ -670,7 +710,7 @@
throw new ArgumentError("Marker option file '$file' doesn't exist.");
}
- Map<String, Uri> markers = {};
+ Map<String, MarkerTester> markers = {};
String text = file.readAsStringSync();
bool isScriptFound = false;
for (String line in text.split('\n')) {
@@ -692,7 +732,7 @@
if (markers.containsKey(marker)) {
throw new ArgumentError("Duplicate marker '$marker' in ${file.uri}");
}
- markers[marker] = testerFile.uri;
+ markers[marker] = new MarkerTester(marker, tester, testerFile.uri);
if (testerFile.absolute.uri == script.absolute.uri) {
isScriptFound = true;
}
@@ -707,14 +747,14 @@
Iterable<String> get supportedMarkers => markers.keys;
Future<void> runAll(List<String> args) async {
- Set<Uri> testers = markers.values.toSet();
+ Set<MarkerTester> testers = markers.values.toSet();
bool allOk = true;
- for (Uri tester in testers) {
+ for (MarkerTester tester in testers) {
print('================================================================');
- print('Running tester: $tester ${args.join(' ')}');
+ print('Running tester: ${tester.path} ${args.join(' ')}');
print('================================================================');
Process process = await Process.start(
- Platform.resolvedExecutable, [tester.toString(), ...args],
+ Platform.resolvedExecutable, [tester.uri.toString(), ...args],
mode: ProcessStartMode.inheritStdio);
if (await process.exitCode != 0) {
allOk = false;
@@ -734,6 +774,40 @@
}
}
+// TODO(johnniwinther): Support --show to show actual data for an input.
+class Options {
+ static const Option<bool> runAll =
+ const Option<bool>('--run-all', const BoolValue(false));
+ static const Option<bool> verbose =
+ const Option<bool>('--verbose', const BoolValue(false), aliases: ['-v']);
+ static const Option<bool> succinct =
+ const Option<bool>('--succinct', const BoolValue(false), aliases: ['-s']);
+ static const Option<bool> shouldContinue =
+ const Option<bool>('--continue', const BoolValue(false), aliases: ['-c']);
+ static const Option<bool> stopAfterFailures = const Option<bool>(
+ '--stop-after-failures', const BoolValue(false),
+ aliases: ['-a']);
+ static const Option<bool> printCode = const Option<bool>(
+ '--print-code', const BoolValue(false),
+ aliases: ['-p']);
+ static const Option<bool> generateAnnotations =
+ const Option<bool>('--generate', const BoolValue(false), aliases: ['-g']);
+ static const Option<bool> forceUpdate = const Option<bool>(
+ '--force-update', const BoolValue(false),
+ aliases: ['-f']);
+}
+
+const List<Option> idTestOptions = [
+ Options.runAll,
+ Options.verbose,
+ Options.succinct,
+ Options.shouldContinue,
+ Options.stopAfterFailures,
+ Options.printCode,
+ Options.generateAnnotations,
+ Options.forceUpdate,
+];
+
/// Check code for all tests in [dataDir] using [runTest].
Future<void> runTests<T>(Directory dataDir,
{List<String> args: const <String>[],
@@ -747,24 +821,26 @@
Map<String, List<String>>? skipMap,
bool preserveWhitespaceInAnnotations: false,
bool preserveInfixWhitespaceInAnnotations: false}) async {
+ ParsedOptions parsedOptions = ParsedOptions.parse(args, idTestOptions);
MarkerOptions markerOptions =
new MarkerOptions.fromDataDir(dataDir, shouldFindScript: shards == 1);
- // TODO(johnniwinther): Support --show to show actual data for an input.
- args = args.toList();
- bool runAll = args.remove('--run-all');
- if (runAll) {
- await markerOptions.runAll(args);
+ if (Options.runAll.read(parsedOptions)) {
+ await markerOptions.runAll(Options.runAll.remove(args.toList()));
return;
}
- bool verbose = args.remove('-v');
- bool succinct = args.remove('-s');
- bool shouldContinue = args.remove('-c');
- bool testAfterFailures = args.remove('-a');
- bool printCode = args.remove('-p');
+ bool verbose = Options.verbose.read(parsedOptions);
+ bool succinct = Options.succinct.read(parsedOptions);
+ bool shouldContinue = Options.shouldContinue.read(parsedOptions);
+ bool stopAfterFailures = Options.stopAfterFailures.read(parsedOptions);
+ bool printCode = Options.printCode.read(parsedOptions);
+ bool generateAnnotations = Options.generateAnnotations.read(parsedOptions);
+ bool forceUpdate = Options.forceUpdate.read(parsedOptions);
+ List<String> arguments = parsedOptions.arguments;
+
bool continued = false;
- bool hasFailures = false;
- bool generateAnnotations = args.remove('-g');
- bool forceUpdate = args.remove('-f');
+
+ Map<String, Set<String>> mismatches = {};
+ Map<String, Set<String>> errors = {};
String relativeDir = dataDir.uri.path.replaceAll(Uri.base.path, '');
print('Data dir: ${relativeDir}');
@@ -783,13 +859,17 @@
}
int testCount = 0;
for (FileSystemEntity entity in entities) {
- String name = getTestName(entity);
- if (args.isNotEmpty && !args.contains(name) && !continued) continue;
+ String testName = getTestName(entity);
+ if (arguments.isNotEmpty && !arguments.contains(testName) && !continued) {
+ continue;
+ }
if (shouldContinue) continued = true;
testCount++;
- if (skipList != null && skipList.contains(name) && !args.contains(name)) {
- print('Skip: ${name}');
+ if (skipList != null &&
+ skipList.contains(testName) &&
+ !arguments.contains(testName)) {
+ print('Skip: ${testName}');
continue;
}
if (onTest != null) {
@@ -814,27 +894,31 @@
preserveInfixWhitespaceInAnnotations);
print('Test: ${testData.testFileUri}');
- Map<String, TestResult<T>> results = await runTest(testData,
- testAfterFailures: testAfterFailures || generateAnnotations,
+ Map<String, TestResult<T>> results = await runTest(markerOptions, testData,
+ testAfterFailures: !stopAfterFailures || generateAnnotations,
verbose: verbose,
succinct: succinct,
printCode: printCode,
skipMap: skipMap,
nullUri: createTestUri(entity.uri.resolve("null"), "null"));
- bool hasMismatches = false;
- bool hasErrors = false;
+ Set<String> mismatchMarkers = {};
+ Set<String> errorMarkers = {};
results.forEach((String marker, TestResult<T> result) {
if (result.hasMismatches) {
- hasMismatches = true;
+ mismatchMarkers.add(marker);
} else if (result.isErroneous) {
- hasErrors = true;
+ errorMarkers.add(marker);
}
});
- if (hasErrors) {
+ if (errorMarkers.isNotEmpty) {
// Cannot generate annotations for erroneous tests.
- hasFailures = true;
- } else if (hasMismatches || (forceUpdate && generateAnnotations)) {
+ if (mismatchMarkers.isNotEmpty) {
+ mismatches[testName] = mismatchMarkers;
+ }
+ errors[testName] = errorMarkers;
+ } else if (mismatchMarkers.isNotEmpty ||
+ (forceUpdate && generateAnnotations)) {
if (generateAnnotations) {
DataInterpreter? dataInterpreter;
Map<String, Map<Uri, Map<Id, ActualData<T>>>> actualData = {};
@@ -885,18 +969,93 @@
print('Generated annotations for ${fileUri}');
});
} else {
- hasFailures = true;
+ mismatches[testName] = mismatchMarkers;
}
}
}
- if (hasFailures) {
- onFailure('Errors found.');
+ if (mismatches.isNotEmpty || errors.isNotEmpty) {
+ onFailure(generateErrorMessage(markerOptions,
+ mismatches: mismatches, errors: errors));
}
if (testCount == 0) {
onFailure("No files were tested.");
}
}
+/// Generates an error message for the [mismatches] and [errors] using
+/// [markerOptions] to provide a re-run/re-generation command.
+///
+/// [mismatches] and [errors] are maps from the test names of the failing tests
+/// to the markers for the configurations in which they failed.
+String generateErrorMessage(MarkerOptions markerOptions,
+ {Map<String, Set<String>> mismatches = const {},
+ Map<String, Set<String>> errors = const {}}) {
+ Set<String> testNames = {...mismatches.keys, ...errors.keys};
+ StringBuffer message = new StringBuffer();
+ message.writeln();
+ message.writeln('==========================================================');
+ message.writeln();
+ if (testNames.length > 1) {
+ message.writeln("Errors found in tests:");
+ message.writeln();
+ for (String testName in testNames.toList()..sort()) {
+ message.writeln(" ${testName}");
+ }
+ } else {
+ message.writeln("Errors found in test '${testNames.single}'");
+ }
+ if (mismatches.isNotEmpty) {
+ Map<MarkerTester, Set<String>> regenerations = {};
+ mismatches.forEach((String testName, Set<String> markers) {
+ for (String marker in markers) {
+ MarkerTester tester = markerOptions.markers[marker]!;
+ (regenerations[tester] ??= {}).add(testName);
+ }
+ });
+ message.writeln();
+ if (regenerations.length > 1) {
+ message.writeln('Run these commands to generate new expectations:');
+ } else {
+ message.writeln('Run this command to generate new expectations:');
+ }
+ message.writeln();
+ regenerations.forEach((MarkerTester tester, Set<String> testNames) {
+ message.write(' dart ${tester.path} -g');
+ for (String testName in testNames) {
+ message.write(' ${testName}');
+ }
+ message.writeln();
+ });
+ }
+ message.writeln();
+ if (errors.isNotEmpty) {
+ Map<MarkerTester, Set<String>> erroneous = {};
+ errors.forEach((String testName, Set<String> markers) {
+ for (String marker in markers) {
+ MarkerTester tester = markerOptions.markers[marker]!;
+ (erroneous[tester] ??= {}).add(testName);
+ }
+ });
+ message.writeln();
+ if (erroneous.length > 1) {
+ message.writeln('Run these commands to re-run the failing tests:');
+ } else {
+ message.writeln('Run this command to re-run the failing test(s):');
+ }
+ message.writeln();
+ erroneous.forEach((MarkerTester tester, Set<String> testNames) {
+ message.write(' dart ${tester.path}');
+ for (String testName in testNames) {
+ message.write(' ${testName}');
+ }
+ message.writeln();
+ });
+ }
+ message.writeln();
+ message.writeln('==========================================================');
+ return message.toString();
+}
+
/// Returns `true` if [testName] is marked as skipped in [skipMap] for
/// the given [configMarker].
bool skipForConfig(
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/options.dart b/pkg/_fe_analyzer_shared/lib/src/util/options.dart
index 17c3c01..59a8442 100644
--- a/pkg/_fe_analyzer_shared/lib/src/util/options.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/util/options.dart
@@ -307,4 +307,12 @@
T read(ParsedOptions parsedOptions) =>
(isDefines ? parsedOptions.defines : parsedOptions.options[flag]) as T;
+
+ List<String> remove(List<String> arguments) {
+ arguments.remove(flag);
+ for (String alias in aliases) {
+ arguments.remove(alias);
+ }
+ return arguments;
+ }
}
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
index c70ad25..127791c 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
@@ -46,14 +46,6 @@
setUpAll(() async {
simpleMacroFile =
File(Platform.script.resolve('simple_macro.dart').toFilePath());
- executor = executorKind == 'Isolated'
- ? await isolatedExecutor.start(mode)
- : executorKind == 'ProcessSocket'
- ? await processExecutor.start(
- mode, CommunicationChannel.socket)
- : await processExecutor.start(
- mode, CommunicationChannel.stdio);
-
tmpDir = Directory.systemTemp.createTempSync('executor_test');
macroUri = simpleMacroFile.absolute.uri;
@@ -86,22 +78,26 @@
reason: 'stdout: ${buildSnapshotResult.stdout}\n'
'stderr: ${buildSnapshotResult.stderr}');
- var clazzId = await executor.loadMacro(macroUri, macroName,
- precompiledKernelUri: kernelOutputFile.uri);
- expect(clazzId, isNotNull, reason: 'Can load a macro.');
+ executor = executorKind == 'Isolated'
+ ? await isolatedExecutor.start(mode, kernelOutputFile.uri)
+ : executorKind == 'ProcessSocket'
+ ? await processExecutor.start(mode,
+ CommunicationChannel.socket, kernelOutputFile.path)
+ : await processExecutor.start(mode,
+ CommunicationChannel.stdio, kernelOutputFile.path);
- instanceId =
- await executor.instantiateMacro(clazzId, '', Arguments([], {}));
+ instanceId = await executor.instantiateMacro(
+ macroUri, macroName, '', Arguments([], {}));
expect(instanceId, isNotNull,
reason: 'Can create an instance with no arguments.');
instanceId = await executor.instantiateMacro(
- clazzId, '', Arguments([1, 2], {}));
+ macroUri, macroName, '', Arguments([1, 2], {}));
expect(instanceId, isNotNull,
reason: 'Can create an instance with positional arguments.');
instanceId = await executor.instantiateMacro(
- clazzId, 'named', Arguments([], {'x': 1, 'y': 2}));
+ macroUri, macroName, 'named', Arguments([], {'x': 1, 'y': 2}));
expect(instanceId, isNotNull,
reason: 'Can create an instance with named arguments.');
});
diff --git a/pkg/_js_interop_checks/OWNERS b/pkg/_js_interop_checks/OWNERS
new file mode 100644
index 0000000..f5bd90c
--- /dev/null
+++ b/pkg/_js_interop_checks/OWNERS
@@ -0,0 +1 @@
+file:/tools/OWNERS_WEB
diff --git a/pkg/analysis_server/benchmark/benchmarks.dart b/pkg/analysis_server/benchmark/benchmarks.dart
index 7037a85..cf25eb4 100644
--- a/pkg/analysis_server/benchmark/benchmarks.dart
+++ b/pkg/analysis_server/benchmark/benchmarks.dart
@@ -75,6 +75,7 @@
Future oneTimeSetup() => Future.value();
Future<BenchMarkResult> run({
+ required String dartSdkPath,
bool quick = false,
bool verbose = false,
});
@@ -194,6 +195,8 @@
final List<Benchmark> benchmarks;
RunCommand(this.benchmarks) {
+ argParser.addOption('dart-sdk',
+ help: 'The absolute normalized path of the Dart SDK.');
argParser.addOption('flutter-repository',
help: 'The absolute normalized path of the Flutter repository.');
argParser.addFlag('quick',
@@ -230,6 +233,7 @@
var benchmarkId = args.rest.first;
var repeatCount = int.parse(args['repeat'] as String);
+ var dartSdkPath = args['dart-sdk'] as String?;
var flutterRepository = args['flutter-repository'] as String?;
var quick = args['quick'] as bool;
var verbose = args['verbose'] as bool;
@@ -240,6 +244,8 @@
exit(1);
});
+ dartSdkPath ??= path.dirname(path.dirname(Platform.resolvedExecutable));
+
if (benchmark is FlutterBenchmark) {
if (flutterRepository != null) {
if (path.isAbsolute(flutterRepository) &&
@@ -274,6 +280,7 @@
for (var iteration = 0; iteration < actualIterations; iteration++) {
var newResult = await benchmark.run(
+ dartSdkPath: dartSdkPath,
quick: quick,
verbose: verbose,
);
diff --git a/pkg/analysis_server/benchmark/integration/driver.dart b/pkg/analysis_server/benchmark/integration/driver.dart
index 9f40d74..b52e80a 100644
--- a/pkg/analysis_server/benchmark/integration/driver.dart
+++ b/pkg/analysis_server/benchmark/integration/driver.dart
@@ -3,9 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:io';
import 'dart:math' show max, sqrt;
import 'package:logging/logging.dart';
+import 'package:path/path.dart';
import '../../test/integration/support/integration_test_methods.dart';
import '../../test/integration/support/integration_tests.dart';
@@ -90,8 +92,9 @@
serverConnected.complete();
});
running = true;
+ var dartSdkPath = dirname(dirname(Platform.resolvedExecutable));
return server
- .start(diagnosticPort: diagnosticPort /*profileServer: true*/)
+ .start(dartSdkPath: dartSdkPath, diagnosticPort: diagnosticPort)
.then((params) {
server.listenToOutput(dispatchNotification);
server.exitCode.then((_) {
diff --git a/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
index fab0850..f0d8533 100644
--- a/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
+++ b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
@@ -27,6 +27,7 @@
@override
Future<BenchMarkResult> run({
+ required String dartSdkPath,
bool quick = false,
bool verbose = false,
}) async {
@@ -36,7 +37,7 @@
if (verbose) {
test.debugStdio();
}
- await test.setUp(getProjectRoots(quick: quick));
+ await test.setUp(dartSdkPath, getProjectRoots(quick: quick));
await test.analysisFinished;
stopwatch.stop();
@@ -156,6 +157,7 @@
@override
Future<BenchMarkResult> run({
+ required String dartSdkPath,
bool quick = false,
bool verbose = false,
}) async {
@@ -166,7 +168,7 @@
var stopwatch = Stopwatch()..start();
var test = testConstructor();
- await test.setUp(getProjectRoots(quick: quick));
+ await test.setUp(dartSdkPath, getProjectRoots(quick: quick));
await test.analysisFinished;
stopwatch.stop();
diff --git a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
index f2d157b3..3c4ae77 100644
--- a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
+++ b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
@@ -5,8 +5,6 @@
import 'dart:convert';
import 'dart:io';
-import 'package:path/path.dart' as path;
-
import '../benchmarks.dart';
Future<int> _runProcess(
@@ -57,6 +55,7 @@
@override
Future<BenchMarkResult> run({
+ required String dartSdkPath,
bool quick = false,
bool verbose = false,
}) async {
@@ -64,12 +63,10 @@
deleteServerCache();
}
- var dartSdkPath = path.dirname(path.dirname(Platform.resolvedExecutable));
-
var stopwatch = Stopwatch()..start();
await _runProcess(
- Platform.resolvedExecutable,
+ '$dartSdkPath/bin/dart',
[
'packages/flutter_tools/bin/flutter_tools.dart',
'analyze',
diff --git a/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart b/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart
index 7863130..a874443 100644
--- a/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart
+++ b/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart
@@ -37,6 +37,7 @@
@override
Future<BenchMarkResult> run({
+ required String dartSdkPath,
bool quick = false,
bool verbose = false,
}) async {
@@ -55,7 +56,7 @@
// Open a small directory, but with the package config that allows us
// to analyze any file in `package:flutter`, including tests.
var startTimer = Stopwatch()..start();
- await test.setUp([
+ await test.setUp(dartSdkPath, [
'$flutterPkgPath/lib/src/physics',
]);
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index 1837834..307b009 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -25,7 +25,7 @@
void debugStdio();
Future<int> getMemoryUsage();
Future<void> openFile(String filePath, String contents);
- Future<void> setUp(List<String> roots);
+ Future<void> setUp(String dartSdkPath, List<String> roots);
Future<void> shutdown();
Future<void> updateFile(String filePath, String contents);
@@ -76,7 +76,8 @@
}
@override
- Future<void> setUp(List<String> roots) async {
+ Future<void> setUp(String dartSdkPath, List<String> roots) async {
+ _test.dartSdkPath = dartSdkPath;
await _test.setUp();
await _test.subscribeToStatusNotifications();
await _test.subscribeToAvailableSuggestions();
@@ -187,7 +188,8 @@
}
@override
- Future<void> setUp(List<String> roots) async {
+ Future<void> setUp(String dartSdkPath, List<String> roots) async {
+ _test.dartSdkPath = dartSdkPath;
_test.instrumentationService = InstrumentationLogAdapter(_logger);
await _test.setUp();
_test.projectFolderPath = roots.single;
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
index 4a0e09d..455d2c5 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
@@ -22,8 +22,42 @@
class AnalysisDomainGetErrorsTest
extends AbstractAnalysisServerIntegrationTest {
String createNonStandardSdk() {
+ String executableFilePathIn(String sdkPath) {
+ var name = Platform.isWindows ? 'dart.exe' : 'dart';
+ return path.join(sdkPath, 'bin', name);
+ }
+
+ String serverSnapshotPathIn(String sdkPath) {
+ return path.join(
+ sdkPath,
+ 'bin',
+ 'snapshots',
+ 'analysis_server.dart.snapshot',
+ );
+ }
+
var sdkPath = path.join(sourceDirectory.path, 'sdk');
+ var standardSdkPath = path.dirname(
+ path.dirname(Platform.resolvedExecutable),
+ );
+
+ Directory(
+ path.join(sdkPath, 'bin', 'snapshots'),
+ ).createSync(recursive: true);
+
+ File(
+ executableFilePathIn(standardSdkPath),
+ ).copySync(
+ executableFilePathIn(sdkPath),
+ );
+
+ File(
+ serverSnapshotPathIn(standardSdkPath),
+ ).copySync(
+ serverSnapshotPathIn(sdkPath),
+ );
+
Directory(path.join(sdkPath, 'lib', 'core')).createSync(recursive: true);
Directory(path.join(sdkPath, 'lib', 'async')).createSync(recursive: true);
Directory(path.join(sdkPath, 'lib', 'fake')).createSync(recursive: true);
@@ -81,7 +115,7 @@
var sdkPath = createNonStandardSdk();
return server.start(
diagnosticPort: diagnosticPort,
- sdkPath: sdkPath,
+ dartSdkPath: sdkPath,
servicesPort: servicesPort);
}
diff --git a/pkg/analysis_server/test/integration/analysis/highlights_test.dart b/pkg/analysis_server/test/integration/analysis/highlights_test.dart
index 57c3736..2f1fbd3 100644
--- a/pkg/analysis_server/test/integration/analysis/highlights_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/highlights_test.dart
@@ -52,6 +52,7 @@
int? servicesPort,
}) {
return server.start(
+ dartSdkPath: dartSdkPath,
diagnosticPort: diagnosticPort,
servicesPort: servicesPort,
useAnalysisHighlight2: true);
diff --git a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
index cbf06cd..c09c72e 100644
--- a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
@@ -20,6 +20,8 @@
LspServerClient? client;
InstrumentationService? instrumentationService;
final Map<num, Completer<ResponseMessage>> _completers = {};
+ String dartSdkPath = dirname(dirname(Platform.resolvedExecutable));
+
LspByteStreamServerChannel get channel => client!.channel!;
@override
@@ -84,7 +86,7 @@
final client = LspServerClient(instrumentationService);
this.client = client;
- await client.start(vmArgs: vmArgs);
+ await client.start(dartSdkPath: dartSdkPath, vmArgs: vmArgs);
client.serverToClient.listen((message) {
if (message is ResponseMessage) {
final id = message.id!.map((number) => number,
@@ -138,26 +140,22 @@
return dirname(pathname);
}
- Future start({List<String>? vmArgs}) async {
+ Future start({
+ required String dartSdkPath,
+ List<String>? vmArgs,
+ }) async {
if (_process != null) {
throw Exception('Process already started');
}
- var dartBinary = Platform.executable;
+ var dartBinary = join(dartSdkPath, 'bin', 'dart');
var useSnapshot = true;
String serverPath;
if (useSnapshot) {
- // Look for snapshots/analysis_server.dart.snapshot.
- serverPath = normalize(join(dirname(Platform.resolvedExecutable),
- 'snapshots', 'analysis_server.dart.snapshot'));
-
- if (!FileSystemEntity.isFileSync(serverPath)) {
- // Look for dart-sdk/bin/snapshots/analysis_server.dart.snapshot.
- serverPath = normalize(join(dirname(Platform.resolvedExecutable),
- 'dart-sdk', 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
- }
+ serverPath = normalize(join(
+ dartSdkPath, 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
} else {
final rootDir =
findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
diff --git a/pkg/analysis_server/test/integration/server/command_line_options_test.dart b/pkg/analysis_server/test/integration/server/command_line_options_test.dart
index 0b085ea..475bf9a 100644
--- a/pkg/analysis_server/test/integration/server/command_line_options_test.dart
+++ b/pkg/analysis_server/test/integration/server/command_line_options_test.dart
@@ -43,6 +43,7 @@
''');
return server.start(
+ dartSdkPath: dartSdkPath,
diagnosticPort: diagnosticPort,
servicesPort: servicesPort,
packagesFile: packagesPath,
diff --git a/pkg/analysis_server/test/integration/support/integration_tests.dart b/pkg/analysis_server/test/integration/support/integration_tests.dart
index 46858e0..ceb7185 100644
--- a/pkg/analysis_server/test/integration/support/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/support/integration_tests.dart
@@ -108,6 +108,8 @@
/// updates.
bool _subscribedToServerStatus = false;
+ String dartSdkPath = path.dirname(path.dirname(Platform.resolvedExecutable));
+
AbstractAnalysisServerIntegrationTest() {
initializeInttestMixin();
}
@@ -236,6 +238,7 @@
int? servicesPort,
}) {
return server.start(
+ dartSdkPath: dartSdkPath,
diagnosticPort: diagnosticPort,
servicesPort: servicesPort,
);
@@ -607,16 +610,17 @@
/// with "--observe" and "--pause-isolates-on-exit", allowing the observatory
/// to be used.
Future start({
+ required String dartSdkPath,
int? diagnosticPort,
String? instrumentationLogFile,
String? packagesFile,
bool profileServer = false,
- String? sdkPath,
int? servicesPort,
bool useAnalysisHighlight2 = false,
}) async {
_time.start();
- var dartBinary = Platform.executable;
+
+ var dartBinary = path.join(dartSdkPath, 'bin', 'dart');
// The integration tests run 3x faster when run from snapshots (you need to
// run test.py with --use-sdk).
@@ -624,21 +628,8 @@
String serverPath;
if (useSnapshot) {
- // Look for snapshots/analysis_server.dart.snapshot.
serverPath = path.normalize(path.join(
- path.dirname(Platform.resolvedExecutable),
- 'snapshots',
- 'analysis_server.dart.snapshot'));
-
- if (!FileSystemEntity.isFileSync(serverPath)) {
- // Look for dart-sdk/bin/snapshots/analysis_server.dart.snapshot.
- serverPath = path.normalize(path.join(
- path.dirname(Platform.resolvedExecutable),
- 'dart-sdk',
- 'bin',
- 'snapshots',
- 'analysis_server.dart.snapshot'));
- }
+ dartSdkPath, 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
} else {
var rootDir =
findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
@@ -673,6 +664,7 @@
// Add server arguments.
//
arguments.add('--suppress-analytics');
+ arguments.add('--sdk=$dartSdkPath');
if (diagnosticPort != null) {
arguments.add('--port');
arguments.add(diagnosticPort.toString());
@@ -683,9 +675,6 @@
if (packagesFile != null) {
arguments.add('--packages=$packagesFile');
}
- if (sdkPath != null) {
- arguments.add('--sdk=$sdkPath');
- }
if (useAnalysisHighlight2) {
arguments.add('--useAnalysisHighlight2');
}
diff --git a/pkg/analysis_server/test/timing/timing_framework.dart b/pkg/analysis_server/test/timing/timing_framework.dart
index b9eb6d0..31ed32a 100644
--- a/pkg/analysis_server/test/timing/timing_framework.dart
+++ b/pkg/analysis_server/test/timing/timing_framework.dart
@@ -147,7 +147,8 @@
serverConnected.complete();
});
skipShutdown = true;
- return server.start(/*profileServer: true*/).then((_) {
+ var dartSdkPath = dirname(dirname(Platform.resolvedExecutable));
+ return server.start(dartSdkPath: dartSdkPath).then((_) {
server.listenToOutput(dispatchNotification);
server.exitCode.then((_) {
skipShutdown = true;
diff --git a/pkg/analyzer/test/id_tests/nullability_test.dart b/pkg/analyzer/test/id_tests/nullability_test.dart
index 0abde94..659e605 100644
--- a/pkg/analyzer/test/id_tests/nullability_test.dart
+++ b/pkg/analyzer/test/id_tests/nullability_test.dart
@@ -6,16 +6,13 @@
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/analysis/testing_data.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/util/ast_data_extractor.dart';
-import 'package:test/test.dart';
import '../util/id_testing_helper.dart';
@@ -30,19 +27,6 @@
const _NullabilityDataComputer(), [analyzerDefaultConfig]));
}
-class FlowTestBase {
- late final FlowAnalysisDataForTesting flowResult;
-
- /// Resolve the given [code] and track nullability in the unit.
- Future<void> trackCode(String code) async {
- TestResult<String> testResult = await checkTests(code,
- const _NullabilityDataComputer(), FeatureSet.latestLanguageVersion());
- if (testResult.hasFailures) {
- fail('Failure(s)');
- }
- }
-}
-
class _NullabilityDataComputer extends DataComputer<String> {
const _NullabilityDataComputer();
diff --git a/pkg/analyzer/test/id_tests/reachability_test.dart b/pkg/analyzer/test/id_tests/reachability_test.dart
index d5b03f8..6997d16 100644
--- a/pkg/analyzer/test/id_tests/reachability_test.dart
+++ b/pkg/analyzer/test/id_tests/reachability_test.dart
@@ -6,12 +6,10 @@
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/analysis/testing_data.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/util/ast_data_extractor.dart';
-import 'package:test/test.dart';
import '../util/id_testing_helper.dart';
@@ -26,19 +24,6 @@
const _ReachabilityDataComputer(), [analyzerDefaultConfig]));
}
-class FlowTestBase {
- late final FlowAnalysisDataForTesting flowResult;
-
- /// Resolve the given [code] and track nullability in the unit.
- Future<void> trackCode(String code) async {
- TestResult<Set<_ReachabilityAssertion>> testResult = await checkTests(code,
- const _ReachabilityDataComputer(), FeatureSet.latestLanguageVersion());
- if (testResult.hasFailures) {
- fail('Failure(s)');
- }
- }
-}
-
enum _ReachabilityAssertion {
doesNotComplete,
unreachable,
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index 69780494..f5e4f87 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -36,28 +36,6 @@
/// tests.
Uri _defaultDir = Uri.parse('file:///a/b/c/');
-Future<TestResult<T>> checkTests<T>(
- String rawCode, DataComputer<T> dataComputer, FeatureSet featureSet) async {
- AnnotatedCode code =
- AnnotatedCode.fromText(rawCode, commentStart, commentEnd);
- String testFileName = 'test.dart';
- var testFileUri = _toTestUri(testFileName);
- var memorySourceFiles = {testFileName: code.sourceCode};
- var marker = 'analyzer';
- Map<String, MemberAnnotations<IdValue>> expectedMaps = {
- marker: MemberAnnotations<IdValue>(),
- };
- computeExpectedMap(testFileUri, testFileName, code, expectedMaps,
- onFailure: onFailure);
- Map<Uri, AnnotatedCode> codeMap = {testFileUri: code};
- var testData = TestData(testFileName, testFileUri, testFileUri,
- memorySourceFiles, codeMap, expectedMaps);
- var config =
- TestConfig(marker, 'provisional test config', featureSet: featureSet);
- return runTestForConfig<T>(testData, dataComputer, config,
- onFailure: onFailure);
-}
-
/// Creates the testing URI used for [fileName] in annotated tests.
Uri createUriForFileName(String fileName) => _toTestUri(fileName);
@@ -68,8 +46,11 @@
/// Runs [dataComputer] on [testData] for all [testedConfigs].
///
/// Returns `true` if an error was encountered.
-Future<Map<String, TestResult<T>>> runTest<T>(TestData testData,
- DataComputer<T> dataComputer, List<TestConfig> testedConfigs,
+Future<Map<String, TestResult<T>>> runTest<T>(
+ MarkerOptions markerOptions,
+ TestData testData,
+ DataComputer<T> dataComputer,
+ List<TestConfig> testedConfigs,
{required bool testAfterFailures,
bool forUserLibrariesOnly = true,
Iterable<Id> globalIds = const <Id>[],
@@ -88,7 +69,7 @@
continue;
}
results[config.marker] = await runTestForConfig(
- testData, dataComputer, config,
+ markerOptions, testData, dataComputer, config,
fatalErrors: !testAfterFailures, onFailure: onFailure);
}
return results;
@@ -97,14 +78,14 @@
/// Creates a test runner for [dataComputer] on [testedConfigs].
RunTestFunction<T> runTestFor<T>(
DataComputer<T> dataComputer, List<TestConfig> testedConfigs) {
- return (TestData testData,
+ return (MarkerOptions markerOptions, TestData testData,
{required bool testAfterFailures,
bool? verbose,
bool? succinct,
bool? printCode,
Map<String, List<String>>? skipMap,
Uri? nullUri}) {
- return runTest(testData, dataComputer, testedConfigs,
+ return runTest(markerOptions, testData, dataComputer, testedConfigs,
testAfterFailures: testAfterFailures,
onFailure: onFailure,
skipMap: skipMap);
@@ -114,7 +95,7 @@
/// Runs [dataComputer] on [testData] for [config].
///
/// Returns `true` if an error was encountered.
-Future<TestResult<T>> runTestForConfig<T>(
+Future<TestResult<T>> runTestForConfig<T>(MarkerOptions markerOptions,
TestData testData, DataComputer<T> dataComputer, TestConfig config,
{bool fatalErrors = true,
required void Function(String message) onFailure,
@@ -213,7 +194,7 @@
});
var compiledData = AnalyzerCompiledData<T>(
testData.code, testData.entryPoint, actualMaps, globalData);
- return checkCode(config.name, testData.testFileUri, testData.code,
+ return checkCode(markerOptions, config.marker, config.name, testData,
memberAnnotations, compiledData, dataComputer.dataValidator,
fatalErrors: fatalErrors, onFailure: onFailure);
}
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index 0f88c4e..aea3172 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -911,14 +911,8 @@
FunctionEntity get checkDeferredIsLoaded =>
_findHelperFunction('checkDeferredIsLoaded');
- FunctionEntity get throwNoSuchMethod =>
- _findHelperFunction('throwNoSuchMethod');
-
FunctionEntity get createRuntimeType => _findRtiFunction('createRuntimeType');
- FunctionEntity get fallThroughError =>
- _findHelperFunction("getFallThroughError");
-
FunctionEntity get createInvocationMirror =>
_findHelperFunction('createInvocationMirror');
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
deleted file mode 100644
index 0156152..0000000
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012, 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 dart2js.common.resolution;
-
-import '../constants/values.dart' show ConstantValue;
-import '../elements/entities.dart';
-import '../native/behavior.dart' show NativeBehavior;
-import '../universe/world_impact.dart' show WorldImpact;
-import '../universe/feature.dart';
-
-class ResolutionImpact extends WorldImpact {
- const ResolutionImpact();
-
- Iterable<Feature> get features => const <Feature>[];
- Iterable<MapLiteralUse> get mapLiterals => const <MapLiteralUse>[];
- Iterable<SetLiteralUse> get setLiterals => const <SetLiteralUse>[];
- Iterable<ListLiteralUse> get listLiterals => const <ListLiteralUse>[];
- Iterable<String> get constSymbolNames => const <String>[];
- Iterable<ConstantValue> get constantLiterals => const <ConstantValue>[];
- Iterable<ClassEntity> get seenClasses => const <ClassEntity>[];
- Iterable<RuntimeTypeUse> get runtimeTypeUses => const <RuntimeTypeUse>[];
- Iterable<NativeBehavior> get nativeData => const <NativeBehavior>[];
-
- Iterable<GenericInstantiation> get genericInstantiations =>
- const <GenericInstantiation>[];
-}
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 77d8144..0101783 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -121,7 +121,7 @@
AbstractValue _resultOfParameter(Local e) =>
_globalInferenceResults.resultOfParameter(e);
- FieldInfo visitField(FieldEntity field, {ClassEntity containingClass}) {
+ FieldInfo visitField(FieldEntity field) {
AbstractValue inferredType = _resultOfMember(field).type;
// If a field has an empty inferred type it is never used.
if (inferredType == null ||
@@ -201,7 +201,7 @@
}
}
} else if (member.isField) {
- FieldInfo fieldInfo = visitField(member, containingClass: clazz);
+ FieldInfo fieldInfo = visitField(member);
if (fieldInfo != null) {
classInfo.fields.add(fieldInfo);
fieldInfo.parent = classInfo;
@@ -436,7 +436,7 @@
_constantToInfo[constant] = info;
result.constants.add(info);
});
- environment.libraries.forEach(visitLibrary);
+ component.libraries.forEach(visitLibrary);
}
/// Whether to emit information about [entity].
@@ -449,24 +449,32 @@
dumpInfoTask.inlineCount.containsKey(entity);
}
- LibraryInfo visitLibrary(LibraryEntity lib) {
- String libname = environment.getLibraryName(lib);
- if (libname.isEmpty) {
+ LibraryInfo visitLibrary(ir.Library lib) {
+ final libEntity = environment.lookupLibrary(lib.importUri);
+ if (libEntity == null) return null;
+
+ String libname = lib.name;
+ if (libname == null || libname.isEmpty) {
libname = '<unnamed>';
}
- int size = dumpInfoTask.sizeOf(lib);
- LibraryInfo info = LibraryInfo(libname, lib.canonicalUri, null, size);
- _entityToInfo[lib] = info;
- environment.forEachLibraryMember(lib, (MemberEntity member) {
- if (member.isFunction || member.isGetter || member.isSetter) {
- FunctionInfo functionInfo = visitFunction(member);
+ int size = dumpInfoTask.sizeOf(libEntity);
+ LibraryInfo info = LibraryInfo(libname, lib.importUri, null, size);
+ _entityToInfo[libEntity] = info;
+
+ lib.members.forEach((ir.Member member) {
+ final memberEntity =
+ environment.lookupLibraryMember(libEntity, member.name.text);
+ if (memberEntity == null) return;
+
+ if (member.function != null) {
+ FunctionInfo functionInfo = visitFunction(memberEntity);
if (functionInfo != null) {
info.topLevelFunctions.add(functionInfo);
functionInfo.parent = info;
}
- } else if (member.isField) {
- FieldInfo fieldInfo = visitField(member);
+ } else {
+ FieldInfo fieldInfo = visitField(member, fieldEntity: memberEntity);
if (fieldInfo != null) {
info.topLevelVariables.add(fieldInfo);
fieldInfo.parent = info;
@@ -474,21 +482,24 @@
}
});
- environment.forEachClass(lib, (ClassEntity clazz) {
- ClassTypeInfo classTypeInfo = visitClassType(clazz);
+ lib.classes.forEach((ir.Class clazz) {
+ final classEntity = environment.lookupClass(libEntity, clazz.name);
+ if (classEntity == null) return;
+
+ ClassTypeInfo classTypeInfo = visitClassType(classEntity);
if (classTypeInfo != null) {
info.classTypes.add(classTypeInfo);
classTypeInfo.parent = info;
}
- ClassInfo classInfo = visitClass(clazz);
+ ClassInfo classInfo = visitClass(clazz, classEntity: classEntity);
if (classInfo != null) {
info.classes.add(classInfo);
classInfo.parent = info;
}
});
- if (info.isEmpty && !shouldKeep(lib)) return null;
+ if (info.isEmpty && !shouldKeep(libEntity)) return null;
result.libraries.add(info);
return info;
}
@@ -499,8 +510,8 @@
AbstractValue _resultOfParameter(Local e) =>
_globalInferenceResults.resultOfParameter(e);
- FieldInfo visitField(FieldEntity field, {ClassEntity containingClass}) {
- AbstractValue inferredType = _resultOfMember(field).type;
+ FieldInfo visitField(ir.Field field, {FieldEntity fieldEntity}) {
+ AbstractValue inferredType = _resultOfMember(fieldEntity).type;
// If a field has an empty inferred type it is never used.
if (inferredType == null ||
closedWorld.abstractValueDomain
@@ -509,21 +520,22 @@
return null;
}
- int size = dumpInfoTask.sizeOf(field);
- List<CodeSpan> code = dumpInfoTask.codeOf(field);
+ int size = dumpInfoTask.sizeOf(fieldEntity);
+ List<CodeSpan> code = dumpInfoTask.codeOf(fieldEntity);
// TODO(het): Why doesn't `size` account for the code size already?
if (code != null) size += code.length;
FieldInfo info = FieldInfo(
- name: field.name,
- type: '${environment.getFieldType(field)}',
+ name: field.name.text,
+ type: field.type.toStringInternal(),
inferredType: '$inferredType',
code: code,
- outputUnit: _unitInfoForMember(field),
+ outputUnit: _unitInfoForMember(fieldEntity),
isConst: field.isConst);
- _entityToInfo[field] = info;
- FieldAnalysisData fieldData = closedWorld.fieldAnalysis.getFieldData(field);
+ _entityToInfo[fieldEntity] = info;
+ FieldAnalysisData fieldData =
+ closedWorld.fieldAnalysis.getFieldData(fieldEntity);
if (fieldData.initialValue != null) {
info.initializer = _constantToInfo[fieldData.initialValue];
}
@@ -534,7 +546,7 @@
info.coverageId = '${field.hashCode}';
}
- int closureSize = _addClosureInfo(info, field);
+ int closureSize = _addClosureInfo(info, fieldEntity);
info.size = size + closureSize;
result.fields.add(info);
@@ -559,18 +571,28 @@
return classTypeInfo;
}
- ClassInfo visitClass(ClassEntity clazz) {
+ ClassInfo visitClass(ir.Class clazz, {ClassEntity classEntity}) {
// Omit class if it is not needed.
ClassInfo classInfo = ClassInfo(
name: clazz.name,
isAbstract: clazz.isAbstract,
- outputUnit: _unitInfoForClass(clazz));
- _entityToInfo[clazz] = classInfo;
+ outputUnit: _unitInfoForClass(classEntity));
+ _entityToInfo[classEntity] = classInfo;
- int size = dumpInfoTask.sizeOf(clazz);
- environment.forEachLocalClassMember(clazz, (member) {
- if (member.isFunction || member.isGetter || member.isSetter) {
- FunctionInfo functionInfo = visitFunction(member);
+ int size = dumpInfoTask.sizeOf(classEntity);
+ clazz.members.forEach((ir.Member member) {
+ MemberEntity memberEntity =
+ environment.lookupClassMember(classEntity, member.name.text);
+ if (memberEntity == null) return;
+ // Note: JWorld representations of a kernel member may omit the field or
+ // getter. Filter those cases here.
+ if ((member is ir.Field && memberEntity is! FieldEntity) ||
+ (member is ir.Procedure && memberEntity is! FunctionEntity)) {
+ return;
+ }
+
+ if (member.function != null) {
+ FunctionInfo functionInfo = visitFunction(memberEntity);
if (functionInfo != null) {
classInfo.functions.add(functionInfo);
functionInfo.parent = classInfo;
@@ -578,8 +600,8 @@
size += closureInfo.size;
}
}
- } else if (member.isField) {
- FieldInfo fieldInfo = visitField(member, containingClass: clazz);
+ } else {
+ FieldInfo fieldInfo = visitField(member, fieldEntity: memberEntity);
if (fieldInfo != null) {
classInfo.fields.add(fieldInfo);
fieldInfo.parent = classInfo;
@@ -587,12 +609,14 @@
size += closureInfo.size;
}
}
- } else {
- throw StateError('Class member not a function or field');
}
});
- environment.forEachConstructor(clazz, (constructor) {
- FunctionInfo functionInfo = visitFunction(constructor);
+
+ clazz.constructors.forEach((ir.Constructor constructor) {
+ final constructorEntity =
+ environment.lookupConstructor(classEntity, constructor.name.text);
+ if (constructorEntity == null) return;
+ FunctionInfo functionInfo = visitFunction(constructorEntity);
if (functionInfo != null) {
classInfo.functions.add(functionInfo);
functionInfo.parent = classInfo;
@@ -604,7 +628,8 @@
classInfo.size = size;
- if (!compiler.backendStrategy.emitterTask.neededClasses.contains(clazz) &&
+ if (!compiler.backendStrategy.emitterTask.neededClasses
+ .contains(classEntity) &&
classInfo.fields.isEmpty &&
classInfo.functions.isEmpty) {
return null;
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 56d4682..2211c3c 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -166,13 +166,6 @@
]);
}
- BackendImpact _fallThroughError;
-
- BackendImpact get fallThroughError {
- return _fallThroughError ??=
- BackendImpact(staticUses: [_commonElements.fallThroughError]);
- }
-
BackendImpact _asCheck;
BackendImpact get asCheck {
@@ -181,19 +174,6 @@
]);
}
- BackendImpact _throwNoSuchMethod;
-
- BackendImpact get throwNoSuchMethod {
- return _throwNoSuchMethod ??= BackendImpact(staticUses: [
- _commonElements.throwNoSuchMethod,
- ], otherImpacts: [
- // Also register the types of the arguments passed to this method.
- _needsList('Needed to encode the arguments for throw NoSuchMethodError.'),
- _needsString('Needed to encode the name for throw NoSuchMethodError.'),
- mapLiteralClass, // noSuchMethod helpers are passed a Map.
- ]);
- }
-
BackendImpact _stringValues;
BackendImpact get stringValues {
@@ -244,15 +224,6 @@
]);
}
- BackendImpact _throwRuntimeError;
-
- BackendImpact get throwRuntimeError {
- return _throwRuntimeError ??= BackendImpact(otherImpacts: [
- // Also register the types of the arguments passed to this method.
- stringValues
- ]);
- }
-
BackendImpact _throwUnsupportedError;
BackendImpact get throwUnsupportedError {
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index e340b31..8e0ff82 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -4,12 +4,8 @@
library js_backend.backend.impact_transformer;
-import '../universe/class_hierarchy.dart' show ClassHierarchyBuilder;
-
-import '../common.dart';
import '../common/elements.dart';
import '../common/codegen.dart' show CodegenImpact;
-import '../common/resolution.dart' show ResolutionImpact;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
@@ -23,335 +19,14 @@
import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact;
import '../util/util.dart';
import '../world.dart';
-import 'annotations.dart';
import 'backend_impact.dart';
import 'backend_usage.dart';
-import 'custom_elements_analysis.dart';
import 'interceptor_data.dart';
import 'namer.dart';
import 'native_data.dart';
import 'runtime_types.dart';
import 'runtime_types_resolution.dart';
-/// JavaScript specific transformation for resolution world impacts.
-///
-/// This processes target-agnostic [ResolutionImpact]s and creates [WorldImpact]
-/// in which JavaScript specific impact data is added, for example: if
-/// a certain feature is used that requires some helper code from the backend
-/// libraries, this will be included by the impact transformer.
-class JavaScriptImpactTransformer {
- final ElementEnvironment _elementEnvironment;
- final CommonElements _commonElements;
- final BackendImpacts _impacts;
- final NativeBasicData _nativeBasicData;
- final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
- final BackendUsageBuilder _backendUsageBuilder;
- final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
- final RuntimeTypesNeedBuilder _rtiNeedBuilder;
- final ClassHierarchyBuilder _classHierarchyBuilder;
- final AnnotationsData _annotationsData;
-
- JavaScriptImpactTransformer(
- this._elementEnvironment,
- this._commonElements,
- this._impacts,
- this._nativeBasicData,
- this._nativeResolutionEnqueuer,
- this._backendUsageBuilder,
- this._customElementsResolutionAnalysis,
- this._rtiNeedBuilder,
- this._classHierarchyBuilder,
- this._annotationsData);
-
- DartTypes get _dartTypes => _commonElements.dartTypes;
-
- /// Transform the [ResolutionImpact] into a [WorldImpact] adding the
- /// backend dependencies for features used in [worldImpact].
- WorldImpact transformResolutionImpact(ResolutionImpact worldImpact) {
- TransformedWorldImpact transformed = TransformedWorldImpact(worldImpact);
-
- void registerImpact(BackendImpact impact) {
- impact.registerImpact(transformed, _elementEnvironment);
- _backendUsageBuilder.processBackendImpact(impact);
- }
-
- for (Feature feature in worldImpact.features) {
- switch (feature) {
- case Feature.ASSERT:
- registerImpact(_impacts.assertWithoutMessage);
- break;
- case Feature.ASSERT_WITH_MESSAGE:
- registerImpact(_impacts.assertWithMessage);
- break;
- case Feature.ASYNC:
- registerImpact(_impacts.asyncBody);
- break;
- case Feature.ASYNC_FOR_IN:
- registerImpact(_impacts.asyncForIn);
- break;
- case Feature.ASYNC_STAR:
- registerImpact(_impacts.asyncStarBody);
- break;
- case Feature.CATCH_STATEMENT:
- registerImpact(_impacts.catchStatement);
- break;
- case Feature.FALL_THROUGH_ERROR:
- registerImpact(_impacts.fallThroughError);
- break;
- case Feature.FIELD_WITHOUT_INITIALIZER:
- case Feature.LOCAL_WITHOUT_INITIALIZER:
- transformed
- .registerTypeUse(TypeUse.instantiation(_commonElements.nullType));
- registerImpact(_impacts.nullLiteral);
- break;
- case Feature.LAZY_FIELD:
- registerImpact(_impacts.lazyField);
- break;
- case Feature.STACK_TRACE_IN_CATCH:
- registerImpact(_impacts.stackTraceInCatch);
- break;
- case Feature.STRING_INTERPOLATION:
- registerImpact(_impacts.stringInterpolation);
- break;
- case Feature.STRING_JUXTAPOSITION:
- registerImpact(_impacts.stringJuxtaposition);
- break;
- case Feature.SUPER_NO_SUCH_METHOD:
- registerImpact(_impacts.superNoSuchMethod);
- break;
- case Feature.SYNC_FOR_IN:
- registerImpact(_impacts.syncForIn);
- break;
- case Feature.SYNC_STAR:
- registerImpact(_impacts.syncStarBody);
- break;
- case Feature.THROW_EXPRESSION:
- registerImpact(_impacts.throwExpression);
- break;
- case Feature.THROW_NO_SUCH_METHOD:
- registerImpact(_impacts.throwNoSuchMethod);
- break;
- case Feature.THROW_RUNTIME_ERROR:
- registerImpact(_impacts.throwRuntimeError);
- break;
- case Feature.THROW_UNSUPPORTED_ERROR:
- registerImpact(_impacts.throwUnsupportedError);
- break;
- case Feature.TYPE_VARIABLE_BOUNDS_CHECK:
- registerImpact(_impacts.typeVariableBoundCheck);
- break;
- case Feature.LOAD_LIBRARY:
- registerImpact(_impacts.loadLibrary);
- break;
- }
- }
-
- bool hasAsCast = false;
- bool hasTypeLiteral = false;
- for (TypeUse typeUse in worldImpact.typeUses) {
- DartType type = typeUse.type;
- switch (typeUse.kind) {
- case TypeUseKind.INSTANTIATION:
- case TypeUseKind.CONST_INSTANTIATION:
- case TypeUseKind.NATIVE_INSTANTIATION:
- break;
- case TypeUseKind.IS_CHECK:
- case TypeUseKind.CATCH_TYPE:
- onIsCheck(type, transformed);
- break;
- case TypeUseKind.AS_CAST:
- if (_annotationsData
- .getExplicitCastCheckPolicy(worldImpact.member)
- .isEmitted) {
- onIsCheck(type, transformed);
- hasAsCast = true;
- }
- break;
- case TypeUseKind.IMPLICIT_CAST:
- if (_annotationsData
- .getImplicitDowncastCheckPolicy(worldImpact.member)
- .isEmitted) {
- onIsCheck(type, transformed);
- }
- break;
- case TypeUseKind.PARAMETER_CHECK:
- case TypeUseKind.TYPE_VARIABLE_BOUND_CHECK:
- if (_annotationsData
- .getParameterCheckPolicy(worldImpact.member)
- .isEmitted) {
- onIsCheck(type, transformed);
- }
- break;
- case TypeUseKind.TYPE_LITERAL:
- _customElementsResolutionAnalysis.registerTypeLiteral(type);
- type.forEachTypeVariable((TypeVariableType variable) {
- TypeVariableType typeWithoutNullability =
- variable.withoutNullability;
- Entity typeDeclaration =
- typeWithoutNullability.element.typeDeclaration;
- if (typeDeclaration is ClassEntity) {
- _rtiNeedBuilder
- .registerClassUsingTypeVariableLiteral(typeDeclaration);
- } else if (typeDeclaration is FunctionEntity) {
- _rtiNeedBuilder
- .registerMethodUsingTypeVariableLiteral(typeDeclaration);
- } else if (typeDeclaration is Local) {
- _rtiNeedBuilder.registerLocalFunctionUsingTypeVariableLiteral(
- typeDeclaration);
- }
- registerImpact(_impacts.typeVariableExpression);
- });
- hasTypeLiteral = true;
- break;
- case TypeUseKind.RTI_VALUE:
- case TypeUseKind.TYPE_ARGUMENT:
- case TypeUseKind.NAMED_TYPE_VARIABLE_NEW_RTI:
- case TypeUseKind.CONSTRUCTOR_REFERENCE:
- failedAt(CURRENT_ELEMENT_SPANNABLE, "Unexpected type use: $typeUse.");
- break;
- }
- }
-
- if (hasAsCast) {
- registerImpact(_impacts.asCheck);
- }
-
- if (hasTypeLiteral) {
- transformed
- .registerTypeUse(TypeUse.instantiation(_commonElements.typeType));
- registerImpact(_impacts.typeLiteral);
- }
-
- for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) {
- // TODO(johnniwinther): Use the [isEmpty] property when factory
- // constructors are registered directly.
- if (mapLiteralUse.isConstant) {
- registerImpact(_impacts.constantMapLiteral);
- } else {
- transformed.registerTypeUse(TypeUse.instantiation(mapLiteralUse.type));
- }
- }
-
- for (SetLiteralUse setLiteralUse in worldImpact.setLiterals) {
- if (setLiteralUse.isConstant) {
- registerImpact(_impacts.constantSetLiteral);
- } else {
- transformed.registerTypeUse(TypeUse.instantiation(setLiteralUse.type));
- }
- }
-
- for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) {
- // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when
- // factory constructors are registered directly.
- transformed.registerTypeUse(TypeUse.instantiation(listLiteralUse.type));
- }
-
- for (RuntimeTypeUse runtimeTypeUse in worldImpact.runtimeTypeUses) {
- // Enable runtime type support if we discover a getter called
- // runtimeType. We have to enable runtime type before hitting the
- // codegen, so that constructors know whether they need to generate code
- // for runtime type.
- _backendUsageBuilder.registerRuntimeTypeUse(runtimeTypeUse);
- }
-
- if (worldImpact.constSymbolNames.isNotEmpty) {
- registerImpact(_impacts.constSymbol);
- }
-
- for (StaticUse staticUse in worldImpact.staticUses) {
- switch (staticUse.kind) {
- case StaticUseKind.CLOSURE:
- registerImpact(_impacts.closure);
- Local closure = staticUse.element;
- FunctionType type = _elementEnvironment.getLocalFunctionType(closure);
- if (type.containsTypeVariables ||
- // TODO(johnniwinther): Can we avoid the need for signatures in
- // Dart 2?
- true) {
- registerImpact(_impacts.computeSignature);
- }
- break;
- default:
- }
- }
-
- for (ConstantValue constant in worldImpact.constantLiterals) {
- switch (constant.kind) {
- case ConstantValueKind.NULL:
- registerImpact(_impacts.nullLiteral);
- break;
- case ConstantValueKind.BOOL:
- registerImpact(_impacts.boolLiteral);
- break;
- case ConstantValueKind.INT:
- registerImpact(_impacts.intLiteral);
- break;
- case ConstantValueKind.DOUBLE:
- registerImpact(_impacts.doubleLiteral);
- break;
- case ConstantValueKind.STRING:
- registerImpact(_impacts.stringLiteral);
- break;
- default:
- assert(
- false,
- failedAt(NO_LOCATION_SPANNABLE,
- "Unexpected constant literal: ${constant.kind}."));
- }
- }
-
- for (NativeBehavior behavior in worldImpact.nativeData) {
- _nativeResolutionEnqueuer.registerNativeBehavior(
- transformed, behavior, worldImpact);
- }
-
- for (ClassEntity classEntity in worldImpact.seenClasses) {
- _classHierarchyBuilder.registerClass(classEntity);
- }
-
- if (worldImpact.genericInstantiations.isNotEmpty) {
- for (GenericInstantiation instantiation
- in worldImpact.genericInstantiations) {
- registerImpact(_impacts
- .getGenericInstantiation(instantiation.typeArguments.length));
- _rtiNeedBuilder.registerGenericInstantiation(instantiation);
- }
- }
-
- return transformed;
- }
-
- // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType].
- void onIsCheck(DartType type, TransformedWorldImpact transformed) {
- void registerImpact(BackendImpact impact) {
- impact.registerImpact(transformed, _elementEnvironment);
- _backendUsageBuilder.processBackendImpact(impact);
- }
-
- registerImpact(_impacts.typeCheck);
-
- var typeWithoutNullability = type.withoutNullability;
- if (!_dartTypes.treatAsRawType(typeWithoutNullability) ||
- typeWithoutNullability.containsTypeVariables ||
- typeWithoutNullability is FunctionType) {
- registerImpact(_impacts.genericTypeCheck);
- if (typeWithoutNullability is TypeVariableType) {
- registerImpact(_impacts.typeVariableTypeCheck);
- }
- }
- if (typeWithoutNullability is FunctionType) {
- registerImpact(_impacts.functionTypeCheck);
- }
- if (typeWithoutNullability is InterfaceType &&
- _nativeBasicData.isNativeClass(typeWithoutNullability.element)) {
- registerImpact(_impacts.nativeTypeCheck);
- }
- if (typeWithoutNullability is FutureOrType) {
- registerImpact(_impacts.futureOrTypeCheck);
- }
- }
-}
-
class CodegenImpactTransformer {
final JClosedWorld _closedWorld;
final ElementEnvironment _elementEnvironment;
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index c53fa5f..391a9fbcc 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -886,6 +886,9 @@
/// Registers that a generic [instantiation] is used.
void registerGenericInstantiation(GenericInstantiation instantiation);
+ /// Registers a [TypeVariableType] literal on this [RuntimeTypesNeedBuilder].
+ void registerTypeVariableLiteral(TypeVariableType variable);
+
/// Computes the [RuntimeTypesNeed] for the data registered with this builder.
RuntimeTypesNeed computeRuntimeTypesNeed(
KClosedWorld closedWorld, CompilerOptions options);
@@ -907,6 +910,9 @@
void registerGenericInstantiation(GenericInstantiation instantiation) {}
@override
+ void registerTypeVariableLiteral(TypeVariableType variable) {}
+
+ @override
RuntimeTypesNeed computeRuntimeTypesNeed(
KClosedWorld closedWorld, CompilerOptions options) {
return TrivialRuntimeTypesNeed(closedWorld.elementEnvironment);
@@ -957,6 +963,18 @@
}
@override
+ void registerTypeVariableLiteral(TypeVariableType variable) {
+ Entity typeDeclaration = variable.element.typeDeclaration;
+ if (typeDeclaration is ClassEntity) {
+ registerClassUsingTypeVariableLiteral(typeDeclaration);
+ } else if (typeDeclaration is FunctionEntity) {
+ registerMethodUsingTypeVariableLiteral(typeDeclaration);
+ } else if (typeDeclaration is Local) {
+ registerLocalFunctionUsingTypeVariableLiteral(typeDeclaration);
+ }
+ }
+
+ @override
RuntimeTypesNeed computeRuntimeTypesNeed(
KClosedWorld closedWorld, CompilerOptions options) {
TypeVariableTests typeVariableTests = TypeVariableTests(
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 4bfe3529..6dc3606 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -15,7 +15,6 @@
import '../common.dart';
import '../common/elements.dart';
import '../common/names.dart';
-import '../common/resolution.dart';
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/indexed.dart';
@@ -33,15 +32,22 @@
import '../ir/visitors.dart';
import '../ir/util.dart';
import '../js/js.dart' as js;
+import '../js_backend/annotations.dart';
+import '../js_backend/backend_impact.dart';
+import '../js_backend/backend_usage.dart';
+import '../js_backend/custom_elements_analysis.dart';
import '../js_backend/namer.dart';
import '../js_backend/native_data.dart';
+import '../js_backend/runtime_types_resolution.dart';
import '../js_model/locals.dart';
import '../kernel/dart2js_target.dart';
import '../native/behavior.dart';
+import '../native/enqueue.dart';
import '../options.dart';
import '../ordered_typeset.dart';
import '../universe/call_structure.dart';
import '../universe/selector.dart';
+import '../universe/world_impact.dart';
import 'element_map.dart';
import 'env.dart';
@@ -103,6 +109,7 @@
BehaviorBuilder _nativeBehaviorBuilder;
Map<KMember, Map<ir.Expression, TypeMap>> typeMapsForTesting;
+ Map<ir.Member, ImpactData> impactDataForTesting;
KernelToElementMap(this.reporter, this._environment, this.options) {
_elementEnvironment = KernelElementEnvironment(this);
@@ -1443,8 +1450,15 @@
_nativeBehaviorBuilder ??= BehaviorBuilder(elementEnvironment,
commonElements, nativeBasicData, reporter, options);
- ResolutionImpact computeWorldImpact(
- KMember member, ImpactBuilderData impactBuilderData) {
+ WorldImpact computeWorldImpact(
+ KMember member,
+ BackendImpacts impacts,
+ NativeResolutionEnqueuer nativeResolutionEnqueuer,
+ BackendUsageBuilder backendUsageBuilder,
+ CustomElementsResolutionAnalysis customElementsResolutionAnalysis,
+ RuntimeTypesNeedBuilder rtiNeedBuilder,
+ AnnotationsData annotationsData,
+ ImpactBuilderData impactBuilderData) {
KMemberData memberData = members.getData(member);
ir.Member node = memberData.node;
@@ -1454,6 +1468,10 @@
}
ImpactData impactData = impactBuilderData.impactData;
memberData.staticTypes = impactBuilderData.cachedStaticTypes;
+ if (retainDataForTesting) {
+ impactDataForTesting ??= {};
+ impactDataForTesting[node] = impactData;
+ }
KernelImpactConverter converter = KernelImpactConverter(
this,
member,
@@ -1462,7 +1480,13 @@
_constantValuefier,
// TODO(johnniwinther): Pull the static type context from the cached
// static types.
- ir.StaticTypeContext(node, typeEnvironment));
+ ir.StaticTypeContext(node, typeEnvironment),
+ impacts,
+ nativeResolutionEnqueuer,
+ backendUsageBuilder,
+ customElementsResolutionAnalysis,
+ rtiNeedBuilder,
+ annotationsData);
return converter.convert(impactData);
}
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 7b863ab..11fa918 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -7,7 +7,6 @@
import '../common.dart';
import '../common/names.dart';
-import '../common/resolution.dart';
import '../common/elements.dart';
import '../constants/values.dart';
import '../elements/entities.dart';
@@ -19,32 +18,54 @@
import '../ir/static_type.dart';
import '../ir/util.dart';
import '../ir/visitors.dart';
+import '../js_backend/annotations.dart';
+import '../js_backend/backend_impact.dart';
+import '../js_backend/backend_usage.dart';
+import '../js_backend/custom_elements_analysis.dart';
import '../js_backend/native_data.dart';
+import '../js_backend/runtime_types_resolution.dart';
import '../native/behavior.dart';
+import '../native/enqueue.dart';
import '../options.dart';
-import '../resolution/registry.dart' show ResolutionWorldImpactBuilder;
import '../universe/call_structure.dart';
import '../universe/feature.dart';
import '../universe/selector.dart';
import '../universe/use.dart';
import '../universe/world_builder.dart';
+import '../universe/world_impact.dart';
import 'element_map.dart';
/// [ImpactRegistry] that converts kernel based impact data to world impact
/// object based on the K model.
class KernelImpactConverter implements ImpactRegistry {
- final ResolutionWorldImpactBuilder impactBuilder;
+ final WorldImpactBuilder impactBuilder;
final KernelToElementMap elementMap;
final DiagnosticReporter reporter;
final CompilerOptions _options;
final MemberEntity currentMember;
final ConstantValuefier _constantValuefier;
final ir.StaticTypeContext staticTypeContext;
+ final BackendImpacts _impacts;
+ final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
+ final BackendUsageBuilder _backendUsageBuilder;
+ final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
+ final RuntimeTypesNeedBuilder _rtiNeedBuilder;
+ final AnnotationsData _annotationsData;
- KernelImpactConverter(this.elementMap, this.currentMember, this.reporter,
- this._options, this._constantValuefier, this.staticTypeContext)
- : this.impactBuilder = ResolutionWorldImpactBuilder(
- elementMap.commonElements.dartTypes, currentMember);
+ KernelImpactConverter(
+ this.elementMap,
+ this.currentMember,
+ this.reporter,
+ this._options,
+ this._constantValuefier,
+ this.staticTypeContext,
+ this._impacts,
+ this._nativeResolutionEnqueuer,
+ this._backendUsageBuilder,
+ this._customElementsResolutionAnalysis,
+ this._rtiNeedBuilder,
+ this._annotationsData)
+ : this.impactBuilder = WorldImpactBuilderImpl(currentMember);
ir.TypeEnvironment get typeEnvironment => elementMap.typeEnvironment;
@@ -52,6 +73,8 @@
NativeBasicData get _nativeBasicData => elementMap.nativeBasicData;
+ ElementEnvironment get elementEnvironment => elementMap.elementEnvironment;
+
DartTypes get dartTypes => commonElements.dartTypes;
String typeToString(DartType type) =>
@@ -72,11 +95,48 @@
return null;
}
+ void registerBackendImpact(BackendImpact impact) {
+ impact.registerImpact(impactBuilder, elementEnvironment);
+ _backendUsageBuilder.processBackendImpact(impact);
+ }
+
+ void registerNativeImpact(NativeBehavior behavior) {
+ _nativeResolutionEnqueuer.registerNativeBehavior(
+ impactBuilder, behavior, impactBuilder);
+ }
+
+ // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType].
+ void onIsCheck(DartType type) {
+ registerBackendImpact(_impacts.typeCheck);
+ var typeWithoutNullability = type.withoutNullability;
+ if (!dartTypes.treatAsRawType(typeWithoutNullability) ||
+ typeWithoutNullability.containsTypeVariables ||
+ typeWithoutNullability is FunctionType) {
+ registerBackendImpact(_impacts.genericTypeCheck);
+ if (typeWithoutNullability is TypeVariableType) {
+ registerBackendImpact(_impacts.typeVariableTypeCheck);
+ }
+ }
+ if (typeWithoutNullability is FunctionType) {
+ registerBackendImpact(_impacts.functionTypeCheck);
+ }
+ if (typeWithoutNullability is InterfaceType &&
+ _nativeBasicData.isNativeClass(typeWithoutNullability.element)) {
+ registerBackendImpact(_impacts.nativeTypeCheck);
+ }
+ if (typeWithoutNullability is FutureOrType) {
+ registerBackendImpact(_impacts.futureOrTypeCheck);
+ }
+ }
+
@override
void registerParameterCheck(ir.DartType irType) {
DartType type = elementMap.getDartType(irType);
if (type is! DynamicType) {
impactBuilder.registerTypeUse(TypeUse.parameterCheck(type));
+ if (_annotationsData.getParameterCheckPolicy(currentMember).isEmitted) {
+ onIsCheck(type);
+ }
}
}
@@ -87,7 +147,7 @@
@override
void registerLazyField() {
- impactBuilder.registerFeature(Feature.LAZY_FIELD);
+ registerBackendImpact(_impacts.lazyField);
}
@override
@@ -105,11 +165,10 @@
getCreatesAnnotations(dartTypes, reporter, commonElements, metadata);
Iterable<String> returnsAnnotations =
getReturnsAnnotations(dartTypes, reporter, commonElements, metadata);
- impactBuilder.registerNativeData(elementMap.getNativeBehaviorForFieldLoad(
+ registerNativeImpact(elementMap.getNativeBehaviorForFieldLoad(
field, createsAnnotations, returnsAnnotations,
isJsInterop: isJsInterop));
- impactBuilder
- .registerNativeData(elementMap.getNativeBehaviorForFieldStore(field));
+ registerNativeImpact(elementMap.getNativeBehaviorForFieldStore(field));
}
}
@@ -126,7 +185,7 @@
getCreatesAnnotations(dartTypes, reporter, commonElements, metadata);
Iterable<String> returnsAnnotations =
getReturnsAnnotations(dartTypes, reporter, commonElements, metadata);
- impactBuilder.registerNativeData(elementMap.getNativeBehaviorForMethod(
+ registerNativeImpact(elementMap.getNativeBehaviorForMethod(
constructor, createsAnnotations, returnsAnnotations,
isJsInterop: isJsInterop));
}
@@ -134,7 +193,7 @@
@override
void registerSyncStar(ir.DartType elementType) {
- impactBuilder.registerFeature(Feature.SYNC_STAR);
+ registerBackendImpact(_impacts.syncStarBody);
impactBuilder.registerStaticUse(StaticUse.staticInvoke(
commonElements.syncStarIterableFactory,
CallStructure.unnamed(1, 1),
@@ -143,7 +202,7 @@
@override
void registerAsync(ir.DartType elementType) {
- impactBuilder.registerFeature(Feature.ASYNC);
+ registerBackendImpact(_impacts.asyncBody);
impactBuilder.registerStaticUse(StaticUse.staticInvoke(
commonElements.asyncAwaitCompleterFactory,
CallStructure.unnamed(0, 1),
@@ -152,7 +211,7 @@
@override
void registerAsyncStar(ir.DartType elementType) {
- impactBuilder.registerFeature(Feature.ASYNC_STAR);
+ registerBackendImpact(_impacts.asyncStarBody);
impactBuilder.registerStaticUse(StaticUse.staticInvoke(
commonElements.asyncStarStreamControllerFactory,
CallStructure.unnamed(1, 1),
@@ -172,7 +231,7 @@
getCreatesAnnotations(dartTypes, reporter, commonElements, metadata);
Iterable<String> returnsAnnotations =
getReturnsAnnotations(dartTypes, reporter, commonElements, metadata);
- impactBuilder.registerNativeData(elementMap.getNativeBehaviorForMethod(
+ registerNativeImpact(elementMap.getNativeBehaviorForMethod(
procedure, createsAnnotations, returnsAnnotations,
isJsInterop: isJsInterop));
}
@@ -180,61 +239,68 @@
@override
void registerIntLiteral(int value) {
- impactBuilder.registerConstantLiteral(
- IntConstantValue(BigInt.from(value).toUnsigned(64)));
+ registerBackendImpact(_impacts.intLiteral);
}
@override
void registerDoubleLiteral(double value) {
- impactBuilder.registerConstantLiteral(DoubleConstantValue(value));
+ registerBackendImpact(_impacts.doubleLiteral);
}
@override
void registerBoolLiteral(bool value) {
- impactBuilder.registerConstantLiteral(BoolConstantValue(value));
+ registerBackendImpact(_impacts.boolLiteral);
}
@override
void registerStringLiteral(String value) {
- impactBuilder.registerConstantLiteral(StringConstantValue(value));
+ registerBackendImpact(_impacts.stringLiteral);
}
@override
void registerSymbolLiteral(String value) {
- impactBuilder.registerConstSymbolName(value);
+ registerBackendImpact(_impacts.constSymbol);
}
@override
void registerNullLiteral() {
- impactBuilder.registerConstantLiteral(NullConstantValue());
+ registerBackendImpact(_impacts.nullLiteral);
}
@override
void registerListLiteral(ir.DartType elementType,
{bool isConst, bool isEmpty}) {
- impactBuilder.registerListLiteral(ListLiteralUse(
- commonElements.listType(elementMap.getDartType(elementType)),
- isConstant: isConst,
- isEmpty: isEmpty));
+ // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when
+ // factory constructors are registered directly.
+ impactBuilder.registerTypeUse(TypeUse.instantiation(
+ commonElements.listType(elementMap.getDartType(elementType))));
}
@override
void registerSetLiteral(ir.DartType elementType,
{bool isConst, bool isEmpty}) {
- impactBuilder.registerSetLiteral(SetLiteralUse(
- commonElements.setType(elementMap.getDartType(elementType)),
- isConstant: isConst,
- isEmpty: isEmpty));
+ // TODO(johnniwinther): Use the [isEmpty] property when factory
+ // constructors are registered directly.
+ if (isConst) {
+ registerBackendImpact(_impacts.constantSetLiteral);
+ } else {
+ impactBuilder.registerTypeUse(TypeUse.instantiation(
+ commonElements.setType(elementMap.getDartType(elementType))));
+ }
}
@override
void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
{bool isConst, bool isEmpty}) {
- impactBuilder.registerMapLiteral(MapLiteralUse(
- commonElements.mapType(
- elementMap.getDartType(keyType), elementMap.getDartType(valueType)),
- isConstant: isConst,
- isEmpty: isEmpty));
+ // TODO(johnniwinther): Use the [isEmpty] property when factory
+ // constructors are registered directly.
+ if (isConst) {
+ registerBackendImpact(_impacts.constantMapLiteral);
+ } else {
+ impactBuilder.registerTypeUse(TypeUse.instantiation(
+ commonElements.mapType(elementMap.getDartType(keyType),
+ elementMap.getDartType(valueType))));
+ }
}
@override
@@ -258,13 +324,13 @@
: StaticUse.typedConstructorInvoke(constructor, callStructure,
elementMap.getDartType(type).withoutNullability, deferredImport));
if (type.typeArguments.any((ir.DartType type) => type is! ir.DynamicType)) {
- impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK);
+ registerBackendImpact(_impacts.typeVariableBoundCheck);
}
if (target.isExternal &&
constructor.isFromEnvironmentConstructor &&
!isConst) {
- impactBuilder.registerFeature(Feature.THROW_UNSUPPORTED_ERROR);
+ registerBackendImpact(_impacts.throwUnsupportedError);
// We need to register the external constructor as live below, so don't
// return here.
}
@@ -294,8 +360,7 @@
{'type': typeToString(value.getType(elementMap.commonElements))});
return;
}
- StringConstantValue stringValue = value;
- impactBuilder.registerConstSymbolName(stringValue.stringValue);
+ registerBackendImpact(_impacts.constSymbol);
}
}
@@ -345,15 +410,14 @@
void registerStaticInvocationNode(ir.StaticInvocation node) {
switch (elementMap.getForeignKind(node)) {
case ForeignKind.JS:
- impactBuilder
- .registerNativeData(elementMap.getNativeBehaviorForJsCall(node));
+ registerNativeImpact(elementMap.getNativeBehaviorForJsCall(node));
break;
case ForeignKind.JS_BUILTIN:
- impactBuilder.registerNativeData(
+ registerNativeImpact(
elementMap.getNativeBehaviorForJsBuiltinCall(node));
break;
case ForeignKind.JS_EMBEDDED_GLOBAL:
- impactBuilder.registerNativeData(
+ registerNativeImpact(
elementMap.getNativeBehaviorForJsEmbeddedGlobalCall(node));
break;
case ForeignKind.JS_INTERCEPTOR_CONSTANT:
@@ -387,8 +451,7 @@
InterfaceType interfaceType = matchedType;
ClassEntity cls = interfaceType.element;
InterfaceType thisType = elementMap.elementEnvironment.getThisType(cls);
-
- impactBuilder.registerTypeUse(TypeUse.isCheck(thisType));
+ _registerIsCheckInternal(thisType);
Selector selector = Selector.callClosure(
0, const <String>[], thisType.typeArguments.length);
@@ -432,7 +495,7 @@
impactBuilder.registerStaticUse(StaticUse.superInvoke(
elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
CallStructure.ONE_ARG));
- impactBuilder.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
+ registerBackendImpact(_impacts.superNoSuchMethod);
}
}
@@ -451,7 +514,7 @@
impactBuilder.registerStaticUse(StaticUse.superInvoke(
elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
CallStructure.ONE_ARG));
- impactBuilder.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
+ registerBackendImpact(_impacts.superNoSuchMethod);
}
}
@@ -470,7 +533,7 @@
impactBuilder.registerStaticUse(StaticUse.superInvoke(
elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
CallStructure.ONE_ARG));
- impactBuilder.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
+ registerBackendImpact(_impacts.superNoSuchMethod);
}
}
@@ -604,62 +667,89 @@
break;
}
}
- impactBuilder.registerRuntimeTypeUse(
+
+ // Enable runtime type support if we discover a getter called
+ // runtimeType. We have to enable runtime type before hitting the
+ // codegen, so that constructors know whether they need to generate code
+ // for runtime type.
+ _backendUsageBuilder.registerRuntimeTypeUse(
RuntimeTypeUse(kind, receiverDartType, argumentDartType));
}
@override
void registerAssert({bool withMessage}) {
- impactBuilder.registerFeature(
- withMessage ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT);
+ registerBackendImpact(withMessage
+ ? _impacts.assertWithMessage
+ : _impacts.assertWithoutMessage);
}
@override
void registerGenericInstantiation(
ir.FunctionType expressionType, List<ir.DartType> typeArguments) {
// TODO(johnniwinther): Track which arities are used in instantiation.
- impactBuilder.registerInstantiation(GenericInstantiation(
+ final instantiation = GenericInstantiation(
elementMap.getDartType(expressionType).withoutNullability,
- typeArguments.map(elementMap.getDartType).toList()));
+ typeArguments.map(elementMap.getDartType).toList());
+ registerBackendImpact(
+ _impacts.getGenericInstantiation(instantiation.typeArguments.length));
+ _rtiNeedBuilder.registerGenericInstantiation(instantiation);
}
@override
void registerStringConcatenation() {
- impactBuilder.registerFeature(Feature.STRING_INTERPOLATION);
- impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION);
+ registerBackendImpact(_impacts.stringInterpolation);
+ registerBackendImpact(_impacts.stringJuxtaposition);
}
@override
void registerLocalFunction(ir.TreeNode node) {
Local function = elementMap.getLocalFunction(node);
impactBuilder.registerStaticUse(StaticUse.closure(function));
+ registerBackendImpact(_impacts.closure);
+ registerBackendImpact(_impacts.computeSignature);
}
@override
void registerLocalWithoutInitializer() {
- impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
- }
-
- @override
- void registerIsCheck(ir.DartType type) {
impactBuilder
- .registerTypeUse(TypeUse.isCheck(elementMap.getDartType(type)));
+ .registerTypeUse(TypeUse.instantiation(commonElements.nullType));
+ registerBackendImpact(_impacts.nullLiteral);
+ }
+
+ void _registerIsCheckInternal(DartType type) {
+ impactBuilder.registerTypeUse(TypeUse.isCheck(type));
+ onIsCheck(type);
}
@override
- void registerImplicitCast(ir.DartType type) {
- impactBuilder
- .registerTypeUse(TypeUse.implicitCast(elementMap.getDartType(type)));
+ void registerIsCheck(ir.DartType irType) {
+ _registerIsCheckInternal(elementMap.getDartType(irType));
}
@override
- void registerAsCast(ir.DartType type) {
- impactBuilder.registerTypeUse(TypeUse.asCast(elementMap.getDartType(type)));
+ void registerImplicitCast(ir.DartType irType) {
+ DartType type = elementMap.getDartType(irType);
+ impactBuilder.registerTypeUse(TypeUse.implicitCast(type));
+ if (_annotationsData
+ .getImplicitDowncastCheckPolicy(currentMember)
+ .isEmitted) {
+ onIsCheck(type);
+ }
+ }
+
+ @override
+ void registerAsCast(ir.DartType irType) {
+ DartType type = elementMap.getDartType(irType);
+ impactBuilder.registerTypeUse(TypeUse.asCast(type));
+ if (_annotationsData.getExplicitCastCheckPolicy(currentMember).isEmitted) {
+ onIsCheck(type);
+ registerBackendImpact(_impacts.asCheck);
+ }
}
@override
void registerThrow() {
- impactBuilder.registerFeature(Feature.THROW_EXPRESSION);
+ registerBackendImpact(_impacts.throwExpression);
}
@override
@@ -667,7 +757,7 @@
ClassRelation iteratorClassRelation) {
Object receiverConstraint =
_computeReceiverConstraint(iteratorType, iteratorClassRelation);
- impactBuilder.registerFeature(Feature.SYNC_FOR_IN);
+ registerBackendImpact(_impacts.syncForIn);
impactBuilder.registerDynamicUse(
DynamicUse(Selectors.iterator, receiverConstraint, const []));
impactBuilder.registerDynamicUse(
@@ -681,7 +771,7 @@
ClassRelation iteratorClassRelation) {
Object receiverConstraint =
_computeReceiverConstraint(iteratorType, iteratorClassRelation);
- impactBuilder.registerFeature(Feature.ASYNC_FOR_IN);
+ registerBackendImpact(_impacts.asyncForIn);
impactBuilder.registerDynamicUse(
DynamicUse(Selectors.cancel, receiverConstraint, const []));
impactBuilder.registerDynamicUse(
@@ -692,25 +782,34 @@
@override
void registerCatch() {
- impactBuilder.registerFeature(Feature.CATCH_STATEMENT);
+ registerBackendImpact(_impacts.catchStatement);
}
@override
void registerStackTrace() {
- impactBuilder.registerFeature(Feature.STACK_TRACE_IN_CATCH);
+ registerBackendImpact(_impacts.stackTraceInCatch);
}
@override
- void registerCatchType(ir.DartType type) {
- impactBuilder
- .registerTypeUse(TypeUse.catchType(elementMap.getDartType(type)));
+ void registerCatchType(ir.DartType irType) {
+ DartType type = elementMap.getDartType(irType);
+ impactBuilder.registerTypeUse(TypeUse.catchType(type));
+ onIsCheck(type);
}
@override
- void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import) {
+ void registerTypeLiteral(ir.DartType irType, ir.LibraryDependency import) {
ImportEntity deferredImport = elementMap.getImport(import);
- impactBuilder.registerTypeUse(
- TypeUse.typeLiteral(elementMap.getDartType(type), deferredImport));
+ DartType type = elementMap.getDartType(irType);
+ impactBuilder.registerTypeUse(TypeUse.typeLiteral(type, deferredImport));
+ _customElementsResolutionAnalysis.registerTypeLiteral(type);
+ type.forEachTypeVariable((TypeVariableType variable) {
+ _rtiNeedBuilder.registerTypeVariableLiteral(variable);
+ registerBackendImpact(_impacts.typeVariableExpression);
+ });
+ impactBuilder
+ .registerTypeUse(TypeUse.instantiation(commonElements.typeType));
+ registerBackendImpact(_impacts.typeLiteral);
}
@override
@@ -744,7 +843,7 @@
void registerLoadLibrary() {
impactBuilder.registerStaticUse(StaticUse.staticInvoke(
commonElements.loadDeferredLibrary, CallStructure.ONE_ARG));
- impactBuilder.registerFeature(Feature.LOAD_LIBRARY);
+ registerBackendImpact(_impacts.loadLibrary);
}
@override
@@ -794,8 +893,8 @@
}
/// Converts a [ImpactData] object based on kernel to the corresponding
- /// [ResolutionImpact] based on the K model.
- ResolutionImpact convert(ImpactData impactData) {
+ /// [WorldImpact] based on the K model.
+ WorldImpact convert(ImpactData impactData) {
impactData.apply(this);
return impactBuilder;
}
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index d45d1bd..6c29404 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -9,7 +9,6 @@
import '../common.dart';
import '../common/elements.dart';
import '../common/names.dart' show Uris;
-import '../common/resolution.dart';
import '../common/tasks.dart';
import '../common/work.dart';
import '../compiler.dart';
@@ -27,7 +26,6 @@
import '../js_backend/backend_usage.dart';
import '../js_backend/custom_elements_analysis.dart';
import '../js_backend/field_analysis.dart' show KFieldAnalysis;
-import '../js_backend/impact_transformer.dart';
import '../js_backend/interceptor_data.dart';
import '../js_backend/native_data.dart';
import '../js_backend/no_such_method_registry.dart';
@@ -155,17 +153,6 @@
// before creating the resolution enqueuer.
AnnotationsData annotationsData = AnnotationsDataImpl(
compiler.options, annotationsDataBuilder.pragmaAnnotations);
- final impactTransformer = JavaScriptImpactTransformer(
- elementEnvironment,
- commonElements,
- impacts,
- nativeBasicData,
- _nativeResolutionEnqueuer,
- _backendUsageBuilder,
- _customElementsResolutionAnalysis,
- rtiNeedBuilder,
- classHierarchyBuilder,
- annotationsData);
InterceptorDataBuilder interceptorDataBuilder = InterceptorDataBuilderImpl(
nativeBasicData, elementEnvironment, commonElements);
return ResolutionEnqueuer(
@@ -207,12 +194,17 @@
nativeBasicData,
nativeDataBuilder,
annotationsDataBuilder,
- impactTransformer,
closureModels,
compiler.impactCache,
_fieldAnalysis,
_modularStrategy,
- _irAnnotationData),
+ _irAnnotationData,
+ impacts,
+ _nativeResolutionEnqueuer,
+ _backendUsageBuilder,
+ _customElementsResolutionAnalysis,
+ rtiNeedBuilder,
+ annotationsData),
annotationsData);
}
@@ -287,7 +279,6 @@
class KernelWorkItemBuilder implements WorkItemBuilder {
final CompilerTask _compilerTask;
final KernelToElementMap _elementMap;
- final JavaScriptImpactTransformer _impactTransformer;
final KernelNativeMemberResolver _nativeMemberResolver;
final AnnotationsDataBuilder _annotationsDataBuilder;
final Map<MemberEntity, ClosureScopeModel> _closureModels;
@@ -295,6 +286,12 @@
final KFieldAnalysis _fieldAnalysis;
final ModularStrategy _modularStrategy;
final IrAnnotationData _irAnnotationData;
+ final BackendImpacts _impacts;
+ final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
+ final BackendUsageBuilder _backendUsageBuilder;
+ final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
+ final RuntimeTypesNeedBuilder _rtiNeedBuilder;
+ final AnnotationsData _annotationsData;
KernelWorkItemBuilder(
this._compilerTask,
@@ -302,12 +299,17 @@
NativeBasicData nativeBasicData,
NativeDataBuilder nativeDataBuilder,
this._annotationsDataBuilder,
- this._impactTransformer,
this._closureModels,
this._impactCache,
this._fieldAnalysis,
this._modularStrategy,
- this._irAnnotationData)
+ this._irAnnotationData,
+ this._impacts,
+ this._nativeResolutionEnqueuer,
+ this._backendUsageBuilder,
+ this._customElementsResolutionAnalysis,
+ this._rtiNeedBuilder,
+ this._annotationsData)
: _nativeMemberResolver = KernelNativeMemberResolver(
_elementMap, nativeBasicData, nativeDataBuilder);
@@ -316,7 +318,6 @@
return KernelWorkItem(
_compilerTask,
_elementMap,
- _impactTransformer,
_nativeMemberResolver,
_annotationsDataBuilder,
entity,
@@ -324,14 +325,19 @@
_impactCache,
_fieldAnalysis,
_modularStrategy,
- _irAnnotationData);
+ _irAnnotationData,
+ _impacts,
+ _nativeResolutionEnqueuer,
+ _backendUsageBuilder,
+ _customElementsResolutionAnalysis,
+ _rtiNeedBuilder,
+ _annotationsData);
}
}
class KernelWorkItem implements WorkItem {
final CompilerTask _compilerTask;
final KernelToElementMap _elementMap;
- final JavaScriptImpactTransformer _impactTransformer;
final KernelNativeMemberResolver _nativeMemberResolver;
final AnnotationsDataBuilder _annotationsDataBuilder;
@override
@@ -341,11 +347,16 @@
final KFieldAnalysis _fieldAnalysis;
final ModularStrategy _modularStrategy;
final IrAnnotationData _irAnnotationData;
+ final BackendImpacts _impacts;
+ final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
+ final BackendUsageBuilder _backendUsageBuilder;
+ final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
+ final RuntimeTypesNeedBuilder _rtiNeedBuilder;
+ final AnnotationsData _annotationsData;
KernelWorkItem(
this._compilerTask,
this._elementMap,
- this._impactTransformer,
this._nativeMemberResolver,
this._annotationsDataBuilder,
this.element,
@@ -353,7 +364,13 @@
this._impactCache,
this._fieldAnalysis,
this._modularStrategy,
- this._irAnnotationData);
+ this._irAnnotationData,
+ this._impacts,
+ this._nativeResolutionEnqueuer,
+ this._backendUsageBuilder,
+ this._customElementsResolutionAnalysis,
+ this._rtiNeedBuilder,
+ this._annotationsData);
@override
WorldImpact run() {
@@ -383,10 +400,15 @@
}
ImpactBuilderData impactBuilderData = modularMemberData.impactBuilderData;
return _compilerTask.measureSubtask('worldImpact', () {
- ResolutionImpact impact =
- _elementMap.computeWorldImpact(element, impactBuilderData);
- WorldImpact worldImpact =
- _impactTransformer.transformResolutionImpact(impact);
+ WorldImpact worldImpact = _elementMap.computeWorldImpact(
+ element,
+ _impacts,
+ _nativeResolutionEnqueuer,
+ _backendUsageBuilder,
+ _customElementsResolutionAnalysis,
+ _rtiNeedBuilder,
+ _annotationsData,
+ impactBuilderData);
if (_impactCache != null) {
_impactCache[element] = worldImpact;
}
diff --git a/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart
index ec145b0..30dd0b8 100644
--- a/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart
@@ -48,7 +48,7 @@
final futureValueType = node.futureValueType!;
_updateFunctionBody(
node,
- ExpressionStatement(StaticInvocation(
+ ReturnStatement(StaticInvocation(
_coreTypes.futureSyncFactory,
Arguments([
FunctionExpression(FunctionNode(node.body,
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 2b6355c..d70d471 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -47,7 +47,7 @@
/// Register [classes] as natively instantiated in [impactBuilder].
void _registerTypeUses(
- WorldImpactBuilder impactBuilder, Set<ClassEntity> classes, cause) {
+ WorldImpactBuilder impactBuilder, Set<ClassEntity> classes /*, cause*/) {
for (ClassEntity cls in classes) {
if (!_unusedClasses.contains(cls)) {
// No need to add [classElement] to [impactBuilder]: it has already been
@@ -62,13 +62,13 @@
/// Registers the [nativeBehavior]. Adds the liveness of its instantiated
/// types to the world.
- void registerNativeBehavior(
- WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {
+ void registerNativeBehavior(WorldImpactBuilder impactBuilder,
+ NativeBehavior nativeBehavior, Object cause) {
_processNativeBehavior(impactBuilder, nativeBehavior, cause);
}
void _processNativeBehavior(
- WorldImpactBuilder impactBuilder, NativeBehavior behavior, cause) {
+ WorldImpactBuilder impactBuilder, NativeBehavior behavior, Object cause) {
void registerInstantiation(InterfaceType type) {
impactBuilder.registerTypeUse(TypeUse.nativeInstantiation(type));
}
@@ -123,7 +123,7 @@
if (matchingClasses.isNotEmpty && _registeredClasses.isEmpty) {
matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
}
- _registerTypeUses(impactBuilder, matchingClasses, cause);
+ _registerTypeUses(impactBuilder, matchingClasses /*, cause*/);
// Give an info so that library developers can compile with -v to find why
// all the native classes are included.
@@ -188,7 +188,7 @@
_nativeClasses.addAll(nativeClasses);
_unusedClasses.addAll(nativeClasses);
if (!enableLiveTypeAnalysis) {
- _registerTypeUses(impactBuilder, _nativeClasses, 'forced');
+ _registerTypeUses(impactBuilder, _nativeClasses /*, 'forced'*/);
}
return impactBuilder;
}
@@ -224,7 +224,7 @@
_unusedClasses.addAll(_nativeClasses);
if (!enableLiveTypeAnalysis) {
- _registerTypeUses(impactBuilder, _nativeClasses, 'forced');
+ _registerTypeUses(impactBuilder, _nativeClasses /*, 'forced'*/);
}
// HACK HACK - add all the resolved classes.
@@ -237,14 +237,14 @@
if (matchingClasses.isNotEmpty && _registeredClasses.isEmpty) {
matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
}
- _registerTypeUses(impactBuilder, matchingClasses, 'was resolved');
+ _registerTypeUses(impactBuilder, matchingClasses /*, 'was resolved'*/);
return impactBuilder;
}
@override
void _registerTypeUses(
- WorldImpactBuilder impactBuilder, Set<ClassEntity> classes, cause) {
- super._registerTypeUses(impactBuilder, classes, cause);
+ WorldImpactBuilder impactBuilder, Set<ClassEntity> classes /*, cause*/) {
+ super._registerTypeUses(impactBuilder, classes /*, cause*/);
for (ClassEntity classElement in classes) {
// Add the information that this class is a subtype of its supertypes. The
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
deleted file mode 100644
index 0d4480f..0000000
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2014, 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 dart2js.resolution.registry;
-
-import '../common/resolution.dart' show ResolutionImpact;
-import '../constants/values.dart';
-import '../elements/entities.dart' show ClassEntity, MemberEntity;
-import '../elements/types.dart';
-import '../native/behavior.dart' show NativeBehavior;
-import '../universe/feature.dart';
-import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilderImpl;
-import '../util/enumset.dart' show EnumSet;
-import '../util/util.dart' show Setlet;
-
-class ResolutionWorldImpactBuilder extends WorldImpactBuilderImpl
- implements ResolutionImpact {
- final DartTypes _dartTypes;
- @override
- final MemberEntity member;
- EnumSet<Feature> _features;
- Setlet<MapLiteralUse> _mapLiterals;
- Setlet<SetLiteralUse> _setLiterals;
- Setlet<ListLiteralUse> _listLiterals;
- Setlet<String> _constSymbolNames;
- Setlet<ConstantValue> _constantLiterals;
- Setlet<NativeBehavior> _nativeData;
- Setlet<ClassEntity> _seenClasses;
- Set<RuntimeTypeUse> _runtimeTypeUses;
- Set<GenericInstantiation> _genericInstantiations;
-
- ResolutionWorldImpactBuilder(this._dartTypes, this.member);
-
- @override
- bool get isEmpty => false;
-
- void registerMapLiteral(MapLiteralUse mapLiteralUse) {
- assert(mapLiteralUse != null);
- _mapLiterals ??= Setlet();
- _mapLiterals.add(mapLiteralUse);
- }
-
- @override
- Iterable<MapLiteralUse> get mapLiterals => _mapLiterals ?? const [];
-
- void registerSetLiteral(SetLiteralUse setLiteralUse) {
- assert(setLiteralUse != null);
- _setLiterals ??= Setlet();
- _setLiterals.add(setLiteralUse);
- }
-
- @override
- Iterable<SetLiteralUse> get setLiterals => _setLiterals ?? const [];
-
- void registerListLiteral(ListLiteralUse listLiteralUse) {
- assert(listLiteralUse != null);
- _listLiterals ??= Setlet();
- _listLiterals.add(listLiteralUse);
- }
-
- @override
- Iterable<ListLiteralUse> get listLiterals => _listLiterals ?? const [];
-
- void registerRuntimeTypeUse(RuntimeTypeUse runtimeTypeUse) {
- assert(runtimeTypeUse != null);
- _runtimeTypeUses ??= Setlet();
- _runtimeTypeUses.add(runtimeTypeUse);
- }
-
- @override
- Iterable<RuntimeTypeUse> get runtimeTypeUses => _runtimeTypeUses ?? const [];
-
- void registerConstSymbolName(String name) {
- _constSymbolNames ??= Setlet();
- _constSymbolNames.add(name);
- }
-
- @override
- Iterable<String> get constSymbolNames => _constSymbolNames ?? const [];
-
- void registerFeature(Feature feature) {
- _features ??= EnumSet();
- _features.add(feature);
- }
-
- @override
- Iterable<Feature> get features {
- return _features != null
- ? _features.iterable(Feature.values)
- : const <Feature>[];
- }
-
- void registerConstantLiteral(ConstantValue constant) {
- _constantLiterals ??= Setlet();
- _constantLiterals.add(constant);
- }
-
- @override
- Iterable<ConstantValue> get constantLiterals => _constantLiterals ?? const [];
-
- void registerNativeData(NativeBehavior nativeData) {
- assert(nativeData != null);
- _nativeData ??= Setlet();
- _nativeData.add(nativeData);
- }
-
- @override
- Iterable<NativeBehavior> get nativeData => _nativeData ?? const [];
-
- void registerSeenClass(ClassEntity seenClass) {
- _seenClasses ??= Setlet();
- _seenClasses.add(seenClass);
- }
-
- @override
- Iterable<ClassEntity> get seenClasses => _seenClasses ?? const [];
-
- void registerInstantiation(GenericInstantiation instantiation) {
- _genericInstantiations ??= Setlet();
- _genericInstantiations.add(instantiation);
- }
-
- @override
- Iterable<GenericInstantiation> get genericInstantiations =>
- _genericInstantiations ?? const [];
-
- @override
- String toString() {
- StringBuffer sb = StringBuffer();
- sb.write('ResolutionWorldImpactBuilder($member)');
- WorldImpact.printOn(sb, this);
- if (_features != null) {
- sb.write('\n features:');
- for (Feature feature in _features.iterable(Feature.values)) {
- sb.write('\n $feature');
- }
- }
- if (_mapLiterals != null) {
- sb.write('\n map-literals:');
- for (MapLiteralUse use in _mapLiterals) {
- sb.write('\n $use');
- }
- }
- if (_setLiterals != null) {
- sb.write('\n set-literals:');
- for (SetLiteralUse use in _setLiterals) {
- sb.write('\n $use');
- }
- }
- if (_listLiterals != null) {
- sb.write('\n list-literals:');
- for (ListLiteralUse use in _listLiterals) {
- sb.write('\n $use');
- }
- }
- if (_constantLiterals != null) {
- sb.write('\n const-literals:');
- for (ConstantValue constant in _constantLiterals) {
- sb.write('\n ${constant.toDartText(_dartTypes)}');
- }
- }
- if (_constSymbolNames != null) {
- sb.write('\n const-symbol-names: $_constSymbolNames');
- }
- if (_nativeData != null) {
- sb.write('\n native-data:');
- for (var data in _nativeData) {
- sb.write('\n $data');
- }
- }
- if (_genericInstantiations != null) {
- sb.write('\n instantiations:');
- for (var data in _genericInstantiations) {
- sb.write('\n $data');
- }
- }
- return sb.toString();
- }
-}
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index 1008089..0d319ea 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -74,14 +74,18 @@
}
}
-abstract class WorldImpactBuilder {
+abstract class WorldImpactBuilder extends WorldImpact {
void registerDynamicUse(DynamicUse dynamicUse);
void registerTypeUse(TypeUse typeUse);
void registerStaticUse(StaticUse staticUse);
void registerConstantUse(ConstantUse constantUse);
}
-class WorldImpactBuilderImpl extends WorldImpact implements WorldImpactBuilder {
+class WorldImpactBuilderImpl extends WorldImpactBuilder {
+ /// The [MemberEntity] associated with this set of impacts. Maybe null.
+ @override
+ final MemberEntity member;
+
// TODO(johnniwinther): Do we benefit from lazy initialization of the
// [Setlet]s?
Set<DynamicUse> _dynamicUses;
@@ -89,10 +93,11 @@
Set<TypeUse> _typeUses;
Set<ConstantUse> _constantUses;
- WorldImpactBuilderImpl();
+ WorldImpactBuilderImpl([this.member]);
WorldImpactBuilderImpl.internal(
- this._dynamicUses, this._staticUses, this._typeUses, this._constantUses);
+ this._dynamicUses, this._staticUses, this._typeUses, this._constantUses,
+ {this.member});
@override
bool get isEmpty =>
@@ -161,7 +166,7 @@
/// Mutable implementation of [WorldImpact] used to transform
/// [ResolutionImpact] or [CodegenImpact] to [WorldImpact].
-class TransformedWorldImpact implements WorldImpact, WorldImpactBuilder {
+class TransformedWorldImpact extends WorldImpactBuilder {
final WorldImpact worldImpact;
Setlet<StaticUse> _staticUses;
@@ -228,16 +233,6 @@
}
@override
- void apply(WorldImpactVisitor visitor) {
- staticUses.forEach((StaticUse use) => visitor.visitStaticUse(member, use));
- dynamicUses
- .forEach((DynamicUse use) => visitor.visitDynamicUse(member, use));
- typeUses.forEach((TypeUse use) => visitor.visitTypeUse(member, use));
- constantUses
- .forEach((ConstantUse use) => visitor.visitConstantUse(member, use));
- }
-
- @override
String toString() {
StringBuffer sb = StringBuffer();
sb.write('TransformedWorldImpact($worldImpact)');
diff --git a/pkg/compiler/test/equivalence/id_equivalence_helper.dart b/pkg/compiler/test/equivalence/id_equivalence_helper.dart
index e8c5eae..d93441e 100644
--- a/pkg/compiler/test/equivalence/id_equivalence_helper.dart
+++ b/pkg/compiler/test/equivalence/id_equivalence_helper.dart
@@ -419,7 +419,8 @@
dataComputer.setup();
- Future<Map<String, TestResult<T>>> checkTest(TestData testData,
+ Future<Map<String, TestResult<T>>> checkTest(
+ MarkerOptions markerOptions, TestData testData,
{bool testAfterFailures,
bool verbose,
bool succinct,
@@ -454,7 +455,11 @@
}
print('--from (${testConfiguration.name})-------------');
results[testConfiguration.marker] = await runTestForConfiguration(
- testConfiguration, dataComputer, testData, testOptions,
+ markerOptions,
+ testConfiguration,
+ dataComputer,
+ testData,
+ testOptions,
filterActualData: filterActualData,
verbose: verbose,
succinct: succinct,
@@ -483,8 +488,12 @@
return Uri.parse('memory:sdk/tests/web/native/$fileName');
}
-Future<TestResult<T>> runTestForConfiguration<T>(TestConfig testConfiguration,
- DataComputer<T> dataComputer, TestData testData, List<String> options,
+Future<TestResult<T>> runTestForConfiguration<T>(
+ MarkerOptions markerOptions,
+ TestConfig testConfiguration,
+ DataComputer<T> dataComputer,
+ TestData testData,
+ List<String> options,
{bool filterActualData(IdValue idValue, ActualData<T> actualData),
bool verbose: false,
bool succinct: false,
@@ -503,8 +512,14 @@
forUserLibrariesOnly: forUserLibrariesOnly,
globalIds: annotations.globalData.keys,
verifyCompiler: verifyCompiler);
- return await checkCode(testConfiguration.name, testData.testFileUri,
- testData.code, annotations, compiledData, dataComputer.dataValidator,
+ return await checkCode(
+ markerOptions,
+ testConfiguration.marker,
+ testConfiguration.name,
+ testData,
+ annotations,
+ compiledData,
+ dataComputer.dataValidator,
filterActualData: filterActualData,
fatalErrors: !testAfterFailures,
onFailure: Expect.fail,
diff --git a/pkg/compiler/test/impact/data/constants/lib.dart b/pkg/compiler/test/impact/data/constants/lib.dart
index 9e25e3c..279fa49 100644
--- a/pkg/compiler/test/impact/data/constants/lib.dart
+++ b/pkg/compiler/test/impact/data/constants/lib.dart
@@ -37,6 +37,7 @@
const Class(field1, this.field2) : super(field1);
+ /*member: Class.staticMethodField:*/
static staticMethodField() {}
}
@@ -99,6 +100,7 @@
const dynamic instantiationField = _instantiation;
+/*member: topLevelMethod:*/
topLevelMethod() {}
const dynamic topLevelTearOffField = topLevelMethod;
diff --git a/pkg/compiler/test/impact/data/constants/main.dart b/pkg/compiler/test/impact/data/constants/main.dart
index be9a623..b750f7c 100644
--- a/pkg/compiler/test/impact/data/constants/main.dart
+++ b/pkg/compiler/test/impact/data/constants/main.dart
@@ -7,7 +7,52 @@
import 'lib.dart';
import 'lib.dart' deferred as defer;
-/*member: main:static=%*/
+/*member: main:static=[
+ boolLiteral(0),
+ boolLiteralDeferred(0),
+ boolLiteralRef(0),
+ doubleLiteral(0),
+ doubleLiteralDeferred(0),
+ doubleLiteralRef(0),
+ instanceConstant(0),
+ instanceConstantDeferred(0),
+ instanceConstantRef(0),
+ instantiation(0),
+ instantiationDeferred(0),
+ instantiationRef(0),
+ intLiteral(0),
+ intLiteralDeferred(0),
+ intLiteralRef(0),
+ listLiteral(0),
+ listLiteralDeferred(0),
+ listLiteralRef(0),
+ mapLiteral(0),
+ mapLiteralDeferred(0),
+ mapLiteralRef(0),
+ nullLiteral(0),
+ nullLiteralDeferred(0),
+ nullLiteralRef(0),
+ setLiteral(0),
+ setLiteralDeferred(0),
+ setLiteralRef(0),
+ staticTearOff(0),
+ staticTearOffDeferred(0),
+ staticTearOffRef(0),
+ stringLiteral(0),
+ stringLiteralDeferred(0),
+ stringLiteralRef(0),
+ stringMapLiteral(0),
+ stringMapLiteralDeferred(0),
+ stringMapLiteralRef(0),
+ symbolLiteral(0),
+ symbolLiteralDeferred(0),
+ symbolLiteralRef(0),
+ topLevelTearOff(0),
+ topLevelTearOffDeferred(0),
+ topLevelTearOffRef(0),
+ typeLiteral(0),
+ typeLiteralDeferred(0),
+ typeLiteralRef(0)]*/
main() {
nullLiteral();
boolLiteral();
@@ -100,7 +145,10 @@
return local;
}
-/*member: symbolLiteral:static=[Symbol.(1)],type=[inst:Symbol]*/
+/*member: symbolLiteral:
+ static=[Symbol.(1)],
+ type=[inst:Symbol]
+*/
symbolLiteral() => #foo;
/*member: listLiteral:type=[
@@ -132,8 +180,12 @@
setLiteral() => const {true, false};
/*member: instanceConstant:
- static=[Class.field2=BoolConstant(false),SuperClass.field1=BoolConstant(true)],
- type=[const:Class,inst:JSBool]
+ static=[
+ Class.field2=BoolConstant(false),
+ SuperClass.field1=BoolConstant(true)],
+ type=[
+ const:Class,
+ inst:JSBool]
*/
instanceConstant() => const Class(true, false);
@@ -151,7 +203,14 @@
return local;
}
-/*member: instantiation:static=[closureFunctionType(1),id,instantiate1(1),instantiatedGenericFunctionType(2)],type=[inst:Instantiation1<dynamic>]*/
+/*member: instantiation:
+ static=[
+ closureFunctionType(1),
+ id,
+ instantiate1(1),
+ instantiatedGenericFunctionType(2)],
+ type=[inst:Instantiation1<dynamic>]
+*/
instantiation() {
const int Function(int) local = id;
return local;
@@ -196,7 +255,10 @@
/*member: stringLiteralRef:type=[inst:JSString]*/
stringLiteralRef() => stringLiteralField;
-/*member: symbolLiteralRef:static=[Symbol.(1)],type=[inst:Symbol]*/
+/*member: symbolLiteralRef:
+ static=[Symbol.(1)],
+ type=[inst:Symbol]
+*/
symbolLiteralRef() => symbolLiteralField;
/*member: listLiteralRef:type=[
@@ -228,8 +290,12 @@
setLiteralRef() => setLiteralField;
/*member: instanceConstantRef:
- static=[Class.field2=BoolConstant(false),SuperClass.field1=BoolConstant(true)],
- type=[const:Class,inst:JSBool]
+ static=[
+ Class.field2=BoolConstant(false),
+ SuperClass.field1=BoolConstant(true)],
+ type=[
+ const:Class,
+ inst:JSBool]
*/
instanceConstantRef() => instanceConstantField;
@@ -244,7 +310,14 @@
*/
typeLiteralRef() => typeLiteralField;
-/*member: instantiationRef:static=[closureFunctionType(1),id,instantiate1(1),instantiatedGenericFunctionType(2)],type=[inst:Instantiation1<dynamic>]*/
+/*member: instantiationRef:
+ static=[
+ closureFunctionType(1),
+ id,
+ instantiate1(1),
+ instantiatedGenericFunctionType(2)],
+ type=[inst:Instantiation1<dynamic>]
+*/
instantiationRef() => instantiationField;
/*member: topLevelTearOffRef:static=[topLevelMethod]*/
@@ -281,7 +354,10 @@
stringLiteralDeferred() => defer.stringLiteralField;
// TODO(johnniwinther): Should we record that this is deferred?
-/*member: symbolLiteralDeferred:static=[Symbol.(1)],type=[inst:Symbol]*/
+/*member: symbolLiteralDeferred:
+ static=[Symbol.(1)],
+ type=[inst:Symbol]
+*/
symbolLiteralDeferred() => defer.symbolLiteralField;
// TODO(johnniwinther): Should we record that this is deferred?
@@ -317,8 +393,12 @@
setLiteralDeferred() => defer.setLiteralField;
/*member: instanceConstantDeferred:
- static=[Class.field2=BoolConstant(false),SuperClass.field1=BoolConstant(true)],
- type=[const:Class{defer},inst:JSBool]
+ static=[
+ Class.field2=BoolConstant(false),
+ SuperClass.field1=BoolConstant(true)],
+ type=[
+ const:Class{defer},
+ inst:JSBool]
*/
instanceConstantDeferred() => defer.instanceConstantField;
@@ -333,7 +413,14 @@
*/
typeLiteralDeferred() => defer.typeLiteralField;
-/*member: instantiationDeferred:static=[closureFunctionType(1),id{defer},instantiate1(1),instantiatedGenericFunctionType(2)],type=[inst:Instantiation1<dynamic>]*/
+/*member: instantiationDeferred:
+ static=[
+ closureFunctionType(1),
+ id{defer},
+ instantiate1(1),
+ instantiatedGenericFunctionType(2)],
+ type=[inst:Instantiation1<dynamic>]
+*/
instantiationDeferred() => defer.instantiationField;
/*member: topLevelTearOffDeferred:static=[topLevelMethod{defer}]*/
diff --git a/pkg/compiler/test/impact/impact_test.dart b/pkg/compiler/test/impact/impact_test.dart
index 7cec147..ff5ed69 100644
--- a/pkg/compiler/test/impact/impact_test.dart
+++ b/pkg/compiler/test/impact/impact_test.dart
@@ -7,10 +7,12 @@
import 'dart:io';
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/common/resolution.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/kernel/element_map.dart';
import 'package:compiler/src/kernel/kernel_strategy.dart';
+import 'package:compiler/src/ir/impact.dart';
+import 'package:compiler/src/ir/runtime_type_analysis.dart';
import 'package:compiler/src/universe/feature.dart';
import 'package:compiler/src/universe/use.dart';
import 'package:compiler/src/universe/world_impact.dart';
@@ -21,7 +23,7 @@
main(List<String> args) {
asyncTest(() async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
- print('Testing computation of ResolutionImpact through ImpactData');
+ print('Testing computation of WorldImpact through ImpactData');
print('==================================================================');
await checkTests(dataDir, const ImpactDataComputer(),
args: args, testedConfigs: allSpecConfigs);
@@ -69,13 +71,8 @@
for (ConstantUse use in impact.constantUses) {
features.addElement(Tags.constantUse, use.shortText);
}
- if (impact is TransformedWorldImpact &&
- impact.worldImpact is ResolutionImpact) {
- ResolutionImpact resolutionImpact = impact.worldImpact;
- for (RuntimeTypeUse use in resolutionImpact.runtimeTypeUses) {
- features.addElement(Tags.runtimeTypeUse, use.shortText);
- }
- }
+ final impactData = frontendStrategy.elementMap.impactDataForTesting[node];
+ impactData.apply(ImpactDataGoldener(frontendStrategy.elementMap, features));
Id id = computeMemberId(node);
ir.TreeNode nodeWithOffset = computeTreeNodeWithOffset(node);
actualMap[id] = new ActualData<Features>(id, features,
@@ -89,3 +86,23 @@
DataInterpreter<Features> get dataValidator =>
const FeaturesDataInterpreter(wildcard: wildcard);
}
+
+class ImpactDataGoldener implements ImpactRegistry {
+ final KernelToElementMap elementMap;
+ final Features features;
+
+ ImpactDataGoldener(this.elementMap, this.features);
+
+ @override
+ void registerRuntimeTypeUse(ir.Expression node, RuntimeTypeUseKind kind,
+ ir.DartType receiverType, ir.DartType argumentType) {
+ final runtimeTypeUse = RuntimeTypeUse(
+ kind,
+ elementMap.getDartType(receiverType),
+ argumentType == null ? null : elementMap.getDartType(argumentType));
+ features.addElement(Tags.runtimeTypeUse, runtimeTypeUse.shortText);
+ }
+
+ @override
+ noSuchMethod(_) {}
+}
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 450b24b..3543755 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -4,7 +4,7 @@
library front_end.compiler_options;
-import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
show DiagnosticMessage, DiagnosticMessageHandler;
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
@@ -108,17 +108,10 @@
/// file system. TODO(paulberry): fix this.
FileSystem fileSystem = StandardFileSystem.instance;
- /// Function that creates a [MacroExecutor] if supported.
+ /// The [MultiMacroExecutor] for loading and executing macros if supported.
///
/// This is part of the experimental macro feature.
- Future<MacroExecutor> Function() macroExecutorProvider =
- () async => throw 'Macro execution is not supported.';
-
- /// Map from library import [Uri]s of libraries that declare macros to
- /// the [Uri] for the precompiled dill that contains the macro code.
- ///
- /// This is part of the experimental macro feature.
- Map<Uri, Uri>? precompiledMacroUris;
+ MultiMacroExecutor? macroExecutor;
/// The [Target] used for compiling macros.
///
@@ -131,7 +124,7 @@
/// [Component].
///
/// This is used to turn a precompiled macro into a [Uri] that can be loaded
- /// by the macro executor provided by [macroExecutorProvider].
+ /// by the [macroExecutor].
///
/// This is part of the experimental macro feature.
MacroSerializer? macroSerializer;
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 959eb38..2a6e8f6 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -8,7 +8,7 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:_fe_analyzer_shared/src/util/libraries_specification.dart'
show
@@ -827,11 +827,8 @@
}
}
- Future<MacroExecutor> Function() get macroExecutorProvider =>
- _raw.macroExecutorProvider;
-
- Map<Uri, Uri> get precompiledMacroUris =>
- _raw.precompiledMacroUris ?? const {};
+ MultiMacroExecutor get macroExecutor =>
+ _raw.macroExecutor ??= new MultiMacroExecutor();
CompilerOptions get rawOptionsForTesting => _raw;
}
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 410e9b1..8375411 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -11,6 +11,9 @@
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
show ScannerConfiguration;
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
+ as macros;
+
import 'package:front_end/src/fasta/kernel/benchmarker.dart'
show BenchmarkPhases, Benchmarker;
@@ -60,8 +63,6 @@
import 'package:package_config/package_config.dart' show Package, PackageConfig;
-import '../api_prototype/compiler_options.dart' show CompilerOptions;
-
import '../api_prototype/file_system.dart' show FileSystem, FileSystemEntity;
import '../api_prototype/incremental_kernel_generator.dart'
@@ -184,6 +185,12 @@
// (enableIncrementalCompilerBenchmarking).
Benchmarker? _benchmarker;
+ /// Map by library [Uri] to the [macros.ExecutorFactoryToken]s that was
+ /// retrieved when registering the compiled macro executor for that library.
+ ///
+ /// This is primarily used for invalidation.
+ final Map<Uri, macros.ExecutorFactoryToken> macroExecutorFactoryTokens = {};
+
RecorderForTesting? get recorderForTesting => null;
static final Uri debugExprUri =
@@ -330,7 +337,8 @@
_benchmarker
?.enterPhase(BenchmarkPhases.incremental_invalidatePrecompiledMacros);
- _invalidatePrecompiledMacros(c.options, reusedResult.notReusedLibraries);
+ await _invalidatePrecompiledMacros(
+ c.options, reusedResult.notReusedLibraries);
// Cleanup: After (potentially) removing builders we have stuff to cleanup
// to not leak, and we might need to re-create the dill target.
@@ -378,9 +386,13 @@
NeededPrecompilations? neededPrecompilations =
await currentKernelTarget.computeNeededPrecompilations();
_benchmarker?.enterPhase(BenchmarkPhases.incremental_precompileMacros);
- if (enableMacros &&
- await precompileMacros(neededPrecompilations, c.options)) {
- continue;
+ if (enableMacros) {
+ Map<Uri, macros.ExecutorFactoryToken>? precompiled =
+ await precompileMacros(neededPrecompilations, c.options);
+ if (precompiled != null) {
+ macroExecutorFactoryTokens.addAll(precompiled);
+ continue;
+ }
}
_benchmarker?.enterPhase(
BenchmarkPhases.incremental_experimentalInvalidationPatchUpScopes);
@@ -1477,21 +1489,19 @@
}
/// Removes the precompiled macros whose libraries cannot be reused.
- void _invalidatePrecompiledMacros(ProcessedOptions processedOptions,
- Set<LibraryBuilder> notReusedLibraries) {
+ Future<void> _invalidatePrecompiledMacros(ProcessedOptions processedOptions,
+ Set<LibraryBuilder> notReusedLibraries) async {
if (notReusedLibraries.isEmpty) {
return;
}
- CompilerOptions compilerOptions = processedOptions.rawOptionsForTesting;
- Map<Uri, Uri>? precompiledMacroUris = compilerOptions.precompiledMacroUris;
- if (precompiledMacroUris != null) {
- Set<Uri> importUris =
- notReusedLibraries.map((library) => library.importUri).toSet();
- for (Uri macroLibraryUri in precompiledMacroUris.keys.toList()) {
- if (importUris.contains(macroLibraryUri)) {
- precompiledMacroUris.remove(macroLibraryUri);
- }
- }
+ if (macroExecutorFactoryTokens.isNotEmpty) {
+ await Future.wait(notReusedLibraries
+ .map((library) => library.importUri)
+ .where(macroExecutorFactoryTokens.containsKey)
+ .map((importUri) => processedOptions.macroExecutor
+ .unregisterExecutorFactory(
+ macroExecutorFactoryTokens.remove(importUri)!,
+ libraries: {importUri})));
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart
index 4bce249..9d67f00 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro/macro.dart
@@ -6,6 +6,8 @@
import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart'
as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
+ as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
as macro;
import 'package:front_end/src/fasta/kernel/benchmarker.dart'
@@ -126,13 +128,10 @@
}
static Future<MacroApplications> loadMacroIds(
- macro.MacroExecutor macroExecutor,
- Map<Uri, Uri> precompiledMacroUris,
+ macro.MultiMacroExecutor macroExecutor,
Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData,
MacroApplicationDataForTesting? dataForTesting,
Benchmarker? benchmarker) async {
- Map<ClassBuilder, macro.MacroClassIdentifier> classIdCache = {};
-
Map<MacroApplication, macro.MacroInstanceIdentifier> instanceIdCache = {};
Future<void> ensureMacroClassIds(
@@ -141,21 +140,17 @@
for (MacroApplication application in applications) {
Uri libraryUri = application.classBuilder.libraryBuilder.importUri;
String macroClassName = application.classBuilder.name;
- Uri? precompiledMacroUri = precompiledMacroUris[libraryUri];
try {
benchmarker?.beginSubdivide(
BenchmarkSubdivides.macroApplications_macroExecutorLoadMacro);
- macro.MacroClassIdentifier macroClassIdentifier =
- classIdCache[application.classBuilder] ??=
- await macroExecutor.loadMacro(libraryUri, macroClassName,
- precompiledKernelUri: precompiledMacroUri);
benchmarker?.endSubdivide();
try {
benchmarker?.beginSubdivide(BenchmarkSubdivides
.macroApplications_macroExecutorInstantiateMacro);
application.instanceIdentifier = instanceIdCache[application] ??=
await macroExecutor.instantiateMacro(
- macroClassIdentifier,
+ libraryUri,
+ macroClassName,
application.constructorName,
// TODO(johnniwinther): Support macro arguments.
new macro.Arguments([], {}));
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 3d323b0..c3c8539 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -11,8 +11,6 @@
import 'package:_fe_analyzer_shared/src/parser/forwarding_listener.dart'
show ForwardingListener;
-import 'package:_fe_analyzer_shared/src/macros/executor.dart'
- show MacroExecutor;
import 'package:_fe_analyzer_shared/src/parser/class_member_parser.dart'
show ClassMemberParser;
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
@@ -1441,16 +1439,14 @@
/// [ClassBuilder]s for the macro classes.
Map<Uri, List<ClassBuilder>> macroLibraries = {};
- Map<Uri, Uri> precompiledMacroUris =
- target.context.options.precompiledMacroUris;
-
for (LibraryBuilder libraryBuilder in libraryBuilders) {
Iterator<Builder> iterator = libraryBuilder.iterator;
while (iterator.moveNext()) {
Builder builder = iterator.current;
if (builder is ClassBuilder && builder.isMacro) {
Uri libraryUri = builder.libraryBuilder.importUri;
- if (!precompiledMacroUris.containsKey(libraryUri)) {
+ if (!target.context.options.macroExecutor
+ .libraryIsRegistered(libraryUri)) {
(macroLibraries[libraryUri] ??= []).add(builder);
if (retainDataForTesting) {
(dataForTesting!.macroDeclarationData
@@ -1520,7 +1516,8 @@
if (builder.importUri.isScheme("dart") && !builder.isSynthetic) {
// Assume the platform is precompiled.
addPrecompiledLibrary(builder.importUri);
- } else if (precompiledMacroUris.containsKey(builder.importUri)) {
+ } else if (target.context.options.macroExecutor
+ .libraryIsRegistered(builder.importUri)) {
// The precompiled macros given are also precompiled.
assert(
!macroLibraries.containsKey(builder.importUri),
@@ -1703,15 +1700,10 @@
if (libraryData.isNotEmpty) {
target.benchmarker?.beginSubdivide(
BenchmarkSubdivides.computeMacroApplications_macroExecutorProvider);
- MacroExecutor macroExecutor =
- await target.context.options.macroExecutorProvider();
target.benchmarker?.endSubdivide();
- Map<Uri, Uri> precompiledMacroUris =
- target.context.options.precompiledMacroUris;
MacroApplications result = await MacroApplications.loadMacroIds(
- macroExecutor,
- precompiledMacroUris,
+ target.context.options.macroExecutor,
libraryData,
dataForTesting?.macroApplicationData,
target.benchmarker);
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 65c8d51..b8eb49e 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -6,6 +6,9 @@
library front_end.kernel_generator_impl;
import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
+ as isolatedExecutor;
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:kernel/ast.dart';
@@ -95,7 +98,9 @@
NeededPrecompilations? neededPrecompilations =
await kernelTarget.computeNeededPrecompilations();
kernelTarget.benchmarker?.enterPhase(BenchmarkPhases.precompileMacros);
- if (await precompileMacros(neededPrecompilations, options)) {
+ Map<Uri, ExecutorFactoryToken>? precompiled =
+ await precompileMacros(neededPrecompilations, options);
+ if (precompiled != null) {
kernelTarget.benchmarker
?.enterPhase(BenchmarkPhases.unknownGenerateKernelInternal);
continue;
@@ -272,32 +277,34 @@
/// Compiles the libraries for the macro classes in [neededPrecompilations].
///
-/// Returns `true` if macro classes were compiled and added to the
-/// [CompilerOptions.precompiledMacroUris] of the provided [options].
+/// Returns a map of library uri to [ExecutorFactoryToken] if macro classes were
+/// compiled and added to the [CompilerOptions.macroExecutor] of the provided
+/// [options].
///
-/// Returns `false` if no macro classes needed precompilation or if macro
+/// Returns `null` if no macro classes needed precompilation or if macro
/// precompilation is not supported.
-Future<bool> precompileMacros(NeededPrecompilations? neededPrecompilations,
+Future<Map<Uri, ExecutorFactoryToken>?> precompileMacros(
+ NeededPrecompilations? neededPrecompilations,
ProcessedOptions options) async {
if (neededPrecompilations != null) {
if (enableMacros) {
// TODO(johnniwinther): Avoid using [rawOptionsForTesting] to compute
// the compiler options for the precompilation.
if (options.rawOptionsForTesting.macroTarget != null) {
- await _compileMacros(
- neededPrecompilations, options.rawOptionsForTesting);
// TODO(johnniwinther): Assert that some works has been done.
// TODO(johnniwinther): Stop in case of compile-time errors.
- return true;
+ return await _compileMacros(
+ neededPrecompilations, options.rawOptionsForTesting);
}
} else {
throw new UnsupportedError('Macro precompilation is not supported');
}
}
- return false;
+ return null;
}
-Future<void> _compileMacros(NeededPrecompilations neededPrecompilations,
+Future<Map<Uri, ExecutorFactoryToken>> _compileMacros(
+ NeededPrecompilations neededPrecompilations,
CompilerOptions options) async {
assert(options.macroSerializer != null);
CompilerOptions precompilationOptions = new CompilerOptions();
@@ -309,11 +316,11 @@
// macros likely need them.
precompilationOptions.environmentDefines = options.environmentDefines ?? {};
precompilationOptions.packagesFileUri = options.packagesFileUri;
- precompilationOptions.precompiledMacroUris = options.precompiledMacroUris;
+ MultiMacroExecutor macroExecutor = precompilationOptions.macroExecutor =
+ options.macroExecutor ??= new MultiMacroExecutor();
// TODO(johnniwinther): What if sdk root isn't set? How do we then get the
// right sdk?
precompilationOptions.sdkRoot = options.sdkRoot;
- precompilationOptions.macroExecutorProvider = options.macroExecutorProvider;
Map<String, Map<String, List<String>>> macroDeclarations = {};
neededPrecompilations.macroDeclarations
@@ -332,9 +339,13 @@
await kernelForProgramInternal(uri, precompilationOptions);
Uri precompiledUri = await options.macroSerializer!
.createUriForComponent(compilerResult!.component!);
- Map<Uri, Uri> precompiledMacroUris = options.precompiledMacroUris ??= {};
- neededPrecompilations.macroDeclarations
- .forEach((Uri uri, Map<String, List<String>> macroClasses) {
- precompiledMacroUris[uri] = precompiledUri;
- });
+ Set<Uri> macroLibraries =
+ neededPrecompilations.macroDeclarations.keys.toSet();
+ ExecutorFactoryToken executorToken = macroExecutor.registerExecutorFactory(
+ () => isolatedExecutor.start(
+ SerializationMode.byteDataServer, precompiledUri),
+ macroLibraries);
+ return <Uri, ExecutorFactoryToken>{
+ for (Uri library in macroLibraries) library: executorToken,
+ };
}
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index 4be720bd..07501ef 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -270,14 +270,14 @@
RunTestFunction<T> runTestFor<T>(
DataComputer<T> dataComputer, List<TestConfig> testedConfigs) {
retainDataForTesting = true;
- return (TestData testData,
+ return (MarkerOptions markerOptions, TestData testData,
{required bool testAfterFailures,
required bool verbose,
required bool succinct,
required bool printCode,
Map<String, List<String>>? skipMap,
required Uri nullUri}) {
- return runTest(testData, dataComputer, testedConfigs,
+ return runTest(markerOptions, testData, dataComputer, testedConfigs,
testAfterFailures: testAfterFailures,
verbose: verbose,
succinct: succinct,
@@ -291,8 +291,11 @@
/// Runs [dataComputer] on [testData] for all [testedConfigs].
///
/// Returns `true` if an error was encountered.
-Future<Map<String, TestResult<T>>> runTest<T>(TestData testData,
- DataComputer<T> dataComputer, List<TestConfig> testedConfigs,
+Future<Map<String, TestResult<T>>> runTest<T>(
+ MarkerOptions markerOptions,
+ TestData testData,
+ DataComputer<T> dataComputer,
+ List<TestConfig> testedConfigs,
{required bool testAfterFailures,
required bool verbose,
required bool succinct,
@@ -315,7 +318,7 @@
continue;
}
results[config.marker] = await runTestForConfig(
- testData, dataComputer, config,
+ markerOptions, testData, dataComputer, config,
fatalErrors: !testAfterFailures,
onFailure: onFailure,
verbose: verbose,
@@ -329,7 +332,7 @@
/// Runs [dataComputer] on [testData] for [config].
///
/// Returns `true` if an error was encountered.
-Future<TestResult<T>> runTestForConfig<T>(
+Future<TestResult<T>> runTestForConfig<T>(MarkerOptions markerOptions,
TestData testData, DataComputer<T> dataComputer, TestConfig config,
{required bool fatalErrors,
required bool verbose,
@@ -560,7 +563,7 @@
CfeCompiledData<T> compiledData = new CfeCompiledData<T>(
compilerResult, testData.entryPoint, actualMaps, globalData);
- return checkCode(config.name, testData.testFileUri, testData.code,
+ return checkCode(markerOptions, config.marker, config.name, testData,
memberAnnotations, compiledData, dataComputer.dataValidator,
fatalErrors: fatalErrors, succinct: succinct, onFailure: onFailure);
}
diff --git a/pkg/front_end/test/macros/application/macro_application_test.dart b/pkg/front_end/test/macros/application/macro_application_test.dart
index 69ae9c6..ca922e9 100644
--- a/pkg/front_end/test/macros/application/macro_application_test.dart
+++ b/pkg/front_end/test/macros/application/macro_application_test.dart
@@ -6,9 +6,6 @@
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
- as isolatedExecutor;
import 'package:_fe_analyzer_shared/src/testing/id.dart'
show ActualData, ClassId, Id, LibraryId;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
@@ -60,7 +57,6 @@
final Directory dataDir;
final MacroSerializer macroSerializer;
final bool generateExpectations;
- final Map<Uri, Uri> precompiledMacroUris = {};
MacroTestConfig(this.dataDir, this.macroSerializer,
{required this.generateExpectations})
@@ -71,10 +67,6 @@
@override
void customizeCompilerOptions(CompilerOptions options, TestData testData) {
- options.macroExecutorProvider = () async {
- return await isolatedExecutor.start(SerializationMode.byteDataServer);
- };
- options.precompiledMacroUris = precompiledMacroUris;
options.macroTarget = new VmTarget(new TargetFlags());
options.macroSerializer = macroSerializer;
}
diff --git a/pkg/front_end/test/macros/declaration/data/tests/all_precompiled.dart b/pkg/front_end/test/macros/declaration/data/tests/all_precompiled.dart
index 9310930..2da2a58 100644
--- a/pkg/front_end/test/macros/declaration/data/tests/all_precompiled.dart
+++ b/pkg/front_end/test/macros/declaration/data/tests/all_precompiled.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/*library:
- macroClassIds=[package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro],
macroInstanceIds=[package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro/()],
macrosAreApplied,
macrosAreAvailable
diff --git a/pkg/front_end/test/macros/declaration/data/tests/applications.dart b/pkg/front_end/test/macros/declaration/data/tests/applications.dart
index 6adb8dc..1f03c5a 100644
--- a/pkg/front_end/test/macros/declaration/data/tests/applications.dart
+++ b/pkg/front_end/test/macros/declaration/data/tests/applications.dart
@@ -6,10 +6,6 @@
compilationSequence=[
package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
main.dart],
- macroClassIds=[
- package:macro/macro.dart/Macro1,
- package:macro/macro.dart/Macro2,
- package:macro/macro.dart/Macro3],
macroInstanceIds=[
package:macro/macro.dart/Macro1/(),
package:macro/macro.dart/Macro1/(),
diff --git a/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main.dart
index 09e50a9..6f2309b 100644
--- a/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main.dart
+++ b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main.dart
@@ -6,7 +6,6 @@
compilationSequence=[
apply_lib_dep.dart|macro_lib.dart|macro_lib_dep.dart|main_lib_dep.dart|package:_fe_analyzer_shared/src/macros/api.dart,
apply_lib.dart|main.dart],
- macroClassIds=[macro_lib.dart/Macro1],
macroInstanceIds=[macro_lib.dart/Macro1/()],
macrosAreAvailable,
neededPrecompilations=[macro_lib.dart=Macro1(new)]
diff --git a/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/main.dart b/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/main.dart
index 103c1ed..1e9ac81 100644
--- a/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/main.dart
+++ b/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/main.dart
@@ -7,10 +7,6 @@
macro_lib1.dart|macro_lib2a.dart|package:_fe_analyzer_shared/src/macros/api.dart,
macro_lib2b.dart,
main.dart],
- macroClassIds=[
- macro_lib1.dart/Macro1,
- macro_lib2a.dart/Macro2a,
- macro_lib2b.dart/Macro2b],
macroInstanceIds=[
macro_lib1.dart/Macro1/(),
macro_lib2a.dart/Macro2a/(),
diff --git a/pkg/front_end/test/macros/declaration/data/tests/precompiled.dart b/pkg/front_end/test/macros/declaration/data/tests/precompiled.dart
index 16171a8..1311d4c 100644
--- a/pkg/front_end/test/macros/declaration/data/tests/precompiled.dart
+++ b/pkg/front_end/test/macros/declaration/data/tests/precompiled.dart
@@ -6,9 +6,6 @@
compilationSequence=[
package:macro/macro.dart,
main.dart],
- macroClassIds=[
- package:macro/macro.dart/Macro1,
- package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro],
macroInstanceIds=[
package:macro/macro.dart/Macro1/(),
package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro/()],
diff --git a/pkg/front_end/test/macros/declaration/data/tests/use_macro_package.dart b/pkg/front_end/test/macros/declaration/data/tests/use_macro_package.dart
index 9fea835..1db43d7 100644
--- a/pkg/front_end/test/macros/declaration/data/tests/use_macro_package.dart
+++ b/pkg/front_end/test/macros/declaration/data/tests/use_macro_package.dart
@@ -6,10 +6,6 @@
compilationSequence=[
package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
main.dart],
- macroClassIds=[
- package:macro/macro.dart/Macro1,
- package:macro/macro.dart/Macro2,
- package:macro/macro.dart/Macro3],
macroInstanceIds=[
package:macro/macro.dart/Macro1/(),
package:macro/macro.dart/Macro1/(),
diff --git a/pkg/front_end/test/macros/declaration/data/tests/use_macro_source/main.dart b/pkg/front_end/test/macros/declaration/data/tests/use_macro_source/main.dart
index 475694d..fb50380 100644
--- a/pkg/front_end/test/macros/declaration/data/tests/use_macro_source/main.dart
+++ b/pkg/front_end/test/macros/declaration/data/tests/use_macro_source/main.dart
@@ -6,9 +6,6 @@
compilationSequence=[
macro_lib.dart|package:_fe_analyzer_shared/src/macros/api.dart,
main.dart],
- macroClassIds=[
- macro_lib.dart/Macro1,
- macro_lib.dart/Macro2],
macroInstanceIds=[
macro_lib.dart/Macro1/(),
macro_lib.dart/Macro1/(),
diff --git a/pkg/front_end/test/macros/declaration/macro_declaration_test.dart b/pkg/front_end/test/macros/declaration/macro_declaration_test.dart
index d1e3f3b..746e1a6 100644
--- a/pkg/front_end/test/macros/declaration/macro_declaration_test.dart
+++ b/pkg/front_end/test/macros/declaration/macro_declaration_test.dart
@@ -6,6 +6,7 @@
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
@@ -42,14 +43,11 @@
@override
TestMacroExecutor customizeCompilerOptions(
CompilerOptions options, TestData testData) {
- TestMacroExecutor macroExecutor = new TestMacroExecutor();
- options.macroExecutorProvider = () async => macroExecutor;
- Uri precompiledPackage =
- Uri.parse('package:precompiled_macro/precompiled_macro.dart');
- options.precompiledMacroUris = {
- precompiledPackage: dummyUri,
- };
- return macroExecutor;
+ TestMacroExecutor testExecutor =
+ options.macroExecutor = new TestMacroExecutor();
+ testExecutor.registerExecutorFactory(() => testExecutor,
+ {Uri.parse('package:precompiled_macro/precompiled_macro.dart')});
+ return testExecutor;
}
}
@@ -101,7 +99,6 @@
static const String neededPrecompilations = 'neededPrecompilations';
static const String declaredMacros = 'declaredMacros';
static const String appliedMacros = 'appliedMacros';
- static const String macroClassIds = 'macroClassIds';
static const String macroInstanceIds = 'macroInstanceIds';
static const String error = 'error';
}
@@ -260,9 +257,6 @@
}
features.addElement(Tags.neededPrecompilations, sb.toString());
}
- for (_MacroClassIdentifier id in macroExecutor.macroClasses) {
- features.addElement(Tags.macroClassIds, id.toText());
- }
for (_MacroInstanceIdentifier id in macroExecutor.macroInstances) {
features.addElement(Tags.macroInstanceIds, id.toText());
}
@@ -289,8 +283,7 @@
}
}
-class TestMacroExecutor implements MacroExecutor {
- List<_MacroClassIdentifier> macroClasses = [];
+class TestMacroExecutor extends MultiMacroExecutor {
List<_MacroInstanceIdentifier> macroInstances = [];
@override
@@ -303,7 +296,7 @@
}
@override
- void close() {
+ Future<void> close() async {
// TODO: implement close
}
@@ -337,58 +330,24 @@
@override
Future<MacroInstanceIdentifier> instantiateMacro(
- MacroClassIdentifier macroClass,
- String constructor,
- Arguments arguments) async {
- _MacroInstanceIdentifier id = new _MacroInstanceIdentifier(
- macroClass as _MacroClassIdentifier, constructor, arguments);
+ Uri library, String name, String constructor, Arguments arguments) async {
+ _MacroInstanceIdentifier id =
+ new _MacroInstanceIdentifier(library, name, constructor, arguments);
macroInstances.add(id);
return id;
}
-
- @override
- Future<MacroClassIdentifier> loadMacro(Uri library, String name,
- {Uri? precompiledKernelUri}) async {
- _MacroClassIdentifier id = new _MacroClassIdentifier(library, name);
- macroClasses.add(id);
- return id;
- }
-}
-
-class _MacroClassIdentifier implements MacroClassIdentifier {
- final Uri uri;
- final String className;
-
- _MacroClassIdentifier(this.uri, this.className);
-
- String toText() => '${importUriToString(uri)}/${className}';
-
- @override
- int get hashCode => uri.hashCode * 13 + className.hashCode * 17;
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return other is _MacroClassIdentifier &&
- uri == other.uri &&
- className == other.className;
- }
-
- @override
- String toString() => 'MacroClassIdentifier($uri,$className)';
-
- @override
- void serialize(Serializer serializer) => throw UnimplementedError();
}
class _MacroInstanceIdentifier implements MacroInstanceIdentifier {
- final _MacroClassIdentifier macroClass;
+ final Uri library;
+ final String name;
final String constructor;
final Arguments arguments;
- _MacroInstanceIdentifier(this.macroClass, this.constructor, this.arguments);
+ _MacroInstanceIdentifier(
+ this.library, this.name, this.constructor, this.arguments);
- String toText() => '${macroClass.toText()}/${constructor}()';
+ String toText() => '${importUriToString(library)}/${name}/${constructor}()';
@override
void serialize(Serializer serializer) => throw UnimplementedError();
diff --git a/pkg/front_end/test/macros/incremental/incremental_macro_test.dart b/pkg/front_end/test/macros/incremental/incremental_macro_test.dart
index 6e38046..1c5ba4b 100644
--- a/pkg/front_end/test/macros/incremental/incremental_macro_test.dart
+++ b/pkg/front_end/test/macros/incremental/incremental_macro_test.dart
@@ -4,9 +4,7 @@
import 'dart:io';
-import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
- as isolatedExecutor;
-import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart';
@@ -95,12 +93,9 @@
ExperimentalFlag.alternativeInvalidationStrategy: true,
}
..macroSerializer = macroSerializer
- ..precompiledMacroUris = {}
- ..macroExecutorProvider = () async {
- return await isolatedExecutor.start(SerializationMode.byteDataServer);
- }
..macroTarget = new VmTarget(new TargetFlags())
..fileSystem = new HybridFileSystem(memoryFileSystem);
+ compilerOptions.macroExecutor ??= new MultiMacroExecutor();
ProcessedOptions processedOptions =
new ProcessedOptions(options: compilerOptions);
diff --git a/pkg/front_end/test/macros/macro_api_test.dart b/pkg/front_end/test/macros/macro_api_test.dart
index 1392e5f..bfb041e 100644
--- a/pkg/front_end/test/macros/macro_api_test.dart
+++ b/pkg/front_end/test/macros/macro_api_test.dart
@@ -4,9 +4,7 @@
import 'dart:io' show Platform;
-import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
- as isolatedExecutor;
-import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:expect/expect.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/api_prototype/front_end.dart';
@@ -29,10 +27,7 @@
options.explicitExperimentalFlags[ExperimentalFlag.macros] = true;
options.packagesFileUri = Platform.script.resolve(
'../../../_fe_analyzer_shared/test/macros/api/package_config.json');
- options.macroExecutorProvider = () async {
- return await isolatedExecutor.start(SerializationMode.byteDataServer);
- };
- options.precompiledMacroUris = {};
+ options.macroExecutor ??= new MultiMacroExecutor();
options.target = options.macroTarget = new VmTarget(new TargetFlags());
options.macroSerializer = macroSerializer;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 88a7263..f822ebb 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -136,6 +136,7 @@
bof
bom
bones
+bookkeeping
bootstrap
bother
boundness
@@ -157,6 +158,7 @@
c
caches
calculations
+callbacks
callee
caller's
callers
@@ -190,7 +192,6 @@
ci
circuited
ck
-callbacks
cl
claim
claimed
@@ -219,8 +220,10 @@
combinations
combinator
combiner
+commands
communicate
communicates
+communicating
communication
compared
compares
@@ -502,6 +505,7 @@
fortunately
fourth
framework
+freed
freely
freshly
frontend
@@ -947,6 +951,7 @@
presubmit
presumably
prev
+primarily
prime
printer
printf
@@ -1051,6 +1056,7 @@
reflectee
reflective
reg
+regenerations
regis
registering
rehash
@@ -1168,6 +1174,8 @@
shrinking
shru
shut
+shutdown
+shuts
shutting
si
sibling
@@ -1213,6 +1221,7 @@
speeding
spend
spent
+spin
spuriously
sq
sra
@@ -1423,6 +1432,8 @@
unqualified
unreachable
unregister
+unregistered
+unregisters
unseen
unset
unshadowed
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.strong.transformed.expect
index d8ebe4a..63a5d71 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.strong.transformed.expect
@@ -4,16 +4,16 @@
import "dart:core" as core;
static method foo1() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */
- asy::Future::sync<core::int>(() → FutureOr<core::int> {
+ return asy::Future::sync<core::int>(() → FutureOr<core::int> {
final core::int c = 3;
return c;
});
static method foo2() → asy::Future<void> /* futureValueType= void */ /* originally async */
- asy::Future::sync<void>(() → FutureOr<void>? {
+ return asy::Future::sync<void>(() → FutureOr<void>? {
final core::int c = 3;
});
static method foo3() → dynamic /* futureValueType= dynamic */ /* originally async */
- asy::Future::sync<dynamic>(() → FutureOr<dynamic>? {
+ return asy::Future::sync<dynamic>(() → FutureOr<dynamic>? {
return 234;
});
static method bar(() → asy::Future<core::int> func) → void {
@@ -21,13 +21,11 @@
}
static method foo4() → asy::Future<core::bool> async /* futureValueType= core::bool */ {
await asy::Future::value<core::int>(2);
- self::bar(() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */
- asy::Future::sync<core::int>(() → FutureOr<core::int> => 3);
-);
+ self::bar(() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ => asy::Future::sync<core::int>(() → FutureOr<core::int> => 3));
return true;
}
static method foo5(core::bool x) → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */
- asy::Future::sync<core::int>(() → FutureOr<core::int> {
+ return asy::Future::sync<core::int>(() → FutureOr<core::int> {
if(x)
return 123;
return 234;
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.weak.transformed.expect
index d8ebe4a..63a5d71 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_await.dart.weak.transformed.expect
@@ -4,16 +4,16 @@
import "dart:core" as core;
static method foo1() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */
- asy::Future::sync<core::int>(() → FutureOr<core::int> {
+ return asy::Future::sync<core::int>(() → FutureOr<core::int> {
final core::int c = 3;
return c;
});
static method foo2() → asy::Future<void> /* futureValueType= void */ /* originally async */
- asy::Future::sync<void>(() → FutureOr<void>? {
+ return asy::Future::sync<void>(() → FutureOr<void>? {
final core::int c = 3;
});
static method foo3() → dynamic /* futureValueType= dynamic */ /* originally async */
- asy::Future::sync<dynamic>(() → FutureOr<dynamic>? {
+ return asy::Future::sync<dynamic>(() → FutureOr<dynamic>? {
return 234;
});
static method bar(() → asy::Future<core::int> func) → void {
@@ -21,13 +21,11 @@
}
static method foo4() → asy::Future<core::bool> async /* futureValueType= core::bool */ {
await asy::Future::value<core::int>(2);
- self::bar(() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */
- asy::Future::sync<core::int>(() → FutureOr<core::int> => 3);
-);
+ self::bar(() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ => asy::Future::sync<core::int>(() → FutureOr<core::int> => 3));
return true;
}
static method foo5(core::bool x) → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */
- asy::Future::sync<core::int>(() → FutureOr<core::int> {
+ return asy::Future::sync<core::int>(() → FutureOr<core::int> {
if(x)
return 123;
return 234;
diff --git a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
index 373a8d8..aea2b09 100644
--- a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
@@ -121,10 +121,10 @@
return null;
else
[yield] null;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::asyncStarString2()){(asy::Stream<core::String>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::asyncStarString2()){(asy::Stream<core::String>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
[yield] let dynamic #t1 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error) in null;
if(:controller.{asy::_AsyncStarStreamController::add}(_in::unsafeCast<core::String>(:result_or_exception)){(core::String) → core::bool})
return null;
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
index 21decd4..01a1fee 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
@@ -652,10 +652,10 @@
#L16:
{
[yield] let dynamic #t55 = asy::_awaitHelper(func<asy::Stream<core::int>>(self::intStream()){(asy::Stream<core::int>) → FutureOr<asy::Stream<core::int>>}, :async_op_then, :async_op_error) in null;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(_in::unsafeCast<asy::Stream<core::int>>(:result_or_exception)){(asy::Stream<core::int>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(_in::unsafeCast<asy::Stream<core::int>>(:result_or_exception)){(asy::Stream<core::int>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect b/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect
index 012142b..2db299f 100644
--- a/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect
@@ -44,10 +44,10 @@
return null;
else
[yield] null;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<dynamic>){(asy::Stream<dynamic>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<dynamic>){(asy::Stream<dynamic>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
}
else
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect
index 2e127fbc..5730a20 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
import "dart:async";
@@ -25,10 +26,10 @@
else
[yield] null;
asy::Stream<core::double*>* s;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(s){(asy::Stream<core::num*>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(s){(asy::Stream<core::num*>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect
index 7f9840f..02bca84 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect
@@ -29,6 +29,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -109,18 +110,18 @@
return null;
else
[yield] null;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
+ :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
- 'List' is from 'dart:core'.
- 'Stream' is from 'dart:async'.
yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
- ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int*>*>*){(asy::Stream<core::List<core::int*>*>) → core::bool})
+ ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int*>*>*){(asy::Stream<core::List<core::int*>*>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::MyStream::•<core::List<core::int*>*>()){(asy::Stream<core::List<core::int*>*>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::MyStream::•<core::List<core::int*>*>()){(asy::Stream<core::List<core::int*>*>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect
index fbcd719..251c281 100644
--- a/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect
@@ -10,6 +10,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -129,10 +130,10 @@
try {
#L3:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect
index 84ea22c..3d5e979 100644
--- a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect
@@ -10,6 +10,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -128,10 +129,10 @@
try {
#L3:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
index cfc0b05..c8058e6 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
@@ -40,6 +40,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
static method getNull() → dynamic
return null;
@@ -160,13 +161,13 @@
try {
#L4:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -203,10 +204,10 @@
try {
#L5:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -285,13 +286,13 @@
try {
#L8:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -328,10 +329,10 @@
try {
#L9:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -402,10 +403,10 @@
try {
#L11:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -440,10 +441,10 @@
try {
#L12:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
index cfc0b05..c8058e6 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
@@ -40,6 +40,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
static method getNull() → dynamic
return null;
@@ -160,13 +161,13 @@
try {
#L4:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -203,10 +204,10 @@
try {
#L5:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -285,13 +286,13 @@
try {
#L8:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -328,10 +329,10 @@
try {
#L9:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -402,10 +403,10 @@
try {
#L11:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
@@ -440,10 +441,10 @@
try {
#L12:
{
- if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
+ :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
+ [yield] null;
+ if(_in::unsafeCast<core::bool>(:result_or_exception))
return null;
- else
- [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart b/pkg/front_end/testcases/nnbd/issue48631_1.dart
new file mode 100644
index 0000000..f995c3e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.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:async';
+
+FutureOr<T?> foo<T>(T t) {}
+
+bar<S>(bool t, S s) {
+ var x = [foo(s), s];
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.strong.expect
new file mode 100644
index 0000000..a26757b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.strong.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo<T extends core::Object? = dynamic>(self::foo::T% t) → FutureOr<self::foo::T?> {}
+static method bar<S extends core::Object? = dynamic>(core::bool t, self::bar::S% s) → dynamic {
+ core::List<FutureOr<self::bar::S?>?> x = <FutureOr<self::bar::S?>?>[self::foo<self::bar::S%>(s), s];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.strong.transformed.expect
new file mode 100644
index 0000000..b425585
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo<T extends core::Object? = dynamic>(self::foo::T% t) → FutureOr<self::foo::T?> {}
+static method bar<S extends core::Object? = dynamic>(core::bool t, self::bar::S% s) → dynamic {
+ core::List<FutureOr<self::bar::S?>?> x = core::_GrowableList::_literal2<FutureOr<self::bar::S?>?>(self::foo<self::bar::S%>(s), s);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.textual_outline.expect
new file mode 100644
index 0000000..65faadd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+import 'dart:async';
+
+FutureOr<T?> foo<T>(T t) {}
+bar<S>(bool t, S s) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..65faadd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.textual_outline_modelled.expect
@@ -0,0 +1,5 @@
+import 'dart:async';
+
+FutureOr<T?> foo<T>(T t) {}
+bar<S>(bool t, S s) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.expect
new file mode 100644
index 0000000..a26757b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo<T extends core::Object? = dynamic>(self::foo::T% t) → FutureOr<self::foo::T?> {}
+static method bar<S extends core::Object? = dynamic>(core::bool t, self::bar::S% s) → dynamic {
+ core::List<FutureOr<self::bar::S?>?> x = <FutureOr<self::bar::S?>?>[self::foo<self::bar::S%>(s), s];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.modular.expect
new file mode 100644
index 0000000..a26757b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.modular.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo<T extends core::Object? = dynamic>(self::foo::T% t) → FutureOr<self::foo::T?> {}
+static method bar<S extends core::Object? = dynamic>(core::bool t, self::bar::S% s) → dynamic {
+ core::List<FutureOr<self::bar::S?>?> x = <FutureOr<self::bar::S?>?>[self::foo<self::bar::S%>(s), s];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.outline.expect
new file mode 100644
index 0000000..f366279
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.outline.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo<T extends core::Object? = dynamic>(self::foo::T% t) → FutureOr<self::foo::T?>
+ ;
+static method bar<S extends core::Object? = dynamic>(core::bool t, self::bar::S% s) → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.transformed.expect
new file mode 100644
index 0000000..b425585
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_1.dart.weak.transformed.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo<T extends core::Object? = dynamic>(self::foo::T% t) → FutureOr<self::foo::T?> {}
+static method bar<S extends core::Object? = dynamic>(core::bool t, self::bar::S% s) → dynamic {
+ core::List<FutureOr<self::bar::S?>?> x = core::_GrowableList::_literal2<FutureOr<self::bar::S?>?>(self::foo<self::bar::S%>(s), s);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart b/pkg/front_end/testcases/nnbd/issue48631_2.dart
new file mode 100644
index 0000000..2cf30ba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart
@@ -0,0 +1,29 @@
+// 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:async';
+
+abstract class A {
+ T foo<T>(B<T> b);
+}
+
+class B<X> {
+ B(X x);
+}
+
+class C<Y> {
+ final Bar<FutureOr<Y>, D<Y>> bar;
+
+ C(this.bar);
+}
+
+abstract class D<W> implements A {}
+
+typedef Bar<V, U extends A> = V Function(U);
+
+final baz = C<int>((a) {
+ return a.foo(B(Future.value(0)));
+});
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.strong.expect
new file mode 100644
index 0000000..e842794
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.strong.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+typedef Bar<V extends core::Object? = dynamic, contravariant U extends self::A> = (U) → V%;
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ abstract method foo<T extends core::Object? = dynamic>(self::B<self::A::foo::T%> b) → self::A::foo::T%;
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ constructor •(self::B::X% x) → self::B<self::B::X%>
+ : super core::Object::•()
+ ;
+}
+class C<Y extends core::Object? = dynamic> extends core::Object {
+ final field (self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar;
+ constructor •((self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar) → self::C<self::C::Y%>
+ : self::C::bar = bar, super core::Object::•()
+ ;
+}
+abstract class D<W extends core::Object? = dynamic> extends core::Object implements self::A {
+ synthetic constructor •() → self::D<self::D::W%>
+ : super core::Object::•()
+ ;
+}
+static final field self::C<core::int> baz = new self::C::•<core::int>((self::D<core::int> a) → FutureOr<core::int> {
+ return a.{self::A::foo}<FutureOr<core::int>>(new self::B::•<FutureOr<core::int>>(asy::Future::value<core::int>(0))){(self::B<FutureOr<core::int>>) → FutureOr<core::int>};
+});
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.strong.transformed.expect
new file mode 100644
index 0000000..e842794
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+typedef Bar<V extends core::Object? = dynamic, contravariant U extends self::A> = (U) → V%;
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ abstract method foo<T extends core::Object? = dynamic>(self::B<self::A::foo::T%> b) → self::A::foo::T%;
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ constructor •(self::B::X% x) → self::B<self::B::X%>
+ : super core::Object::•()
+ ;
+}
+class C<Y extends core::Object? = dynamic> extends core::Object {
+ final field (self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar;
+ constructor •((self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar) → self::C<self::C::Y%>
+ : self::C::bar = bar, super core::Object::•()
+ ;
+}
+abstract class D<W extends core::Object? = dynamic> extends core::Object implements self::A {
+ synthetic constructor •() → self::D<self::D::W%>
+ : super core::Object::•()
+ ;
+}
+static final field self::C<core::int> baz = new self::C::•<core::int>((self::D<core::int> a) → FutureOr<core::int> {
+ return a.{self::A::foo}<FutureOr<core::int>>(new self::B::•<FutureOr<core::int>>(asy::Future::value<core::int>(0))){(self::B<FutureOr<core::int>>) → FutureOr<core::int>};
+});
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.textual_outline.expect
new file mode 100644
index 0000000..a409162
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+import 'dart:async';
+
+abstract class A {
+ T foo<T>(B<T> b);
+}
+
+class B<X> {
+ B(X x);
+}
+
+class C<Y> {
+ final Bar<FutureOr<Y>, D<Y>> bar;
+ C(this.bar);
+}
+
+abstract class D<W> implements A {}
+
+typedef Bar<V, U extends A> = V Function(U);
+final baz = C<int>((a) {
+ return a.foo(B(Future.value(0)));
+});
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..bee82dc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+import 'dart:async';
+
+abstract class A {
+ T foo<T>(B<T> b);
+}
+
+abstract class D<W> implements A {}
+
+class B<X> {
+ B(X x);
+}
+
+class C<Y> {
+ C(this.bar);
+ final Bar<FutureOr<Y>, D<Y>> bar;
+}
+
+final baz = C<int>((a) {
+ return a.foo(B(Future.value(0)));
+});
+main() {}
+typedef Bar<V, U extends A> = V Function(U);
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.expect
new file mode 100644
index 0000000..e842794
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+typedef Bar<V extends core::Object? = dynamic, contravariant U extends self::A> = (U) → V%;
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ abstract method foo<T extends core::Object? = dynamic>(self::B<self::A::foo::T%> b) → self::A::foo::T%;
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ constructor •(self::B::X% x) → self::B<self::B::X%>
+ : super core::Object::•()
+ ;
+}
+class C<Y extends core::Object? = dynamic> extends core::Object {
+ final field (self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar;
+ constructor •((self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar) → self::C<self::C::Y%>
+ : self::C::bar = bar, super core::Object::•()
+ ;
+}
+abstract class D<W extends core::Object? = dynamic> extends core::Object implements self::A {
+ synthetic constructor •() → self::D<self::D::W%>
+ : super core::Object::•()
+ ;
+}
+static final field self::C<core::int> baz = new self::C::•<core::int>((self::D<core::int> a) → FutureOr<core::int> {
+ return a.{self::A::foo}<FutureOr<core::int>>(new self::B::•<FutureOr<core::int>>(asy::Future::value<core::int>(0))){(self::B<FutureOr<core::int>>) → FutureOr<core::int>};
+});
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.modular.expect
new file mode 100644
index 0000000..e842794
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.modular.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+typedef Bar<V extends core::Object? = dynamic, contravariant U extends self::A> = (U) → V%;
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ abstract method foo<T extends core::Object? = dynamic>(self::B<self::A::foo::T%> b) → self::A::foo::T%;
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ constructor •(self::B::X% x) → self::B<self::B::X%>
+ : super core::Object::•()
+ ;
+}
+class C<Y extends core::Object? = dynamic> extends core::Object {
+ final field (self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar;
+ constructor •((self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar) → self::C<self::C::Y%>
+ : self::C::bar = bar, super core::Object::•()
+ ;
+}
+abstract class D<W extends core::Object? = dynamic> extends core::Object implements self::A {
+ synthetic constructor •() → self::D<self::D::W%>
+ : super core::Object::•()
+ ;
+}
+static final field self::C<core::int> baz = new self::C::•<core::int>((self::D<core::int> a) → FutureOr<core::int> {
+ return a.{self::A::foo}<FutureOr<core::int>>(new self::B::•<FutureOr<core::int>>(asy::Future::value<core::int>(0))){(self::B<FutureOr<core::int>>) → FutureOr<core::int>};
+});
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.outline.expect
new file mode 100644
index 0000000..4eff2cf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.outline.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Bar<V extends core::Object? = dynamic, contravariant U extends self::A> = (U) → V%;
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+ abstract method foo<T extends core::Object? = dynamic>(self::B<self::A::foo::T%> b) → self::A::foo::T%;
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ constructor •(self::B::X% x) → self::B<self::B::X%>
+ ;
+}
+class C<Y extends core::Object? = dynamic> extends core::Object {
+ final field (self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar;
+ constructor •((self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar) → self::C<self::C::Y%>
+ ;
+}
+abstract class D<W extends core::Object? = dynamic> extends core::Object implements self::A {
+ synthetic constructor •() → self::D<self::D::W%>
+ ;
+}
+static final field self::C<core::int> baz;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.transformed.expect
new file mode 100644
index 0000000..e842794
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48631_2.dart.weak.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+typedef Bar<V extends core::Object? = dynamic, contravariant U extends self::A> = (U) → V%;
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ abstract method foo<T extends core::Object? = dynamic>(self::B<self::A::foo::T%> b) → self::A::foo::T%;
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ constructor •(self::B::X% x) → self::B<self::B::X%>
+ : super core::Object::•()
+ ;
+}
+class C<Y extends core::Object? = dynamic> extends core::Object {
+ final field (self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar;
+ constructor •((self::D<self::C::Y%>) → FutureOr<self::C::Y%>% bar) → self::C<self::C::Y%>
+ : self::C::bar = bar, super core::Object::•()
+ ;
+}
+abstract class D<W extends core::Object? = dynamic> extends core::Object implements self::A {
+ synthetic constructor •() → self::D<self::D::W%>
+ : super core::Object::•()
+ ;
+}
+static final field self::C<core::int> baz = new self::C::•<core::int>((self::D<core::int> a) → FutureOr<core::int> {
+ return a.{self::A::foo}<FutureOr<core::int>>(new self::B::•<FutureOr<core::int>>(asy::Future::value<core::int>(0))){(self::B<FutureOr<core::int>>) → FutureOr<core::int>};
+});
+static method main() → dynamic {}
diff --git a/pkg/frontend_server/lib/compute_kernel.dart b/pkg/frontend_server/lib/compute_kernel.dart
index e51cafc..6e89be6 100644
--- a/pkg/frontend_server/lib/compute_kernel.dart
+++ b/pkg/frontend_server/lib/compute_kernel.dart
@@ -314,28 +314,41 @@
'${parsedArgs['macro-serialization-mode']}');
}
+ // TODO: Handle invalidation of precompiled macros.
+ // TODO: Handle multiple macro libraries compiled to a single precompiled
+ // kernel file.
+ var macroExecutor = state.options.macroExecutor;
var format = parsedArgs['precompiled-macro-format'];
- switch (format) {
- case 'kernel':
- state.options.macroExecutorProvider =
- () => isolatedExecutor.start(serializationMode);
- break;
- case 'aot':
- state.options.macroExecutorProvider = () => processExecutor.start(
- serializationMode, processExecutor.CommunicationChannel.socket);
- break;
- default:
- throw ArgumentError('Unrecognized precompiled macro format $format');
- }
- var precompiledMacroUris = state.options.precompiledMacroUris = {};
for (var parts in (parsedArgs['precompiled-macro'] as List<String>)
.map((arg) => arg.split(';'))) {
- precompiledMacroUris[Uri.parse(parts[0])] = toUri(parts[1]);
+ var library = Uri.parse(parts[0]);
+ if (macroExecutor.libraryIsRegistered(library)) {
+ continue;
+ }
+ var programUri = toUri(parts[1]);
+ switch (format) {
+ case 'kernel':
+ macroExecutor.registerExecutorFactory(
+ () => isolatedExecutor.start(serializationMode, programUri),
+ {library});
+ break;
+ case 'aot':
+ macroExecutor.registerExecutorFactory(
+ () => processExecutor.start(
+ serializationMode,
+ processExecutor.CommunicationChannel.socket,
+ programUri.toFilePath()),
+ {library});
+ break;
+ default:
+ throw ArgumentError('Unrecognized precompiled macro format $format');
+ }
}
} else {
enableMacros = false;
forceEnableMacros = false;
- state.options.precompiledMacroUris = {};
+ await state.options.macroExecutor?.close();
+ state.options.macroExecutor = null;
}
void onDiagnostic(fe.DiagnosticMessage message) {
diff --git a/pkg/js_ast/lib/src/characters.dart b/pkg/js_ast/lib/src/characters.dart
index aaa068d..5fd1196 100644
--- a/pkg/js_ast/lib/src/characters.dart
+++ b/pkg/js_ast/lib/src/characters.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.15
-
library js_character_codes;
const int $EOF = 0;
diff --git a/pkg/js_ast/test/deferred_expression_test.dart b/pkg/js_ast/test/deferred_expression_test.dart
index da1e158..f519964 100644
--- a/pkg/js_ast/test/deferred_expression_test.dart
+++ b/pkg/js_ast/test/deferred_expression_test.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.10
-
import 'package:expect/expect.dart';
import 'package:js_ast/js_ast.dart';
@@ -55,7 +53,7 @@
void test(Map<Expression, DeferredExpression> map, String template,
List<Expression> arguments, String expectedOutput) {
Expression directExpression =
- js.expressionTemplateFor(template).instantiate(arguments);
+ js.expressionTemplateFor(template).instantiate(arguments) as Expression;
_Context directContext = _Context();
Printer directPrinter =
Printer(const JavaScriptPrintingOptions(), directContext);
@@ -64,7 +62,7 @@
Expression deferredExpression = js
.expressionTemplateFor(template)
- .instantiate(arguments.map((e) => map[e]).toList());
+ .instantiate(arguments.map((e) => map[e]).toList()) as Expression;
_Context deferredContext = _Context();
Printer deferredPrinter =
Printer(const JavaScriptPrintingOptions(), deferredContext);
@@ -72,7 +70,7 @@
Expect.equals(expectedOutput, deferredContext.text);
for (Expression argument in arguments) {
- DeferredExpression deferred = map[argument];
+ DeferredExpression deferred = map[argument]!;
Expect.isTrue(
directContext.enterPositions.containsKey(argument),
'Argument ${DebugPrint(argument)} not found in direct enter positions: '
@@ -144,7 +142,7 @@
@override
void exitNode(
- Node node, int startPosition, int endPosition, int closingPosition) {
+ Node node, int startPosition, int endPosition, int? closingPosition) {
exitPositions[node] =
_Position(startPosition, endPosition, closingPosition);
Expect.equals(enterPositions[node], startPosition);
@@ -161,7 +159,7 @@
class _Position {
final int startPosition;
final int endPosition;
- final int closingPosition;
+ final int? closingPosition;
_Position(this.startPosition, this.endPosition, this.closingPosition);
diff --git a/pkg/js_ast/test/deferred_statement_test.dart b/pkg/js_ast/test/deferred_statement_test.dart
index 4db27a6..1ec6f13 100644
--- a/pkg/js_ast/test/deferred_statement_test.dart
+++ b/pkg/js_ast/test/deferred_statement_test.dart
@@ -2,16 +2,15 @@
// 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.10
-
import 'package:expect/expect.dart';
import 'package:js_ast/js_ast.dart';
class _DeferredStatement extends DeferredStatement {
+ final Statement? _statement;
@override
- final Statement statement;
+ Statement get statement => _statement!;
- _DeferredStatement(this.statement);
+ _DeferredStatement(this._statement);
}
void main() {
@@ -38,14 +37,21 @@
// Nested Blocks in DeferredStatements are elided.
Expect.equals(
- DebugPrint(Block([
- _DeferredStatement(Block([
- _DeferredStatement(Block.empty()),
- Block.empty(),
- Block([_DeferredStatement(Block.empty()), Block.empty()]),
- _DeferredStatement(_DeferredStatement(Block.empty()))
- ]))
- ])),
+ DebugPrint(
+ Block([
+ _DeferredStatement(
+ Block([
+ _DeferredStatement(Block.empty()),
+ Block.empty(),
+ Block([
+ _DeferredStatement(Block.empty()),
+ Block.empty(),
+ ]),
+ _DeferredStatement(_DeferredStatement(Block.empty())),
+ ]),
+ ),
+ ]),
+ ),
'{\n}\n');
// DeferredStatement with empty Statement prints semicolon and a newline.
diff --git a/pkg/js_ast/test/printer_callback_test.dart b/pkg/js_ast/test/printer_callback_test.dart
index 433d3ad..45912bb 100644
--- a/pkg/js_ast/test/printer_callback_test.dart
+++ b/pkg/js_ast/test/printer_callback_test.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.10
-
// Note: This test relies on LF line endings in the source file.
// Test that JS printer callbacks occur when expected.
@@ -178,11 +176,8 @@
void check(TestCase testCase) {
Map<TestMode, String> map = testCase.data;
- String code = map[TestMode.INPUT];
-
- // Input is the same as output.
- code ??= map[TestMode.NONE];
-
+ // Unspecified input is the same as output.
+ String? code = map[TestMode.INPUT] ?? map[TestMode.NONE]!;
JavaScriptPrintingOptions options = JavaScriptPrintingOptions();
Map arguments = {};
testCase.environment.forEach((String name, String value) {
@@ -221,7 +216,7 @@
@override
void exitNode(
- Node node, int startPosition, int endPosition, int delimiterPosition) {
+ Node node, int startPosition, int endPosition, int? delimiterPosition) {
int value = id(node);
if (mode == TestMode.DELIMITER && delimiterPosition != null) {
tagMap.putIfAbsent(delimiterPosition, () => []).add(tag(value));
@@ -239,7 +234,7 @@
if (offset < position) {
sb.write(text.substring(offset, position));
}
- tagMap[position].forEach((String tag) => sb.write(tag));
+ tagMap[position]!.forEach((String tag) => sb.write(tag));
offset = position;
}
if (offset < text.length) {
diff --git a/pkg/js_ast/test/string_escape_test.dart b/pkg/js_ast/test/string_escape_test.dart
index c483ba9..c61a3ff 100644
--- a/pkg/js_ast/test/string_escape_test.dart
+++ b/pkg/js_ast/test/string_escape_test.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.10
-
library js_ast.string_escape_test;
import 'package:js_ast/js_ast.dart';
@@ -14,9 +12,11 @@
const int $RCURLY = $CLOSE_CURLY_BRACKET;
void main() {
- void check(input, expected, {bool utf8 = false}) {
- if (input is List) input = String.fromCharCodes(input);
- String actual = DebugPrint(js.string(input), utf8: utf8);
+ void check(Object input, Object expected, {bool utf8 = false}) {
+ String string = input is String
+ ? input
+ : String.fromCharCodes(List<int>.from(input as Iterable));
+ String actual = DebugPrint(js.string(string), utf8: utf8);
if (expected is List) {
expect(actual.codeUnits, expected);
} else {
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 7afdf2d..fe6e356 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -614,7 +614,22 @@
int before = useCounter;
DartType typeArgument = node.typeArgument.accept(this);
if (useCounter == before) return node;
- return new FutureOrType(typeArgument, node.declaredNullability);
+
+ // The top-level nullability of a FutureOr should remain the same, with the
+ // exception of the case of [Nullability.undetermined]. In that case it
+ // remains undetermined if the nullability of [typeArgument] is
+ // undetermined, and otherwise it should become [Nullability.nonNullable].
+ Nullability nullability;
+ if (node.declaredNullability == Nullability.undetermined) {
+ if (typeArgument.nullability == Nullability.undetermined) {
+ nullability = Nullability.undetermined;
+ } else {
+ nullability = Nullability.nonNullable;
+ }
+ } else {
+ nullability = node.declaredNullability;
+ }
+ return new FutureOrType(typeArgument, nullability);
}
@override
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index b287bcc..d27db05 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -892,6 +892,8 @@
exec = "$simBuildDir/gen_snapshot";
} else if (_isArm64 && _configuration.useQemu) {
exec = "$buildDir/clang_x64/gen_snapshot";
+ } else if (_isRiscv64 && _configuration.useQemu) {
+ exec = "$buildDir/x64/gen_snapshot";
} else {
exec = "$buildDir/gen_snapshot";
}
diff --git a/pkg/vm/lib/transformations/continuation.dart b/pkg/vm/lib/transformations/continuation.dart
index b5c3949..fa535fc 100644
--- a/pkg/vm/lib/transformations/continuation.dart
+++ b/pkg/vm/lib/transformations/continuation.dart
@@ -1319,10 +1319,21 @@
functionType: addMethodFunctionType)
..fileOffset = stmt.fileOffset;
- statements.add(new IfStatement(
- addExpression,
- new ReturnStatement(new NullLiteral()),
- createContinuationPoint()..fileOffset = stmt.fileOffset));
+ if (stmt.isYieldStar) {
+ statements.add(ExpressionStatement(addExpression));
+ statements.add(createContinuationPoint()..fileOffset = stmt.fileOffset);
+ final wasCancelled = StaticInvocation(
+ helper.unsafeCast,
+ Arguments(<Expression>[VariableGet(expressionRewriter!.asyncResult)],
+ types: <DartType>[helper.coreTypes.boolNonNullableRawType]));
+ statements
+ .add(IfStatement(wasCancelled, ReturnStatement(NullLiteral()), null));
+ } else {
+ statements.add(new IfStatement(
+ addExpression,
+ new ReturnStatement(new NullLiteral()),
+ createContinuationPoint()..fileOffset = stmt.fileOffset));
+ }
return removalSentinel ?? EmptyStatement();
}
diff --git a/runtime/tests/vm/dart/causal_stacks/flutter_regress_100441_test.dart b/runtime/tests/vm/dart/causal_stacks/flutter_regress_100441_test.dart
new file mode 100644
index 0000000..b5ff8ad
--- /dev/null
+++ b/runtime/tests/vm/dart/causal_stacks/flutter_regress_100441_test.dart
@@ -0,0 +1,77 @@
+// 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.
+//
+// VMOptions=--lazy-async-stacks
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+import 'utils.dart' show assertStack;
+
+String effectOrder = '';
+StackTrace? stackAfterYield = null;
+
+void emit(String m) => effectOrder += m;
+
+main() async {
+ emit('1');
+ await for (final value in produce()) {
+ emit('5');
+ Expect.equals('|value|', value);
+ }
+ emit('8');
+ Expect.equals('12345678', effectOrder);
+
+ assertStack(const <String>[
+ r'^#0 produceInner .*$',
+ r'^<asynchronous suspension>$',
+ r'^#1 produce .*$',
+ r'^<asynchronous suspension>$',
+ r'^#2 main .*$',
+ r'^<asynchronous suspension>$',
+ ], stackAfterYield!);
+
+ effectOrder = '';
+
+ emit('1');
+ await for (final value in produceYieldStar()) {
+ emit('5');
+ Expect.equals('|value|', value);
+ break;
+ }
+ emit('6');
+ Expect.equals('123456', effectOrder);
+}
+
+Stream<dynamic> produce() async* {
+ emit('2');
+ await for (String response in produceInner()) {
+ emit('4');
+ yield response;
+ }
+ emit('7');
+}
+
+Stream produceInner() async* {
+ emit('3');
+ yield '|value|';
+ emit('6');
+ stackAfterYield = StackTrace.current;
+}
+
+Stream<dynamic> produceYieldStar() async* {
+ emit('2');
+ await for (String response in produceInner()) {
+ emit('4');
+ yield response;
+ }
+ emit('x');
+}
+
+Stream produceInnerYieldStar() async* {
+ emit('3');
+ yield* Stream.fromIterable(['|value|', '|value2|']);
+ emit('x');
+}
diff --git a/runtime/tests/vm/dart_2/causal_stacks/flutter_regress_100441_test.dart b/runtime/tests/vm/dart_2/causal_stacks/flutter_regress_100441_test.dart
new file mode 100644
index 0000000..2d4d2ef
--- /dev/null
+++ b/runtime/tests/vm/dart_2/causal_stacks/flutter_regress_100441_test.dart
@@ -0,0 +1,78 @@
+// 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.
+//
+// VMOptions=--lazy-async-stacks
+
+// @dart = 2.9
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+import 'utils.dart' show assertStack;
+
+String effectOrder = '';
+StackTrace stackAfterYield = null;
+
+void emit(String m) => effectOrder += m;
+
+main() async {
+ emit('1');
+ await for (final value in produce()) {
+ emit('5');
+ Expect.equals('|value|', value);
+ }
+ emit('8');
+ Expect.equals('12345678', effectOrder);
+
+ assertStack(const <String>[
+ r'^#0 produceInner .*$',
+ r'^<asynchronous suspension>$',
+ r'^#1 produce .*$',
+ r'^<asynchronous suspension>$',
+ r'^#2 main .*$',
+ r'^<asynchronous suspension>$',
+ ], stackAfterYield);
+
+ effectOrder = '';
+
+ emit('1');
+ await for (final value in produceYieldStar()) {
+ emit('5');
+ Expect.equals('|value|', value);
+ break;
+ }
+ emit('6');
+ Expect.equals('123456', effectOrder);
+}
+
+Stream<dynamic> produce() async* {
+ emit('2');
+ await for (String response in produceInner()) {
+ emit('4');
+ yield response;
+ }
+ emit('7');
+}
+
+Stream produceInner() async* {
+ emit('3');
+ yield '|value|';
+ emit('6');
+ stackAfterYield = StackTrace.current;
+}
+
+Stream<dynamic> produceYieldStar() async* {
+ emit('2');
+ await for (String response in produceInner()) {
+ emit('4');
+ yield response;
+ }
+ emit('x');
+}
+
+Stream produceInnerYieldStar() async* {
+ emit('3');
+ yield* Stream.fromIterable(['|value|', '|value2|']);
+ emit('x');
+}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
index b89c53f..30d5374 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
@@ -1031,7 +1031,24 @@
void FlowGraphCompiler::LoadBSSEntry(BSS::Relocation relocation,
Register dst,
Register tmp) {
- UNIMPLEMENTED();
+ compiler::Label skip_reloc;
+ __ j(&skip_reloc, compiler::Assembler::kNearJump);
+ InsertBSSRelocation(relocation);
+ __ Bind(&skip_reloc);
+
+ __ auipc(tmp, 0);
+ __ addi(tmp, tmp, -compiler::target::kWordSize);
+
+ // tmp holds the address of the relocation.
+ __ lx(dst, compiler::Address(tmp));
+
+ // dst holds the relocation itself: tmp - bss_start.
+ // tmp = tmp + (bss_start - tmp) = bss_start
+ __ add(tmp, tmp, dst);
+
+ // tmp holds the start of the BSS section.
+ // Load the "get-thread" routine: *bss_start.
+ __ lx(dst, compiler::Address(tmp));
}
#undef __
diff --git a/runtime/vm/heap/safepoint_test.cc b/runtime/vm/heap/safepoint_test.cc
index 15eedc5..0693ec1 100644
--- a/runtime/vm/heap/safepoint_test.cc
+++ b/runtime/vm/heap/safepoint_test.cc
@@ -316,27 +316,38 @@
uword last_sync = OS::GetCurrentTimeMillis();
while (!data()->IsIn(kPleaseExit)) {
+ OS::SleepMicros(100); // Make test avoid consuming 100% CPU x kTaskCount.
switch (data()->level) {
case SafepointLevel::kGC: {
// This thread should join only GC safepoint operations.
RuntimeCallDeoptScope no_deopt(
Thread::Current(), RuntimeCallDeoptAbility::kCannotLazyDeopt);
- SafepointIfRequested(thread_, data()->gc_only_checkins);
+ if (SafepointIfRequested(thread_, data()->gc_only_checkins)) {
+ last_sync = OS::GetCurrentTimeMillis();
+ }
break;
}
case SafepointLevel::kGCAndDeopt: {
// This thread should join any safepoint operations.
- SafepointIfRequested(thread_, data()->deopt_checkin);
+ if (SafepointIfRequested(thread_, data()->deopt_checkin)) {
+ last_sync = OS::GetCurrentTimeMillis();
+ }
break;
}
case SafepointLevel::kNumLevels:
UNREACHABLE();
}
- // If we are asked to join a deopt safepoint operation we will comply with
- // that but only every second.
+ // If the main thread asks us to join a deopt safepoint but we are
+ // instructed to only really collaborate with GC safepoints we won't
+ // participate in the above cases (and therefore not register our
+ // check-in by increasing the checkin counts).
+ //
+ // After being quite sure to not have joined deopt safepoint if we only
+ // support GC safepoints, we will eventually comply here to make main
+ // thread continue.
const auto now = OS::GetCurrentTimeMillis();
- if ((now - last_sync) > 200) {
+ if ((now - last_sync) > 1000) {
thread_->EnterSafepoint();
thread_->ExitSafepoint();
last_sync = now;
@@ -344,13 +355,14 @@
}
}
- void SafepointIfRequested(Thread* thread, std::atomic<intptr_t>* checkins) {
- OS::SleepMicros(10);
+ bool SafepointIfRequested(Thread* thread, std::atomic<intptr_t>* checkins) {
if (thread->IsSafepointRequested()) {
// Collaborates by checking into the safepoint.
thread->BlockForSafepoint();
(*checkins)++;
+ return true;
}
+ return false;
}
};
@@ -392,11 +404,11 @@
}
{
{ GcSafepointOperationScope safepoint_operation(thread); }
- OS::SleepMicros(500);
+ OS::SleepMicros(1000); // Wait for threads to exit safepoint
{ DeoptSafepointOperationScope safepoint_operation(thread); }
- OS::SleepMicros(500);
+ OS::SleepMicros(1000); // Wait for threads to exit safepoint
{ GcSafepointOperationScope safepoint_operation(thread); }
- OS::SleepMicros(500);
+ OS::SleepMicros(1000); // Wait for threads to exit safepoint
{ DeoptSafepointOperationScope safepoint_operation(thread); }
}
for (intptr_t i = 0; i < kTaskCount; i++) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2a287b9..a8eb8b1 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -15757,34 +15757,70 @@
}
intptr_t ICData::NumberOfChecks() const {
- const intptr_t length = Length();
- for (intptr_t i = 0; i < length; i++) {
- if (IsSentinelAt(i)) {
- return i;
- }
- }
- UNREACHABLE();
- return -1;
+ DEBUG_ONLY(AssertInvariantsAreSatisfied());
+ return Length() - 1;
}
bool ICData::NumberOfChecksIs(intptr_t n) const {
- const intptr_t length = Length();
- for (intptr_t i = 0; i < length; i++) {
- if (i == n) {
- return IsSentinelAt(i);
- } else {
- if (IsSentinelAt(i)) return false;
+ DEBUG_ONLY(AssertInvariantsAreSatisfied());
+ return NumberOfChecks() == n;
+}
+
+#if defined(DEBUG)
+void ICData::AssertInvariantsAreSatisfied() const {
+ // See layout and invariant of [ICData] in class comment in object.h.
+ //
+ // This method can be called without holding any locks, it will grab a
+ // snapshot of `entries()` and do it's verification logic on that.
+ auto zone = Thread::Current()->zone();
+ const auto& array = Array::Handle(zone, entries());
+
+ const intptr_t entry_length = TestEntryLength();
+ const intptr_t num_checks = array.Length() / entry_length - 1;
+ const intptr_t num_args = NumArgsTested();
+
+ /// Backing store must be multiple of entry length.
+ ASSERT((array.Length() % entry_length) == 0);
+
+ /// Entries must be valid.
+ for (intptr_t i = 0; i < num_checks; ++i) {
+ // Should be valid entry.
+ const intptr_t start = entry_length * i;
+ for (intptr_t i = 0; i < num_args; ++i) {
+ ASSERT(!array.At(start + i)->IsHeapObject());
+ ASSERT(array.At(start + i) != smi_illegal_cid().ptr());
+ }
+ ASSERT(array.At(start + TargetIndexFor(num_args))->IsHeapObject());
+ if (is_tracking_exactness()) {
+ ASSERT(!array.At(start + ExactnessIndexFor(num_args))->IsHeapObject());
}
}
- return n == length;
+
+ /// Sentinel at end must be valid.
+ const intptr_t sentinel_start = num_checks * entry_length;
+ for (intptr_t i = 0; i < entry_length - 1; ++i) {
+ ASSERT(array.At(sentinel_start + i) == smi_illegal_cid().ptr());
+ }
+ if (num_checks == 0) {
+ ASSERT(array.At(sentinel_start + entry_length - 1) ==
+ smi_illegal_cid().ptr());
+ ASSERT(ICData::CachedEmptyICDataArray(num_args, is_tracking_exactness()) ==
+ entries());
+ } else {
+ ASSERT(array.At(sentinel_start + entry_length - 1) == ptr());
+ }
+
+ // Invariants for ICData of static calls.
+ if (num_args == 0) {
+ ASSERT(Length() == 2);
+ ASSERT(TestEntryLength() == 2);
+ }
}
+#endif // defined(DEBUG)
// Discounts any checks with usage of zero.
intptr_t ICData::NumberOfUsedChecks() const {
- intptr_t n = NumberOfChecks();
- if (n == 0) {
- return 0;
- }
+ const intptr_t n = NumberOfChecks();
intptr_t count = 0;
for (intptr_t i = 0; i < n; i++) {
if (GetCountAt(i) > 0) {
@@ -15799,10 +15835,11 @@
const Object& back_ref) {
ASSERT(!data.IsNull());
RELEASE_ASSERT(smi_illegal_cid().Value() == kIllegalCid);
- for (intptr_t i = 2; i <= test_entry_length; i++) {
- data.SetAt(data.Length() - i, smi_illegal_cid());
+ const intptr_t entry_start = data.Length() - test_entry_length;
+ for (intptr_t i = 0; i < test_entry_length - 1; i++) {
+ data.SetAt(entry_start + i, smi_illegal_cid());
}
- data.SetAt(data.Length() - 1, back_ref);
+ data.SetAt(entry_start + test_entry_length - 1, back_ref);
}
#if defined(DEBUG)
@@ -15832,27 +15869,35 @@
return -1;
}
-void ICData::WriteSentinelAt(intptr_t index,
- const CallSiteResetter& proof_of_reload) const {
+void ICData::TruncateTo(intptr_t num_checks,
+ const CallSiteResetter& proof_of_reload) const {
USE(proof_of_reload); // This method can only be called during reload.
- Thread* thread = Thread::Current();
- const intptr_t len = Length();
- ASSERT(index >= 0);
- ASSERT(index < len);
+ DEBUG_ONLY(AssertInvariantsAreSatisfied());
+ ASSERT(num_checks <= NumberOfChecks());
+
+ // Nothing to do.
+ if (NumberOfChecks() == num_checks) return;
+
+ auto thread = Thread::Current();
REUSABLE_ARRAY_HANDLESCOPE(thread);
- Array& data = thread->ArrayHandle();
- data = entries();
- const intptr_t start = index * TestEntryLength();
- const intptr_t end = start + TestEntryLength();
- for (intptr_t i = start; i < end; i++) {
- data.SetAt(i, smi_illegal_cid());
+ auto& array = thread->ArrayHandle();
+
+ // If we make the ICData empty, use the pre-allocated shared backing stores.
+ const intptr_t num_args = NumArgsTested();
+ if (num_checks == 0) {
+ array = ICData::CachedEmptyICDataArray(num_args, is_tracking_exactness());
+ set_entries(array);
+ return;
}
- // The last slot in the last entry of the [ICData::entries_] is a back-ref to
- // the [ICData] itself.
- if (index == (len - 1)) {
- data.SetAt(end - 1, *this);
- }
+
+ // Otherwise truncate array and initialize sentinel.
+ // Use kSmiCid for all slots in the entry except the last, which is a backref
+ // to ICData.
+ const intptr_t entry_length = TestEntryLength();
+ array = entries();
+ array.Truncate((num_checks + 1) * entry_length);
+ WriteSentinel(array, entry_length, *this);
}
void ICData::ClearCountAt(intptr_t index,
@@ -15869,50 +15914,27 @@
const CallSiteResetter& proof_of_reload) const {
USE(proof_of_reload); // This method can only be called during reload.
- if (IsImmutable()) {
- return;
- }
- const intptr_t len = Length();
- if (len == 0) {
- return;
- }
- Thread* thread = Thread::Current();
-
// The final entry is always the sentinel.
- ASSERT(IsSentinelAt(len - 1));
- const intptr_t num_args_tested = NumArgsTested();
- if (num_args_tested == 0) {
- // No type feedback is being collected.
- REUSABLE_ARRAY_HANDLESCOPE(thread);
- Array& data = thread->ArrayHandle();
- data = entries();
- // Static calls with no argument checks hold only one target and the
- // sentinel value.
- ASSERT(len == 2);
- // Static calls with no argument checks only need two words.
- ASSERT(TestEntryLength() == 2);
- // Set the target.
- data.SetAt(TargetIndexFor(num_args_tested), func);
- // Set count to 0 as this is called during compilation, before the
- // call has been executed.
- data.SetAt(CountIndexFor(num_args_tested), Object::smi_zero());
- } else {
- // Type feedback on arguments is being collected.
- // Fill all but the first entry with the sentinel.
- for (intptr_t i = len - 1; i > 0; i--) {
- WriteSentinelAt(i, proof_of_reload);
- }
- REUSABLE_ARRAY_HANDLESCOPE(thread);
- Array& data = thread->ArrayHandle();
- data = entries();
- // Rewrite the dummy entry.
- const Smi& object_cid = Smi::Handle(Smi::New(kObjectCid));
- for (intptr_t i = 0; i < NumArgsTested(); i++) {
- data.SetAt(i, object_cid);
- }
- data.SetAt(TargetIndexFor(num_args_tested), func);
- data.SetAt(CountIndexFor(num_args_tested), Object::smi_zero());
+ DEBUG_ONLY(AssertInvariantsAreSatisfied());
+
+ if (IsImmutable()) return;
+ if (NumberOfChecks() == 0) return;
+
+ // Leave one entry.
+ TruncateTo(/*num_checks=*/1, proof_of_reload);
+
+ // Reinitialize the one and only entry.
+ const intptr_t num_args = NumArgsTested();
+ Thread* thread = Thread::Current();
+ REUSABLE_ARRAY_HANDLESCOPE(thread);
+ Array& data = thread->ArrayHandle();
+ data = entries();
+ const Smi& object_cid = Smi::Handle(Smi::New(kObjectCid));
+ for (intptr_t i = 0; i < num_args; i++) {
+ data.SetAt(i, object_cid);
}
+ data.SetAt(TargetIndexFor(num_args), func);
+ data.SetAt(CountIndexFor(num_args), Object::smi_zero());
}
bool ICData::ValidateInterceptor(const Function& target) const {
@@ -16004,13 +16026,10 @@
}
ArrayPtr ICData::Grow(intptr_t* index) const {
+ DEBUG_ONLY(AssertInvariantsAreSatisfied());
+
+ *index = NumberOfChecks();
Array& data = Array::Handle(entries());
- // Last entry in array should be a sentinel and will be the new entry
- // that can be updated after growing.
- *index = Length() - 1;
- ASSERT(*index >= 0);
- ASSERT(IsSentinelAt(*index));
- // Grow the array and write the new final sentinel into place.
const intptr_t new_len = data.Length() + TestEntryLength();
data = Array::Grow(data, new_len, Heap::kOld);
WriteSentinel(data, TestEntryLength(), *this);
@@ -16133,29 +16152,11 @@
(*target) ^= data.At(data_pos + TargetIndexFor(NumArgsTested()));
}
-bool ICData::IsSentinelAt(intptr_t index) const {
- ASSERT(index < Length());
- Thread* thread = Thread::Current();
- REUSABLE_ARRAY_HANDLESCOPE(thread);
- Array& data = thread->ArrayHandle();
- data = entries();
- const intptr_t entry_length = TestEntryLength();
- intptr_t data_pos = index * TestEntryLength();
- const intptr_t kBackRefLen = (index == (Length() - 1)) ? 1 : 0;
- for (intptr_t i = 0; i < entry_length - kBackRefLen; i++) {
- if (data.At(data_pos++) != smi_illegal_cid().ptr()) {
- return false;
- }
- }
- // The entry at |index| was filled with the value kIllegalCid.
- return true;
-}
-
void ICData::GetClassIdsAt(intptr_t index,
GrowableArray<intptr_t>* class_ids) const {
ASSERT(index < Length());
ASSERT(class_ids != NULL);
- ASSERT(!IsSentinelAt(index));
+ ASSERT(IsValidEntryIndex(index));
class_ids->Clear();
Thread* thread = Thread::Current();
REUSABLE_ARRAY_HANDLESCOPE(thread);
@@ -16200,7 +16201,7 @@
intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const {
ASSERT(index < Length());
- ASSERT(!IsSentinelAt(index));
+ ASSERT(IsValidEntryIndex(index));
const intptr_t data_pos = index * TestEntryLength();
NoSafepointScope no_safepoint;
ArrayPtr raw_data = entries();
@@ -16469,6 +16470,13 @@
}
}
+bool ICData::IsCachedEmptyEntry(const Array& array) {
+ for (int i = 0; i < kCachedICDataArrayCount; ++i) {
+ if (cached_icdata_arrays_[i] == array.ptr()) return true;
+ }
+ return false;
+}
+
// Does not initialize ICData array.
ICDataPtr ICData::NewDescriptor(Zone* zone,
const Function& owner,
@@ -16643,14 +16651,21 @@
AbstractType::Handle(zone, from.receivers_static_type())));
// Clone entry array.
const Array& from_array = Array::Handle(zone, from.entries());
- const intptr_t len = from_array.Length();
- const Array& cloned_array = Array::Handle(zone, Array::New(len, Heap::kOld));
- Object& obj = Object::Handle(zone);
- for (intptr_t i = 0; i < len; i++) {
- obj = from_array.At(i);
- cloned_array.SetAt(i, obj);
+ if (ICData::IsCachedEmptyEntry(from_array)) {
+ result.set_entries(from_array);
+ } else {
+ const intptr_t len = from_array.Length();
+ const Array& cloned_array =
+ Array::Handle(zone, Array::New(len, Heap::kOld));
+ Object& obj = Object::Handle(zone);
+ for (intptr_t i = 0; i < len; i++) {
+ obj = from_array.At(i);
+ cloned_array.SetAt(i, obj);
+ }
+ // Update backref in our clone.
+ cloned_array.SetAt(cloned_array.Length() - 1, result);
+ result.set_entries(cloned_array);
}
- result.set_entries(cloned_array);
// Copy deoptimization reasons.
result.SetDeoptReasons(from.DeoptReasons());
result.set_is_megamorphic(is_megamorphic);
@@ -16658,6 +16673,8 @@
RELEASE_ASSERT(!is_megamorphic ||
result.NumberOfChecks() >= FLAG_max_polymorphic_checks);
+ DEBUG_ONLY(result.AssertInvariantsAreSatisfied());
+
return result.ptr();
}
#endif
@@ -16665,20 +16682,12 @@
ICDataPtr ICData::ICDataOfEntriesArray(const Array& array) {
const auto& back_ref = Object::Handle(array.At(array.Length() - 1));
if (back_ref.ptr() == smi_illegal_cid().ptr()) {
- // The ICData must be empty.
-#if defined(DEBUG)
- const int kMaxTestEntryLen = TestEntryLengthFor(2, true);
- ASSERT(array.Length() <= kMaxTestEntryLen);
- for (intptr_t i = 0; i < array.Length(); ++i) {
- ASSERT(array.At(i) == Object::sentinel().ptr());
- }
-#endif
+ ASSERT(IsCachedEmptyEntry(array));
return ICData::null();
}
+
const auto& ic_data = ICData::Cast(back_ref);
-#if defined(DEBUG)
- ic_data.IsSentinelAt(ic_data.Length() - 1);
-#endif
+ DEBUG_ONLY(ic_data.AssertInvariantsAreSatisfied());
return ic_data.ptr();
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index cb2be7d..4d16d9c 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2131,6 +2131,30 @@
// or the original ICData object. In case of background compilation we
// copy the ICData in a child object, thus freezing it during background
// compilation. Code may contain only original ICData objects.
+//
+// ICData's backing store is an array that logically contains several valid
+// entries followed by a sentinal entry.
+//
+// [<entry-0>, <...>, <entry-N>, <sentinel>]
+//
+// Each entry has the following form:
+//
+// [arg0?, arg1?, argN?, count, target-function/code, exactness?]
+//
+// The <entry-X> need to contain valid type feedback.
+// The <sentinel> entry and must have kIllegalCid value for all
+// members of the entry except for the last one (`exactness` if
+// present, otherwise `target-function/code`) - which we use as a backref:
+//
+// * For empty ICData we use a cached/shared backing store. So there is no
+// unique backref, we use kIllegalCid instead.
+// * For non-empty ICData the backref in the backing store array will point to
+// the ICData object.
+//
+// Updating the ICData happens under a lock to avoid phantom-reads. The backing
+// is treated as an immutable Copy-on-Write data structure: Adding to the ICData
+// makes a copy with length+1 which will be store-release'd so any reader can
+// see it (and doesn't need to hold a lock).
class ICData : public CallSiteData {
public:
FunctionPtr Owner() const;
@@ -2239,16 +2263,18 @@
// the final one.
intptr_t Length() const;
- // Takes O(result) time!
intptr_t NumberOfChecks() const;
// Discounts any checks with usage of zero.
// Takes O(result)) time!
intptr_t NumberOfUsedChecks() const;
- // Takes O(n) time!
bool NumberOfChecksIs(intptr_t n) const;
+ bool IsValidEntryIndex(intptr_t index) const {
+ return 0 <= index && index < NumberOfChecks();
+ }
+
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(UntaggedICData));
}
@@ -2275,10 +2301,14 @@
}
#endif
- // Replaces entry |index| with the sentinel.
// NOTE: Can only be called during reload.
- void WriteSentinelAt(intptr_t index,
- const CallSiteResetter& proof_of_reload) const;
+ void Clear(const CallSiteResetter& proof_of_reload) const {
+ TruncateTo(0, proof_of_reload);
+ }
+
+ // NOTE: Can only be called during reload.
+ void TruncateTo(intptr_t num_checks,
+ const CallSiteResetter& proof_of_reload) const;
// Clears the count for entry |index|.
// NOTE: Can only be called during reload.
@@ -2483,9 +2513,9 @@
}
// Does entry |index| contain the sentinel value?
- bool IsSentinelAt(intptr_t index) const;
void SetNumArgsTested(intptr_t value) const;
void SetReceiversStaticType(const AbstractType& type) const;
+ DEBUG_ONLY(void AssertInvariantsAreSatisfied() const;)
static void SetTargetAtPos(const Array& data,
intptr_t data_pos,
@@ -2567,6 +2597,7 @@
bool tracking_exactness);
static ArrayPtr CachedEmptyICDataArray(intptr_t num_args_tested,
bool tracking_exactness);
+ static bool IsCachedEmptyEntry(const Array& array);
static ICDataPtr NewDescriptor(Zone* zone,
const Function& owner,
const String& target_name,
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 87874b8..f591661 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -858,7 +858,6 @@
ICData::RebindRule rule = ic.rebind_rule();
if (rule == ICData::kInstance) {
const intptr_t num_args = ic.NumArgsTested();
- const bool tracking_exactness = ic.is_tracking_exactness();
const intptr_t len = ic.Length();
// We need at least one non-sentinel entry to require a check
// for the smi fast path case.
@@ -878,15 +877,12 @@
// The smi fast path case, preserve the initial entry but reset the
// count.
ic.ClearCountAt(0, *this);
- ic.WriteSentinelAt(1, *this);
- entries_ = ic.entries();
- entries_.Truncate(2 * ic.TestEntryLength());
+ ic.TruncateTo(/*num_checks=*/1, *this);
return;
}
// Fall back to the normal behavior with cached empty ICData arrays.
}
- entries_ = ICData::CachedEmptyICDataArray(num_args, tracking_exactness);
- ic.set_entries(entries_);
+ ic.Clear(*this);
ic.set_is_megamorphic(false);
return;
} else if (rule == ICData::kNoRebind || rule == ICData::kNSMDispatch) {
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index eed635d..05f9ee4 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -106,6 +106,12 @@
}
int64_t OS::GetCurrentThreadCPUMicros() {
+ if (__builtin_available(macOS 10.12, iOS 10.0, *)) {
+ // This is more efficient when available.
+ return clock_gettime_nsec_np(CLOCK_THREAD_CPUTIME_ID) /
+ kNanosecondsPerMicrosecond;
+ }
+
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
thread_basic_info_data_t info_data;
thread_basic_info_t info = &info_data;
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 4c7cbcf..eee21f8 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -71,7 +71,7 @@
future_listener_class(Class::Handle(zone)),
async_start_stream_controller_class(Class::Handle(zone)),
stream_controller_class(Class::Handle(zone)),
- async_stream_controller_class(Class::Handle(zone)),
+ sync_stream_controller_class(Class::Handle(zone)),
controller_subscription_class(Class::Handle(zone)),
buffering_stream_subscription_class(Class::Handle(zone)),
stream_iterator_class(Class::Handle(zone)),
@@ -100,9 +100,9 @@
stream_controller_class =
async_lib.LookupClassAllowPrivate(Symbols::_StreamController());
ASSERT(!stream_controller_class.IsNull());
- async_stream_controller_class =
- async_lib.LookupClassAllowPrivate(Symbols::_AsyncStreamController());
- ASSERT(!async_stream_controller_class.IsNull());
+ sync_stream_controller_class =
+ async_lib.LookupClassAllowPrivate(Symbols::_SyncStreamController());
+ ASSERT(!sync_stream_controller_class.IsNull());
controller_subscription_class =
async_lib.LookupClassAllowPrivate(Symbols::_ControllerSubscription());
ASSERT(!controller_subscription_class.IsNull());
@@ -171,7 +171,7 @@
const Instance& controller = Instance::Cast(context_entry_);
controller_ = controller.GetField(controller_controller_field);
ASSERT(!controller_.IsNull());
- ASSERT(controller_.GetClassId() == async_stream_controller_class.id());
+ ASSERT(controller_.GetClassId() == sync_stream_controller_class.id());
// Get the _StreamController._state field.
state_ = Instance::Cast(controller_).GetField(state_field);
@@ -209,7 +209,7 @@
// contains the iterator's value. In that case we cannot unwind anymore.
//
// Notice: With correct async* semantics this may never be true: The async*
- // generator should only be invoked to produce a vaue if there's an
+ // generator should only be invoked to produce a value if there's an
// in-progress `await streamIterator.moveNext()` call. Once such call has
// finished the async* generator should be paused/yielded until the next
// such call - and being paused/yielded means it should not appear in stack
diff --git a/runtime/vm/stack_trace.h b/runtime/vm/stack_trace.h
index 0683cf7..58a4cba 100644
--- a/runtime/vm/stack_trace.h
+++ b/runtime/vm/stack_trace.h
@@ -78,7 +78,7 @@
Class& future_listener_class;
Class& async_start_stream_controller_class;
Class& stream_controller_class;
- Class& async_stream_controller_class;
+ Class& sync_stream_controller_class;
Class& controller_subscription_class;
Class& buffering_stream_subscription_class;
Class& stream_iterator_class;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 52ec048..f96d8d3 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -278,7 +278,6 @@
V(Values, "values") \
V(WeakSerializationReference, "WeakSerializationReference") \
V(_AsyncStarStreamController, "_AsyncStarStreamController") \
- V(_AsyncStreamController, "_AsyncStreamController") \
V(_BufferingStreamSubscription, "_BufferingStreamSubscription") \
V(_ByteBuffer, "_ByteBuffer") \
V(_ByteBufferDot_New, "_ByteBuffer._New") \
@@ -381,6 +380,7 @@
V(_StreamIterator, "_StreamIterator") \
V(_String, "String") \
V(_SyncIterator, "_SyncIterator") \
+ V(_SyncStreamController, "_SyncStreamController") \
V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl") \
V(_Type, "_Type") \
V(_FunctionType, "_FunctionType") \
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 9452ed3..3c7ccc7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -171,7 +171,7 @@
/// This function should be used to ensure that a function is a native JS
/// function before it is passed to native JS code.
@NoReifyGeneric()
-F assertInterop<F extends Function>(F f) {
+F assertInterop<F extends Function?>(F f) {
assert(
_isJsObject(f) ||
!JS<bool>('bool', '# instanceof #.Function', f, global_),
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 7c43ba8..cd6018f 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2451,10 +2451,6 @@
return JS('var', r'#[#]', jsObject, property);
}
-/// Called at the end of unaborted switch cases to get the singleton
-/// FallThroughError exception that will be thrown.
-getFallThroughError() => new FallThroughErrorImplementation();
-
/// A metadata annotation describing the types instantiated by a native element.
///
/// The annotation is valid on a native method and a field of a native class.
@@ -2587,14 +2583,6 @@
if (assertTest(condition)) throw AssertionError();
}
-/// Called by generated code when a method that must be statically
-/// resolved cannot be found.
-void throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) {
- Symbol memberName = new _symbol_dev.Symbol.unvalidated(name);
- throw new NoSuchMethodError(
- obj, memberName, arguments, new Map<Symbol, dynamic>());
-}
-
/// Called by generated code when a static field's initializer references the
/// field that is currently being initialized.
void throwCyclicInit(String staticName) {
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 2e322f1..9fddad2 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -117,6 +117,13 @@
bool isSuspendedAtYield = false;
_Future? cancellationFuture = null;
+ /// Argument passed to the generator when it is resumed after an addStream.
+ ///
+ /// `true` if the generator should exit after `yield*` resumes.
+ /// `false` if the generator should continue after `yield*` resumes.
+ /// `null` otherwies.
+ bool? continuationArgument = null;
+
Stream<T> get stream {
final Stream<T> local = controller.stream;
if (local is _StreamImpl<T>) {
@@ -128,7 +135,8 @@
void runBody() {
isScheduled = false;
isSuspendedAtYield = false;
- asyncStarBody(null, null);
+ asyncStarBody(continuationArgument, null);
+ continuationArgument = null;
}
void scheduleGenerator() {
@@ -152,11 +160,11 @@
bool add(T event) {
if (!onListenReceived) _fatal("yield before stream is listened to");
if (isSuspendedAtYield) _fatal("unexpected yield");
- // If stream is cancelled, tell caller to exit the async generator.
+ controller.add(event);
if (!controller.hasListener) {
return true;
}
- controller.add(event);
+
scheduleGenerator();
isSuspendedAtYield = true;
return false;
@@ -165,22 +173,41 @@
// Adds the elements of stream into this controller's stream.
// The generator will be scheduled again when all of the
// elements of the added stream have been consumed.
- // Returns true if the caller should terminate
- // execution of the generator.
- bool addStream(Stream<T> stream) {
+ void addStream(Stream<T> stream) {
if (!onListenReceived) _fatal("yield before stream is listened to");
- // If stream is cancelled, tell caller to exit the async generator.
- if (!controller.hasListener) return true;
+
+ if (exitAfterYieldStarIfCancelled()) return;
+
isAdding = true;
- var whenDoneAdding = controller.addStream(stream, cancelOnError: false);
+ final whenDoneAdding = controller.addStream(stream, cancelOnError: false);
whenDoneAdding.then((_) {
isAdding = false;
- scheduleGenerator();
- if (!isScheduled) isSuspendedAtYield = true;
+ if (exitAfterYieldStarIfCancelled()) return;
+ resumeNormallyAfterYieldStar();
});
+ }
+
+ /// Schedules the generator to exit after `yield*` if stream was cancelled.
+ ///
+ /// Returns `true` if generator is told to exit and `false` otherwise.
+ bool exitAfterYieldStarIfCancelled() {
+ // If consumer cancelled subscription we should tell async* generator to
+ // finish (i.e. run finally clauses and return).
+ if (!controller.hasListener) {
+ continuationArgument = true;
+ scheduleGenerator();
+ return true;
+ }
return false;
}
+ /// Schedules the generator to resume normally after `yield*`.
+ void resumeNormallyAfterYieldStar() {
+ continuationArgument = false;
+ scheduleGenerator();
+ if (!isScheduled) isSuspendedAtYield = true;
+ }
+
void addError(Object error, StackTrace stackTrace) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
@@ -211,7 +238,7 @@
}
_AsyncStarStreamController(this.asyncStarBody)
- : controller = new StreamController() {
+ : controller = new StreamController(sync: true) {
controller.onListen = this.onListen;
controller.onResume = this.onResume;
controller.onCancel = this.onCancel;
diff --git a/sdk/lib/vmservice/asset.dart b/sdk/lib/vmservice/asset.dart
index 7e086ff..0b6a249 100644
--- a/sdk/lib/vmservice/asset.dart
+++ b/sdk/lib/vmservice/asset.dart
@@ -55,7 +55,7 @@
}
@pragma("vm:external-name", "VMService_DecodeAssets")
-external List<Object> _decodeAssets(Uint8List data);
+external List<dynamic> _decodeAssets(Uint8List data);
Map<String, Asset>? _assets;
Map<String, Asset>? get assets {
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 75ebe8c..ea38443 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -42,6 +42,7 @@
LanguageFeatures/Abstract-external-fields/static_analysis_external_A05_t03: SkipByDesign # Non-JS-interop external members are not supported
LanguageFeatures/Abstract-external-fields/syntax_A01_t03: SkipByDesign # Non-JS-interop external members are not supported
LanguageFeatures/Abstract-external-fields/syntax_A02_t03: SkipByDesign # Non-JS-interop external members are not supported
+LanguageFeatures/Enhanced-Enum/grammar_A07_t01: SkipByDesign # Non-JS-interop external members are not supported
LanguageFeatures/FinalizationRegistry/ffi/*: SkipByDesign # dart:ffi is not supported
LibTest/core/DateTime/DateTime.fromMicrosecondsSinceEpoch_A01_t01: SkipByDesign # microseconds are not supported in JavaScript
LibTest/core/DateTime/microsecond_A01_t01: SkipByDesign # microseconds are not supported in JavaScript
diff --git a/tests/co19/co19-dartdevc.status b/tests/co19/co19-dartdevc.status
index 94d2a50..8103c34 100644
--- a/tests/co19/co19-dartdevc.status
+++ b/tests/co19/co19-dartdevc.status
@@ -39,6 +39,7 @@
LanguageFeatures/Abstract-external-fields/static_analysis_external_A05_t03: SkipByDesign # External variables are not supported
LanguageFeatures/Abstract-external-fields/syntax_A01_t03: SkipByDesign # External variables are not supported
LanguageFeatures/Abstract-external-fields/syntax_A02_t03: SkipByDesign # External variables are not supported
+LanguageFeatures/Enhanced-Enum/grammar_A07_t01: SkipByDesign # Non-JS-interop external members are not supported
LanguageFeatures/FinalizationRegistry/ffi/*: SkipByDesign # dart:ffi is not supported
LibTest/core/DateTime/DateTime.fromMicrosecondsSinceEpoch_A01_t01: SkipByDesign # microseconds are not supported in JavaScript
LibTest/core/DateTime/microsecond_A01_t01: SkipByDesign # microseconds are not supported in JavaScript
diff --git a/tests/language/async_star/pause2_test.dart b/tests/language/async_star/pause2_test.dart
index a240d3d..3df0223 100644
--- a/tests/language/async_star/pause2_test.dart
+++ b/tests/language/async_star/pause2_test.dart
@@ -72,8 +72,8 @@
f() async* {
int i = 0;
while (true) {
- yield i;
list.add(i);
+ yield i;
i++;
}
}
diff --git a/tests/language/async_star/throw_in_catch_test.dart b/tests/language/async_star/throw_in_catch_test.dart
index 88982e5..7509a00 100644
--- a/tests/language/async_star/throw_in_catch_test.dart
+++ b/tests/language/async_star/throw_in_catch_test.dart
@@ -115,7 +115,7 @@
test() async {
// TODO(sigurdm): These tests are too dependent on scheduling, and buffering
// behavior.
- await runTest(foo1, "abcYdgC", null, true);
+ await runTest(foo1, "abcYgC", null, true);
await runTest(foo2, "abcX", "Error", false);
await runTest(foo3, "abcYX", "Error", false);
await runTest(foo4, "abcYdYefX", "Error2", false);
diff --git a/tests/language_2/async_star/pause2_test.dart b/tests/language_2/async_star/pause2_test.dart
index 11e0429..f6e8d5f 100644
--- a/tests/language_2/async_star/pause2_test.dart
+++ b/tests/language_2/async_star/pause2_test.dart
@@ -74,8 +74,8 @@
f() async* {
int i = 0;
while (true) {
- yield i;
list.add(i);
+ yield i;
i++;
}
}
diff --git a/tests/language_2/async_star/throw_in_catch_test.dart b/tests/language_2/async_star/throw_in_catch_test.dart
index 57b6b0e..6a26245 100644
--- a/tests/language_2/async_star/throw_in_catch_test.dart
+++ b/tests/language_2/async_star/throw_in_catch_test.dart
@@ -118,7 +118,7 @@
test() async {
// TODO(sigurdm): These tests are too dependent on scheduling, and buffering
// behavior.
- await runTest(foo1, "abcYdgC", null, true);
+ await runTest(foo1, "abcYgC", null, true);
await runTest(foo2, "abcX", "Error", false);
await runTest(foo3, "abcYX", "Error", false);
await runTest(foo4, "abcYdYefX", "Error2", false);
diff --git a/tools/VERSION b/tools/VERSION
index 46decc5..eaf4277 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 274
+PRERELEASE 275
PRERELEASE_PATCH 0
\ No newline at end of file