Version 3.12.0-234.0.dev

Merge 2b36b13ecdf10f30c96175165b03b4aeff23ebae into dev
diff --git a/BUILD.gn b/BUILD.gn
index 2a6e0a1..c117953 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -61,6 +61,7 @@
     deps += [
       "runtime/bin:dartaotruntime",
       "runtime/bin:dartaotruntime_product",
+      "utils/dart_runtime_service_vm:dart_runtime_service_vm_aot_snapshot",
       "utils/dartdev:dartdev_aot_snapshot",
       "utils/dds:dds_aot",
       "utils/dtd:dtd_aot",
@@ -68,6 +69,7 @@
     ]
   } else {
     deps += [
+      "utils/dart_runtime_service_vm",
       "utils/dds",
       "utils/dtd",
       "utils/kernel-service:frontend_server",
diff --git a/pkg/analysis_server/lib/src/handler/legacy/edit_format.dart b/pkg/analysis_server/lib/src/handler/legacy/edit_format.dart
index 7f7d30b..a2da8d5 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/edit_format.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/edit_format.dart
@@ -7,9 +7,9 @@
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/handler/legacy/legacy_handler.dart';
-import 'package:analysis_server/src/utilities/extensions/formatter_options.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/src/utilities/formatter.dart';
 import 'package:dart_style/dart_style.dart' hide TrailingCommas;
 
 /// The handler for the `edit.format` request.
@@ -47,25 +47,17 @@
       length = null;
     }
 
+    var formatter = createFormatter(unit, defaultPageWidth: params.lineLength);
     var unformattedCode = unit.content;
-    var code = SourceCode(
-      unformattedCode,
-      selectionStart: start,
-      selectionLength: length,
-    );
-
-    var formatterOptions = unit.analysisOptions.formatterOptions;
-    var effectivePageWidth = formatterOptions.pageWidth ?? params.lineLength;
-    var effectiveTrailingCommas = formatterOptions.dartStyleTrailingCommas;
-    var effectiveLanguageVersion = unit.unit.languageVersion.effective;
-    var formatter = DartFormatter(
-      pageWidth: effectivePageWidth,
-      trailingCommas: effectiveTrailingCommas,
-      languageVersion: effectiveLanguageVersion,
-    );
     SourceCode formattedResult;
     try {
-      formattedResult = formatter.formatSource(code);
+      formattedResult = formatter.formatSource(
+        SourceCode(
+          unformattedCode,
+          selectionStart: start,
+          selectionLength: length,
+        ),
+      );
     } on FormatterException {
       sendResponse(Response.formatWithErrors(request));
       return;
diff --git a/pkg/analysis_server/lib/src/handler/legacy/edit_format_if_enabled.dart b/pkg/analysis_server/lib/src/handler/legacy/edit_format_if_enabled.dart
index acbfc4a..17ba7d2 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/edit_format_if_enabled.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/edit_format_if_enabled.dart
@@ -36,6 +36,9 @@
     var originalContent = file.readAsStringSync();
     var code = SourceCode(originalContent);
 
+    // TODO(dantup): Consider using createFormatter() which takes a result and
+    //  correctly applies settings like page_width, trailing_commas, and enabled
+    //  experiments.
     var formatter = DartFormatter(
       languageVersion: languageVersion ?? DartFormatter.latestLanguageVersion,
     );
diff --git a/pkg/analysis_server/lib/src/lsp/source_edits.dart b/pkg/analysis_server/lib/src/lsp/source_edits.dart
index e07a1a8..3adf3f8 100644
--- a/pkg/analysis_server/lib/src/lsp/source_edits.dart
+++ b/pkg/analysis_server/lib/src/lsp/source_edits.dart
@@ -8,7 +8,6 @@
 import 'package:analysis_server/src/protocol_server.dart'
     as server
     show SourceEdit;
-import 'package:analysis_server/src/utilities/extensions/formatter_options.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -17,6 +16,7 @@
 import 'package:analyzer/source/source.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/src/utilities/formatter.dart';
 import 'package:dart_style/dart_style.dart' hide TrailingCommas;
 
 /// Checks whether a string contains only characters that are allowed to differ
@@ -130,25 +130,10 @@
 }) {
   var unformattedSource = result.content;
 
-  var formatterOptions = result.analysisOptions.formatterOptions;
-  // The analysis options page width always takes priority over the default from
-  // the LSP configuration.
-  var effectivePageWidth = formatterOptions.pageWidth ?? defaultPageWidth;
-  var effectiveTrailingCommas = formatterOptions.dartStyleTrailingCommas;
-  var effectiveLanguageVersion = result.unit.languageVersion.effective;
-
-  var code = SourceCode(unformattedSource);
-  SourceCode formattedResult;
+  var formatter = createFormatter(result, defaultPageWidth: defaultPageWidth);
+  String formattedSource;
   try {
-    // Create a new formatter on every request because it may contain state that
-    // affects repeated formats.
-    // https://github.com/dart-lang/dart_style/issues/1337
-    var formatter = DartFormatter(
-      pageWidth: effectivePageWidth,
-      trailingCommas: effectiveTrailingCommas,
-      languageVersion: effectiveLanguageVersion,
-    );
-    formattedResult = formatter.formatSource(code);
+    formattedSource = formatter.format(unformattedSource);
   } on FormatterException {
     // If the document fails to parse, just return no edits to avoid the
     // use seeing edits on every save with invalid code (if LSP gains the
@@ -156,7 +141,6 @@
     // we may wish to change this to return an error for that case).
     return success(null);
   }
-  var formattedSource = formattedResult.text;
 
   if (formattedSource == unformattedSource) {
     return success(null);
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 4387c7b..1a71fd8 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -13850,6 +13850,7 @@
   ],
 )
 final class FunctionExpressionInvocationImpl extends InvocationExpressionImpl
+    with DotShorthandMixin
     implements RewrittenMethodInvocationImpl, FunctionExpressionInvocation {
   @generated
   ExpressionImpl _function;
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 8bd1bce..90a43e7 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -4042,16 +4042,14 @@
     var dotShorthand = pop() as ExpressionImpl;
     if (dotShorthand is DotShorthandMixin) {
       dotShorthand.isDotShorthand = true;
+    } else {
+      assert(
+        false,
+        "'$dotShorthand' must be a 'DotShorthandMixin' because we "
+        "should only call 'handleDotShorthandContext' after parsing "
+        "expressions that have a context type we can cache.",
+      );
     }
-    // TODO(kallentu): Add this assert once we've applied the DotShorthandMixin
-    // on all possible expressions that can be a dot shorthand.
-    // } else {
-    //   assert(
-    //       false,
-    //       "'$dotShorthand' must be a 'DotShorthandMixin' because we "
-    //       "should only call 'handleDotShorthandContext' after parsing "
-    //       "expressions that have a context type we can cache.");
-    // }
     push(dotShorthand);
   }
 
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 7fbb5b7..33b034d 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -3084,6 +3084,12 @@
     TypeImpl contextType = UnknownInferredType.instance,
   }) {
     inferenceLogWriter?.enterExpression(node, contextType);
+
+    // If [isDotShorthand] is set, cache the context type for resolution.
+    if (isDotShorthand(node)) {
+      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
+    }
+
     analyzeExpression(
       node.function,
       SharedTypeSchemaView(UnknownInferredType.instance),
@@ -3107,6 +3113,11 @@
       whyNotPromotedArguments,
     );
     _insertImplicitCallReference(replacement, contextType: contextType);
+
+    if (isDotShorthand(node)) {
+      popDotShorthandContext();
+    }
+
     inferenceLogWriter?.exitExpression(node);
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_constructor_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_constructor_invocation_test.dart
index dd54e93..a499c1a 100644
--- a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_constructor_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_constructor_invocation_test.dart
@@ -869,6 +869,279 @@
     );
   }
 
+  test_functionExpression() async {
+    await assertErrorsInCode(
+      r'''
+class C {}
+
+void main() {
+  final C _ = .new()();
+}
+''',
+      [error(diag.invocationOfNonFunctionExpression, 40, 6)],
+    );
+  }
+
+  test_functionExpression_call() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C call() => this;
+}
+
+void main() {
+  final C _ = .new()();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandConstructorInvocation
+    period: .
+    constructorName: SimpleIdentifier
+      token: new
+      element: <testLibrary>::@class::C::@constructor::new
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_argument() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C call(int x) => this;
+}
+
+void main() {
+  C _ = .new()(0);
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandConstructorInvocation
+    period: .
+    constructorName: SimpleIdentifier
+      token: new
+      element: <testLibrary>::@class::C::@constructor::new
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        correspondingParameter: <testLibrary>::@class::C::@method::call::@formalParameter::x
+        staticType: int
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function(int)
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_extension() async {
+    await assertNoErrorsInCode(r'''
+class C {}
+
+extension CallC on C {
+  C call() => this;
+}
+
+void main() {
+  final C _ = .new()();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandConstructorInvocation
+    period: .
+    constructorName: SimpleIdentifier
+      token: new
+      element: <testLibrary>::@class::C::@constructor::new
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@extension::CallC::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_generic() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C call<T>(T t) => this;
+}
+
+void main() {
+  C _ = .new()<int>(0);
+}
+''');
+
+    var constructor = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(constructor, r'''
+FunctionExpressionInvocation
+  function: DotShorthandConstructorInvocation
+    period: .
+    constructorName: SimpleIdentifier
+      token: new
+      element: <testLibrary>::@class::C::@constructor::new
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticType: C
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: int
+        element: dart:core::@class::int
+        type: int
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        correspondingParameter: ParameterMember
+          baseElement: <testLibrary>::@class::C::@method::call::@formalParameter::t
+          substitution: {T: int}
+        staticType: int
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function(int)
+  staticType: C
+  typeArgumentTypes
+    int
+''');
+  }
+
+  test_functionExpression_call_namedConstructor() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C.named();
+  C call() => this;
+}
+
+void main() {
+  final C _ = .named()();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandConstructorInvocation
+    period: .
+    constructorName: SimpleIdentifier
+      token: named
+      element: <testLibrary>::@class::C::@constructor::named
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_nested() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C(C c);
+  C.a();
+  C call() => this;
+}
+
+void main() {
+  C _ = .new(.a())();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandConstructorInvocation
+    period: .
+    constructorName: SimpleIdentifier
+      token: new
+      element: <testLibrary>::@class::C::@constructor::new
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      arguments
+        DotShorthandConstructorInvocation
+          period: .
+          constructorName: SimpleIdentifier
+            token: a
+            element: <testLibrary>::@class::C::@constructor::a
+            staticType: null
+          argumentList: ArgumentList
+            leftParenthesis: (
+            rightParenthesis: )
+          isDotShorthand: true
+          correspondingParameter: <testLibrary>::@class::C::@constructor::new::@formalParameter::c
+          staticType: C
+      rightParenthesis: )
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_nested() async {
+    await assertErrorsInCode(
+      r'''
+class C {
+  C(C c);
+  C.a();
+}
+
+void main() {
+  C _ = .new(.a())();
+}
+''',
+      [error(diag.invocationOfNonFunctionExpression, 54, 10)],
+    );
+  }
+
   test_nested_invocation() async {
     await assertNoErrorsInCode(r'''
 class C<T> {
diff --git a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_invocation_test.dart
index 903705b..4c7fb72 100644
--- a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_invocation_test.dart
@@ -149,95 +149,6 @@
 ''');
   }
 
