Version 2.18.0-94.0.dev

Merge commit '2d1dc8523aabb11960d596968819b519aa9d326d' into 'dev'
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
new file mode 100644
index 0000000..b61b6ad
--- /dev/null
+++ b/.github/workflows/scorecards-analysis.yml
@@ -0,0 +1,54 @@
+name: Scorecards supply-chain security
+on:
+  # Only the default branch is supported.
+  branch_protection_rule:
+  schedule:
+    # “At 00:00 (UTC) daily.”
+    - cron: '0 0 * * *'
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+  analysis:
+    name: Scorecards analysis
+    runs-on: ubuntu-latest
+    permissions:
+      # Needed to upload the results to code-scanning dashboard.
+      security-events: write
+      actions: read
+      contents: read
+
+    steps:
+      - name: "Checkout code"
+        uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
+        with:
+          persist-credentials: false
+
+      - name: "Run analysis"
+        uses: ossf/scorecard-action@c1aec4ac820532bab364f02a81873c555a0ba3a1 # v1.0.4
+        with:
+          results_file: results.sarif
+          results_format: sarif
+          # Read-only PAT token. To create it,
+          # follow the steps in https://github.com/ossf/scorecard-action#pat-token-creation.
+          repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
+          # Publish the results to enable scorecard badges. For more details, see
+          # https://github.com/ossf/scorecard-action#publishing-results.
+          # For private repositories, `publish_results` will automatically be set to `false`,
+          # regardless of the value entered here.
+          publish_results: true
+
+      # Upload the results as artifacts (optional).
+      - name: "Upload artifact"
+        uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
+        with:
+          name: SARIF file
+          path: results.sarif
+          retention-days: 5
+
+      # Upload the results to GitHub's code scanning dashboard.
+      - name: "Upload to code-scanning"
+        uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
+        with:
+          sarif_file: results.sarif
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f90627..ce00d95 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -274,9 +274,23 @@
 
 #### Linter
 
-Updated the Linter to `1.22.0`, which includes changes that
+Updated the Linter to `1.23.0`, which includes changes that
 
-- fixes null-safe variance exceptions in `invariant_booleans`
+- fixes `no_leading_underscores_for_local_identifiers`
+  to lint local function declarations.
+- fixes `avoid_init_to_null` to correctly handle super
+  initializing defaults that are non-null.
+- updates `no_leading_underscores_for_local_identifiers`
+  to allow identifiers with just underscores.
+- fixes `flutter_style_todos` to support usernames that
+  start with a digit.
+- updates `require_trailing_commas` to handle functions
+  in asserts and multi-line strings.
+- updates `unsafe_html` to allow assignments to 
+  `img.src`.
+- fixes `unnecessary_null_checks` to properly handle map
+  literal entries.
+- fixes null-safe variance exceptions in `invariant_booleans`.
 - updates `depend_on_referenced_packages` to treat `flutter_gen` as a virtual
   package, not needing an explicit dependency.
 - updates `unnecessary_null_checks` and
diff --git a/DEPS b/DEPS
index e12bacc..2b71b25 100644
--- a/DEPS
+++ b/DEPS
@@ -122,7 +122,7 @@
   "intl_rev": "9669926609e7efc17dfd74fbb44ec719a7e573cc",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
-  "linter_rev": "14c916a16e78315e212cf79e7ccf4c19159a1bda",
+  "linter_rev": "4305b933c8ed0275f26a99bd1ade39fe9130e6a5", # 1.23.0
   "lints_rev": "8294e5648ab49474541527e2911e72e4c5aefe55",
   "logging_rev": "dfbe88b890c3b4f7bc06da5a7b3b43e9e263b688",
   "markdown_rev": "7479783f0493f6717e1d7ae31cb37d39a91026b2",
@@ -170,8 +170,8 @@
   "webdev_rev": "8c814f9d89915418d8abe354ff9befec8f2906b2",
   "webdriver_rev": "ff5ccb1522edf4bed578ead4d65e0cbc1f2c4f02",
   "webkit_inspection_protocol_rev": "dd6fb5d8b536e19cedb384d0bbf1f5631923f1e8",
