Version 2.14.0-170.0.dev

Merge commit '8580370162ad5f0cb801de383104fccf6b47cf42' into 'dev'
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
new file mode 100644
index 0000000..72e884b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -0,0 +1,55 @@
+// 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 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/micro/resolve_file.dart';
+import 'package:analyzer/src/dart/micro/utils.dart';
+
+class CiderRenameComputer {
+  final FileResolver _fileResolver;
+
+  CiderRenameComputer(this._fileResolver);
+
+  /// Check if the identifier at the [line], [column] for the file at the
+  /// [filePath] can be renamed.
+  RenameRefactoringElement? canRename(String filePath, int line, int column) {
+    var resolvedUnit = _fileResolver.resolve(path: filePath);
+    var lineInfo = resolvedUnit.lineInfo;
+    var offset = lineInfo.getOffsetOfLine(line) + column;
+
+    var node = NodeLocator(offset).searchWithin(resolvedUnit.unit);
+    var element = getElementOfNode(node);
+
+    if (node == null || element == null) {
+      return null;
+    }
+    if (element.source != null && element.source!.isInSystemLibrary) {
+      return null;
+    }
+    if (element is MethodElement && element.isOperator) {
+      return null;
+    }
+    if (!_canRenameElement(element)) {
+      return null;
+    }
+    return RenameRefactoring.getElementToRename(node, element);
+  }
+
+  bool _canRenameElement(Element element) {
+    if (element is PropertyAccessorElement) {
+      element = element.variable;
+    }
+    var enclosingElement = element.enclosingElement;
+    if (element is LabelElement || element is LocalElement) {
+      return true;
+    }
+    if (enclosingElement is ClassElement ||
+        enclosingElement is ExtensionElement) {
+      return true;
+    }
+    return false;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index e748921..0d20c79 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -160,6 +160,8 @@
     }
     // prepare type
     HighlightRegionType type;
+    SemanticTokenTypes? semanticType;
+    Set<SemanticTokenModifiers>? semanticModifiers;
     var parent = node.parent;
     var grandParent = parent?.parent;
     if (parent is TypeName &&
@@ -167,13 +169,20 @@
         grandParent.parent is InstanceCreationExpression) {
       // new Class()
       type = HighlightRegionType.CONSTRUCTOR;
+      semanticType = SemanticTokenTypes.class_;
+      semanticModifiers = {CustomSemanticTokenModifiers.constructor};
     } else if (element.isEnum) {
       type = HighlightRegionType.ENUM;
     } else {
       type = HighlightRegionType.CLASS;
     }
     // add region
-    return _addRegion_node(node, type);
+    return _addRegion_node(
+      node,
+      type,
+      semanticTokenType: semanticType,
+      semanticTokenModifiers: semanticModifiers,
+    );
   }
 
   bool _addIdentifierRegion_constructor(SimpleIdentifier node) {
@@ -181,7 +190,14 @@
     if (element is! ConstructorElement) {
       return false;
     }
-    return _addRegion_node(node, HighlightRegionType.CONSTRUCTOR);
+    return _addRegion_node(
+      node,
+      HighlightRegionType.CONSTRUCTOR,
+      // For semantic tokens, constructor names are coloured like methods but
+      // have a modifier applied.
+      semanticTokenType: SemanticTokenTypes.method,
+      semanticTokenModifiers: {CustomSemanticTokenModifiers.constructor},
+    );
   }
 
   bool _addIdentifierRegion_dynamicLocal(SimpleIdentifier node) {
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
index ef2eda3..0b7c262 100644
--- a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
@@ -15,7 +15,6 @@
   HighlightRegionType.COMMENT_DOCUMENTATION: {
     SemanticTokenModifiers.documentation
   },
-  HighlightRegionType.CONSTRUCTOR: {CustomSemanticTokenModifiers.constructor},
   HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION: {
     SemanticTokenModifiers.declaration
   },
@@ -88,7 +87,6 @@
   HighlightRegionType.COMMENT_BLOCK: SemanticTokenTypes.comment,
   HighlightRegionType.COMMENT_DOCUMENTATION: SemanticTokenTypes.comment,
   HighlightRegionType.COMMENT_END_OF_LINE: SemanticTokenTypes.comment,
-  HighlightRegionType.CONSTRUCTOR: SemanticTokenTypes.class_,
   HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION:
       SemanticTokenTypes.variable,
   HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_REFERENCE:
diff --git a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
index a966f00..08367b2 100644
--- a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
+++ b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
@@ -87,10 +87,12 @@
     class MyClass {
       MyClass();
       MyClass.named();
+      factory MyClass.factory() => MyClass();
     }
 
     final a = MyClass();
     final b = MyClass.named();
+    final c = MyClass.factory();
     ''';
 
     final expected = [
@@ -98,7 +100,13 @@
       _Token('MyClass', SemanticTokenTypes.class_),
       _Token('MyClass', SemanticTokenTypes.class_),
       _Token('MyClass', SemanticTokenTypes.class_),
-      _Token('named', SemanticTokenTypes.class_,
+      _Token('named', SemanticTokenTypes.method,
+          [CustomSemanticTokenModifiers.constructor]),
+      _Token('factory', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('factory', SemanticTokenTypes.method,
+          [CustomSemanticTokenModifiers.constructor]),
+      _Token('MyClass', SemanticTokenTypes.class_,
           [CustomSemanticTokenModifiers.constructor]),
       _Token('final', SemanticTokenTypes.keyword),
       _Token('a', SemanticTokenTypes.variable,
@@ -110,7 +118,14 @@
           [SemanticTokenModifiers.declaration]),
       _Token('MyClass', SemanticTokenTypes.class_,
           [CustomSemanticTokenModifiers.constructor]),
-      _Token('named', SemanticTokenTypes.class_,
+      _Token('named', SemanticTokenTypes.method,
+          [CustomSemanticTokenModifiers.constructor]),
+      _Token('final', SemanticTokenTypes.keyword),
+      _Token('c', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token('MyClass', SemanticTokenTypes.class_,
+          [CustomSemanticTokenModifiers.constructor]),
+      _Token('factory', SemanticTokenTypes.method,
           [CustomSemanticTokenModifiers.constructor])
     ];
 
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
new file mode 100644
index 0000000..290379f
--- /dev/null
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -0,0 +1,150 @@
+// 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 'package:analysis_server/src/cider/rename.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'cider_service.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CiderRenameComputerTest);
+  });
+}
+
+@reflectiveTest
+class CiderRenameComputerTest extends CiderServiceTest {
+  late _CorrectionContext _correctionContext;
+
+  void test_canRename_field() {
+    var refactor = _compute(r'''
+class A {
+ int ^bar;
+ void foo() {
+   bar = 5;
+ }
+}
+''');
+
+    expect(refactor, isNotNull);
+    expect(refactor!.element.name, 'bar');
+    expect(refactor.offset, _correctionContext.offset);
+  }
+
+  void test_canRename_function() {
+    var refactor = _compute(r'''
+void ^foo() {
+}
+''');
+
+    expect(refactor, isNotNull);
+    expect(refactor!.element.name, 'foo');
+    expect(refactor.offset, _correctionContext.offset);
+  }
+
+  void test_canRename_label() {
+    var refactor = _compute(r'''
+main() {
+  myLabel:
+  while (true) {
+    continue ^myLabel;
+    break myLabel;
+  }
+}
+''');
+
+    expect(refactor, isNotNull);
+    expect(refactor!.element.name, 'myLabel');
+    expect(refactor.offset, _correctionContext.offset);
+  }
+
+  void test_canRename_local() {
+    var refactor = _compute(r'''
+void foo() {
+  var ^a = 0; var b = a + 1;
+}
+''');
+
+    expect(refactor, isNotNull);
+    expect(refactor!.element.name, 'a');
+    expect(refactor.offset, _correctionContext.offset);
+  }
+
+  void test_canRename_method() {
+    var refactor = _compute(r'''
+extension E on int {
+  void ^foo() {}
+}
+''');
+
+    expect(refactor, isNotNull);
+    expect(refactor!.element.name, 'foo');
+    expect(refactor.offset, _correctionContext.offset);
+  }
+
+  void test_canRename_operator() {
+    var refactor = _compute(r'''
+class A{
+  A operator ^+(A other) => this;
+}
+''');
+
+    expect(refactor, isNull);
+  }
+
+  void test_canRename_parameter() {
+    var refactor = _compute(r'''
+void foo(int ^bar) {
+  var a = bar + 1;
+}
+''');
+
+    expect(refactor, isNotNull);
+    expect(refactor!.element.name, 'bar');
+    expect(refactor.offset, _correctionContext.offset);
+  }
+
+  RenameRefactoringElement? _compute(String content) {
+    _updateFile(content);
+
+    return CiderRenameComputer(
+      fileResolver,
+    ).canRename(
+      convertPath(testPath),
+      _correctionContext.line,
+      _correctionContext.character,
+    );
+  }
+
+  void _updateFile(String content) {
+    var offset = content.indexOf('^');
+    expect(offset, isPositive, reason: 'Expected to find ^');
+    expect(content.indexOf('^', offset + 1), -1, reason: 'Expected only one ^');
+
+    var lineInfo = LineInfo.fromContent(content);
+    var location = lineInfo.getLocation(offset);
+
+    content = content.substring(0, offset) + content.substring(offset + 1);
+    newFile(testPath, content: content);
+
+    _correctionContext = _CorrectionContext(
+      content,
+      offset,
+      location.lineNumber - 1,
+      location.columnNumber - 1,
+    );
+  }
+}
+
+class _CorrectionContext {
+  final String content;
+  final int offset;
+  final int line;
+  final int character;
+
+  _CorrectionContext(this.content, this.offset, this.line, this.character);
+}
diff --git a/pkg/analysis_server/test/src/cider/test_all.dart b/pkg/analysis_server/test/src/cider/test_all.dart
index 524383b..95c39ca 100644
--- a/pkg/analysis_server/test/src/cider/test_all.dart
+++ b/pkg/analysis_server/test/src/cider/test_all.dart
@@ -7,11 +7,13 @@
 import 'assists_test.dart' as assists;
 import 'completion_test.dart' as completion;
 import 'fixes_test.dart' as fixes;
+import 'rename_test.dart' as rename;
 
 void main() {
   defineReflectiveSuite(() {
     assists.main();
     completion.main();
     fixes.main();
+    rename.main();
   });
 }
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 90a7369..285d5f7 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -41,6 +41,10 @@
 class BestPracticesVerifier extends RecursiveAstVisitor<void> {
   static const String _TO_INT_METHOD_NAME = "toInt";
 
+  static final Map<String, TargetKind> _targetKindsByName = {
+    for (final kind in TargetKind.values) kind.toString(): kind,
+  };
+
   /// The class containing the AST nodes being visited, or `null` if we are not
   /// in the scope of a class.
   ClassElementImpl? _enclosingClass;
@@ -1623,9 +1627,23 @@
       if (annotation.isTarget) {
         var value = annotation.computeConstantValue()!;
         var kinds = <TargetKind>{};
+
         for (var kindObject in value.getField('kinds')!.toSetValue()!) {
+          // We can't directly translate the index from the analyzed TargetKind
+          // constant to TargetKinds.values because the analyzer from the SDK
+          // may have been compiled with a different version of pkg:meta.
           var index = kindObject.getField('index')!.toIntValue()!;
-          kinds.add(TargetKind.values[index]);
+          var targetKindClass =
+              (kindObject.type as InterfaceType).element as EnumElementImpl;
+          // Instead, map constants to their TargetKind by comparing getter
+          // names.
+          var getter = targetKindClass.constants[index];
+          var name = 'TargetKind.${getter.name}';
+
+          var foundTargetKind = _targetKindsByName[name];
+          if (foundTargetKind != null) {
+            kinds.add(foundTargetKind);
+          }
         }
         return kinds;
       }
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 5dcfc27..8c58caf 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -998,7 +998,6 @@
           property = existing;
         } else {
           var field = TopLevelVariableElementImpl(name, -1);
-          field.isFinal = true;
           property = field;
         }
       } else {
@@ -1007,7 +1006,6 @@
           property = existing;
         } else {
           var field = FieldElementImpl(name, -1);
-          field.isFinal = true;
           field.isStatic = accessor.isStatic;
           property = field;
         }
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index f8033c7..cb397b5 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -23,6 +23,7 @@
 
   final _exports = <ExportElement>[];
   final _imports = <ImportElement>[];
+  var _isFirstLibraryDirective = true;
   var _hasCoreImport = false;
   var _hasExtUri = false;
   var _partDirectiveIndex = 0;
@@ -82,10 +83,13 @@
 
     var firstDirective = unit.directives.firstOrNull;
     if (firstDirective != null) {
-      _libraryElement.metadata = _buildAnnotations(firstDirective.metadata);
       _libraryElement.documentationComment = getCommentNodeRawText(
         firstDirective.documentationComment,
       );
+      var firstDirectiveMetadata = firstDirective.element?.metadata;
+      if (firstDirectiveMetadata != null) {
+        _libraryElement.metadata = firstDirectiveMetadata;
+      }
     }
   }
 
@@ -621,7 +625,13 @@
   }
 
   @override
-  void visitLibraryDirective(LibraryDirective node) {}
+  void visitLibraryDirective(covariant LibraryDirectiveImpl node) {
+    if (_isFirstLibraryDirective) {
+      _isFirstLibraryDirective = false;
+      node.element = _libraryElement;
+      _libraryElement.metadata = _buildAnnotations(node.metadata);
+    }
+  }
 
   @override
   void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 577d10f..d0ec493 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -160,7 +160,9 @@
       var superType = classElement.supertype;
       if (superType != null) {
         var index = classElement.constructors.indexOf(_constructor);
-        var superConstructors = superType.element.constructors;
+        var superConstructors = superType.element.constructors
+            .where((element) => element.isAccessibleIn(classElement.library))
+            .toList();
         if (index < superConstructors.length) {
           _baseConstructor = _BaseConstructor(
             superType,
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
index cfd22eb..2761da8 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
@@ -1033,7 +1033,6 @@
     bool isStatic = false,
   }) {
     var field = FieldElementImpl(name, -1);
-    field.isFinal = true;
     field.isStatic = isStatic;
     field.isSynthetic = true;
     field.type = type;
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index bd68a35..af2043f 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -997,6 +997,7 @@
     } else {
       writeDocumentation(e);
       writeMetadata(e, '', '\n');
+      writeIf(e.isSynthetic, 'synthetic ');
       writeIf(e is TopLevelVariableElementImpl && e.isExternal, 'external ');
     }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 590f551..bd6e007 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1149,11 +1149,15 @@
 
   test_class_getter_static() async {
     var library = await checkLibrary('class C { static int get x => null; }');
-    checkElementText(library, r'''
+    checkElementText(
+        library,
+        r'''
 class C {
+  synthetic static int x;
   static int get x {}
 }
-''');
+''',
+        withSyntheticFields: true);
   }
 
   test_class_getters() async {
@@ -1174,12 +1178,16 @@
   void set x(int value) {} 
 }
 ''');