-  test_call_getter() async {
-    await assertNoErrorsInCode(r'''
-class C {
-  const C();
-  static C get id1 => const C();
-  C call() => const C();
-}
-
-void main() {
-  C c1 = .id1();
-  print(c1);
-}
-''');
-
-    // The [DotShorthandInvocation] is rewritten to a
-    // [FunctionExpressionInvocation].
-    var node = findNode.singleFunctionExpressionInvocation;
-    assertResolvedNodeText(node, r'''
-FunctionExpressionInvocation
-  function: DotShorthandPropertyAccess
-    period: .
-    propertyName: SimpleIdentifier
-      token: id1
-      element: <testLibrary>::@class::C::@getter::id1
-      staticType: C
-    isDotShorthand: false
-    staticType: C
-  argumentList: ArgumentList
-    leftParenthesis: (
-    rightParenthesis: )
-  element: <testLibrary>::@class::C::@method::call
-  staticInvokeType: C Function()
-  staticType: C
-''');
-  }
-
-  test_call_noCallMethod() async {
-    await assertErrorsInCode(
-      r'''
-class C {
-  const C();
-  static C id1 = const C();
-}
-
-void main() {
-  C c1 = .id1();
-  print(c1);
-}
-''',
-      [error(diag.invocationOfNonFunctionExpression, 77, 4)],
-    );
-  }
-
-  test_call_property() async {
-    await assertNoErrorsInCode(r'''
-class C {
-  const C();
-  static C id1 = const C();
-  C call() => const C();
-}
-
-void main() {
-  C c1 = .id1();
-  print(c1);
-}
-''');
-
-    // The [DotShorthandInvocation] is rewritten to a
-    // [FunctionExpressionInvocation].
-    var node = findNode.singleFunctionExpressionInvocation;
-    assertResolvedNodeText(node, r'''
-FunctionExpressionInvocation
-  function: DotShorthandPropertyAccess
-    period: .
-    propertyName: SimpleIdentifier
-      token: id1
-      element: <testLibrary>::@class::C::@getter::id1
-      staticType: C
-    isDotShorthand: false
-    staticType: C
-  argumentList: ArgumentList
-    leftParenthesis: (
-    rightParenthesis: )
-  element: <testLibrary>::@class::C::@method::call
-  staticInvokeType: C Function()
-  staticType: C
-''');
-  }
-
   test_chain_method() async {
     await assertNoErrorsInCode(r'''
 class C {
@@ -471,6 +382,257 @@
 ''');
   }
 
+  test_functionExpression() async {
+    await assertErrorsInCode(
+      r'''
+class C {
+  static C member() => C();
+}
+
+void main() {
+  final C _ = .member()();
+}
+''',
+      [error(diag.invocationOfNonFunctionExpression, 69, 9)],
+    );
+  }
+
+  test_functionExpression_call() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static C member() => C();
+  C call() => this;
+}
+
+void main() {
+  final C _ = .member()();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandInvocation
+    period: .
+    memberName: SimpleIdentifier
+      token: member
+      element: <testLibrary>::@class::C::@method::member
+      staticType: C Function()
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticInvokeType: C Function()
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_argument() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static C member() => C();
+  C call(int a) => this;
+}
+
+void main() {
+  final C _ = .member()(1);
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandInvocation
+    period: .
+    memberName: SimpleIdentifier
+      token: member
+      element: <testLibrary>::@class::C::@method::member
+      staticType: C Function()
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticInvokeType: C Function()
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 1
+        correspondingParameter: <testLibrary>::@class::C::@method::call::@formalParameter::a
+        staticType: int
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function(int)
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_extension() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static C member() => C();
+}
+
+extension CallC on C {
+  C call() => this;
+}
+
+void main() {
+  final C _ = .member()();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandInvocation
+    period: .
+    memberName: SimpleIdentifier
+      token: member
+      element: <testLibrary>::@class::C::@method::member
+      staticType: C Function()
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticInvokeType: C Function()
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@extension::CallC::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_generic() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static C member() => C();
+  C call<T>(T t) => this;
+}
+
+void main() {
+  final C _ = .member()<int>(1);
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandInvocation
+    period: .
+    memberName: SimpleIdentifier
+      token: member
+      element: <testLibrary>::@class::C::@method::member
+      staticType: C Function()
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    isDotShorthand: false
+    staticInvokeType: C Function()
+    staticType: C
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: int
+        element: dart:core::@class::int
+        type: int
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 1
+        correspondingParameter: ParameterMember
+          baseElement: <testLibrary>::@class::C::@method::call::@formalParameter::t
+          substitution: {T: int}
+        staticType: int
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function(int)
+  staticType: C
+  typeArgumentTypes
+    int
+''');
+  }
+
+  test_functionExpression_call_nested() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static C member(C c) => C();
+  static C one() => C(); 
+  C call() => this;
+}
+
+void main() {
+  C _ = .member(.one())();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandInvocation
+    period: .
+    memberName: SimpleIdentifier
+      token: member
+      element: <testLibrary>::@class::C::@method::member
+      staticType: C Function(C)
+    argumentList: ArgumentList
+      leftParenthesis: (
+      arguments
+        DotShorthandInvocation
+          period: .
+          memberName: SimpleIdentifier
+            token: one
+            element: <testLibrary>::@class::C::@method::one
+            staticType: C Function()
+          argumentList: ArgumentList
+            leftParenthesis: (
+            rightParenthesis: )
+          isDotShorthand: true
+          correspondingParameter: <testLibrary>::@class::C::@method::member::@formalParameter::c
+          staticInvokeType: C Function()
+          staticType: C
+      rightParenthesis: )
+    isDotShorthand: false
+    staticInvokeType: C Function(C)
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_nested() async {
+    await assertErrorsInCode(
+      r'''
+class C {
+  static C member(C c) => C();
+  static C one() => C(); 
+}
+
+void main() {
+  C _ = .member(.one())();
+}
+''',
+      [error(diag.invocationOfNonFunctionExpression, 92, 15)],
+    );
+  }
+
   test_futureOr() async {
     await assertNoErrorsInCode(r'''
 import 'dart:async';
diff --git a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart
index f9175fb..0c7f1de 100644
--- a/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/dot_shorthand_property_access_test.dart
@@ -464,6 +464,256 @@
 ''');
   }
 
+  test_functionExpression_call_argument() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static final C field = C();
+  C call(int a) => this;
+}
+
+void main() {
+  final C _ = .field(1);
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandPropertyAccess
+    period: .
+    propertyName: SimpleIdentifier
+      token: field
+      element: <testLibrary>::@class::C::@getter::field
+      staticType: C
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 1
+        correspondingParameter: <testLibrary>::@class::C::@method::call::@formalParameter::a
+        staticType: int
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function(int)
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_extension_field() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static final C field = C();
+}
+
+extension CallC on C {
+  C call() => this;
+}
+
+void main() {
+  final C _ = .field();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandPropertyAccess
+    period: .
+    propertyName: SimpleIdentifier
+      token: field
+      element: <testLibrary>::@class::C::@getter::field
+      staticType: C
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@extension::CallC::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_extension_getter() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static C get getter => C();
+}
+
+extension CallC on C {
+  C call() => this;
+}
+
+void main() {
+  final C _ = .getter();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandPropertyAccess
+    period: .
+    propertyName: SimpleIdentifier
+      token: getter
+      element: <testLibrary>::@class::C::@getter::getter
+      staticType: C
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@extension::CallC::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_field() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static final C field = C();
+  C call() => this;
+}
+
+void main() {
+  final C _ = .field();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandPropertyAccess
+    period: .
+    propertyName: SimpleIdentifier
+      token: field
+      element: <testLibrary>::@class::C::@getter::field
+      staticType: C
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_call_generic() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static final C field = C();
+  C call<T>(T t) => this;
+}
+
+void main() {
+  final C _ = .field<int>(1);
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandPropertyAccess
+    period: .
+    propertyName: SimpleIdentifier
+      token: field
+      element: <testLibrary>::@class::C::@getter::field
+      staticType: C
+    isDotShorthand: false
+    staticType: C
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: int
+        element: dart:core::@class::int
+        type: int
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 1
+        correspondingParameter: ParameterMember
+          baseElement: <testLibrary>::@class::C::@method::call::@formalParameter::t
+          substitution: {T: int}
+        staticType: int
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function(int)
+  staticType: C
+  typeArgumentTypes
+    int
+''');
+  }
+
+  test_functionExpression_call_getter() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static C get getter => C();
+  C call() => this;
+}
+
+void main() {
+  final C _ = .getter();
+}
+''');
+
+    var node = findNode.singleFunctionExpressionInvocation;
+    assertResolvedNodeText(node, r'''
+FunctionExpressionInvocation
+  function: DotShorthandPropertyAccess
+    period: .
+    propertyName: SimpleIdentifier
+      token: getter
+      element: <testLibrary>::@class::C::@getter::getter
+      staticType: C
+    isDotShorthand: false
+    staticType: C
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  element: <testLibrary>::@class::C::@method::call
+  staticInvokeType: C Function()
+  staticType: C
+''');
+  }
+
+  test_functionExpression_field() async {
+    await assertErrorsInCode(
+      r'''
+class C {
+  static final C field = C();
+}
+
+void main() {
+  final C _ = .field();
+}
+''',
+      [error(diag.invocationOfNonFunctionExpression, 71, 6)],
+    );
+  }
+
+  test_functionExpression_getter() async {
+    await assertErrorsInCode(
+      r'''
+class C {
+  static C get getter => C();
+}
+
+void main() {
+  final C _ = .getter();
+}
+''',
+      [error(diag.invocationOfNonFunctionExpression, 71, 7)],
+    );
+  }
+
   test_functionReference() async {
     await assertNoErrorsInCode(r'''
 class C<T> {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 69448af..57d348d 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -23,6 +23,7 @@
 import 'package:analyzer_plugin/src/utilities/charcodes.dart';
 import 'package:analyzer_plugin/src/utilities/directive_sort.dart';
 import 'package:analyzer_plugin/src/utilities/extensions/resolved_unit_result.dart';
+import 'package:analyzer_plugin/src/utilities/formatter.dart';
 import 'package:analyzer_plugin/src/utilities/library.dart';
 import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
@@ -1895,16 +1896,14 @@
       }
     }
 