-  "yaml_edit_rev": "4fadb43801b07f90b3f0c6065dbce4efc6d8d55e",
-  "yaml_rev": "ad0779d1baa25c6b10a192d080efc45de02b6a32",
+  "yaml_edit_rev": "0b74d85fac10b4fbf7d1a347debcf16c8f7b0e9c",
+  "yaml_rev": "0971c06490b9670add644ed62182acd6a5536946",
   "zlib_rev": "faff052b6b6edcd6dd548513fe44ac0941427bf0",
 
   # Windows deps
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_trailing_comma.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_trailing_comma.dart
index a7948d5..2e22191 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_trailing_comma.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_trailing_comma.dart
@@ -30,6 +30,10 @@
       await _insertComma(builder, node.parameters.last);
     } else if (node is Assertion) {
       await _insertComma(builder, node.message ?? node.condition);
+    } else if (node is ListLiteral) {
+      await _insertComma(builder, node.elements.last);
+    } else if (node is SetOrMapLiteral) {
+      await _insertComma(builder, node.elements.last);
     }
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
index 474e1d8..cd498c1 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
@@ -102,6 +102,50 @@
 ''');
   }
 
+  @failingTest
+  Future<void> test_list_literal() async {
+    await resolveTestCode('''
+void f() {
+  var l = [
+    'a',
+    'b'
+  ];
+  print(l);
+}
+''');
+    await assertHasFix('''
+void f() {
+  var l = [
+    'a',
+    'b',
+  ];
+  print(l);
+}
+''');
+  }
+
+  @failingTest
+  Future<void> test_map_literal() async {
+    await resolveTestCode('''
+void f() {
+  var l = {
+    'a': 1,
+    'b': 2
+  };
+  print(l);
+}
+''');
+    await assertHasFix('''
+void f() {
+  var l = {
+    'a': 1,
+    'b': 2,
+  };
+  print(l);
+}
+''');
+  }
+
   Future<void> test_named() async {
     await resolveTestCode('''
 void f({a, b}) {
@@ -142,4 +186,26 @@
 }
 ''');
   }
+
+  @failingTest
+  Future<void> test_set_literal() async {
+    await resolveTestCode('''
+void f() {
+  var l = {
+    'a',
+    'b'
+  };
+  print(l);
+}
+''');
+    await assertHasFix('''
+void f() {
+  var l = {
+    'a',
+    'b',
+  };
+  print(l);
+}
+''');
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
index 42ac2f3..8ca3caf 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -10,11 +10,14 @@
 import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart' as macro;
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/summary2/library_builder.dart';
 import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/macro_application_error.dart';
 import 'package:analyzer/src/summary2/macro_declarations.dart';
 
@@ -25,9 +28,12 @@
 
   final List<_MacroTarget> _targets = [];
 
-  final macro.IdentifierResolver _identifierResolver = _IdentifierResolver();
+  late final macro.IdentifierResolver _identifierResolver =
+      _IdentifierResolver(_linker.elementFactory, declarationBuilder);
 
-  final macro.TypeResolver _typeResolver = _TypeResolver();
+  late final macro.TypeResolver _typeResolver = _TypeResolver(
+    typeSystem: libraryBuilder.element.typeSystem,
+  );
 
   late final macro.ClassIntrospector _classIntrospector =
       _ClassIntrospector(declarationBuilder);
@@ -451,9 +457,13 @@
   }
 
   @override
-  Future<List<macro.FieldDeclaration>> fieldsOf(macro.ClassDeclaration clazz) {
-    // TODO: implement fieldsOf
-    throw UnimplementedError();
+  Future<List<macro.FieldDeclaration>> fieldsOf(
+    covariant ClassDeclarationImpl clazz,
+  ) async {
+    return clazz.element.fields
+        .where((e) => !e.isSynthetic)
+        .map(declarationBuilder.fromElement.fieldElement)
+        .toList();
   }
 
   @override
@@ -493,10 +503,19 @@
 }
 
 class _IdentifierResolver extends macro.IdentifierResolver {
+  final LinkedElementFactory elementFactory;
+  final DeclarationBuilder declarationBuilder;
+
+  _IdentifierResolver(
+    this.elementFactory,
+    this.declarationBuilder,
+  );
+
   @override
-  Future<macro.Identifier> resolveIdentifier(Uri library, String name) {
-    // TODO: implement resolveIdentifier
-    throw UnimplementedError();
+  Future<macro.Identifier> resolveIdentifier(Uri library, String name) async {
+    final libraryElement = elementFactory.libraryOfUri2(library.toString());
+    final element = libraryElement.scope.lookup(name).getter!;
+    return declarationBuilder.fromElement.identifier(element);
   }
 }
 
@@ -571,12 +590,61 @@
   }
 }
 
-class _TypeResolver implements macro.TypeResolver {
+class _StaticTypeImpl extends macro.StaticType {
+  final TypeSystemImpl typeSystem;
+  final DartType type;
+
+  _StaticTypeImpl(this.typeSystem, this.type);
+
   @override
-  Future<macro.StaticType> resolve(macro.TypeAnnotationCode type) {
-    // TODO: implement resolve
+  Future<bool> isExactly(_StaticTypeImpl other) {
+    // TODO: implement isExactly
     throw UnimplementedError();
   }
+
+  @override
+  Future<bool> isSubtypeOf(_StaticTypeImpl other) {
+    // TODO(scheglov) write tests
+    return Future.value(
+      typeSystem.isSubtypeOf(type, other.type),
+    );
+  }
+}
+
+class _TypeResolver implements macro.TypeResolver {
+  final TypeSystemImpl typeSystem;
+
+  _TypeResolver({
+    required this.typeSystem,
+  });
+
+  @override
+  Future<macro.StaticType> resolve(macro.TypeAnnotationCode type) async {
+    var dartType = _resolve(type);
+    return _StaticTypeImpl(typeSystem, dartType);
+  }
+
+  DartType _resolve(macro.TypeAnnotationCode type) {
+    // TODO(scheglov) write tests
+    if (type is macro.NamedTypeAnnotationCode) {
+      final identifier = type.name as IdentifierImpl;
+      final element = identifier.element;
+      if (element is ClassElementImpl) {
+        return element.instantiate(
+          typeArguments: type.typeArguments.map(_resolve).toList(),
+          nullabilitySuffix: type.isNullable
+              ? NullabilitySuffix.question
+              : NullabilitySuffix.none,
+        );
+      } else {
+        // TODO(scheglov) Implement other elements.
+        throw UnimplementedError('(${element.runtimeType}) $element');
+      }
+    } else {
+      // TODO(scheglov) Implement other types.
+      throw UnimplementedError('(${type.runtimeType}) $type');
+    }
+  }
 }
 
 extension on macro.MacroExecutionResult {
diff --git a/pkg/analyzer/lib/src/summary2/macro_declarations.dart b/pkg/analyzer/lib/src/summary2/macro_declarations.dart
index 21707bc..f855d8b 100644
--- a/pkg/analyzer/lib/src/summary2/macro_declarations.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_declarations.dart
@@ -45,6 +45,15 @@
   /// corresponding elements. So, we can access them uniformly via interfaces,
   /// mixins, etc.
   void transferToElements() {
+    for (final entry in fromNode._identifierMap.entries) {
+      final element = entry.key.staticElement;
+      if (element != null) {
+        final declaration = entry.value;
+        declaration.element = element;
+        fromElement._identifierMap[element] = declaration;
+      }
+    }
+
     for (final entry in fromNode._classMap.entries) {
       final element = entry.key.declaredElement as ClassElement;
       final declaration = entry.value;
@@ -55,7 +64,12 @@
 }
 
 class DeclarationBuilderFromElement {
+  final Map<Element, IdentifierImpl> _identifierMap = Map.identity();
+
   final Map<ClassElement, ClassDeclarationImpl> _classMap = Map.identity();
+
+  final Map<FieldElement, FieldDeclarationImpl> _fieldMap = Map.identity();
+
   final Map<TypeParameterElement, macro.TypeParameterDeclarationImpl>
       _typeParameterMap = Map.identity();
 
@@ -63,6 +77,17 @@
     return _classMap[element] ??= _classElement(element);
   }
 
+  macro.FieldDeclarationImpl fieldElement(FieldElement element) {
+    return _fieldMap[element] ??= _fieldElement(element);
+  }
+
+  macro.IdentifierImpl identifier(Element element) {
+    return _identifierMap[element] ??= IdentifierImpl(
+      id: macro.RemoteInstance.uniqueId,
+      name: element.name!,
+    )..element = element;
+  }
+
   macro.TypeParameterDeclarationImpl typeParameter(
     TypeParameterElement element,
   ) {
@@ -73,7 +98,7 @@
     assert(!_classMap.containsKey(element));
     return ClassDeclarationImpl._(
       id: macro.RemoteInstance.uniqueId,
-      identifier: _identifier(element.name),
+      identifier: identifier(element),
       typeParameters: element.typeParameters.map(_typeParameter).toList(),
       interfaces: element.interfaces.map(_dartType).toList(),
       isAbstract: element.isAbstract,
@@ -88,14 +113,14 @@
       return macro.NamedTypeAnnotationImpl(
         id: macro.RemoteInstance.uniqueId,
         isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
-        identifier: _identifier(type.element.name),
+        identifier: identifier(type.element),
         typeArguments: type.typeArguments.map(_dartType).toList(),
       );
     } else if (type is TypeParameterType) {
       return macro.NamedTypeAnnotationImpl(
         id: macro.RemoteInstance.uniqueId,
         isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
-        identifier: _identifier(type.element.name),
+        identifier: identifier(type.element),
         typeArguments: const [],
       );
     } else {
@@ -104,10 +129,18 @@
     }
   }
 
-  macro.IdentifierImpl _identifier(String name) {
-    return _IdentifierImpl(
+  FieldDeclarationImpl _fieldElement(FieldElement element) {
+    assert(!_fieldMap.containsKey(element));
+    final enclosingClass = element.enclosingElement as ClassElement;
+    return FieldDeclarationImpl(
       id: macro.RemoteInstance.uniqueId,
-      name: name,
+      identifier: identifier(element),
+      isExternal: element.isExternal,
+      isFinal: element.isFinal,
+      isLate: element.isLate,
+      type: _dartType(element.type),
+      definingClass: identifier(enclosingClass),
+      isStatic: element.isStatic,
     );
   }
 
@@ -116,13 +149,16 @@
   ) {
     return macro.TypeParameterDeclarationImpl(
       id: macro.RemoteInstance.uniqueId,
-      identifier: _identifier(element.name),
+      identifier: identifier(element),
       bound: element.bound.mapOrNull(_dartType),
     );
   }
 }
 
 class DeclarationBuilderFromNode {
+  final Map<ast.SimpleIdentifier, IdentifierImpl> _identifierMap =
+      Map.identity();
+
   final Map<ast.ClassDeclaration, ClassDeclarationImpl> _classMap =
       Map.identity();
 
@@ -174,15 +210,15 @@
   }
 
   macro.IdentifierImpl _identifier(ast.Identifier node) {
-    final String name;
+    final ast.SimpleIdentifier simpleIdentifier;
     if (node is ast.SimpleIdentifier) {
-      name = node.name;
+      simpleIdentifier = node;
     } else {
-      name = (node as ast.PrefixedIdentifier).identifier.name;
+      simpleIdentifier = (node as ast.PrefixedIdentifier).identifier;
     }
-    return _IdentifierImpl(
+    return _identifierMap[simpleIdentifier] ??= IdentifierImpl(
       id: macro.RemoteInstance.uniqueId,
-      name: name,
+      name: simpleIdentifier.name,
     );
   }
 
@@ -249,8 +285,32 @@
   }
 }
 
-class _IdentifierImpl extends macro.IdentifierImpl {
-  _IdentifierImpl({required int id, required String name})
+class FieldDeclarationImpl extends macro.FieldDeclarationImpl {
+  FieldDeclarationImpl({
+    required int id,
+    required macro.IdentifierImpl identifier,
+    required bool isExternal,
+    required bool isFinal,
+    required bool isLate,
+    required macro.TypeAnnotationImpl type,
+    required macro.IdentifierImpl definingClass,
+    required bool isStatic,
+  }) : super(
+          id: id,
+          identifier: identifier,
+          isExternal: isExternal,
+          isFinal: isFinal,
+          isLate: isLate,
+          type: type,
+          definingClass: definingClass,
+          isStatic: isStatic,
+        );
+}
+
+class IdentifierImpl extends macro.IdentifierImpl {
+  late final Element? element;
+
+  IdentifierImpl({required int id, required String name})
       : super(id: id, name: name);
 }
 
diff --git a/pkg/analyzer/test/src/summary/macro/introspect_declarations_phase.dart b/pkg/analyzer/test/src/summary/macro/introspect_declarations_phase.dart
index d5889ae..2682d7c 100644
--- a/pkg/analyzer/test/src/summary/macro/introspect_declarations_phase.dart
+++ b/pkg/analyzer/test/src/summary/macro/introspect_declarations_phase.dart
@@ -10,9 +10,17 @@
 
 const introspectMacro = IntrospectDeclarationsPhaseMacro();
 
+const introspectMacroX = IntrospectDeclarationsPhaseMacro(
+  withDetailsFor: {'X'},
+);
+
 /*macro*/ class IntrospectDeclarationsPhaseMacro
     implements ClassDeclarationsMacro {
-  const IntrospectDeclarationsPhaseMacro();
+  final Set<Object?> withDetailsFor;
+
+  const IntrospectDeclarationsPhaseMacro({
+    this.withDetailsFor = const {},
+  });
 
   @override
   Future<void> buildDeclarationsForClass(
@@ -20,7 +28,9 @@
     ClassMemberDeclarationBuilder builder,
   ) async {
     final printer = _DeclarationPrinter(
+      withDetailsFor: withDetailsFor.cast(),
       classIntrospector: builder,
+      identifierResolver: builder,
       typeResolver: builder,
     );
     await printer.writeClassDeclaration(declaration);
@@ -36,13 +46,20 @@
 }
 
 class _DeclarationPrinter {
+  final Set<String> withDetailsFor;
   final ClassIntrospector classIntrospector;
+  final IdentifierResolver identifierResolver;
   final TypeResolver typeResolver;
+
   final StringBuffer _sink = StringBuffer();
   String _indent = '';
 
+  Identifier? _enclosingDeclarationIdentifier;
+
   _DeclarationPrinter({
+    required this.withDetailsFor,
     required this.classIntrospector,
+    required this.identifierResolver,
     required this.typeResolver,
   });
 
@@ -53,8 +70,12 @@
 
     _writeln('class ${e.identifier.name}');
 
+    if (!_shouldWriteDetailsFor(e)) {
+      return;
+    }
+
     await _withIndent(() async {
-      var superclass = await classIntrospector.superclassOf(e);
+      final superclass = await classIntrospector.superclassOf(e);
       if (superclass != null) {
         _writelnWithIndent('superclass');
         await _withIndent(() => writeClassDeclaration(superclass));
@@ -63,11 +84,29 @@
       await _writeTypeParameters(e.typeParameters);
       await _writeTypeAnnotations('mixins', e.mixins);
       await _writeTypeAnnotations('interfaces', e.interfaces);
+
+      _enclosingDeclarationIdentifier = e.identifier;
+      await _writeElements<FieldDeclaration>(
+        'fields',
+        await classIntrospector.fieldsOf(e),
+        _writeField,
+      );
     });
   }
 
+  void _assertEnclosingClass(ClassMemberDeclaration e) {
+    if (e.definingClass != _enclosingDeclarationIdentifier) {
+      throw StateError('Mismatch: definingClass');
+    }
+  }
+
+  bool _shouldWriteDetailsFor(Declaration declaration) {
+    return withDetailsFor.isEmpty ||
+        withDetailsFor.contains(declaration.identifier.name);
+  }
+
   Future<void> _withIndent(Future<void> Function() f) async {
-    var savedIndent = _indent;
+    final savedIndent = _indent;
     _indent = '$savedIndent  ';
     await f();
     _indent = savedIndent;
@@ -81,19 +120,41 @@
     if (elements.isNotEmpty) {
       _writelnWithIndent(name);
       await _withIndent(() async {
-        for (var element in elements) {
+        for (final element in elements) {
           await f(element);
         }
       });
     }
   }
 
+  Future<void> _writeField(FieldDeclaration e) async {
+    _assertEnclosingClass(e);
+
+    _writeIndentedLine(() {
+      _writeIf(e.isStatic, 'static ');
+      _writeIf(e.isExternal, 'external ');
+      _writeIf(e.isLate, 'late ');
+      _writeIf(e.isFinal, 'final ');
+      _writeName(e);
+    });
+
+    await _withIndent(() async {
+      _writeTypeAnnotation('type', e.type);
+    });
+  }
+
   void _writeIf(bool flag, String str) {
     if (flag) {
       _sink.write(str);
     }
   }
 
+  void _writeIndentedLine(void Function() f) {
+    _sink.write(_indent);
+    f();
+    _sink.writeln();
+  }
+
   void _writeln(String line) {
     _sink.writeln(line);
   }
@@ -103,6 +164,10 @@
     _sink.writeln(line);
   }
 
+  void _writeName(Declaration e) {
+    _sink.write(e.identifier.name);
+  }
+
   void _writeTypeAnnotation(String name, TypeAnnotation? type) {
     _sink.write(_indent);
     _sink.write('$name: ');
@@ -129,7 +194,7 @@
     _writelnWithIndent(e.identifier.name);
 
     await _withIndent(() async {
-      var bound = e.bound;
+      final bound = e.bound;
       if (bound != null) {
         _writeTypeAnnotation('bound', bound);
       }
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index 27d3339..5c0869f 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -1307,6 +1307,101 @@
 ''');
   }
 