-    checkElementText(library, r'''
+    checkElementText(
+        library,
+        r'''
 class C {
+  synthetic int x;
   int get x {}
   void set x(int value) {}
 }
-''');
+''',
+        withSyntheticFields: true);
   }
 
   test_class_implicitField_setterFirst() async {
@@ -1189,12 +1197,16 @@
   int get x => 0;
 }
 ''');
-    checkElementText(library, r'''
+    checkElementText(
+        library,
+        r'''
 class C {
+  synthetic int x;
   void set x(int value) {}
   int get x {}
 }
-''');
+''',
+        withSyntheticFields: true);
   }
 
   test_class_interfaces() async {
@@ -11004,12 +11016,15 @@
   }
 
   test_metadata_importDirective() async {
-    addLibrarySource('/foo.dart', 'const b = 0;');
-    var library = await checkLibrary('@a import "foo.dart"; const a = b;');
+    var library = await checkLibrary('''
+@a
+import "dart:math";
+const a = 0;
+''');
     checkElementText(
         library,
         '''
-import 'foo.dart';
+import 'dart:math';
   metadata
     Annotation
       element: self::@getter::a
@@ -11019,10 +11034,9 @@
         token: a
 const int a;
   constantInitializer
-    SimpleIdentifier
-      staticElement: ${toUriStr('/foo.dart')}::@getter::b
+    IntegerLiteral
+      literal: 0
       staticType: int