-    var languageVersion = resolvedUnit.libraryElement.languageVersion.effective;
-    var formattedResult = DartFormatter(languageVersion: languageVersion)
-        .formatSource(
-          SourceCode(
-            newContent,
-            isCompilationUnit: true,
-            selectionStart: newRangeOffset,
-            selectionLength: newRangeLength,
-          ),
-        );
+    var formatter = createFormatter(resolvedUnit);
+    var formattedResult = formatter.formatSource(
+      SourceCode(
+        newContent,
+        selectionStart: newRangeOffset,
+        selectionLength: newRangeLength,
+      ),
+    );
 
     replaceEdits(
       range,
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/formatter_options.dart b/pkg/analyzer_plugin/lib/src/utilities/extensions/formatter_options.dart
similarity index 100%
rename from pkg/analysis_server/lib/src/utilities/extensions/formatter_options.dart
rename to pkg/analyzer_plugin/lib/src/utilities/extensions/formatter_options.dart
diff --git a/pkg/analyzer_plugin/lib/src/utilities/formatter.dart b/pkg/analyzer_plugin/lib/src/utilities/formatter.dart
new file mode 100644
index 0000000..152983c
--- /dev/null
+++ b/pkg/analyzer_plugin/lib/src/utilities/formatter.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2026, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart'
+    show ExperimentStatus;
+import 'package:analyzer_plugin/src/utilities/extensions/formatter_options.dart';
+import 'package:dart_style/dart_style.dart';
+
+/// A list of all features that are currently enabled by an experiment flag.
+final _allowedExperiments = ExperimentStatus.knownFeatures.values
+    .where((feature) => feature.status == FeatureStatus.future)
+    .toList();
+
+/// Creates a formatter with the appropriate settings for [result].
+DartFormatter createFormatter(
+  ParsedUnitResult result, {
+  int? defaultPageWidth,
+}) {
+  var featureSet = result.unit.featureSet;
+  var formatterOptions = result.analysisOptions.formatterOptions;
+  var effectivePageWidth = formatterOptions.pageWidth ?? defaultPageWidth;
+  var effectiveTrailingCommas = formatterOptions.dartStyleTrailingCommas;
+  var effectiveLanguageVersion = result.unit.languageVersion.effective;
+  return DartFormatter(
+    pageWidth: effectivePageWidth,
+    trailingCommas: effectiveTrailingCommas,
+    languageVersion: effectiveLanguageVersion,
+    experimentFlags: _getExperiments(featureSet),
+  );
+}
+
+/// Gets the list of experiment strings enabled by [featureSet] that are
+/// required for future features.
+List<String> _getExperiments(FeatureSet featureSet) {
+  return _allowedExperiments
+      .where(featureSet.isEnabled)
+      .map((feature) => feature.enableString)
+      .toList();
+}
diff --git a/pkg/analyzer_plugin/test/src/utilities/formatter_test.dart b/pkg/analyzer_plugin/test/src/utilities/formatter_test.dart
new file mode 100644
index 0000000..2c6cd462
--- /dev/null
+++ b/pkg/analyzer_plugin/test/src/utilities/formatter_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2026, 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:analyzer_plugin/src/utilities/formatter.dart';
+import 'package:analyzer_testing/experiments/experiments.dart';
+import 'package:dart_style/dart_style.dart';
+import 'package:pub_semver/pub_semver.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../support/abstract_single_unit.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FormatterTest);
+  });
+}
+
+@reflectiveTest
+class FormatterTest extends AbstractSingleUnitTest {
+  Future<void> test_experiments() async {
+    await resolveTestCode('');
+    var formatter = createFormatter(result);
+    expect(formatter.experimentFlags, experimentsForTests);
+  }
+
+  Future<void> test_languageVersion_default() async {
+    await resolveTestCode('');
+    var formatter = createFormatter(result);
+    expect(formatter.languageVersion, DartFormatter.latestLanguageVersion);
+  }
+
+  Future<void> test_languageVersion_override() async {
+    await resolveTestCode('// @dart=2.12');
+    var formatter = createFormatter(result);
+    expect(formatter.languageVersion, Version(2, 12, 0));
+  }
+
+  Future<void> test_pageWidth() async {
+    newFile(convertPath('$testPackageRootPath/analysis_options.yaml'), '''
+formatter:
+  page_width: 123
+''');
+    await resolveTestCode('');
+    var formatter = createFormatter(result);
+    expect(formatter.pageWidth, 123);
+  }
+
+  Future<void> test_trailingCommas() async {
+    newFile(convertPath('$testPackageRootPath/analysis_options.yaml'), '''
+formatter:
+  trailing_commas: preserve
+''');
+    await resolveTestCode('');
+    var formatter = createFormatter(result);
+    expect(formatter.trailingCommas, TrailingCommas.preserve);
+  }
+}
diff --git a/pkg/analyzer_plugin/test/src/utilities/test_all.dart b/pkg/analyzer_plugin/test/src/utilities/test_all.dart
index fb88ce8..49bf1b4 100644
--- a/pkg/analyzer_plugin/test/src/utilities/test_all.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/test_all.dart
@@ -7,6 +7,7 @@
 import 'change_builder/test_all.dart' as change_builder;
 import 'client_uri_converter_test.dart' as client_uri_converter;
 import 'completion/test_all.dart' as completion;
+import 'formatter_test.dart' as formatter;
 import 'navigation/test_all.dart' as navigation;
 import 'string_utilities_test.dart' as string_utilities;
 import 'visitors/test_all.dart' as visitors;
@@ -16,6 +17,7 @@
     change_builder.main();
     client_uri_converter.main();
     completion.main();
+    formatter.main();
     navigation.main();
     string_utilities.main();
     visitors.main();
diff --git a/pkg/dart_runtime_service/lib/dart_runtime_service.dart b/pkg/dart_runtime_service/lib/dart_runtime_service.dart
index 4adf99d..5d7cd08 100644
--- a/pkg/dart_runtime_service/lib/dart_runtime_service.dart
+++ b/pkg/dart_runtime_service/lib/dart_runtime_service.dart
@@ -6,3 +6,4 @@
 export 'src/dart_runtime_service_backend.dart';
 export 'src/dart_runtime_service_options.dart';
 export 'src/exceptions.dart';
+export 'src/rpc_exceptions.dart';
diff --git a/pkg/dart_runtime_service/lib/src/clients.dart b/pkg/dart_runtime_service/lib/src/clients.dart
index 38f9e1f..2e8060a 100644
--- a/pkg/dart_runtime_service/lib/src/clients.dart
+++ b/pkg/dart_runtime_service/lib/src/clients.dart
@@ -7,6 +7,8 @@
 import 'package:meta/meta.dart';
 import 'package:stream_channel/stream_channel.dart';
 
+import 'dart_runtime_service.dart';
+import 'dart_runtime_service_backend.dart';
 import 'dart_runtime_service_rpcs.dart';
 import 'event_streams.dart';
 import 'rpc_exceptions.dart';
@@ -22,6 +24,7 @@
     required StreamChannel<String> connection,
     required UnmodifiableNamedLookup<Client> clients,
     required EventStreamMethods eventStreamMethods,
