Skip to content

Commit

Permalink
Update to package:dds ^4.2.5, use DartDevelopmentServiceLauncher
Browse files Browse the repository at this point in the history
  • Loading branch information
bkonyi committed Aug 1, 2024
1 parent cb4451e commit b3ffc26
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 202 deletions.
205 changes: 4 additions & 201 deletions dwds/lib/src/services/debug_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'dart:io';
import 'dart:math';
import 'dart:typed_data';

import 'package:dds/dds_launcher.dart';
import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/connections/app_connection.dart';
import 'package:dwds/src/debugging/execution_context.dart';
Expand Down Expand Up @@ -122,204 +123,6 @@ Future<void> _handleSseConnections(
}
}

/// Wrapper around a `dart development-service` process.
class DartDevelopmentService {
static Future<DartDevelopmentService> start({
required Uri remoteVmServiceUri,
required Uri serviceUri,
}) async {
final process = await Process.start(
Platform.executable,
<String>[
'development-service',
'--vm-service-uri=$remoteVmServiceUri',
'--bind-address=${serviceUri.host}',
'--bind-port=${serviceUri.port}',
],
);
final completer = Completer<DartDevelopmentService>();
late StreamSubscription<Object?> stderrSub;
stderrSub = process.stderr
.transform(utf8.decoder)
.transform(json.decoder)
.listen((Object? result) {
if (result
case {
'state': 'started',
'ddsUri': final String ddsUriStr,
}) {
final ddsUri = Uri.parse(ddsUriStr);
completer.complete(
DartDevelopmentService._(
process: process,
uri: ddsUri,
),
);
} else if (result
case {
'state': 'error',
'error': final String error,
}) {
final exceptionDetails =
result['ddsExceptionDetails'] as Map<String, Object?>?;
completer.completeError(
exceptionDetails != null
? DartDevelopmentServiceException.fromJson(exceptionDetails)
: StateError(error),
);
} else {
throw StateError('Unexpected result from DDS: $result');
}
stderrSub.cancel();
});
return completer.future;
}

DartDevelopmentService._({
required Process process,
required this.uri,
}) : _ddsInstance = process;

final Process _ddsInstance;

final Uri uri;

Uri get sseUri => _toSse(uri)!;
Uri get wsUri => _toWebSocket(uri)!;

List<String> _cleanupPathSegments(Uri uri) {
final pathSegments = <String>[];
if (uri.pathSegments.isNotEmpty) {
pathSegments.addAll(
uri.pathSegments.where(
// Strip out the empty string that appears at the end of path segments.
// Empty string elements will result in an extra '/' being added to the
// URI.
(s) => s.isNotEmpty,
),
);
}
return pathSegments;
}

Uri? _toWebSocket(Uri? uri) {
if (uri == null) {
return null;
}
final pathSegments = _cleanupPathSegments(uri);
pathSegments.add('ws');
return uri.replace(scheme: 'ws', pathSegments: pathSegments);
}

Uri? _toSse(Uri? uri) {
if (uri == null) {
return null;
}
final pathSegments = _cleanupPathSegments(uri);
pathSegments.add(_kSseHandlerPath);
return uri.replace(scheme: 'sse', pathSegments: pathSegments);
}

Future<void> shutdown() {
_ddsInstance.kill();
return _ddsInstance.exitCode;
}
}

/// Thrown by DDS during initialization failures, unexpected connection issues,
/// and when attempting to spawn DDS when an existing DDS instance exists.
class DartDevelopmentServiceException implements Exception {
factory DartDevelopmentServiceException.fromJson(Map<String, Object?> json) {
if (json
case {
'error_code': final int errorCode,
'message': final String message,
'uri': final String? uri
}) {
return switch (errorCode) {
existingDdsInstanceError =>
DartDevelopmentServiceException.existingDdsInstance(
message,
ddsUri: Uri.parse(uri!),
),
failedToStartError => DartDevelopmentServiceException.failedToStart(),
connectionError =>
DartDevelopmentServiceException.connectionIssue(message),
_ => throw StateError(
'Invalid DartDevelopmentServiceException error_code: $errorCode',
),
};
}
throw StateError('Invalid DartDevelopmentServiceException JSON: $json');
}

/// Thrown when `DartDeveloperService.startDartDevelopmentService` is called
/// and the target VM service already has a Dart Developer Service instance
/// connected.
factory DartDevelopmentServiceException.existingDdsInstance(
String message, {
Uri? ddsUri,
}) {
return ExistingDartDevelopmentServiceException._(
message,
ddsUri: ddsUri,
);
}

/// Thrown when the connection to the remote VM service terminates unexpectedly
/// during Dart Development Service startup.
factory DartDevelopmentServiceException.failedToStart() {
return DartDevelopmentServiceException._(
failedToStartError,
'Failed to start Dart Development Service',
);
}

/// Thrown when a connection error has occurred after startup.
factory DartDevelopmentServiceException.connectionIssue(String message) {
return DartDevelopmentServiceException._(connectionError, message);
}

DartDevelopmentServiceException._(this.errorCode, this.message);

/// Set when `DartDeveloperService.startDartDevelopmentService` is called and
/// the target VM service already has a Dart Developer Service instance
/// connected.
static const int existingDdsInstanceError = 1;

/// Set when the connection to the remote VM service terminates unexpectedly
/// during Dart Development Service startup.
static const int failedToStartError = 2;

/// Set when a connection error has occurred after startup.
static const int connectionError = 3;

@override
String toString() => 'DartDevelopmentServiceException: $message';

final int errorCode;
final String message;
}

/// Thrown when attempting to start a new DDS instance when one already exists.
class ExistingDartDevelopmentServiceException
extends DartDevelopmentServiceException {
ExistingDartDevelopmentServiceException._(
String message, {
this.ddsUri,
}) : super._(
DartDevelopmentServiceException.existingDdsInstanceError,
message,
);

/// The URI of the existing DDS instance, if available.
///
/// This URI is the base HTTP URI such as `http://127.0.0.1:1234/AbcDefg=/`,
/// not the WebSocket URI (which can be obtained by mapping the scheme to
/// `ws` (or `wss`) and appending `ws` to the path segments).
final Uri? ddsUri;
}

/// A Dart Web Debug Service.
///
/// Creates a [ChromeProxyService] from an existing Chrome instance.
Expand All @@ -335,7 +138,7 @@ class DebugService {
final bool _useSse;
final bool _spawnDds;
final UrlEncoder? _urlEncoder;
DartDevelopmentService? _dds;
DartDevelopmentServiceLauncher? _dds;

/// Null until [close] is called.
///
Expand All @@ -359,10 +162,10 @@ class DebugService {
if (_dds != null) _dds!.shutdown(),
]);

Future<DartDevelopmentService> startDartDevelopmentService() async {
Future<DartDevelopmentServiceLauncher> startDartDevelopmentService() async {
// Note: DDS can handle both web socket and SSE connections with no
// additional configuration.
_dds = await DartDevelopmentService.start(
_dds = await DartDevelopmentServiceLauncher.start(
remoteVmServiceUri: Uri(
scheme: 'http',
host: hostname,
Expand Down
2 changes: 1 addition & 1 deletion dwds/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies:
built_value: ^8.3.0
collection: ^1.15.0
crypto: ^3.0.2
dds: ^4.1.0
dds: ^4.2.5
file: ">=6.1.4 <8.0.0"
http: ^1.0.0
http_multi_server: ^3.2.0
Expand Down

0 comments on commit b3ffc26

Please sign in to comment.