+  test_introspect_declarations_FieldDeclaration_isExternal() async {
+    await _assertIntrospectDeclarationsText(r'''
+@introspectMacroX
+class X {
+  external int a;
+  int b = 0;
+}
+''', r'''
+class X
+  superclass
+    class Object
+  fields
+    external a
+      type: int
+    b
+      type: int
+''');
+  }
+
+  test_introspect_declarations_FieldDeclaration_isFinal() async {
+    await _assertIntrospectDeclarationsText(r'''
+@introspectMacroX
+class X {
+  final int a = 0;
+  int b = 0;
+}
+''', r'''
+class X
+  superclass
+    class Object
+  fields
+    final a
+      type: int
+    b
+      type: int
+''');
+  }
+
+  test_introspect_declarations_FieldDeclaration_isLate() async {
+    await _assertIntrospectDeclarationsText(r'''
+@introspectMacroX
+class X {
+  late final int a;
+  final int b = 0;
+}
+''', r'''
+class X
+  superclass
+    class Object
+  fields
+    late final a
+      type: int
+    final b
+      type: int
+''');
+  }
+
+  test_introspect_declarations_FieldDeclaration_isStatic() async {
+    await _assertIntrospectDeclarationsText(r'''
+@introspectMacroX
+class X {
+  static int a = 0;
+  int b = 0;
+}
+''', r'''
+class X
+  superclass
+    class Object
+  fields
+    static a
+      type: int
+    b
+      type: int
+''');
+  }
+
+  test_introspect_declarations_FieldDeclaration_type_explicit() async {
+    await _assertIntrospectDeclarationsText(r'''
+@introspectMacroX
+class X {
+  int a = 0;
+  List<String> b = [];
+}
+''', r'''
+class X
+  superclass
+    class Object
+  fields
+    a
+      type: int
+    b
+      type: List<String>
+''');
+  }
+
   test_introspect_types_ClassDeclaration_interfaces() async {
     await _assertTypesPhaseIntrospectionText(r'''
 class A implements B, C<int, String> {}
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index 27c63f4..8872c1a 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -5,6 +5,8 @@
 // @dart = 2.10
 
 import '../common.dart';
+import '../constants/common_elements_for_constants.dart'
+    as common_elements_for_constants;
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
 import '../elements/entities.dart';
@@ -17,7 +19,11 @@
 import 'names.dart' show Identifiers, Uris;
 
 /// The common elements and types in Dart.
-abstract class CommonElements implements CommonElementsForDartTypes {
+abstract class CommonElements
+    implements
+        CommonElementsForDartTypes,
+        common_elements_for_constants.CommonElements {
+  @override
   final DartTypes dartTypes;
   final ElementEnvironment _env;
   ClassEntity _objectClass;
@@ -329,6 +335,7 @@
       element.name == 'apply' && element.enclosingClass == functionClass;
 
   /// The `dynamic` type.
+  @override
   DynamicType get dynamicType => _env.dynamicType;
 
   /// The `Object` type defined in 'dart:core'.
@@ -336,6 +343,7 @@
   InterfaceType get objectType => _getRawType(objectClass);
 
   /// The `bool` type defined in 'dart:core'.
+  @override
   InterfaceType get boolType => _getRawType(boolClass);
 
   /// The `num` type defined in 'dart:core'.
@@ -350,6 +358,7 @@
   InterfaceType get doubleType => _getRawType(doubleClass);
 
   /// The `String` type defined in 'dart:core'.
+  @override
   InterfaceType get stringType => _getRawType(stringClass);
 
   /// The `Symbol` type defined in 'dart:core'.
diff --git a/pkg/compiler/lib/src/constants/common_elements_for_constants.dart b/pkg/compiler/lib/src/constants/common_elements_for_constants.dart
new file mode 100644
index 0000000..1d07407
--- /dev/null
+++ b/pkg/compiler/lib/src/constants/common_elements_for_constants.dart
@@ -0,0 +1,19 @@
+// 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 '../elements/types.dart';
+
+/// This is a facade interface for the members of CommonElements that are
+/// required by 'constants/value.dart'.
+// TODO(48820): When CommonElements is migrated, remove this facade.
+abstract class CommonElements {
+  DartType get boolType;
+  DartType get doubleType;
+  DartType get dynamicType;
+  DartType get intType;
+  DartType get nullType;
+  DartType get stringType;
+
+  DartTypes get dartTypes;
+}
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 8852f21..e6d286a 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -2,18 +2,19 @@
 // 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 dart2js.constants.values;
 
 import '../common.dart';
-import '../common/elements.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
-import '../deferred_load/output_unit.dart' show OutputUnit;
+import '../deferred_load/output_unit_migrated.dart' show OutputUnit;
 import '../js/js.dart' as js;
 import '../util/util.dart';
 
+import 'common_elements_for_constants.dart';
+// TODO(48820): When CommonElements is migrated, replace this import with
+//   import '../common/elements.dart' show CommonElements;
+
 enum ConstantValueKind {
   FUNCTION,
   NULL,
@@ -104,9 +105,9 @@
   bool get isNegativeInfinity => false;
 
   // TODO(johnniwinther): Replace with a 'type' getter.
-  DartType /*!*/ getType(CommonElements types);
+  DartType getType(CommonElements types);
 
-  List<ConstantValue /*!*/ > /*!*/ getDependencies();
+  List<ConstantValue> getDependencies();
 
   accept(ConstantValueVisitor visitor, arg);
 
@@ -118,10 +119,10 @@
   /// For the synthetic constants, [DeferredConstantValue],
   /// [DeferredGlobalConstantValue], [SyntheticConstantValue],
   /// [InterceptorConstantValue] the unparse is descriptive only.
-  String toDartText(DartTypes dartTypes);
+  String toDartText(DartTypes? dartTypes);
 
   /// Returns a structured representation of this constant suited for debugging.
-  String toStructuredText(DartTypes dartTypes);
+  String toStructuredText(DartTypes? dartTypes);
 
   ConstantValueKind get kind;
 
@@ -135,9 +136,9 @@
 }
 
 class FunctionConstantValue extends ConstantValue {
-  final FunctionEntity /*!*/ element;
+  final FunctionEntity element;
   // TODO(johnniwinther): Should the type be derived from [element].
-  final FunctionType /*!*/ type;
+  final FunctionType type;
 
   FunctionConstantValue(this.element, this.type);
 
@@ -166,16 +167,16 @@
   ConstantValueKind get kind => ConstantValueKind.FUNCTION;
 
   @override
-  String toDartText(DartTypes dartTypes) {
+  String toDartText(DartTypes? dartTypes) {
     if (element.enclosingClass != null) {
-      return '${element.enclosingClass.name}.${element.name}';
+      return '${element.enclosingClass!.name}.${element.name}';
     } else {
       return '${element.name}';
     }
   }
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     return 'FunctionConstant(${toDartText(dartTypes)})';
   }
 }
@@ -228,10 +229,10 @@
   ConstantValueKind get kind => ConstantValueKind.NULL;
 
   @override
-  String toStructuredText(DartTypes dartTypes) => 'NullConstant';
+  String toStructuredText(DartTypes? dartTypes) => 'NullConstant';
 
   @override
-  String toDartText(DartTypes dartTypes) => 'null';
+  String toDartText(DartTypes? dartTypes) => 'null';
 }
 
 abstract class NumConstantValue extends PrimitiveConstantValue {
@@ -244,7 +245,7 @@
 }
 
 class IntConstantValue extends NumConstantValue {
-  final BigInt /*!*/ intValue;
+  final BigInt intValue;
 
   // Caching IntConstantValues representing -2 through 10 so that we don't have
   // to create new ones every time those values are used.
@@ -253,7 +254,7 @@
   @override
   double get doubleValue => intValue.toDouble();
 
-  factory IntConstantValue(BigInt /*!*/ value) {
+  factory IntConstantValue(BigInt value) {
     var existing = _cachedValues[value];
     if (existing != null) return existing;
     var intConstantVal = IntConstantValue._internal(value);
@@ -302,11 +303,11 @@
   ConstantValueKind get kind => ConstantValueKind.INT;
 
   @override
-  String toStructuredText(DartTypes dartTypes) =>
+  String toStructuredText(DartTypes? dartTypes) =>
       'IntConstant(${toDartText(dartTypes)})';
 
   @override
-  String toDartText(DartTypes dartTypes) => intValue.toString();
+  String toDartText(DartTypes? dartTypes) => intValue.toString();
 }
 
 class DoubleConstantValue extends NumConstantValue {
@@ -380,11 +381,11 @@
   ConstantValueKind get kind => ConstantValueKind.DOUBLE;
 
   @override
-  String toStructuredText(DartTypes dartTypes) =>
+  String toStructuredText(DartTypes? dartTypes) =>
       'DoubleConstant(${toDartText(dartTypes)})';
 
   @override
-  String toDartText(DartTypes dartTypes) => doubleValue.toString();
+  String toDartText(DartTypes? dartTypes) => doubleValue.toString();
 }
 
 abstract class BoolConstantValue extends PrimitiveConstantValue {
@@ -411,7 +412,7 @@
   ConstantValueKind get kind => ConstantValueKind.BOOL;
 
   @override
-  String toStructuredText(DartTypes dartTypes) =>
+  String toStructuredText(DartTypes? dartTypes) =>
       'BoolConstant(${toDartText(dartTypes)})';
 }
 
@@ -438,7 +439,7 @@
   int get hashCode => 499;
 
   @override
-  String toDartText(DartTypes dartTypes) => boolValue.toString();
+  String toDartText(DartTypes? dartTypes) => boolValue.toString();
 }
 
 class FalseConstantValue extends BoolConstantValue {
@@ -464,11 +465,11 @@
   int get hashCode => 536555975;
 
   @override
-  String toDartText(DartTypes dartTypes) => boolValue.toString();
+  String toDartText(DartTypes? dartTypes) => boolValue.toString();
 }
 
 class StringConstantValue extends PrimitiveConstantValue {
-  final String /*!*/ stringValue;
+  final String stringValue;
 
   @override
   final int hashCode;
@@ -505,10 +506,10 @@
 
   // TODO(johnniwinther): Ensure correct escaping.
   @override
-  String toDartText(DartTypes dartTypes) => '"${stringValue}"';
+  String toDartText(DartTypes? dartTypes) => '"${stringValue}"';
 
   @override
-  String toStructuredText(DartTypes dartTypes) =>
+  String toStructuredText(DartTypes? dartTypes) =>
       'StringConstant(${toDartText(dartTypes)})';
 }
 
@@ -523,7 +524,7 @@
   @override
   DartType getType(CommonElements types) => type;
 
-  void _unparseTypeArguments(DartTypes dartTypes, StringBuffer sb) {
+  void _unparseTypeArguments(DartTypes? dartTypes, StringBuffer sb) {
     if (dartTypes == null || !dartTypes.treatAsRawType(type)) {
       sb.write('<');
       sb.write(type.typeArguments.join(', '));
@@ -560,15 +561,15 @@
   ConstantValueKind get kind => ConstantValueKind.TYPE;
 
   @override
-  String toDartText(DartTypes dartTypes) => '$representedType';
+  String toDartText(DartTypes? dartTypes) => '$representedType';
 
   @override
-  String toStructuredText(DartTypes dartTypes) =>
+  String toStructuredText(DartTypes? dartTypes) =>
       'TypeConstant(${representedType})';
 }
 
 class ListConstantValue extends ObjectConstantValue {
-  final List<ConstantValue /*!*/ > /*!*/ entries;
+  final List<ConstantValue> entries;
   @override
   final int hashCode;
 
@@ -606,7 +607,7 @@
   ConstantValueKind get kind => ConstantValueKind.LIST;
 
   @override
-  String toDartText(DartTypes dartTypes) {
+  String toDartText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     _unparseTypeArguments(dartTypes, sb);
     sb.write('[');
@@ -619,7 +620,7 @@
   }
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     sb.write('ListConstant(');
     _unparseTypeArguments(dartTypes, sb);
@@ -669,7 +670,7 @@
   accept(ConstantValueVisitor visitor, arg) => visitor.visitSet(this, arg);
 
   @override
-  String toDartText(DartTypes dartTypes) {
+  String toDartText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     _unparseTypeArguments(dartTypes, sb);
     sb.write('{');
@@ -679,7 +680,7 @@
   }
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     sb.write('SetConstant(');
     _unparseTypeArguments(dartTypes, sb);
@@ -702,7 +703,7 @@
   final List<ConstantValue> values;
   @override
   final int hashCode;
-  Map<ConstantValue, ConstantValue> _lookupMap;
+  Map<ConstantValue, ConstantValue>? _lookupMap;
 
   MapConstantValue(
       InterfaceType type, List<ConstantValue> keys, List<ConstantValue> values)
@@ -742,7 +743,7 @@
 
   int get length => keys.length;
 
-  ConstantValue lookup(ConstantValue key) {
+  ConstantValue? lookup(ConstantValue key) {
     var lookupMap = _lookupMap ??= Map.fromIterables(keys, values);
     return lookupMap[key];
   }
@@ -754,7 +755,7 @@
   ConstantValueKind get kind => ConstantValueKind.MAP;
 
   @override
-  String toDartText(DartTypes dartTypes) {
+  String toDartText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     _unparseTypeArguments(dartTypes, sb);
     sb.write('{');
@@ -769,7 +770,7 @@
   }
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     sb.write('MapConstant(');
     _unparseTypeArguments(dartTypes, sb);
@@ -818,12 +819,12 @@
   ConstantValueKind get kind => ConstantValueKind.INTERCEPTOR;
 
   @override
-  String toDartText(DartTypes dartTypes) {
+  String toDartText(DartTypes? dartTypes) {
     return 'interceptor($cls)';
   }
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     return 'InterceptorConstant(${cls.name})';
   }
 }
@@ -859,13 +860,13 @@
   ConstantValueKind get kind => ConstantValueKind.JS_NAME;
 
   @override
-  String toDartText(DartTypes dartTypes) {
+  String toDartText(DartTypes? dartTypes) {
     if (name.isFinalized) 'js_name(${name})';
     return 'js_name(name.nonfinalizedDebugText())';
   }
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     if (name.isFinalized) return 'JsNameConstant(${name})';
     return 'JsNameConstant(name.nonfinalizedDebugText())';
   }
@@ -898,10 +899,10 @@
   ConstantValueKind get kind => ConstantValueKind.DUMMY_INTERCEPTOR;
 
   @override
-  String toDartText(DartTypes dartTypes) => 'dummy_interceptor()';
+  String toDartText(DartTypes? dartTypes) => 'dummy_interceptor()';
 
   @override
-  String toStructuredText(DartTypes dartTypes) => 'DummyInterceptorConstant()';
+  String toStructuredText(DartTypes? dartTypes) => 'DummyInterceptorConstant()';
 }
 
 /// A constant used to represent the sentinel for uninitialized late fields and
@@ -926,10 +927,10 @@
   ConstantValueKind get kind => ConstantValueKind.LATE_SENTINEL;
 
   @override
-  String toDartText(DartTypes dartTypes) => 'late_sentinel()';
+  String toDartText(DartTypes? dartTypes) => 'late_sentinel()';
 
   @override
-  String toStructuredText(DartTypes dartTypes) => 'LateSentinelConstant()';
+  String toStructuredText(DartTypes? dartTypes) => 'LateSentinelConstant()';
 }
 
 // A constant with an empty type used in [HInstruction]s of an expression
@@ -957,10 +958,10 @@
   ConstantValueKind get kind => ConstantValueKind.UNREACHABLE;
 
   @override
-  String toDartText(DartTypes dartTypes) => 'unreachable()';
+  String toDartText(DartTypes? dartTypes) => 'unreachable()';
 
   @override
-  String toStructuredText(DartTypes dartTypes) => 'UnreachableConstant()';
+  String toStructuredText(DartTypes? dartTypes) => 'UnreachableConstant()';
 }
 
 class ConstructedConstantValue extends ObjectConstantValue {
@@ -975,7 +976,7 @@
       : this.fields = fields,
         hashCode = Hashing.unorderedMapHash(fields, Hashing.objectHash(type)),
         super(type) {
-    assert(type != null);
+    assert((type as dynamic) != null);
     assert(!fields.containsKey(null));
     assert(!fields.containsValue(null));
   }
@@ -1009,18 +1010,18 @@
   ConstantValueKind get kind => ConstantValueKind.CONSTRUCTED;
 
   Iterable<FieldEntity> get _fieldsSortedByName {
-    return fields.keys.toList()..sort((a, b) => a.name.compareTo(b.name));
+    return fields.keys.toList()..sort((a, b) => a.name!.compareTo(b.name!));
   }
 
   @override
-  String toDartText(DartTypes dartTypes) {
+  String toDartText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     sb.write(type.element.name);
     _unparseTypeArguments(dartTypes, sb);
     sb.write('(');
     int i = 0;
     for (FieldEntity field in _fieldsSortedByName) {
-      ConstantValue value = fields[field];
+      ConstantValue value = fields[field]!;
       if (i > 0) sb.write(',');
       sb.write(field.name);
       sb.write('=');
@@ -1032,14 +1033,14 @@
   }
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     StringBuffer sb = StringBuffer();
     sb.write('ConstructedConstant(');
     sb.write(type);
     sb.write('(');
     int i = 0;
     for (FieldEntity field in _fieldsSortedByName) {
-      ConstantValue value = fields[field];
+      ConstantValue value = fields[field]!;
       if (i > 0) sb.write(',');
       sb.write(field.name);
       sb.write('=');
@@ -1087,11 +1088,11 @@
   ConstantValueKind get kind => ConstantValueKind.INSTANTIATION;
 
   @override
-  String toDartText(DartTypes dartTypes) =>
+  String toDartText(DartTypes? dartTypes) =>
       '<${typeArguments.join(', ')}>(${function.toDartText(dartTypes)})';
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     return 'InstantiationConstant($typeArguments,'
         '${function.toStructuredText(dartTypes)})';
   }
@@ -1113,7 +1114,7 @@
   DeferredGlobalConstantValue(this.referenced, this.unit);
 
   final ConstantValue referenced;
-  final OutputUnit unit;
+  final OutputUnit? unit;
 
   bool get isReference => true;
 
@@ -1141,11 +1142,11 @@
   ConstantValueKind get kind => ConstantValueKind.DEFERRED_GLOBAL;
 
   @override
-  String toDartText(DartTypes dartTypes) =>
+  String toDartText(DartTypes? dartTypes) =>
       'deferred_global(${referenced.toDartText(dartTypes)})';
 
   @override
-  String toStructuredText(DartTypes dartTypes) {
+  String toStructuredText(DartTypes? dartTypes) {
     return 'DeferredGlobalConstant(${referenced.toStructuredText(dartTypes)})';
   }
 }
@@ -1172,8 +1173,8 @@
   ConstantValueKind get kind => ConstantValueKind.NON_CONSTANT;
 
   @override
-  String toStructuredText(DartTypes dartTypes) => 'NonConstant';
+  String toStructuredText(DartTypes? dartTypes) => 'NonConstant';
 
   @override
-  String toDartText(DartTypes dartTypes) => '>>non-constant<<';
+  String toDartText(DartTypes? dartTypes) => '>>non-constant<<';
 }
diff --git a/pkg/compiler/lib/src/deferred_load/output_unit.dart b/pkg/compiler/lib/src/deferred_load/output_unit.dart
index dd0c7b8..5d8345f0 100644
--- a/pkg/compiler/lib/src/deferred_load/output_unit.dart
+++ b/pkg/compiler/lib/src/deferred_load/output_unit.dart
@@ -13,52 +13,9 @@
 import '../serialization/serialization.dart';
 import '../options.dart';
 
-/// A "hunk" of the program that will be loaded whenever one of its [imports]
-/// are loaded.
-///
-/// Elements that are only used in one deferred import, is in an OutputUnit with
-/// the deferred import as single element in the [imports] set.
-///
-/// Whenever a deferred Element is shared between several deferred imports it is
-/// in an output unit with those imports in the [imports] Set.
-///
-/// We never create two OutputUnits sharing the same set of [imports].
-class OutputUnit implements Comparable<OutputUnit> {
-  /// `true` if this output unit is for the main output file.
-  final bool isMainOutput;
-
-  /// A unique name representing this [OutputUnit].
-  final String name;
-
-  /// The deferred imports that use the elements in this output unit.
-  final Set<ImportEntity> imports;
-
-  OutputUnit(this.isMainOutput, this.name, this.imports);
-
-  @override
-  int compareTo(OutputUnit other) {
-    if (identical(this, other)) return 0;
-    if (isMainOutput && !other.isMainOutput) return -1;
-    if (!isMainOutput && other.isMainOutput) return 1;
-    var size = imports.length;
-    var otherSize = other.imports.length;
-    if (size != otherSize) return size.compareTo(otherSize);
-    var thisImports = imports.toList();
-    var otherImports = other.imports.toList();
-    for (var i = 0; i < size; i++) {
-      var cmp = compareImportEntities(thisImports[i], otherImports[i]);
-      if (cmp != 0) return cmp;
-    }
-    // TODO(sigmund): make compare stable.  If we hit this point, all imported
-    // libraries are the same, however [this] and [other] use different deferred
-    // imports in the program. We can make this stable if we sort based on the
-    // deferred imports themselves (e.g. their declaration location).
-    return name.compareTo(other.name);
-  }
-
-  @override
-  String toString() => "OutputUnit($name, $imports)";
-}
+// TODO(48820): Move OutputUnit and compareImportEntities back here.
+import 'output_unit_migrated.dart';
+export 'output_unit_migrated.dart';
 
 /// Interface for updating an [OutputUnitData] object with data for late
 /// members, that is, members created on demand during code generation.
@@ -397,11 +354,3 @@
   String extension = addExtension ? ".part.js" : "";
   return "${outName}_$name$extension";
 }
-
-int compareImportEntities(ImportEntity a, ImportEntity b) {
-  if (a == b) {
-    return 0;
-  } else {
-    return a.uri.path.compareTo(b.uri.path);
-  }
-}
diff --git a/pkg/compiler/lib/src/deferred_load/output_unit_migrated.dart b/pkg/compiler/lib/src/deferred_load/output_unit_migrated.dart
new file mode 100644
index 0000000..f7c026a
--- /dev/null
+++ b/pkg/compiler/lib/src/deferred_load/output_unit_migrated.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2021, 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 '../elements/entities.dart' show ImportEntity;
+
+/// A "hunk" of the program that will be loaded whenever one of its [imports]
+/// are loaded.
+///
+/// Elements that are only used in one deferred import, is in an OutputUnit with
+/// the deferred import as single element in the [imports] set.
+///
+/// Whenever a deferred Element is shared between several deferred imports it is
+/// in an output unit with those imports in the [imports] Set.
+///
+/// We never create two OutputUnits sharing the same set of [imports].
+class OutputUnit implements Comparable<OutputUnit> {
+  /// `true` if this output unit is for the main output file.
+  final bool isMainOutput;
+
+  /// A unique name representing this [OutputUnit].
+  final String name;
+
+  /// The deferred imports that use the elements in this output unit.
+  final Set<ImportEntity> imports;
+
+  OutputUnit(this.isMainOutput, this.name, this.imports);
+
+  @override
+  int compareTo(OutputUnit other) {
+    if (identical(this, other)) return 0;
+    if (isMainOutput && !other.isMainOutput) return -1;
+    if (!isMainOutput && other.isMainOutput) return 1;
+    var size = imports.length;
+    var otherSize = other.imports.length;
+    if (size != otherSize) return size.compareTo(otherSize);
+    var thisImports = imports.toList();
+    var otherImports = other.imports.toList();
+    for (var i = 0; i < size; i++) {
+      var cmp = compareImportEntities(thisImports[i], otherImports[i]);
+      if (cmp != 0) return cmp;
+    }
+    // TODO(sigmund): make compare stable.  If we hit this point, all imported
+    // libraries are the same, however [this] and [other] use different deferred
+    // imports in the program. We can make this stable if we sort based on the
+    // deferred imports themselves (e.g. their declaration location).
+    return name.compareTo(other.name);
+  }
+
+  @override
+  String toString() => "OutputUnit($name, $imports)";
+}
+
+int compareImportEntities(ImportEntity a, ImportEntity b) {
+  if (a == b) {
+    return 0;
+  } else {
+    return a.uri.path.compareTo(b.uri.path);
+  }
+}
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index 72efd4f..7fdb67f 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -916,8 +916,8 @@
     return InstantiationConstantValue(typeArguments, function);
   }
 
-  List<ConstantValue> _handleValues(List<ConstantValue> values) {
-    List<ConstantValue> result;
+  List<ConstantValue /*!*/ > _handleValues(List<ConstantValue /*!*/ > values) {
+    List<ConstantValue /*!*/ > result;
     for (int i = 0; i < values.length; i++) {
       var value = values[i];
       var newValue = value.accept(this, null);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 72dff8e..b03f82b 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -1242,7 +1242,7 @@
       domain.isPrimitiveOrNull(instructionType);
 
   /// Type of the instruction.
-  AbstractValue instructionType;
+  AbstractValue /*!*/ instructionType;
 
   HInstruction getDartReceiver(JClosedWorld closedWorld) => null;
   bool onlyThrowsNSM() => false;
@@ -2934,7 +2934,7 @@
 }
 
 class HConstant extends HInstruction {
-  final ConstantValue constant;
+  final ConstantValue /*!*/ constant;
   HConstant.internal(this.constant, AbstractValue constantType)
       : super([], constantType);
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 950ab438..4f37948 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -124,7 +124,6 @@
 /// parameters that were *not* deferred.
 List<_ParamInfo> _computeUndeferredParamInfo(List<DartType> formalTypes,
     List<_DeferredParamInfo> deferredFunctionLiterals) {
-  // TODO(paulberry): test that the right thing happens when evaluation order differs from classic (positional/named) order.
   Set<int> evaluationOrderIndicesAlreadyCovered = {
     for (_DeferredParamInfo functionLiteral in deferredFunctionLiterals)
       functionLiteral.evaluationOrderIndex
diff --git a/tools/VERSION b/tools/VERSION
index b210de9..8377cf9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 93
+PRERELEASE 94
 PRERELEASE_PATCH 0
\ No newline at end of file