+    required this.backend,
   }) {
     _clientPeer = json_rpc.Peer(connection, strictProtocolChecks: false);
     _internalRpcs = DartRuntimeServiceRpcs(
@@ -35,6 +38,7 @@
 
   late json_rpc.Peer _clientPeer;
   late final DartRuntimeServiceRpcs _internalRpcs;
+  final DartRuntimeServiceBackend backend;
 
   /// The logger to be used when handling requests from this client.
   Logger get logger => Logger('Client ($name)');
@@ -66,6 +70,9 @@
   @mustCallSuper
   void registerRpcHandlers() {
     _internalRpcs.registerRpcsWithPeer(_clientPeer);
+    backend.registerRpcs(_clientPeer);
+    _internalRpcs.registerServiceExtensionForwarder(_clientPeer);
+    backend.registerFallbacks(_clientPeer);
   }
 
   /// Attempts to register a [service] to be provided by this client.
@@ -159,10 +166,10 @@
 ///
 /// Call [addClient] when a client connects to your service.
 base class ClientManager {
-  ClientManager({required this.eventStreamMethods});
+  ClientManager({required this.backend, required this.eventStreamMethods});
 
   static const _kServicePrologue = 's';
-
+  final DartRuntimeServiceBackend backend;
   final EventStreamMethods eventStreamMethods;
 
   /// The set of [Client]s currently connected to the service.
@@ -183,6 +190,7 @@
       connection: connection,
       clients: UnmodifiableNamedLookup(clients),
       eventStreamMethods: eventStreamMethods,
+      backend: backend,
     );
     final namespace = clients.add(client);
     client.initialize(namespace: namespace).then((_) {
diff --git a/pkg/dart_runtime_service/lib/src/dart_runtime_service.dart b/pkg/dart_runtime_service/lib/src/dart_runtime_service.dart
index 3ceaff1..754883d 100644
--- a/pkg/dart_runtime_service/lib/src/dart_runtime_service.dart
+++ b/pkg/dart_runtime_service/lib/src/dart_runtime_service.dart
@@ -18,6 +18,8 @@
 import 'handlers.dart';
 import 'utils.dart';
 
+typedef RpcResponse = Map<String, Object?>;
+
 class DartRuntimeService {
   DartRuntimeService._({required this.config, required this.backend})
     : authCode = config.disableAuthCodes ? null : generateSecret() {
@@ -26,12 +28,12 @@
     }
   }
 
-  static Future<DartRuntimeService> start({
+  static Future<DartRuntimeService> initialize({
     required DartRuntimeServiceOptions config,
     required DartRuntimeServiceBackend backend,
   }) async {
     final service = DartRuntimeService._(config: config, backend: backend);
-    await service._startService();
+    await service._initialize();
     return service;
   }
 
@@ -40,10 +42,31 @@
   final DartRuntimeServiceBackend backend;
 
   /// The ws:// URI pointing to this [DartRuntimeService]'s server.
-  Uri get uri => _uri!;
+  ///
+  /// Throws [DartRuntimeServiceServerNotRunning] if the HTTP server is not
+  /// active.
+  Uri get uri {
+    if (_server == null) {
+      throw const DartRuntimeServiceServerNotRunning();
+    }
+    return _uri!;
+  }
+
   Uri? _uri;
 
+  /// The http:// URI pointing to this [DartRuntimeService]'s server.
+  ///
+  /// Throws [DartRuntimeServiceServerNotRunning] if the HTTP server is not
+  /// active.
+  Uri get httpUri => uri.replace(scheme: 'http');
+
   /// The sse:// URI pointing to this [DartRuntimeService]'s server.
+  ///
+  /// Throws [StateError] if [DartRuntimeServiceOptions.sseHandlerPath] is not
+  /// set.
+  ///
+  /// Throws [DartRuntimeServiceServerNotRunning] if the HTTP server is not
+  /// active.
   Uri get sseUri {
     if (config.sseHandlerPath == null) {
       throw StateError('SSE handler path not configured.');
@@ -63,6 +86,7 @@
 
   @visibleForTesting
   late final ClientManager clientManager = ClientManager(
+    backend: backend,
     eventStreamMethods: eventStreamManager,
   );
 
@@ -73,15 +97,42 @@
 
   HttpServer? _server;
 
+  /// Initializes the service's state without starting the web server.
+  Future<void> _initialize() async {
+    await backend.initialize();
+
+    if (config.autoStart) {
+      _logger.info('Autostart enabled. Starting server.');
+      await _startServer();
+    }
+    await backend.onServiceReady(this);
+  }
+
   /// Shuts down the service and cleans up backend state.
   Future<void> shutdown() async {
-    await _server?.close(force: true);
-    await clientManager.shutdown();
+    await backend.clearState();
     await backend.shutdown();
+    await _shutdownServer();
+    await clientManager.shutdown();
     Logger.root.clearListeners();
   }
 
-  Future<void> _startService() async {
+  Future<void> toggleServer() async {
+    // TODO(bkonyi): verify there's no race conditions
+    if (_server != null) {
+      await _shutdownServer();
+    } else {
+      await _startServer();
+    }
+  }
+
+  Future<void> _startServer() async {
+    if (_server != null) {
+      _logger.warning(
+        "Attempted to start the HTTP server, but it's already running.",
+      );
+      throw const DartRuntimeServiceServerAlreadyRunning();
+    }
     // TODO(bkonyi): support IPv6
     final host = InternetAddress.loopbackIPv4.host;
 
@@ -120,11 +171,28 @@
       port: server.port,
       path: authCode != null ? '/$authCode' : '',
     );
+    await backend.onServerStarted(httpUri: httpUri, wsUri: uri);
     _logger.info(
-      'Dart Runtime Service started successfully and is listening at $uri.',
+      'Dart Runtime Service HTTP server started successfully and is listening '
+      'at $uri.',
     );
   }
 
+  Future<void> _shutdownServer() async {
+    final server = _server;
+    if (server == null) {
+      _logger.warning(
+        "Attempting to shut down the HTTP server, but it's not "
+        'running.',
+      );
+      throw const DartRuntimeServiceServerNotRunning();
+    }
+    _logger.info('Dart Runtime Service HTTP server is shutting down.');
+    _server = null;
+    _uri = null;
+    await server.close();
+  }
+
   shelf.Handler _handlers() {
     _logger.info('Building Shelf handlers.');
     var pipeline = const shelf.Pipeline();
diff --git a/pkg/dart_runtime_service/lib/src/dart_runtime_service_backend.dart b/pkg/dart_runtime_service/lib/src/dart_runtime_service_backend.dart
index e84aa1d..fc814d3 100644
--- a/pkg/dart_runtime_service/lib/src/dart_runtime_service_backend.dart
+++ b/pkg/dart_runtime_service/lib/src/dart_runtime_service_backend.dart
@@ -2,10 +2,50 @@
 // 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:json_rpc_2/json_rpc_2.dart' as json_rpc;
+
 import 'dart_runtime_service.dart';
 
 /// A backend implementation of a service used to inject non-common
 /// functionality into a [DartRuntimeService].
 abstract class DartRuntimeServiceBackend {
+  /// Invoked by the [DartRuntimeService] when the service is initializing,
+  /// before the service's HTTP server is started.
+  ///
+  /// The backend should not expect for this to be invoked more than once.
+  Future<void> initialize();
+
+  /// Invoked by the [DartRuntimeService] once it has completely finished
+  /// initializing.
+  ///
+  /// The backend should not expect for this to be invoked more than once.
+  Future<void> onServiceReady(DartRuntimeService service);
+
+  /// Invoked by the [DartRuntimeService] when the service is shutting down,
+  /// allowing for the backend to clean up its state.
+  ///
+  /// The backend should not expect to be reinitialized after shutting down.
   Future<void> shutdown();
+
+  /// Invoked by the [DartRuntimeService] when the service is no longer
+  /// available, either due to the HTTP server being disabled or the service
+  /// shutting down.
+  ///
+  /// This is always invoked immediately before [shutdown].
+  Future<void> clearState();
+
+  /// Invoked by the [DartRuntimeService] when the service's HTTP server has
+  /// started.
+  Future<void> onServerStarted({required Uri httpUri, required Uri wsUri});
+
+  /// Invoked by the [DartRuntimeService] to register handlers for the RPCs
+  /// provided by the backend.
+  void registerRpcs(json_rpc.Peer clientPeer);
+
+  /// Invoked by the [DartRuntimeService] to register fallback handlers
+  /// provided by the backend.
+  ///
+  /// Backend fallbacks are executed after incoming RPC requests fail to match
+  /// any registered RPCs or service extensions provided by other clients.
+  void registerFallbacks(json_rpc.Peer clientPeer);
 }
diff --git a/pkg/dart_runtime_service/lib/src/dart_runtime_service_options.dart b/pkg/dart_runtime_service/lib/src/dart_runtime_service_options.dart
index a33a9bf..6325503 100644
--- a/pkg/dart_runtime_service/lib/src/dart_runtime_service_options.dart
+++ b/pkg/dart_runtime_service/lib/src/dart_runtime_service_options.dart
@@ -11,6 +11,7 @@
     this.port = 0,
     this.disableAuthCodes = false,
     this.sseHandlerPath,
+    this.autoStart = true,
   });
 
   /// If true, enables log output for the service.
@@ -33,17 +34,22 @@
   /// Defaults to null.
   final String? sseHandlerPath;
 
+  /// If true, the HTTP server will be started on initialization.
+  final bool autoStart;
+
   DartRuntimeServiceOptions copyWith({
     bool? enableLogging,
     int? port,
     bool? disableAuthCodes,
     String? sseHandlerPath,
+    bool? autoStart,
   }) {
     return DartRuntimeServiceOptions(
       enableLogging: enableLogging ?? this.enableLogging,
       port: port ?? this.port,
       disableAuthCodes: disableAuthCodes ?? this.disableAuthCodes,
       sseHandlerPath: sseHandlerPath ?? this.sseHandlerPath,
+      autoStart: autoStart ?? this.autoStart,
     );
   }
 }
diff --git a/pkg/dart_runtime_service/lib/src/dart_runtime_service_rpcs.dart b/pkg/dart_runtime_service/lib/src/dart_runtime_service_rpcs.dart
index 47e0607..ff9066c 100644
--- a/pkg/dart_runtime_service/lib/src/dart_runtime_service_rpcs.dart
+++ b/pkg/dart_runtime_service/lib/src/dart_runtime_service_rpcs.dart
@@ -15,7 +15,6 @@
 import 'rpc_exceptions.dart';
 import 'utils.dart';
 
-typedef RpcResponse = Map<String, Object?>;
 typedef RpcHandlerWithNoParameters = FutureOr<RpcResponse> Function();
 typedef RpcHandlerWithParameters =
     FutureOr<RpcResponse> Function(json_rpc.Parameters);
@@ -80,7 +79,9 @@
         }
       });
     }
+  }
 
+  void registerServiceExtensionForwarder(json_rpc.Peer clientPeer) {
     clientPeer.registerFallback(serviceExtensionForwarderFallback);
   }
 
diff --git a/pkg/dart_runtime_service/lib/src/exceptions.dart b/pkg/dart_runtime_service/lib/src/exceptions.dart
index 11c7d60..6b3cc5c 100644
--- a/pkg/dart_runtime_service/lib/src/exceptions.dart
+++ b/pkg/dart_runtime_service/lib/src/exceptions.dart
@@ -20,3 +20,19 @@
   const DartRuntimeServiceFailedToStartException({required String message})
     : super(message: 'Failed to start: $message');
 }