-      token: b
 ''',
         withFullyResolvedAst: true);
   }
@@ -14771,6 +14785,36 @@
 ''');
   }
 
+  test_unit_implicitVariable_getterFirst() async {
+    var library = await checkLibrary('''
+int get x => 0;
+void set x(int value) {} 
+''');
+    checkElementText(
+        library,
+        r'''
+synthetic int x;
+int get x {}
+void set x(int value) {}
+''',
+        withSyntheticFields: true);
+  }
+
+  test_unit_implicitVariable_setterFirst() async {
+    var library = await checkLibrary('''
+void set x(int value) {}
+int get x => 0;
+''');
+    checkElementText(
+        library,
+        r'''
+synthetic int x;
+void set x(int value) {}
+int get x {}
+''',
+        withSyntheticFields: true);
+  }
+
   test_unit_variable_final_withSetter() async {
     var library = await checkLibrary(r'''
 final int foo = 0;
@@ -15165,7 +15209,7 @@
         as PropertyAccessorElementImpl;
     var variable = getter.variable as TopLevelVariableElementImpl;
     expect(variable, isNotNull);
-    expect(variable.isFinal, isTrue);
+    expect(variable.isFinal, isFalse);
     expect(variable.getter, same(getter));
     expect('${variable.type}', 'int');
     expect(variable, same(_elementOfDefiningUnit(library, ['@variable', 'x'])));
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index 906d2c1..b778258 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -1514,7 +1514,7 @@
 }
 class B implements A {
   int x;
-  synthetic final int y;
+  synthetic int y;
   synthetic int z;
   int get y {}
   void set z(int _) {}
@@ -1565,7 +1565,7 @@
 }
 class B<T> implements A<T> {
   T x;
-  synthetic final T y;
+  synthetic T y;
   synthetic T z;
   T get y {}
   void set z(T _) {}
@@ -1816,7 +1816,7 @@
         library,
         r'''
 abstract class A {
-  synthetic final int x;
+  synthetic int x;
   int get x;
 }
 abstract class B {
@@ -1824,7 +1824,7 @@
   void set x(String _);
 }
 class C implements A, B {
-  synthetic final int x;
+  synthetic int x;
   int get x {}
 }
 ''',
@@ -1848,7 +1848,7 @@
         library,
         r'''
 abstract class A {
-  synthetic final int x;
+  synthetic int x;
   int get x;
 }
 abstract class B {
@@ -1904,7 +1904,7 @@
         library,
         r'''
 abstract class A {
-  synthetic final int x;
+  synthetic int x;
   int get x;
 }
 abstract class B {
@@ -1912,7 +1912,7 @@
   void set x(int _);
 }
 class C implements A, B {
-  synthetic final int x;
+  synthetic int x;
   int get x {}
 }
 ''',
@@ -1935,7 +1935,7 @@
         library,
         r'''
 abstract class A {
-  synthetic final int x;
+  synthetic int x;
   int get x;
 }
 abstract class B {
diff --git a/pkg/test_runner/lib/src/command.dart b/pkg/test_runner/lib/src/command.dart
index 27ca02d..8ba9f27 100644
--- a/pkg/test_runner/lib/src/command.dart
+++ b/pkg/test_runner/lib/src/command.dart
@@ -609,6 +609,7 @@
 class AdbPrecompilationCommand extends Command implements AdbCommand {
   final String buildPath; // Path to the output directory of the build.
   final String processTestFilename;
+  final String abstractSocketTestFilename;
   final String precompiledTestDirectory;
   final List<String> arguments;
   final bool useElf;
@@ -617,6 +618,7 @@
   AdbPrecompilationCommand(
       this.buildPath,
       this.processTestFilename,
+      this.abstractSocketTestFilename,
       this.precompiledTestDirectory,
       this.arguments,
       this.useElf,
@@ -627,6 +629,7 @@
   AdbPrecompilationCommand indexedCopy(int index) => AdbPrecompilationCommand(
       buildPath,
       processTestFilename,
+      abstractSocketTestFilename,
       precompiledTestDirectory,
       arguments,
       useElf,
@@ -662,17 +665,28 @@
 class AdbDartkCommand extends Command implements AdbCommand {
   final String buildPath;
   final String processTestFilename;
+  final String abstractSocketTestFilename;
   final String kernelFile;
   final List<String> arguments;
   final List<String> extraLibraries;
 
-  AdbDartkCommand(this.buildPath, this.processTestFilename, this.kernelFile,
-      this.arguments, this.extraLibraries,
+  AdbDartkCommand(
+      this.buildPath,
+      this.processTestFilename,
+      this.abstractSocketTestFilename,
+      this.kernelFile,
+      this.arguments,
+      this.extraLibraries,
       {int index = 0})
       : super._("adb_precompilation", index: index);
 
   AdbDartkCommand indexedCopy(int index) => AdbDartkCommand(
-      buildPath, processTestFilename, kernelFile, arguments, extraLibraries,
+      buildPath,
+      processTestFilename,
+      abstractSocketTestFilename,
+      kernelFile,
+      arguments,
+      extraLibraries,
       index: index);
 
   _buildHashCode(HashCodeBuilder builder) {
diff --git a/pkg/test_runner/lib/src/process_queue.dart b/pkg/test_runner/lib/src/process_queue.dart
index ff3e1f1..3c8e5bb 100644
--- a/pkg/test_runner/lib/src/process_queue.dart
+++ b/pkg/test_runner/lib/src/process_queue.dart
@@ -639,6 +639,7 @@
       AdbDevice device, AdbPrecompilationCommand command, int timeout) async {
     var buildPath = command.buildPath;
     var processTest = command.processTestFilename;
+    var abstractSocketTest = command.abstractSocketTestFilename;
     var testdir = command.precompiledTestDirectory;
     var arguments = command.arguments;
     var devicedir = DartPrecompiledAdbRuntimeConfiguration.deviceDir;
@@ -662,10 +663,12 @@
         '$devicedir/dart_precompiled_runtime'));
     steps.add(
         () => device.pushCachedData(processTest, '$devicedir/process_test'));
+    steps.add(() => device.pushCachedData(
+        abstractSocketTest, '$devicedir/abstract_socket_test'));
     steps.add(() => device.runAdbShellCommand([
           'chmod',
           '777',
-          '$devicedir/dart_precompiled_runtime $devicedir/process_test'
+          '$devicedir/dart_precompiled_runtime $devicedir/process_test $devicedir/abstract_socket_test'
         ]));
 
     steps.addAll(_pushLibraries(command, device, devicedir, deviceTestDir));
diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart
index e8a4d82..27623e3 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -125,6 +125,13 @@
     return processTestExecutable;
   }
 
+  String get abstractSocketTestBinaryFileName {
+    var abstractSocketTestExecutable =
+        '$buildDir/abstract_socket_test$executableExtension';
+    TestUtils.ensureExists(abstractSocketTestExecutable, _configuration);
+    return abstractSocketTestExecutable;
+  }
+
   String get d8FileName {
     var d8Dir = Repository.dir.append('third_party/d8');
     var d8Path =
@@ -358,8 +365,10 @@
 
     var buildPath = buildDir;
     var processTest = processTestBinaryFileName;
+    var abstractSocketTest = abstractSocketTestBinaryFileName;
     return [
-      AdbDartkCommand(buildPath, processTest, script, arguments, extraLibs)
+      AdbDartkCommand(buildPath, processTest, abstractSocketTest, script,
+          arguments, extraLibs)
     ];
   }
 }
@@ -385,9 +394,10 @@
     }
 
     var processTest = processTestBinaryFileName;
+    var abstractSocketTest = abstractSocketTestBinaryFileName;
     return [
-      AdbPrecompilationCommand(
-          buildDir, processTest, script, arguments, useElf, extraLibs)
+      AdbPrecompilationCommand(buildDir, processTest, abstractSocketTest,
+          script, arguments, useElf, extraLibs)
     ];
   }
 }
diff --git a/sdk/lib/_internal/vm/lib/double.dart b/sdk/lib/_internal/vm/lib/double.dart
index 7500050..cc518e5 100644
--- a/sdk/lib/_internal/vm/lib/double.dart
+++ b/sdk/lib/_internal/vm/lib/double.dart
@@ -359,19 +359,16 @@
             (other <= MAX_EXACT_INT_TO_DOUBLE)) {
           return EQUAL;
         }
-        const bool limitIntsTo64Bits = ((1 << 64) == 0);
-        if (limitIntsTo64Bits) {
-          // With integers limited to 64 bits, double.toInt() clamps
-          // double value to fit into the MIN_INT64..MAX_INT64 range.
-          // MAX_INT64 is not precisely representable as double, so
-          // integers near MAX_INT64 compare as equal to (MAX_INT64 + 1) when
-          // represented as doubles.
-          // There is no similar problem with MIN_INT64 as it is precisely
-          // representable as double.
-          const double maxInt64Plus1AsDouble = 9223372036854775808.0;
-          if (this >= maxInt64Plus1AsDouble) {
-            return GREATER;
-          }
+        // With int limited to 64 bits, double.toInt() clamps
+        // double value to fit into the MIN_INT64..MAX_INT64 range.
+        // MAX_INT64 is not precisely representable as double, so
+        // integers near MAX_INT64 compare as equal to (MAX_INT64 + 1) when
+        // represented as doubles.
+        // There is no similar problem with MIN_INT64 as it is precisely
+        // representable as double.
+        const double maxInt64Plus1AsDouble = 9223372036854775808.0;
+        if (this >= maxInt64Plus1AsDouble) {
+          return GREATER;
         }
         return toInt().compareTo(other);
       } else {
diff --git a/sdk/lib/_internal/vm/lib/integers.dart b/sdk/lib/_internal/vm/lib/integers.dart
index 95e3826..ec5daff 100644
--- a/sdk/lib/_internal/vm/lib/integers.dart
+++ b/sdk/lib/_internal/vm/lib/integers.dart
@@ -204,25 +204,18 @@
     if (other is double) {
       const int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992; // 2^53.
       const int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE;
-      const bool limitIntsTo64Bits = ((1 << 64) == 0);
-      if (limitIntsTo64Bits) {
-        // With integers limited to 64 bits, double.toInt() clamps
-        // double value to fit into the MIN_INT64..MAX_INT64 range.
-        // Check if the double value is outside of this range.
-        // This check handles +/-infinity as well.
-        const double minInt64AsDouble = -9223372036854775808.0;
-        // MAX_INT64 is not precisely representable in doubles, so
-        // check against (MAX_INT64 + 1).
-        const double maxInt64Plus1AsDouble = 9223372036854775808.0;
-        if (other < minInt64AsDouble) {
-          return GREATER;
-        } else if (other >= maxInt64Plus1AsDouble) {
-          return LESS;
-        }
-      } else {
-        if (other.isInfinite) {
-          return other.isNegative ? GREATER : LESS;
-        }
+      // With int limited to 64 bits, double.toInt() clamps
+      // double value to fit into the MIN_INT64..MAX_INT64 range.
+      // Check if the double value is outside of this range.
+      // This check handles +/-infinity as well.
+      const double minInt64AsDouble = -9223372036854775808.0;
+      // MAX_INT64 is not precisely representable in doubles, so
+      // check against (MAX_INT64 + 1).
+      const double maxInt64Plus1AsDouble = 9223372036854775808.0;
+      if (other < minInt64AsDouble) {
+        return GREATER;
+      } else if (other >= maxInt64Plus1AsDouble) {
+        return LESS;
       }
       if (other.isNaN) {
         return LESS;
@@ -337,7 +330,7 @@
     final bool isNegative = this < 0;
     int value = isNegative ? -this : this;
     if (value < 0) {
-      // With integers limited to 64 bits, the value
+      // With int limited to 64 bits, the value
       // MIN_INT64 = -0x8000000000000000 overflows at negation:
       // -MIN_INT64 == MIN_INT64, so it requires special handling.
       return _minInt64ToRadixString(radix);
@@ -368,7 +361,7 @@
       value = -value;
       length = 1;
       if (value < 0) {
-        // With integers limited to 64 bits, the value
+        // With int limited to 64 bits, the value
         // MIN_INT64 = -0x8000000000000000 overflows at negation:
         // -MIN_INT64 == MIN_INT64, so it requires special handling.
         return _minInt64ToRadixString(radix);
diff --git a/tests/corelib/symbol_arbitrary_string_test.dart b/tests/corelib/symbol_arbitrary_string_test.dart
new file mode 100644
index 0000000..c4c4d25
--- /dev/null
+++ b/tests/corelib/symbol_arbitrary_string_test.dart
@@ -0,0 +1,111 @@
+// 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.
+
+// Note that this library violates the formatting provided by `dartfmt` in
+// a few locations, to verify that `"""...""""z"` can be parsed as two
+// consecutive strings, `dartfmt` will insert whitespace before `"z"`.
+
+import 'package:expect/expect.dart';
+
+main() {
+  const string = "X";
+  const integer = 42;
+  const boolean = true;
+  const none = null;
+
+  var s00 = new Symbol('');
+  var s01 = new Symbol(r'@!#$%^&*(()\\|_-][');
+  var s02 = new Symbol('\x00');
+  var s03 = new Symbol('a');
+  var s04 = new Symbol('ab');
+  var s05 = new Symbol('\x80');
+  var s06 = new Symbol('\xff');
+  var s07 = new Symbol('\u2028');
+  var s08 = new Symbol('abcdef\u2028');
+  var s09 = new Symbol('\u{10002}');
+  var s10 = new Symbol('\ud800');
+  var s11 = new Symbol('\udfff');
+  var s12 = new Symbol('\u{10FFFF}');
+  var s13 = new Symbol('abcdef\u{10002}');
+  var s14 = new Symbol('πŸ‡ΊπŸ‡Έ 😊 πŸ‡©πŸ‡°');
+  var s15 = new Symbol('\udc00');
+
+  // The multi-line string below is "abcd\ne:X42truenullz".
+  var s16 = new Symbol("""
+a${"b" // line break
+          "c"}d
+e:$string$integer$boolean$none""""z");
+
+  Expect.isTrue(s00 == new Symbol(''));
+  Expect.isTrue(s01 == new Symbol(r'@!#$%^&*(()\\|_-]['));
+  Expect.isTrue(s02 == new Symbol('\x00'));
+  Expect.isTrue(s03 == new Symbol('a'));
+  Expect.isTrue(s04 == new Symbol('ab'));
+  Expect.isTrue(s05 == new Symbol('\x80'));
+  Expect.isTrue(s06 == new Symbol('\xff'));
+  Expect.isTrue(s07 == new Symbol('\u2028'));
+  Expect.isTrue(s08 == new Symbol('abcdef\u2028'));
+  Expect.isTrue(s09 == new Symbol('\u{10002}'));
+  Expect.isTrue(s10 == new Symbol('\ud800'));
+  Expect.isTrue(s11 == new Symbol('\udfff'));
+  Expect.isTrue(s12 == new Symbol('\u{10FFFF}'));
+  Expect.isTrue(s13 == new Symbol('abcdef\u{10002}'));
+  Expect.isTrue(s14 == new Symbol('πŸ‡ΊπŸ‡Έ 😊 πŸ‡©πŸ‡°'));
+  Expect.isTrue(s15 == new Symbol('\udc00'));
+
+  // The multi-line string below is "abcd\ne:X42truenullz".
+  Expect.isTrue(s16 ==
+      new Symbol("""
+a${"b" // line break
+              "c"}d
+e:$string$integer$boolean$none""""z"));
+
+  const s00c = const Symbol('');
+  const s01c = const Symbol(r'@!#$%^&*(()\\|_-][');
+  const s02c = const Symbol('\x00');
+  const s03c = const Symbol('a');
+  const s04c = const Symbol('ab');
+  const s05c = const Symbol('\x80');
+  const s06c = const Symbol('\xff');
+  const s07c = const Symbol('\u2028');
+  const s08c = const Symbol('abcdef\u2028');
+  const s09c = const Symbol('\u{10002}');
+  const s10c = const Symbol('\ud800');
+  const s11c = const Symbol('\udfff');
+  const s12c = const Symbol('\u{10FFFF}');
+  const s13c = const Symbol('abcdef\u{10002}');
+  const s14c = const Symbol('πŸ‡ΊπŸ‡Έ 😊 πŸ‡©πŸ‡°');
+  const s15c = const Symbol('\udc00');
+
+  // The multi-line string below is "abcd\ne:X42truenullz".
+  const s16c = const Symbol("""
+a${"b" // line break
+          "c"}d
+e:$string$integer$boolean$none""""z");
+
+  Expect.isTrue(identical(s00c, const Symbol('')));
+  Expect.isTrue(identical(s01c, const Symbol(r'@!#$%^&*(()\\|_-][')));
+  Expect.isTrue(identical(s02c, const Symbol('\x00')));
+  Expect.isTrue(identical(s03c, const Symbol('a')));
+  Expect.isTrue(identical(s04c, const Symbol('ab')));
+  Expect.isTrue(identical(s05c, const Symbol('\x80')));
+  Expect.isTrue(identical(s06c, const Symbol('\xff')));
+  Expect.isTrue(identical(s07c, const Symbol('\u2028')));
+  Expect.isTrue(identical(s08c, const Symbol('abcdef\u2028')));
+  Expect.isTrue(identical(s09c, const Symbol('\u{10002}')));
+  Expect.isTrue(identical(s10c, const Symbol('\ud800')));
+  Expect.isTrue(identical(s11c, const Symbol('\udfff')));
+  Expect.isTrue(identical(s12c, const Symbol('\u{10FFFF}')));
+  Expect.isTrue(identical(s13c, const Symbol('abcdef\u{10002}')));
+  Expect.isTrue(identical(s14c, const Symbol('πŸ‡ΊπŸ‡Έ 😊 πŸ‡©πŸ‡°')));
+  Expect.isTrue(identical(s15c, const Symbol('\udc00')));
+
+  // The multi-line string below is "abcd\ne:X42truenullz".
+  Expect.isTrue(identical(
+      s16c,
+      const Symbol("""
+a${"b" // line break
+              "c"}d
+e:$string$integer$boolean$none""""z")));
+}
diff --git a/tests/corelib/symbol_reserved_word_error_test.dart b/tests/corelib/symbol_reserved_word_error_test.dart
new file mode 100644
index 0000000..fe7d96b
--- /dev/null
+++ b/tests/corelib/symbol_reserved_word_error_test.dart
@@ -0,0 +1,507 @@
+// 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.
+
+main() {
+  // ----- 'void' is allowed as a symbol name.
+
+  #void;
+  const Symbol('void');
+  new Symbol('void');
+
+  // ----- 'void' is not allowed in a dot-separated multi-part symbol literal.
+
+  #void.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.void;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  // ----- All other reserved words are disallowed.
+
+  #assert;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #break;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #case;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #catch;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #class;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #const;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #continue;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #default;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #do;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #else;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #enum;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #extends;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #false;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #final;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #finally;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #for;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #if;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #in;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #is;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #new;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #null;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #rethrow;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #return;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #super;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #switch;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #this;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #throw;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #true;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #try;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #var;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #while;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #with;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  // ----- Reserved words also disallowed in dot-separated multi-part symbol.
+
+  #foo.assert;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.break;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.case;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.catch;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.class;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.const;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.continue;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.default;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.do;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.else;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.enum;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.extends;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.false;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.final;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.finally;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.for;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.if;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.in;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.is;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.new;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.null;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.rethrow;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.return;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.super;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.switch;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.this;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.throw;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.true;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.try;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.var;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.while;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #foo.with;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #assert.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #break.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #case.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #catch.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #class.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #const.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #continue.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #default.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #do.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #else.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #enum.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #extends.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #false.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #final.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #finally.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #for.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #if.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #in.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #is.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #new.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #null.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #rethrow.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #return.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #super.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #switch.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #this.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #throw.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #true.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #try.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #var.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #while.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  #with.foo;
+  //^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+}
diff --git a/tests/corelib/symbol_reserved_word_test.dart b/tests/corelib/symbol_reserved_word_test.dart
index d6eec3b..961bdcd 100644
--- a/tests/corelib/symbol_reserved_word_test.dart
+++ b/tests/corelib/symbol_reserved_word_test.dart
@@ -4,121 +4,225 @@
 
 import "package:expect/expect.dart";
 
-void checkBadSymbol(String s) {
-  Expect.throwsArgumentError(() => new Symbol(s));
+var b = true;
+
+@pragma("vm:never-inline")
+void checkSymbol(String string) {
+  // Just check that it can be created.
+  new Symbol(string);
+  // Prevent inlining.
+  try {} finally {}
 }
 
 main() {
   var x;
 
   // 'void' is allowed as a symbol name.
-  x = const Symbol('void'); //     //# 01: ok
-  x = #void; //                    //# 02: ok
-  x = new Symbol('void'); //       //# 03: ok
+  x = const Symbol('void');
+  x = #void;
+  x = new Symbol('void');
 
-  // However, it is not allowed as a part of a symbol name.
-  x = const Symbol('void.foo'); // //# 04: compile-time error
-  x = #void.foo; //                //# 05: compile-time error
-  checkBadSymbol('void.foo'); //   //# 06: ok
-  x = const Symbol('foo.void'); // //# 07: compile-time error
-  x = #foo.void; //                //# 08: compile-time error
-  checkBadSymbol('foo.void'); //   //# 09: ok
+  // 'void' can be part of a dotted symbol name, via the constructor.
+  checkSymbol('void.foo');
+  checkSymbol('foo.void');
 
-  // All other reserved words are disallowed.
-  x = const Symbol('assert'); //   //# 10: compile-time error
-  x = const Symbol('break'); //    //# 10: continued
-  x = const Symbol('case'); //     //# 10: continued
-  x = const Symbol('catch'); //    //# 10: continued
-  x = const Symbol('class'); //    //# 10: continued
-  x = const Symbol('const'); //    //# 10: continued
-  x = const Symbol('continue'); // //# 10: continued
-  x = const Symbol('default'); //  //# 10: continued
-  x = const Symbol('do'); //       //# 10: continued
-  x = const Symbol('else'); //     //# 10: continued
-  x = const Symbol('enum'); //     //# 10: continued
-  x = const Symbol('extends'); //  //# 10: continued
-  x = #assert; //                  //# 11: compile-time error
-  x = const Symbol('false'); //    //# 10: continued
-  x = const Symbol('final'); //    //# 10: continued
-  x = const Symbol('finally'); //  //# 10: continued
-  x = const Symbol('for'); //      //# 10: continued
-  x = const Symbol('if'); //       //# 10: continued
-  x = const Symbol('in'); //       //# 10: continued
-  x = const Symbol('is'); //       //# 10: continued
-  x = const Symbol('new'); //      //# 10: continued
-  x = const Symbol('null'); //     //# 10: continued
-  x = const Symbol('rethrow'); //  //# 10: continued
-  x = const Symbol('return'); //   //# 10: continued
-  x = const Symbol('super'); //    //# 10: continued
-  x = const Symbol('switch'); //   //# 10: continued
-  x = const Symbol('this'); //     //# 10: continued
-  x = const Symbol('throw'); //    //# 10: continued
-  x = const Symbol('true'); //     //# 10: continued
-  x = const Symbol('try'); //      //# 10: continued
-  x = const Symbol('var'); //      //# 10: continued
-  x = const Symbol('while'); //    //# 10: continued
-  x = const Symbol('with'); //     //# 10: continued
-  x = #break; //                   //# 11: continued
-  x = #case; //                    //# 11: continued
-  x = #catch; //                   //# 11: continued
-  x = #class; //                   //# 11: continued
-  x = #const; //                   //# 11: continued
-  x = #continue; //                //# 11: continued
-  x = #default; //                 //# 11: continued
-  x = #do; //                      //# 11: continued
-  x = #else; //                    //# 11: continued
-  x = #enum; //                    //# 11: continued
-  x = #extends; //                 //# 11: continued
-  x = #false; //                   //# 11: continued
-  x = #final; //                   //# 11: continued
-  x = #finally; //                 //# 11: continued
-  x = #for; //                     //# 11: continued
-  x = #if; //                      //# 11: continued
-  x = #in; //                      //# 11: continued
-  x = #is; //                      //# 11: continued
-  x = #new; //                     //# 11: continued
-  x = #null; //                    //# 11: continued
-  x = #rethrow; //                 //# 11: continued
-  x = #return; //                  //# 11: continued
-  x = #super; //                   //# 11: continued
-  x = #switch; //                  //# 11: continued
-  x = #this; //                    //# 11: continued
-  x = #throw; //                   //# 11: continued
-  x = #true; //                    //# 11: continued
-  x = #try; //                     //# 11: continued
-  x = #var; //                     //# 11: continued
-  x = #while; //                   //# 11: continued
-  x = #with; //                    //# 11: continued
-  checkBadSymbol('assert'); //     //# 12: ok
-  checkBadSymbol('break'); //      //# 12: continued
-  checkBadSymbol('case'); //       //# 12: continued
-  checkBadSymbol('catch'); //      //# 12: continued
-  checkBadSymbol('class'); //      //# 12: continued
-  checkBadSymbol('const'); //      //# 12: continued
-  checkBadSymbol('continue'); //   //# 12: continued
-  checkBadSymbol('default'); //    //# 12: continued
-  checkBadSymbol('do'); //         //# 12: continued
-  checkBadSymbol('else'); //       //# 12: continued
-  checkBadSymbol('enum'); //       //# 12: continued
-  checkBadSymbol('extends'); //    //# 12: continued
-  checkBadSymbol('false'); //      //# 12: continued
-  checkBadSymbol('final'); //      //# 12: continued
-  checkBadSymbol('finally'); //    //# 12: continued
-  checkBadSymbol('for'); //        //# 12: continued
-  checkBadSymbol('if'); //         //# 12: continued
-  checkBadSymbol('in'); //         //# 12: continued
-  checkBadSymbol('is'); //         //# 12: continued
-  checkBadSymbol('new'); //        //# 12: continued
-  checkBadSymbol('null'); //       //# 12: continued
-  checkBadSymbol('rethrow'); //    //# 12: continued
-  checkBadSymbol('return'); //     //# 12: continued
-  checkBadSymbol('super'); //      //# 12: continued
-  checkBadSymbol('switch'); //     //# 12: continued
-  checkBadSymbol('this'); //       //# 12: continued
-  checkBadSymbol('throw'); //      //# 12: continued
-  checkBadSymbol('true'); //       //# 12: continued
-  checkBadSymbol('try'); //        //# 12: continued
-  checkBadSymbol('var'); //        //# 12: continued
-  checkBadSymbol('while'); //      //# 12: continued
-  checkBadSymbol('with'); //       //# 12: continued
+  // Reserved words are allowed, via the constructor.
+  checkSymbol('assert');
+  checkSymbol('break');
+  checkSymbol('case');
+  checkSymbol('catch');
+  checkSymbol('class');
+  checkSymbol('const');
+  checkSymbol('continue');
+  checkSymbol('default');
+  checkSymbol('do');
+  checkSymbol('else');
+  checkSymbol('enum');
+  checkSymbol('extends');
+  checkSymbol('false');
+  checkSymbol('final');
+  checkSymbol('finally');
+  checkSymbol('for');
+  checkSymbol('if');
+  checkSymbol('in');
+  checkSymbol('is');
+  checkSymbol('new');
+  checkSymbol('null');
+  checkSymbol('rethrow');
+  checkSymbol('return');
+  checkSymbol('super');
+  checkSymbol('switch');
+  checkSymbol('this');
+  checkSymbol('throw');
+  checkSymbol('true');
+  checkSymbol('try');
+  checkSymbol('var');
+  checkSymbol('while');
+  checkSymbol('with');
+
+  // Reserved words can also be part of a dot separated list, via constructor.
+  checkSymbol('foo.assert');
+  checkSymbol('foo.break');
+  checkSymbol('foo.case');
+  checkSymbol('foo.catch');
+  checkSymbol('foo.class');
+  checkSymbol('foo.const');
+  checkSymbol('foo.continue');
+  checkSymbol('foo.default');
+  checkSymbol('foo.do');
+  checkSymbol('foo.else');
+  checkSymbol('foo.enum');
+  checkSymbol('foo.extends');
+  checkSymbol('foo.false');
+  checkSymbol('foo.final');
+  checkSymbol('foo.finally');
+  checkSymbol('foo.for');
+  checkSymbol('foo.if');
+  checkSymbol('foo.in');
+  checkSymbol('foo.is');
+  checkSymbol('foo.new');
+  checkSymbol('foo.null');
+  checkSymbol('foo.rethrow');
+  checkSymbol('foo.return');
+  checkSymbol('foo.super');
+  checkSymbol('foo.switch');
+  checkSymbol('foo.this');
+  checkSymbol('foo.throw');
+  checkSymbol('foo.true');
+  checkSymbol('foo.try');
+  checkSymbol('foo.var');
+  checkSymbol('foo.while');
+  checkSymbol('foo.with');
+  checkSymbol('assert.foo');
+  checkSymbol('break.foo');
+  checkSymbol('case.foo');
+  checkSymbol('catch.foo');
+  checkSymbol('class.foo');
+  checkSymbol('const.foo');
+  checkSymbol('continue.foo');
+  checkSymbol('default.foo');
+  checkSymbol('do.foo');
+  checkSymbol('else.foo');
+  checkSymbol('enum.foo');
+  checkSymbol('extends.foo');
+  checkSymbol('false.foo');
+  checkSymbol('final.foo');
+  checkSymbol('finally.foo');
+  checkSymbol('for.foo');
+  checkSymbol('if.foo');
+  checkSymbol('in.foo');
+  checkSymbol('is.foo');
+  checkSymbol('new.foo');
+  checkSymbol('null.foo');
+  checkSymbol('rethrow.foo');
+  checkSymbol('return.foo');
+  checkSymbol('super.foo');
+  checkSymbol('switch.foo');
+  checkSymbol('this.foo');
+  checkSymbol('throw.foo');
+  checkSymbol('true.foo');
+  checkSymbol('try.foo');
+  checkSymbol('var.foo');
+  checkSymbol('while.foo');
+  checkSymbol('with.foo');
+
+  // A constant symbol with a reserved word is allowed, via constructor.
+  x = const Symbol('void.foo');
+  x = const Symbol('foo.void');
+  x = const Symbol('assert');
+  x = const Symbol('break');
+  x = const Symbol('case');
+  x = const Symbol('catch');
+  x = const Symbol('class');
+  x = const Symbol('const');
+  x = const Symbol('continue');
+  x = const Symbol('default');
+  x = const Symbol('do');
+  x = const Symbol('else');
+  x = const Symbol('enum');
+  x = const Symbol('extends');
+  x = const Symbol('false');
+  x = const Symbol('final');
+  x = const Symbol('finally');
+  x = const Symbol('for');
+  x = const Symbol('if');
+  x = const Symbol('in');
+  x = const Symbol('is');
+  x = const Symbol('new');
+  x = const Symbol('null');
+  x = const Symbol('rethrow');
+  x = const Symbol('return');
+  x = const Symbol('super');
+  x = const Symbol('switch');
+  x = const Symbol('this');
+  x = const Symbol('throw');
+  x = const Symbol('true');
+  x = const Symbol('try');
+  x = const Symbol('var');
+  x = const Symbol('while');
+  x = const Symbol('with');
+  x = const Symbol('foo.assert');
+  x = const Symbol('foo.break');
+  x = const Symbol('foo.case');
+  x = const Symbol('foo.catch');
+  x = const Symbol('foo.class');
+  x = const Symbol('foo.const');
+  x = const Symbol('foo.continue');
+  x = const Symbol('foo.default');
+  x = const Symbol('foo.do');
+  x = const Symbol('foo.else');
+  x = const Symbol('foo.enum');
+  x = const Symbol('foo.extends');
+  x = const Symbol('foo.false');
+  x = const Symbol('foo.final');
+  x = const Symbol('foo.finally');
+  x = const Symbol('foo.for');
+  x = const Symbol('foo.if');
+  x = const Symbol('foo.in');
+  x = const Symbol('foo.is');
+  x = const Symbol('foo.new');
+  x = const Symbol('foo.null');
+  x = const Symbol('foo.rethrow');
+  x = const Symbol('foo.return');
+  x = const Symbol('foo.super');
+  x = const Symbol('foo.switch');
+  x = const Symbol('foo.this');
+  x = const Symbol('foo.throw');
+  x = const Symbol('foo.true');
+  x = const Symbol('foo.try');
+  x = const Symbol('foo.var');
+  x = const Symbol('foo.while');
+  x = const Symbol('foo.with');
+  x = const Symbol('assert.foo');
+  x = const Symbol('break.foo');
+  x = const Symbol('case.foo');
+  x = const Symbol('catch.foo');
+  x = const Symbol('class.foo');
+  x = const Symbol('const.foo');
+  x = const Symbol('continue.foo');
+  x = const Symbol('default.foo');
+  x = const Symbol('do.foo');
+  x = const Symbol('else.foo');
+  x = const Symbol('enum.foo');
+  x = const Symbol('extends.foo');
+  x = const Symbol('false.foo');
+  x = const Symbol('final.foo');
+  x = const Symbol('finally.foo');
+  x = const Symbol('for.foo');
+  x = const Symbol('if.foo');
+  x = const Symbol('in.foo');
+  x = const Symbol('is.foo');
+  x = const Symbol('new.foo');
+  x = const Symbol('null.foo');
+  x = const Symbol('rethrow.foo');
+  x = const Symbol('return.foo');
+  x = const Symbol('super.foo');
+  x = const Symbol('switch.foo');
+  x = const Symbol('this.foo');
+  x = const Symbol('throw.foo');
+  x = const Symbol('true.foo');
+  x = const Symbol('try.foo');
+  x = const Symbol('var.foo');
+  x = const Symbol('while.foo');
+  x = const Symbol('with.foo');
 }
diff --git a/tests/standalone/io/unix_socket_test.dart b/tests/standalone/io/unix_socket_test.dart
index 7c84792..0553e6a 100644
--- a/tests/standalone/io/unix_socket_test.dart
+++ b/tests/standalone/io/unix_socket_test.dart
@@ -175,7 +175,11 @@
   if (!Platform.isLinux && !Platform.isAndroid) {
     return;
   }
+  var retries = 10;
+  var retryDelay = const Duration(seconds: 1);
   Process? process;
+  Future? stdoutFuture;
+  Future? stderrFuture;
   try {
     var socketAddress = '@hidden';
     var abstractSocketServer = getAbstractSocketTestFileName();
@@ -184,10 +188,36 @@
     if (!File(abstractSocketServer).existsSync()) {
       return;
     }
+
+    // Start up a subprocess that listens on '@hidden'.
     process = await Process.start(abstractSocketServer, [socketAddress]);
+    stdoutFuture = process.stdout
+        .transform(const Utf8Decoder(allowMalformed: true))
+        .listen(stdout.write)
+        .asFuture(null);
+    stderrFuture = process.stderr
+        .transform(const Utf8Decoder(allowMalformed: true))
+        .listen(stderr.write)
+        .asFuture(null);
     var serverAddress =
         InternetAddress(socketAddress, type: InternetAddressType.unix);
-    Socket client = await Socket.connect(serverAddress, 0);
+
+    // The subprocess may take some time to start, so retry setting up the
+    // connection a few times.
+    Socket? client;
+    while (true) {
+      try {
+        client = await Socket.connect(serverAddress, 0);
+        break;
+      } catch (e, st) {
+        if (retries <= 0) {
+          rethrow;
+        }
+        retries--;
+      }
+      await Future.delayed(retryDelay);
+    }
+
     List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
     List<int> data = [];
     var completer = Completer<void>();
@@ -206,6 +236,9 @@
     Expect.fail('Failed with exception:\n$e\n$st');
   } finally {
     process?.kill(ProcessSignal.sigkill);
+    await stdoutFuture;
+    await stderrFuture;
+    await process?.exitCode;
   }
 }
 
diff --git a/tests/standalone_2/io/unix_socket_test.dart b/tests/standalone_2/io/unix_socket_test.dart
index 0549fea..e63b9d8 100644
--- a/tests/standalone_2/io/unix_socket_test.dart
+++ b/tests/standalone_2/io/unix_socket_test.dart
@@ -5,8 +5,8 @@
 // @dart = 2.9
 
 import 'dart:async';
-import 'dart:io';
 import 'dart:convert';
+import 'dart:io';
 
 import 'package:expect/expect.dart';
 
@@ -177,7 +177,11 @@
   if (!Platform.isLinux && !Platform.isAndroid) {
     return;
   }
+  var retries = 10;
+  var retryDelay = const Duration(seconds: 1);
   Process process;
+  var stdoutFuture;
+  var stderrFuture;
   try {
     var socketAddress = '@hidden';
     var abstractSocketServer = getAbstractSocketTestFileName();
@@ -186,10 +190,36 @@
     if (!File(abstractSocketServer).existsSync()) {
       return;
     }
+
+    // Start up a subprocess that listens on '@hidden'.
     process = await Process.start(abstractSocketServer, [socketAddress]);
+    stdoutFuture = process.stdout
+        .transform(const Utf8Decoder(allowMalformed: true))
+        .listen(stdout.write)
+        .asFuture(null);
+    stderrFuture = process.stderr
+        .transform(const Utf8Decoder(allowMalformed: true))
+        .listen(stderr.write)
+        .asFuture(null);
     var serverAddress =
         InternetAddress(socketAddress, type: InternetAddressType.unix);
-    Socket client = await Socket.connect(serverAddress, 0);
+
+    // The subprocess may take some time to start, so retry setting up the
+    // connection a few times.
+    Socket client;
+    while (true) {
+      try {
+        client = await Socket.connect(serverAddress, 0);
+        break;
+      } catch (e, st) {
+        if (retries <= 0) {
+          rethrow;
+        }
+        retries--;
+      }
+      await Future.delayed(retryDelay);
+    }
+
     List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
     List<int> data = [];
     var completer = Completer<void>();
@@ -208,6 +238,9 @@
     Expect.fail('Failed with exception:\n$e\n$st');
   } finally {
     process?.kill(ProcessSignal.sigkill);
+    await stdoutFuture;
+    await stderrFuture;
+    await process?.exitCode;
   }
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index be9c9e0..f6daae7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 169
+PRERELEASE 170
 PRERELEASE_PATCH 0
\ No newline at end of file