+
+/// Thrown when the [DartRuntimeService] attempts to start the server when it's
+/// already active.
+final class DartRuntimeServiceServerAlreadyRunning
+    extends DartRuntimeServiceException {
+  const DartRuntimeServiceServerAlreadyRunning()
+    : super(message: 'The HTTP server is already running.');
+}
+
+/// Thrown when the [DartRuntimeService] attempts to shutdown the server when
+/// it's not active.
+final class DartRuntimeServiceServerNotRunning
+    extends DartRuntimeServiceException {
+  const DartRuntimeServiceServerNotRunning()
+    : super(message: 'The HTTP server is not running.');
+}
diff --git a/pkg/dart_runtime_service/lib/src/rpc_exceptions.dart b/pkg/dart_runtime_service/lib/src/rpc_exceptions.dart
index 09d1099..05252cb 100644
--- a/pkg/dart_runtime_service/lib/src/rpc_exceptions.dart
+++ b/pkg/dart_runtime_service/lib/src/rpc_exceptions.dart
@@ -8,8 +8,9 @@
 enum RpcException {
   // These error codes must be kept in sync with those in vm/json_stream.h and
   // vmservice.dart.
-  serverError(code: SERVER_ERROR, message: 'Server error'),
-  methodNotFound(code: METHOD_NOT_FOUND, message: 'Method not found'),
+  serverError(code: SERVER_ERROR, message: 'Server error.'),
+  methodNotFound(code: METHOD_NOT_FOUND, message: 'Method not found.'),
+  internalError(code: INTERNAL_ERROR, message: 'Internal error.'),
   connectionDisposed(code: -32010, message: 'Service connection disposed.'),
   featureDisabled(code: 100, message: 'Feature is disabled.'),
   streamAlreadySubscribed(code: 103, message: 'Stream already subscribed.'),
diff --git a/pkg/dart_runtime_service/test/utils/mocks.dart b/pkg/dart_runtime_service/test/utils/mocks.dart
index b098f0e..b55dc26 100644
--- a/pkg/dart_runtime_service/test/utils/mocks.dart
+++ b/pkg/dart_runtime_service/test/utils/mocks.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:dart_runtime_service/dart_runtime_service.dart';
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:test/fake.dart';
 
 /// Fake implementation of [DartRuntimeServiceBackend] that throws when
@@ -13,5 +14,26 @@
 base class FakeDartRuntimeServiceBackend extends Fake
     implements DartRuntimeServiceBackend {
   @override
+  Future<void> initialize() async {}
+
+  @override
+  Future<void> onServiceReady(DartRuntimeService service) async {}
+
+  @override
   Future<void> shutdown() async {}
+
+  @override
+  Future<void> clearState() async {}
+
+  @override
+  Future<void> onServerStarted({
+    required Uri httpUri,
+    required Uri wsUri,
+  }) async {}
+
+  @override
+  void registerRpcs(json_rpc.Peer clientPeer) {}
+
+  @override
+  void registerFallbacks(json_rpc.Peer clientPeer) {}
 }
diff --git a/pkg/dart_runtime_service/test/utils/utilities.dart b/pkg/dart_runtime_service/test/utils/utilities.dart
index 6366f16..7f25c23 100644
--- a/pkg/dart_runtime_service/test/utils/utilities.dart
+++ b/pkg/dart_runtime_service/test/utils/utilities.dart
@@ -22,7 +22,7 @@
   DartRuntimeService? service;
   addTearDown(() async => await service?.shutdown());
 
-  service = await DartRuntimeService.start(
+  service = await DartRuntimeService.initialize(
     config: config,
     backend: FakeDartRuntimeServiceBackend(),
   );
diff --git a/pkg/dart_runtime_service_vm/OWNERS b/pkg/dart_runtime_service_vm/OWNERS
new file mode 100644
index 0000000..104bde4
--- /dev/null
+++ b/pkg/dart_runtime_service_vm/OWNERS
@@ -0,0 +1 @@
+file:/tools/OWNERS_DEV_INFRA
\ No newline at end of file
diff --git a/pkg/dart_runtime_service_vm/analysis_options.yaml b/pkg/dart_runtime_service_vm/analysis_options.yaml
new file mode 100644
index 0000000..d5248da
--- /dev/null
+++ b/pkg/dart_runtime_service_vm/analysis_options.yaml
@@ -0,0 +1 @@
+include: ../dart_runtime_service/analysis_options.yaml
diff --git a/pkg/dart_runtime_service_vm/bin/vm_service_entrypoint.dart b/pkg/dart_runtime_service_vm/bin/vm_service_entrypoint.dart
new file mode 100644
index 0000000..2afe4c9
--- /dev/null
+++ b/pkg/dart_runtime_service_vm/bin/vm_service_entrypoint.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:dart_runtime_service/dart_runtime_service.dart';
+import 'package:dart_runtime_service_vm/dart_runtime_service_vm.dart';
+
+// ignore: unreachable_from_main
+const entrypoint = pragma(
+  'vm:entry-point',
+  !bool.fromEnvironment('dart.vm.product'),
+);
+
+// The TCP IP that DDS listens on.
+@entrypoint
+// ignore: unused_element
+String _ddsIP = '';
+
+// The TCP port that DDS listens on.
+@entrypoint
+// ignore: unused_element
+int _ddsPort = 0;
+
+// The TCP port that the HTTP server listens on.
+@entrypoint
+int _port = 0;
+
+// The TCP IP that the HTTP server listens on.
+@entrypoint
+// ignore: unused_element
+String _ip = '';
+
+// Should the HTTP server auto start?
+@entrypoint
+bool _autoStart = false;
+
+// Should the HTTP server require an auth code?
+@entrypoint
+bool _authCodesDisabled = false;
+
+// Should the HTTP server run in devmode?
+@entrypoint
+// ignore: unused_element
+bool _originCheckDisabled = false;
+
+// Location of file to output VM service connection info.
+@entrypoint
+// ignore: unused_element
+String? _serviceInfoFilename;
+
+@entrypoint
+// ignore: unused_element
+bool _isWindows = false;
+
+@entrypoint
+// ignore: unused_element
+bool _isFuchsia = false;
+
+@entrypoint
+Stream<ProcessSignal> Function(ProcessSignal signal)? _signalWatch;
+
+@entrypoint
+// ignore: unused_element
+StreamSubscription<ProcessSignal>? _signalSubscription;
+
+@entrypoint
+// ignore: unused_element
+bool _serveDevtools = true;
+
+@entrypoint
+// ignore: unused_element
+bool _enableServicePortFallback = false;
+
+@entrypoint
+// ignore: unused_element
+bool _waitForDdsToAdvertiseService = false;
+
+@entrypoint
+// ignore: unused_element
+bool _printDtd = false;
+
+// ignore: unused_element
+File? _residentCompilerInfoFile;
+
+@entrypoint
+// ignore: unused_element
+void _populateResidentCompilerInfoFile(
+  /// If either `--resident-compiler-info-file` or `--resident-server-info-file`
+  /// was supplied on the command line, the CLI argument should be forwarded as
+  /// the argument to this parameter. If neither option was supplied, the
+  /// argument to this parameter should be null.
+  String? residentCompilerInfoFilePathArgumentFromCli,
+) {
+  // TODO(bkonyi): implement
+}
+
+Future<void> main([List<String> args = const []]) async {
+  if (args case ['--help']) {
+    return;
+  }
+  await DartRuntimeService.initialize(
+    config: DartRuntimeServiceOptions(
+      enableLogging: true,
+      port: _port,
+      disableAuthCodes: _authCodesDisabled,
+      autoStart: _autoStart,
+    ),
+    backend: DartRuntimeServiceVMBackend(signalWatch: _signalWatch!),
+  );
+}
diff --git a/pkg/dart_runtime_service_vm/lib/dart_runtime_service_vm.dart b/pkg/dart_runtime_service_vm/lib/dart_runtime_service_vm.dart
new file mode 100644
index 0000000..0404404
--- /dev/null
+++ b/pkg/dart_runtime_service_vm/lib/dart_runtime_service_vm.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:dart_runtime_service/dart_runtime_service.dart';
+
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:logging/logging.dart';
+
+import 'src/native_bindings.dart';
+
+class DartRuntimeServiceVMBackend extends DartRuntimeServiceBackend {
+  /// The backend implementation for the Dart VM Service.
+  ///
+  /// [signalWatch] is the internal implementation of [ProcessSignal.watch],
+  /// which bypasses checks that prevent [ProcessSignal.sigquit] from being
+  /// watched.
+  DartRuntimeServiceVMBackend({required this.signalWatch});
+
+  /// The internal implementation of [ProcessSignal.watch].
+  final Stream<ProcessSignal> Function(ProcessSignal signal) signalWatch;
+
+  final _nativeBindings = NativeBindings();
+  final _logger = Logger('VM Backend');
+
+  StreamSubscription<ProcessSignal>? _sigquitSubscription;
+
+  @override
+  Future<void> initialize() async {
+    _logger.info('Initializing...');
+    _nativeBindings.onStart();
+    _logger.info('Initialized!');
+  }
+
+  @override
+  Future<void> onServiceReady(DartRuntimeService service) async {
+    // SIGQUIT isn't supported on Fuchsia or Windows.
+    if (Platform.isFuchsia || Platform.isWindows) {
+      return;
+    }
+    _sigquitSubscription = signalWatch(ProcessSignal.sigquit).listen((_) {
+      _logger.info('SIGQUIT received. Toggling VM Service HTTP server.');
+      service.toggleServer();
+    });
+  }
+
+  @override
+  Future<void> onServerStarted({
+    required Uri httpUri,
+    required Uri wsUri,
+  }) async {
+    // TODO(bkonyi): handle DDS connection case.
+    stdout.writeln('The Dart VM service is listening on $httpUri');
+    _nativeBindings.onServerAddressChange(httpUri.toString());
+  }
+
+  @override
+  Future<void> clearState() async {
+    // Do nothing for now.
+  }
+
+  @override
+  Future<void> shutdown() async {
+    await _sigquitSubscription?.cancel();
+    _nativeBindings.onExit();
+  }
+
+  @override
+  void registerRpcs(json_rpc.Peer clientPeer) {
+    // The VM service handles its service requests in service.cc.
+  }
+
+  @override
+  void registerFallbacks(json_rpc.Peer clientPeer) {
+    // If the registered Dart RPC handlers can't handle a request, forward it
+    // it to the native VM service implementation for processing.
+    clientPeer.registerFallback(sendToRuntime);
+  }
+
+  /// Sends service requests to the Dart VM runtime for processing.
+  Future<RpcResponse> sendToRuntime(json_rpc.Parameters request) async {
+    final method = request.method;
+    final params = request.asMap.cast<String, Object?>();
+    if (params case {'isolateId': final String _}) {
+      // TODO(bkonyi): handle isolate requests
+      RpcException.serverError.throwException();
+    }
+    return await _nativeBindings.sendToVM(method: method, params: params);
+  }
+}
diff --git a/pkg/dart_runtime_service_vm/lib/src/native_bindings.dart b/pkg/dart_runtime_service_vm/lib/src/native_bindings.dart
new file mode 100644
index 0000000..ee400b3
--- /dev/null
+++ b/pkg/dart_runtime_service_vm/lib/src/native_bindings.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This is a special situation where we're allowed to import dart:_vmservice
+// from outside the core libraries to access the native entrypoints.
+//
+// See VmTarget in package:vm for the exception for this library to access
+// dart:_vmservice.
+// ignore: uri_does_not_exist
+import 'dart:_vmservice' as vm_service_natives;
+import 'dart:async';
+import 'dart:convert';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:dart_runtime_service/dart_runtime_service.dart';
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+
+/// Allows for sending messages to the native VM service implementation.
+class NativeBindings {
+  static final jsonUtf8Decoder = json.fuse(utf8);
+
+  /// Sends a general RPC to the VM for processing.
+  ///
+  /// The RPC is not executed in the scope of any particular isolate.
+  Future<RpcResponse> sendToVM({
+    required String method,
+    required Map<String, Object?> params,
+  }) {
+    final receivePort = RawReceivePort(null, 'VM Message');
+    final completer = Completer<RpcResponse>();
+    receivePort.handler = (Object value) {
+      receivePort.close();
+      try {
+        completer.complete(_toResponse(value: value));
+      } on json_rpc.RpcException catch (e) {
+        completer.completeError(e);
+      }
+    };
+    vm_service_natives.sendRootServiceMessage(
+      _toRequest(responsePort: receivePort, method: method, params: params),
+    );
+    return completer.future;
+  }
+
+  /// Notifies the VM that the VM service server has finished initializing.
+  void onStart() => vm_service_natives.onStart();
+
+  /// Notifies the VM that the VM service server has finished exiting.
+  void onExit() => vm_service_natives.onExit();
+
+  /// Notifies the VM that the VM service server address has been updated.
+  ///
+  /// If [address] is null, the VM will assume the server is not running.
+  void onServerAddressChange(String? address) =>
+      vm_service_natives.onServerAddressChange(address);
+
+  RpcResponse _toResponse({required Object value}) {
+    const kResult = 'result';
+    const kError = 'error';
+    const kCode = 'code';
+    const kMessage = 'message';
+    const kData = 'data';
+
+    final Object? converted;
+    if (value case [final Uint8List utf8String]) {
+      converted = jsonUtf8Decoder.decode(utf8String);
+    } else {
+      RpcException.internalError.throwException();
+    }
+    if (converted case {kResult: final Map<String, Object?> result}) {
+      return result;
+    } else if (converted case {
+      kError: {kCode: final int code, kMessage: final String message},
+    }) {
+      final data = converted[kData];
+      throw json_rpc.RpcException(code, message, data: data);
+    } else {
+      RpcException.internalError.throwException();
+    }
+  }
+
+  // Calls toString on all non-String elements of [list]. We do this so all
+  // elements in the list are strings, making consumption by C++ simpler.
+  // This has a side effect that boolean literal values like true become 'true'
+  // and thus indistinguishable from the string literal 'true'.
+  static void _convertAllToStringInPlace(List<Object?> list) {
+    for (var i = 0; i < list.length; i++) {
+      list[i] = list[i].toString();
+    }
+  }
+
+  List<Object?> _toRequest({
+    required RawReceivePort responsePort,
+    required String method,
+    required Map<String, Object?> params,
+  }) {
+    final parametersAreObjects = _methodNeedsObjectParameters(method);
+    final keys = params.keys.toList(growable: false);
+    final values = params.values.cast<Object?>().toList(growable: false);
+    if (!parametersAreObjects) {
+      _convertAllToStringInPlace(values);
+    }
+
+    // This is the request ID that will be inserted into the JSON response in
+    // service.cc. package:json_rpc_2 already handles these IDs, so we just
+    // pass in a placeholder for now until we can update Service::InvokeMethod
+    // to not expect it.
+    // TODO(bkonyi): remove request ID from service message.
+    const kPlaceholderRequestId = -1;
+
+    // Keep in sync with Service::InvokeMethod in service.cc.
+    return List<Object?>.filled(7, null)
+      ..[0] =
+          0 // Make room for OOB message type.
+      ..[1] = responsePort.sendPort
+      ..[2] = kPlaceholderRequestId
+      ..[3] = method
+      ..[4] = parametersAreObjects
+      ..[5] = keys
+      ..[6] = values;
+  }
+
+  // We currently support two ways of passing parameters from Dart code to C
+  // code. The original way always converts the parameters to strings before
+  // passing them over. Our goal is to convert all C handlers to take the
+  // parameters as Dart objects but until the conversion is complete, we
+  // maintain the list of supported methods below.
+  bool _methodNeedsObjectParameters(String method) {
+    switch (method) {
+      case '_listDevFS':
+      case '_listDevFSFiles':
+      case '_createDevFS':
+      case '_deleteDevFS':
+      case '_writeDevFSFile':
+      case '_writeDevFSFiles':
+      case '_readDevFSFile':
+      case '_spawnUri':
+      case '_reloadKernel':
+      case '_reloadSources':
+      case 'reloadSources':
+        return true;
+      default:
+        return false;
+    }
+  }
+}
diff --git a/pkg/dart_runtime_service_vm/pubspec.yaml b/pkg/dart_runtime_service_vm/pubspec.yaml
new file mode 100644
index 0000000..0f7be90
--- /dev/null
+++ b/pkg/dart_runtime_service_vm/pubspec.yaml
@@ -0,0 +1,14 @@
+name: dart_runtime_service_vm
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
+
+environment:
+  sdk: ^3.8.0
+
+resolution: workspace
+
+# Use 'any' constraints here; we get our versions from the DEPS file.
+dependencies:
+  dart_runtime_service: any
+  json_rpc_2: any
+  logging: any
diff --git a/pkg/dtd_impl/bin/dtd.dart b/pkg/dtd_impl/bin/dtd.dart
index a8a3f0d..1a26bc9 100644
--- a/pkg/dtd_impl/bin/dtd.dart
+++ b/pkg/dtd_impl/bin/dtd.dart
@@ -12,7 +12,7 @@
 /// When [port] is non-null, the [DartToolingDaemon.startService] method will
 /// send information about the DTD connection back over [port] instead of
 /// printing it to stdout.
-void main(List<String> args, dynamic port) async {
+void main(List<String> args, Object? port) async {
   await DartToolingDaemon.startService(
     args,
     sendPort: port as SendPort?,
diff --git a/pkg/dtd_impl/lib/src/dtd_client.dart b/pkg/dtd_impl/lib/src/dtd_client.dart
index 602348e..c44f517 100644
--- a/pkg/dtd_impl/lib/src/dtd_client.dart
+++ b/pkg/dtd_impl/lib/src/dtd_client.dart
@@ -59,15 +59,18 @@
   Future<void> close() => _clientPeer.close();
 
   @override
-  Future<dynamic> sendRequest({
+  Future<Object?> sendRequest({
     required String method,
-    dynamic parameters,
+    Object? parameters,
   }) async {
     if (_clientPeer.isClosed) {
-      return;
+      return null;
     }
 
-    return await _clientPeer.sendRequest(method, parameters.value);
+    if (parameters == null) {
+      return await _clientPeer.sendRequest(method);
+    }
+    return await _clientPeer.sendRequest(method, parameters);
   }
 
   @override
@@ -399,7 +402,7 @@
 
     return await client.sendRequest(
       method: combinedName,
-      parameters: parameters,
+      parameters: parameters.value,
     );
   }
 
diff --git a/pkg/dtd_impl/test/dtd_test.dart b/pkg/dtd_impl/test/dtd_test.dart
index cb8caa2..682dfdf 100644
--- a/pkg/dtd_impl/test/dtd_test.dart
+++ b/pkg/dtd_impl/test/dtd_test.dart
@@ -404,8 +404,7 @@
         await client.close();
 
         // TODO: replace this polling when notification streams are implemented.
-
-        dynamic client2RegisterResult;
+        Object? client2RegisterResult;
         for (var i = 0; i < 10; i++) {
           try {
             // The service method registration should succeed once the other
diff --git a/pkg/linter/messages.yaml b/pkg/linter/messages.yaml
index f9c491c..fb1b205 100644
--- a/pkg/linter/messages.yaml
+++ b/pkg/linter/messages.yaml
@@ -13663,6 +13663,58 @@
       stable: "2.19"
     categories: [brevity]
     hasPublishedDocs: false
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a `library` directive
+      doesn't have a documentation comment or any annotations.
+
+      If no documentation comment or annotation precedes the library directive,
+      then either it's unnecessary or the documentation comment and/or
+      annotations are misplaced and should be moved.
+
+      #### Examples
+
+      The following code produces this diagnostic because the `library`
+      directive doesn't have a documentation comment or annotation:
+
+      ```dart
+      [!library;!]
+
+      class C {}
+      ```
+
+      The following code produces this diagnostic because the library's
+      documentation comment is below the `library` directive:
+
+      ```dart
+      [!library;!]
+
+      /// This library provides the [C] class.
+
+      /// The [C] class.
+      class C {}
+      ```
+
+      #### Common fixes
+
+      If you don't want to add a documentation comment or annotation
+      to the library, then remove the `library` directive:
+
+      ```dart
+      class C {}
+      ```
+
+      If you intend to add a documentation comment or annotation,
+      then add or move it to the `library` directive:
+
+      ```dart
+      /// This library provides the [C] class.
+      library;
+
+      /// The [C] class.
+      class C {}
+      ```
     deprecatedDetails: |-
       **DO** use library directives if you want to document a library and/or annotate
       a library.
diff --git a/pkg/vm/lib/modular/target/vm.dart b/pkg/vm/lib/modular/target/vm.dart
index 5e85637..3c9a4bf0 100644
--- a/pkg/vm/lib/modular/target/vm.dart
+++ b/pkg/vm/lib/modular/target/vm.dart
@@ -442,7 +442,9 @@
       importer.path.contains('runtime/tests/vm/dart') ||
       importer.path.contains('tests/standalone/io') ||
       importer.path.contains('test-lib') ||
-      importer.path.contains('tests/ffi');
+      importer.path.contains('tests/ffi') ||
+      (importer.path == 'dart_runtime_service_vm/src/native_bindings.dart' &&
+          imported.path == '_vmservice');
 
   @override
   Component configureComponent(Component component) {
diff --git a/pubspec.yaml b/pubspec.yaml
index cbb9143..43b6e92 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -39,6 +39,7 @@
   - pkg/dart_data_home
   - pkg/dart_internal
   - pkg/dart_runtime_service
+  - pkg/dart_runtime_service_vm
   - pkg/dart_service_protocol_shared
   - pkg/dds
   - pkg/dds_service_extensions
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 7f46c4b..ea85616 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -245,6 +245,10 @@
     defines += [ "DART_DYNAMIC_MODULES" ]
   }
 
+  if (include_experimental_vm_service) {
+    defines += [ "EXPERIMENTAL_VM_SERVICE" ]
+  }
+
   if (is_fuchsia) {
     lib_dirs = [ "${fuchsia_arch_root}/lib" ]
 
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index c73d77d..a1a7bda 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -886,7 +886,6 @@
       ":crashpad",
       ":icudtl_cc",
       "//third_party/boringssl",
-      "//third_party/icu:icui18n",
       "//third_party/icu:icuuc",
       "//third_party/zlib",
     ]
diff --git a/runtime/bin/dartdev.cc b/runtime/bin/dartdev.cc
index 42938f6..9829558 100644
--- a/runtime/bin/dartdev.cc
+++ b/runtime/bin/dartdev.cc
@@ -1065,24 +1065,12 @@
 
   Loader::InitOnce();
 
-  // Setup script_name to point to the dartdev AOT snapshot.
-  auto dartdev_path = DartDev::ResolvedSnapshotPath();
-  char* script_name = dartdev_path.get();
-  if (script_name == nullptr || !CheckForInvalidPath(script_name)) {
-    Syslog::PrintErr("Unable to find AOT snapshot for dartdev\n");
+  auto [app_snapshot, script_name] =
+      Snapshot::TryReadSDKSnapshot("dartdev_aot.dart.snapshot");
+  if (app_snapshot == nullptr) {
     FreeConvertedArgs(argc, argv, argv_converted);
     Platform::Exit(kErrorExitCode);
   }
-  AppSnapshot* app_snapshot = Snapshot::TryReadAppSnapshot(
-      script_name, /*force_load_from_memory*/ false, /*decode_uri*/ false);
-  if (app_snapshot == nullptr || !app_snapshot->IsAOT()) {
-    Syslog::PrintErr("%s is not an AOT snapshot\n", script_name);
-    FreeConvertedArgs(argc, argv, argv_converted);
-    if (app_snapshot != nullptr) {
-      delete app_snapshot;
-    }
-    Platform::Exit(kErrorExitCode);
-  }
   app_snapshot->SetBuffers(
       &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
       &app_isolate_snapshot_data, &app_isolate_snapshot_instructions);
@@ -1152,7 +1140,7 @@
   // - Exit the process due to some command parsing errors
   // - Run the Dart script in a JIT mode by execing the JIT runtime
   // - Run the Dart AOT snapshot by creating a new Isolate
-  DartDev::RunDartDev(script_name, &dart_vm_options, &dart_options);
+  DartDev::RunDartDev(script_name.get(), &dart_vm_options, &dart_options);
 
   // Terminate process exit-code handler.
   Process::TerminateExitCodeHandler();
diff --git a/runtime/bin/main_impl.cc b/runtime/bin/main_impl.cc
index 966f527..472dc1c 100644
--- a/runtime/bin/main_impl.cc
+++ b/runtime/bin/main_impl.cc
@@ -532,8 +532,6 @@
 #endif  // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
 
 // Returns newly created Service Isolate on success, nullptr on failure.
-// For now we only support the service isolate coming up from sources
-// which are compiled by the VM parser.
 static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
                                                  const char* packages_config,
                                                  Dart_IsolateFlags* flags,
@@ -547,30 +545,48 @@
                            packages_config, nullptr, false);
   ASSERT(flags != nullptr);
 
+  const uint8_t* isolate_snapshot_data = nullptr;
+  const uint8_t* isolate_snapshot_instructions = nullptr;
+
+#if defined(EXPERIMENTAL_VM_SERVICE)
+  if (Options::experimental_vm_service()) {
+    VmService::enable_experimental_vm_service = true;
+    auto [app_snapshot, script_name] = Snapshot::TryReadSDKSnapshot(
+#if defined(DART_PRECOMIPLED_RUNTIME)
+        "dart_runtime_service_vm_aot.dart.snapshot");
+#else
+        "dart_runtime_service_vm.dart.snapshot");
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+    if (app_snapshot == nullptr) {
+      Platform::Exit(kErrorExitCode);
+    }
+    const uint8_t* ignore_vm_snapshot_data;
+    const uint8_t* ignore_vm_snapshot_instructions;
+    app_snapshot->SetBuffers(
+        &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
+        &isolate_snapshot_data, &isolate_snapshot_instructions);
+  } else {
+#endif  // defined(EXPERIMENTAL_VM_SERVICE)
 #if defined(DART_PRECOMPILED_RUNTIME)
-  // AOT: The service isolate is included in any AOT snapshot in non-PRODUCT
-  // mode - so we launch the vm-service from the main app AOT snapshot.
-  const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
-  const uint8_t* isolate_snapshot_instructions =
-      app_isolate_snapshot_instructions;
-  isolate = Dart_CreateIsolateGroup(
-      script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
-      isolate_snapshot_instructions, flags, isolate_group_data,
-      /*isolate_data=*/nullptr, error);
+    // AOT: The service isolate is included in any AOT snapshot in non-PRODUCT
+    // mode - so we launch the vm-service from the main app AOT snapshot.
+    isolate_snapshot_data = app_isolate_snapshot_data;
+    isolate_snapshot_instructions = app_isolate_snapshot_instructions;
 #else
   // JIT: Service isolate uses the core libraries snapshot.
-
   // Set flag to load and retain the vmservice library.
   flags->load_vmservice_library = true;
   flags->null_safety = true;  // Service isolate runs in sound null safe mode.
-  const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
-  const uint8_t* isolate_snapshot_instructions =
-      core_isolate_snapshot_instructions;
+  isolate_snapshot_data = core_isolate_snapshot_data;
+  isolate_snapshot_instructions = core_isolate_snapshot_instructions;
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+#if defined(EXPERIMENTAL_VM_SERVICE)
+  }
+#endif  // defined(EXPERIMENTAL_VM_SERVICE)
   isolate = Dart_CreateIsolateGroup(
       script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
       isolate_snapshot_instructions, flags, isolate_group_data,
       /*isolate_data=*/nullptr, error);
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   if (isolate == nullptr) {
     delete isolate_group_data;
     return nullptr;
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 7210550..0c093ee 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -62,7 +62,8 @@
   V(profile_microtasks, profile_microtasks)                                    \
   /* The purpose of this flag is documented in */                              \
   /* pkg/dartdev/lib/src/commands/run.dart. */                                 \
-  V(resident, resident)
+  V(resident, resident)                                                        \
+  V(experimental_vm_service, experimental_vm_service)
 
 // Boolean flags that have a short form.
 #define SHORT_BOOL_OPTIONS_LIST(V)                                             \
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index e5e2e1c..d48aa11 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -11,6 +11,7 @@
 #include "bin/dfe.h"
 #include "bin/elf_loader.h"
 #include "bin/error_exit.h"
+#include "bin/exe_utils.h"
 #include "bin/file.h"
 #include "bin/macho_loader.h"
 #include "bin/platform.h"
@@ -846,6 +847,67 @@
 }
 #endif
 
+// TODO(bkonyi): dedup
+static bool CheckForInvalidPath(const char* path) {
+  // TODO(zichangguo): "\\?\" is a prefix for paths on Windows.
+  // Arguments passed are parsed as an URI. "\\?\" causes problems as a part
+  // of URIs. This is a temporary workaround to prevent VM from crashing.
+  // Issue: https://github.com/dart-lang/sdk/issues/42779
+  if (strncmp(path, R"(\\?\)", 4) == 0) {
+    Syslog::PrintErr(R"(\\?\ prefix is not supported)");
+    return false;
+  }
+  return true;
+}
+
+std::pair<AppSnapshot*, CStringUniquePtr> Snapshot::TryReadSDKSnapshot(
+    const char* snapshot_name) {
+  auto try_resolve_path = [&](CStringUniquePtr dir_prefix) {
+    // |dir_prefix| includes the last path separator.
+    // First assume we're in dart-sdk/bin.
+    char* snapshot_path =
+        Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), snapshot_name);
+    if (File::Exists(nullptr, snapshot_path)) {
+      return CStringUniquePtr(snapshot_path);
+    }
+    free(snapshot_path);
+
+    // If we're not in dart-sdk/bin, we might be in one of the $SDK/out*/
+    // directories, Try to use a snapshot from that directory.
+    snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), snapshot_name);
+    if (File::Exists(nullptr, snapshot_path)) {
+      return CStringUniquePtr(snapshot_path);
+    }
+    free(snapshot_path);
+    return CStringUniquePtr(nullptr);
+  };
+
+  auto script_path =
+      try_resolve_path(EXEUtils::GetDirectoryPrefixFromResolvedExeName());
+  if (script_path == nullptr) {
+    script_path =
+        try_resolve_path(EXEUtils::GetDirectoryPrefixFromUnresolvedExeName());
+  }
+  if (script_path == nullptr || !CheckForInvalidPath(script_path.get())) {
+    Syslog::PrintErr("Unable to find snapshot: %s\n", snapshot_name);
+    return std::make_pair(static_cast<AppSnapshot*>(nullptr),
+                          std::move(script_path));
+  }
+
+  AppSnapshot* app_snapshot =
+      TryReadAppSnapshot(script_path.get(), /*force_load_from_memory*/ false,
+                         /*decode_uri*/ false);
+  if (app_snapshot == nullptr) {
+    Syslog::PrintErr("%s is not a valid snapshot\n", script_path.get());
+    if (app_snapshot != nullptr) {
+      delete app_snapshot;
+    }
+    return std::make_pair(static_cast<AppSnapshot*>(nullptr),
+                          std::move(script_path));
+  }
+  return std::make_pair(app_snapshot, std::move(script_path));
+}
+
 static bool WriteInt64(File* file, int64_t size) {
   return file->WriteFully(&size, sizeof(size));
 }
diff --git a/runtime/bin/snapshot_utils.h b/runtime/bin/snapshot_utils.h
index 3103d12..a68d152ee 100644
--- a/runtime/bin/snapshot_utils.h
+++ b/runtime/bin/snapshot_utils.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_BIN_SNAPSHOT_UTILS_H_
 #define RUNTIME_BIN_SNAPSHOT_UTILS_H_
 
+#include <utility>
+
 #include "bin/dartutils.h"
 #include "platform/globals.h"
 
@@ -59,6 +61,8 @@
   static AppSnapshot* TryReadAppSnapshot(const char* script_uri,
                                          bool force_load_from_memory = false,
                                          bool decode_uri = true);
+  static std::pair<AppSnapshot*, CStringUniquePtr> TryReadSDKSnapshot(
+      const char* snapshot_name);
   static void WriteAppSnapshot(const char* filename,
                                uint8_t* isolate_data_buffer,
                                intptr_t isolate_data_size,
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 4220875..a99635a 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -20,6 +20,8 @@
 
 #if !defined(PRODUCT)
 
+bool VmService::enable_experimental_vm_service = false;
+
 #define RETURN_ERROR_HANDLE(handle)                                            \
   if (Dart_IsError(handle)) {                                                  \
     return handle;                                                             \
@@ -33,9 +35,6 @@
     return false;                                                              \
   }
 
-static constexpr const char* kVMServiceIOLibraryUri = "dart:vmservice_io";
-static constexpr const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost";
-
 void NotifyServerState(Dart_NativeArguments args) {
   Dart_EnterScope();
   const char* uri_chars;
@@ -66,6 +65,8 @@
 };
 
 static VmServiceIONativeEntry _VmServiceIONativeEntries[] = {
+    // TODO(bkonyi): these aren't used by any known embedders and can be
+    // removed.
     {"VMServiceIO_NotifyServerState", 1, NotifyServerState},
     {"VMServiceIO_Shutdown", 0, Shutdown},
 };
@@ -105,7 +106,12 @@
 const char* VmService::error_msg_ = nullptr;
 char VmService::server_uri_[kServerUriStringBufferSize];
 
+static constexpr const char* kVMServiceIOLibraryUri = "dart:vmservice_io";
+
 void VmService::SetNativeResolver() {
+  if (enable_experimental_vm_service) {
+    return;
+  }
   Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
   Dart_Handle library = Dart_LookupLibrary(url);
   if (!Dart_IsError(library)) {
@@ -114,6 +120,8 @@
   }
 }
 
+static constexpr const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost";
+
 bool VmService::Setup(const char* server_ip,
                       intptr_t server_port,
                       bool dev_mode_server,
@@ -140,14 +148,16 @@
       /*flag_profile_microtasks=*/false, DartIoSettings{});
   SHUTDOWN_ON_ERROR(result);
 
-  Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
-  Dart_Handle library = Dart_LookupLibrary(url);
-  SHUTDOWN_ON_ERROR(library);
-  result = Dart_SetRootLibrary(library);
-  SHUTDOWN_ON_ERROR(library);
-  result = Dart_SetNativeResolver(library, VmServiceIONativeResolver,
-                                  VmServiceIONativeSymbol);
-  SHUTDOWN_ON_ERROR(result);
+  if (!enable_experimental_vm_service) {
+    Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
+    Dart_Handle library = Dart_LookupLibrary(url);
+    SHUTDOWN_ON_ERROR(library);
+    result = Dart_SetRootLibrary(library);
+    SHUTDOWN_ON_ERROR(library);
+    result = Dart_SetNativeResolver(library, VmServiceIONativeResolver,
+                                    VmServiceIONativeSymbol);
+    SHUTDOWN_ON_ERROR(result);
+  }
 
   // Make runnable.
   Dart_ExitScope();
@@ -161,7 +171,7 @@
   Dart_EnterIsolate(isolate);
   Dart_EnterScope();
 
-  library = Dart_RootLibrary();
+  Dart_Handle library = Dart_RootLibrary();
   SHUTDOWN_ON_ERROR(library);
 
   // Set HTTP server state.
@@ -172,6 +182,12 @@
     // port when the HTTP server is started.
     server_port = 0;
   }
+#if defined(EXPERIMENTAL_VM_SERVICE)
+  if (enable_experimental_vm_service) {
+    // TODO(bkonyi): remove once DDS support is added.
+    wait_for_dds_to_advertise_service = false;
+  }
+#endif
   if (wait_for_dds_to_advertise_service) {
     result = DartUtils::SetStringField(library, "_ddsIP", server_ip);
     SHUTDOWN_ON_ERROR(result);
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 71a3309..dbb24fb 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -64,6 +64,12 @@
       // argument to this parameter should be null.
       const char* resident_compiler_info_file_path);
 
+  // Specifies that the experimental VM service implementation should be used.
+  // TODO(bkonyi): remove this variable when the experimental service is
+  // stable. This was only added as a public static to avoid temporarily
+  // modifying the signature of Setup(...).
+  static bool enable_experimental_vm_service;
+
   static void SetNativeResolver();
 
   // Error message if startup failed.
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index cef09e9..c638151 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -139,5 +139,4 @@
 #endif
   return Object::null();
 }
-
 }  // namespace dart
diff --git a/runtime/tests/concurrency/stress_test_list.json b/runtime/tests/concurrency/stress_test_list.json
index 94f51e70..a99aa99 100644
--- a/runtime/tests/concurrency/stress_test_list.json
+++ b/runtime/tests/concurrency/stress_test_list.json
@@ -3091,8 +3091,8 @@
   "../../../tests/language/variable/scope_variable_runtime_test.dart",
   "../../../tests/language/variable/scoped_variables_try_catch_test.dart",
   "../../../tests/language/variable/variable_named_dart_test.dart",
-  "../../../tests/language/variance/syntax/variance_disabled_keyword_identifier_syntax_test.dart",
-  "../../../tests/language/variance/syntax/variance_keyword_identifier_syntax_test.dart",
+  "../../../tests/language/variance/syntax/variance_builtin_identifier_syntax_test.dart",
+  "../../../tests/language/variance/syntax/variance_disabled_builtin_identifier_syntax_test.dart",
   "../../../tests/language/void/generalized_void_syntax_test.dart",
   "../../../tests/language/void/generalized_void_usage_test.dart",
   "../../../tests/language/void/return_future_future_or_void_async_test.dart",
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index dc4f61a..4b17532 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -73,10 +73,7 @@
   target_type = "source_set"
   extra_product_deps = []
   extra_nonproduct_deps = []
-  extra_deps = [
-    "//third_party/icu:icui18n",
-    "//third_party/icu:icuuc",
-  ]
+  extra_deps = [ "//third_party/icu:icuuc" ]
   if (dart_support_perfetto) {
     extra_deps += [ "//third_party/perfetto:libprotozero" ]
   }
@@ -273,7 +270,6 @@
   ]
   deps = [
     "../platform:libdart_platform_jit",
-    "//third_party/icu:icui18n",
     "//third_party/icu:icuuc",
   ]
   sources = [ "regexp/gen_regexp_special_case.cc" ]
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 64fe45d..b430522 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -54,6 +54,8 @@
 # ........dart2bytecode.snapshot (AOT snapshot, for selected targets)
 # ........dart2js_aot.dart.snapshot (AOT snapshot)
 # ........dart2wasm_product.snapshot (AOT snapshot)
+# ........dart_runtime_service_vm_aot.snapshot (AOT snapshot)
+# ........dart_runtime_service_vm.snapshot (JIT snapshot)
 # ........dartdev_aot.dart.snapshot (AOT snapshot)
 # ........dartdevc_aot.dart.snapshot (AOT snapshot)
 # ........dds_aot.dart.snapshot (AOT snapshot)
@@ -153,6 +155,13 @@
       "dart_mcp_server_aot",
     ],
   ]
+  if (include_experimental_vm_service) {
+    _platform_sdk_snapshots += [ [
+          "dart_runtime_service_vm_aot",
+          "../utils/dart_runtime_service_vm:dart_runtime_service_vm_aot",
+          "dart_runtime_service_vm_aot",
+        ] ]
+  }
 } else {
   _platform_sdk_snapshots += [ [
         "dds",
@@ -160,12 +169,20 @@
         "dds",
       ] ]
 }
+
 if (dart_snapshot_kind == "app-jit") {
   _platform_sdk_snapshots += [ [
         "kernel-service",
         "../utils/kernel-service:kernel-service_snapshot",
         "kernel-service",
       ] ]
+  if (include_experimental_vm_service) {
+    _platform_sdk_snapshots += [ [
+          "dart_runtime_service_vm",
+          "../utils/dart_runtime_service_vm:dart_runtime_service_vm",
+          "dart_runtime_service_vm",
+        ] ]
+  }
 }
 
 # dart2bytecode is an AOT snapshot, which is not supported on the ia32
@@ -398,9 +415,7 @@
       "tsan",
     ]
     if (is_clang) {
-      sanitizers += [
-        "msan",
-      ]
+      sanitizers += [ "msan" ]
     }
   } else if (current_cpu == "riscv64") {
     # Fuchsia Clang is missing the riscv64 MSAN runtime.
@@ -536,7 +551,8 @@
   # The dartdev, dds and dtd snapshots are output to root_out_dir in order to
   # be compatible with the way the dart sdk is distributed internally.
   if (snapshot[0] == "dartdev_aot" || snapshot[0] == "dds_aot_product" ||
-      snapshot[0] == "dart_tooling_daemon_aot_product") {
+      snapshot[0] == "dart_tooling_daemon_aot_product" ||
+      snapshot[0] == "dart_runtime_service_vm_aot") {
     root = root_out_dir
   }
   copy("copy_${snapshot[0]}_snapshot") {
diff --git a/sdk/lib/_internal/vm_shared/lib/bigint_patch.dart b/sdk/lib/_internal/vm_shared/lib/bigint_patch.dart
index da90df3..238b5b3 100644
--- a/sdk/lib/_internal/vm_shared/lib/bigint_patch.dart
+++ b/sdk/lib/_internal/vm_shared/lib/bigint_patch.dart
@@ -86,6 +86,7 @@
     int remUsed,
     int rem_nsh,
   ) {
+    _dividendDigits = dividendDigits;
     _dividendUsed = dividendUsed;
     _divisorDigits = divisorDigits;
     _divisorUsed = divisorUsed;
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index bbdc863..2aa66d8 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -290,7 +290,7 @@
     clients.remove(client);
     for (final streamId in client.streams) {
       if (!_isAnyClientSubscribed(streamId)) {
-        _vmCancelStream(streamId);
+        vmCancelStream(streamId);
       }
     }
     for (final pair in client.createdServiceIdZones) {
@@ -444,7 +444,7 @@
     await VMServiceEmbedderHooks.cleanup!();
     await clearState();
     // Notify the VM that we have exited.
-    _onExit();
+    onExit();
   }
 
   void messageHandler(message) {
@@ -497,7 +497,7 @@
     if (instance == null) {
       instance = VMService._internal();
       VMService._instance = instance;
-      _onStart();
+      onStart();
     }
     return instance;
   }
@@ -533,7 +533,7 @@
     if (!_isAnyClientSubscribed(streamId)) {
       final includePrivates = message.params['_includePrivateMembers'] == true;
       if (!serviceStreams.contains(streamId) &&
-          !_vmListenStream(streamId, includePrivates)) {
+          !vmListenStream(streamId, includePrivates)) {
         return encodeRpcError(
           message,
           kInvalidParams,
@@ -569,7 +569,7 @@
     client.streams.remove(streamId);
     if (!serviceStreams.contains(streamId) &&
         !_isAnyClientSubscribed(streamId)) {
-      _vmCancelStream(streamId);
+      vmCancelStream(streamId);
     }
 
     return encodeSuccess(message);
@@ -807,24 +807,19 @@
 
 /// Notify the VM that the service is running.
 @pragma("vm:external-name", "VMService_OnStart")
-external void _onStart();
+external void onStart();
 
 /// Notify the VM that the service is no longer running.
 @pragma("vm:external-name", "VMService_OnExit")
-external void _onExit();
-
-/// Notify the VM that the server's address has changed.
-void onServerAddressChange(String? address) {
-  _onServerAddressChange(address);
-}
+external void onExit();
 
 @pragma("vm:external-name", "VMService_OnServerAddressChange")
-external void _onServerAddressChange(String? address);
+external void onServerAddressChange(String? address);
 
 /// Subscribe to a service stream.
 @pragma("vm:external-name", "VMService_ListenStream")
-external bool _vmListenStream(String streamId, bool include_privates);
+external bool vmListenStream(String streamId, bool include_privates);
 
 /// Cancel a subscription to a service stream.
 @pragma("vm:external-name", "VMService_CancelStream")
-external void _vmCancelStream(String streamId);
+external void vmCancelStream(String streamId);
diff --git a/sdk_args.gni b/sdk_args.gni
index 542d7b8..4013efd 100644
--- a/sdk_args.gni
+++ b/sdk_args.gni
@@ -38,6 +38,12 @@
   # can significantly improve iteration time when iteration on changes in
   # core libraries.
   precompile_tools = false
+
+  # When set to `true`, the Dart Runtime Service based implementation of the
+  # VM service will be included in the build. By default, the legacy VM
+  # service implementation will be launched by the VM, unless the
+  # --include-experimental-vm-service VM flag is provided.
+  include_experimental_vm_service = false
 }
 
 if (default_git_folder == "") {
diff --git a/tests/language/primary_constructors/syntax/empty_body_error_test.dart b/tests/language/primary_constructors/syntax/empty_body_error_test.dart
index bb85f80..069755f 100644
--- a/tests/language/primary_constructors/syntax/empty_body_error_test.dart
+++ b/tests/language/primary_constructors/syntax/empty_body_error_test.dart
@@ -2,11 +2,11 @@
 // 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.
 
+// SharedOptions=--enable-experiment=primary-constructors
+
 // Enums that have an empty body (i.e. `;`) can be parsed, but will cause a
 // compile-time error when there's no enum constant declared.
 
-// SharedOptions=--enable-experiment=primary-constructors
-
 enum E1;
 //   ^
 // [analyzer] unspecified
@@ -26,3 +26,24 @@
 //   ^
 // [analyzer] unspecified
 // [cfe] unspecified
+
+// Mixin application classes cannot have an explicit (empty) class body.
+
+class S;
+mixin M on S;
+class C = S with M {}
+//               ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ';' after this.
+//                 ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
+// [cfe] Expected a declaration, but got '{'.
+
+class I;
+class C2 = S with M implements I {}
+//                             ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ';' after this.
+//                               ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
+// [cfe] Expected a declaration, but got '{'.
diff --git a/tools/VERSION b/tools/VERSION
index aa32dab..32706cd 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 12
 PATCH 0
-PRERELEASE 233
+PRERELEASE 234
 PRERELEASE_PATCH 0
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index a8406fb..7a7c829 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -1045,6 +1045,7 @@
           "script": "tools/build.py",
           "arguments": [
             "--codesigning-identity=-",
+            "--include-experimental-vm-service",
             "runtime"
           ]
         },
@@ -1075,6 +1076,7 @@
           "script": "tools/build.py",
           "arguments": [
             "--codesigning-identity=-",
+            "--include-experimental-vm-service",
             "runtime"
           ]
         },
@@ -1155,6 +1157,7 @@
           "script": "tools/build.py",
           "arguments": [
             "--codesigning-identity=-",
+            "--include-experimental-vm-service",
             "runtime",
             "dartaotruntime"
           ]
@@ -3611,4 +3614,4 @@
     "macos": "buildtools/mac-x64/clang/bin/llvm-symbolizer",
     "windows": "buildtools/win-x64/clang/bin/llvm-symbolizer.exe"
   }
-}
+}
\ No newline at end of file
diff --git a/tools/gn.py b/tools/gn.py
index 90e4001..a01d121 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -280,6 +280,10 @@
     if not args.platform_sdk:
         gn_args['dart_platform_sdk'] = args.platform_sdk
 
+    if args.include_experimental_vm_service:
+        gn_args[
+            'include_experimental_vm_service'] = args.include_experimental_vm_service
+
     # We don't support stripping on Windows
     if host_os != 'win':
         gn_args['dart_stripped_binary'] = 'exe.stripped/dart'
@@ -555,6 +559,11 @@
                         help='Sign executables using the given identity.',
                         default='',
                         type=str)
+    parser.add_argument(
+        '--include-experimental-vm-service',
+        help='Use the Dart Runtime Service based VM service implementation.',
+        default=False,
+        action='store_true')
 
 
 def AddCommonConfigurationArgs(parser):
diff --git a/utils/dart_runtime_service_vm/BUILD.gn b/utils/dart_runtime_service_vm/BUILD.gn
new file mode 100644
index 0000000..9f256fa
--- /dev/null
+++ b/utils/dart_runtime_service_vm/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright (c) 2026, 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("../../runtime/runtime_args.gni")
+import("../aot_snapshot.gni")
+import("../application_snapshot.gni")
+
+group("dart_runtime_service_vm_aot") {
+  public_deps = [ ":dart_runtime_service_vm_aot_snapshot" ]
+}
+
+aot_snapshot("dart_runtime_service_vm_aot_snapshot") {
+  main_dart = "../../pkg/dart_runtime_service_vm/bin/vm_service_entrypoint.dart"
+  output = "$root_out_dir/dart_runtime_service_vm_aot.dart.snapshot"
+}
+
+group("dart_runtime_service_vm") {
+  public_deps = [ ":copy_dart_runtime_service_vm_snapshot" ]
+}
+
+copy("copy_dart_runtime_service_vm_snapshot") {
+  visibility = [ ":dart_runtime_service_vm" ]
+  public_deps = [ ":generate_dart_runtime_service_vm_snapshot" ]
+  sources = [ "$root_gen_dir/dart_runtime_service_vm.dart.snapshot" ]
+  outputs = [ "$root_out_dir/dart_runtime_service_vm.dart.snapshot" ]
+}
+
+application_snapshot("generate_dart_runtime_service_vm_snapshot") {
+  main_dart = "../../pkg/dart_runtime_service_vm/bin/vm_service_entrypoint.dart"
+  training_args = [ "--help" ]
+  output = "$root_gen_dir/dart_runtime_service_vm.dart.snapshot"
+}