diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 418ff21e7..2269ab02f 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,3 +1,10 @@ +## 24.3.12-wip + +- Implemented a WebSocket-based communication protocol that provides essential developer tooling (hot reload, service extensions) when Chrome debugger access is unavailable. - [#2605](https://github.com/dart-lang/webdev/issues/2605) +- Added WebSocket-based hot reload and service extension support via new `WebSocketProxyService` class that implements VM service protocol over WebSockets. +- Created new files: `WebSocketProxyService`, `WebSocketDebugService`, `WebSocketAppDebugServices`, and `WebSocketDwdsVmClient` to support socket-based DWDS functionality. +- Enhanced `DevHandler` with `useWebSocketConnection` flag to toggle between Chrome-based and WebSocket-based communication protocols. + ## 24.3.11 - Changed DWDS to always inject the client and added `useDwdsWebSocketConnection` flag to control communication protocol: when true uses socket-based implementation, when false uses Chrome-based communication protocol. diff --git a/dwds/lib/dart_web_debug_service.dart b/dwds/lib/dart_web_debug_service.dart index ff960f0f0..587e8af43 100644 --- a/dwds/lib/dart_web_debug_service.dart +++ b/dwds/lib/dart_web_debug_service.dart @@ -31,6 +31,7 @@ class Dwds { final DevHandler _devHandler; final AssetReader _assetReader; final bool _enableDebugging; + final bool _useDwdsWebSocketConnection; Dwds._( this.middleware, @@ -38,6 +39,7 @@ class Dwds { this._devHandler, this._assetReader, this._enableDebugging, + this._useDwdsWebSocketConnection, ) : handler = _devHandler.handler; Stream get connectedApps => _devHandler.connectedApps; @@ -53,12 +55,18 @@ class Dwds { await _assetReader.close(); } + /// Creates a debug connection for the given app connection. + /// + /// Returns a [DebugConnection] that wraps the appropriate debug services + /// based on the connection type (WebSocket or Chrome-based). Future debugConnection(AppConnection appConnection) async { if (!_enableDebugging) throw StateError('Debugging is not enabled.'); - final appDebugServices = await _devHandler.loadAppServices(appConnection); - final chromeProxyService = appDebugServices.chromeProxyService; - await chromeProxyService.isInitialized; - return DebugConnection(appDebugServices); + + if (_useDwdsWebSocketConnection) { + return await _devHandler.createDebugConnectionForWebSocket(appConnection); + } else { + return await _devHandler.createDebugConnectionForChrome(appConnection); + } } static Future start({ @@ -123,10 +131,7 @@ class Dwds { _logger.info('Serving DevTools at $uri\n'); } - final injected = DwdsInjector( - extensionUri: extensionUri, - useDwdsWebSocketConnection: useDwdsWebSocketConnection, - ); + final injected = DwdsInjector(extensionUri: extensionUri); final devHandler = DevHandler( chromeConnection, @@ -143,6 +148,7 @@ class Dwds { debugSettings.spawnDds, debugSettings.ddsPort, debugSettings.launchDevToolsInNewWindow, + useWebSocketConnection: useDwdsWebSocketConnection, ); return Dwds._( @@ -151,6 +157,7 @@ class Dwds { devHandler, assetReader, debugSettings.enableDebugging, + useDwdsWebSocketConnection, ); } } diff --git a/dwds/lib/data/serializers.dart b/dwds/lib/data/serializers.dart index 11755912f..4d6614f85 100644 --- a/dwds/lib/data/serializers.dart +++ b/dwds/lib/data/serializers.dart @@ -14,6 +14,8 @@ import 'error_response.dart'; import 'extension_request.dart'; import 'hot_reload_request.dart'; import 'hot_reload_response.dart'; +import 'service_extension_request.dart'; +import 'service_extension_response.dart'; import 'isolate_events.dart'; import 'register_event.dart'; import 'run_request.dart'; @@ -40,5 +42,7 @@ part 'serializers.g.dart'; ErrorResponse, RegisterEvent, RunRequest, + ServiceExtensionRequest, + ServiceExtensionResponse, ]) final Serializers serializers = _$serializers; diff --git a/dwds/lib/data/serializers.g.dart b/dwds/lib/data/serializers.g.dart index 3f229a323..a061bae9e 100644 --- a/dwds/lib/data/serializers.g.dart +++ b/dwds/lib/data/serializers.g.dart @@ -27,6 +27,8 @@ Serializers _$serializers = ..add(IsolateStart.serializer) ..add(RegisterEvent.serializer) ..add(RunRequest.serializer) + ..add(ServiceExtensionRequest.serializer) + ..add(ServiceExtensionResponse.serializer) ..addBuilderFactory( const FullType(BuiltList, const [const FullType(DebugEvent)]), () => new ListBuilder(), diff --git a/dwds/lib/data/service_extension_request.dart b/dwds/lib/data/service_extension_request.dart new file mode 100644 index 000000000..7539a9b3b --- /dev/null +++ b/dwds/lib/data/service_extension_request.dart @@ -0,0 +1,43 @@ +// Copyright (c) 2025, the Dart project authors. All rights reserved. +// Defines the request for service extension calls over WebSocket. + +import 'dart:convert'; +import 'package:built_value/built_value.dart'; +import 'package:built_value/serializer.dart'; + +part 'service_extension_request.g.dart'; + +abstract class ServiceExtensionRequest + implements Built { + String get id; + String get method; + String + get argsJson; // Store args as JSON string for built_value compatibility + + // Helper method to get args as Map + Map get args => + argsJson.isEmpty + ? {} + : json.decode(argsJson) as Map; + + ServiceExtensionRequest._(); + factory ServiceExtensionRequest([ + void Function(ServiceExtensionRequestBuilder) updates, + ]) = _$ServiceExtensionRequest; + + // Convenient factory method to create with args Map + factory ServiceExtensionRequest.fromArgs({ + required String id, + required String method, + required Map args, + }) => ServiceExtensionRequest( + (b) => + b + ..id = id + ..method = method + ..argsJson = json.encode(args), + ); + + static Serializer get serializer => + _$serviceExtensionRequestSerializer; +} diff --git a/dwds/lib/data/service_extension_request.g.dart b/dwds/lib/data/service_extension_request.g.dart new file mode 100644 index 000000000..94379fd36 --- /dev/null +++ b/dwds/lib/data/service_extension_request.g.dart @@ -0,0 +1,228 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'service_extension_request.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +Serializer _$serviceExtensionRequestSerializer = + new _$ServiceExtensionRequestSerializer(); + +class _$ServiceExtensionRequestSerializer + implements StructuredSerializer { + @override + final Iterable types = const [ + ServiceExtensionRequest, + _$ServiceExtensionRequest, + ]; + @override + final String wireName = 'ServiceExtensionRequest'; + + @override + Iterable serialize( + Serializers serializers, + ServiceExtensionRequest object, { + FullType specifiedType = FullType.unspecified, + }) { + final result = [ + 'id', + serializers.serialize(object.id, specifiedType: const FullType(String)), + 'method', + serializers.serialize( + object.method, + specifiedType: const FullType(String), + ), + 'argsJson', + serializers.serialize( + object.argsJson, + specifiedType: const FullType(String), + ), + ]; + + return result; + } + + @override + ServiceExtensionRequest deserialize( + Serializers serializers, + Iterable serialized, { + FullType specifiedType = FullType.unspecified, + }) { + final result = new ServiceExtensionRequestBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'id': + result.id = + serializers.deserialize( + value, + specifiedType: const FullType(String), + )! + as String; + break; + case 'method': + result.method = + serializers.deserialize( + value, + specifiedType: const FullType(String), + )! + as String; + break; + case 'argsJson': + result.argsJson = + serializers.deserialize( + value, + specifiedType: const FullType(String), + )! + as String; + break; + } + } + + return result.build(); + } +} + +class _$ServiceExtensionRequest extends ServiceExtensionRequest { + @override + final String id; + @override + final String method; + @override + final String argsJson; + + factory _$ServiceExtensionRequest([ + void Function(ServiceExtensionRequestBuilder)? updates, + ]) => (new ServiceExtensionRequestBuilder()..update(updates))._build(); + + _$ServiceExtensionRequest._({ + required this.id, + required this.method, + required this.argsJson, + }) : super._() { + BuiltValueNullFieldError.checkNotNull(id, r'ServiceExtensionRequest', 'id'); + BuiltValueNullFieldError.checkNotNull( + method, + r'ServiceExtensionRequest', + 'method', + ); + BuiltValueNullFieldError.checkNotNull( + argsJson, + r'ServiceExtensionRequest', + 'argsJson', + ); + } + + @override + ServiceExtensionRequest rebuild( + void Function(ServiceExtensionRequestBuilder) updates, + ) => (toBuilder()..update(updates)).build(); + + @override + ServiceExtensionRequestBuilder toBuilder() => + new ServiceExtensionRequestBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is ServiceExtensionRequest && + id == other.id && + method == other.method && + argsJson == other.argsJson; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, id.hashCode); + _$hash = $jc(_$hash, method.hashCode); + _$hash = $jc(_$hash, argsJson.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'ServiceExtensionRequest') + ..add('id', id) + ..add('method', method) + ..add('argsJson', argsJson)) + .toString(); + } +} + +class ServiceExtensionRequestBuilder + implements + Builder { + _$ServiceExtensionRequest? _$v; + + String? _id; + String? get id => _$this._id; + set id(String? id) => _$this._id = id; + + String? _method; + String? get method => _$this._method; + set method(String? method) => _$this._method = method; + + String? _argsJson; + String? get argsJson => _$this._argsJson; + set argsJson(String? argsJson) => _$this._argsJson = argsJson; + + ServiceExtensionRequestBuilder(); + + ServiceExtensionRequestBuilder get _$this { + final $v = _$v; + if ($v != null) { + _id = $v.id; + _method = $v.method; + _argsJson = $v.argsJson; + _$v = null; + } + return this; + } + + @override + void replace(ServiceExtensionRequest other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$ServiceExtensionRequest; + } + + @override + void update(void Function(ServiceExtensionRequestBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + ServiceExtensionRequest build() => _build(); + + _$ServiceExtensionRequest _build() { + final _$result = + _$v ?? + new _$ServiceExtensionRequest._( + id: BuiltValueNullFieldError.checkNotNull( + id, + r'ServiceExtensionRequest', + 'id', + ), + method: BuiltValueNullFieldError.checkNotNull( + method, + r'ServiceExtensionRequest', + 'method', + ), + argsJson: BuiltValueNullFieldError.checkNotNull( + argsJson, + r'ServiceExtensionRequest', + 'argsJson', + ), + ); + replace(_$result); + return _$result; + } +} + +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/dwds/lib/data/service_extension_response.dart b/dwds/lib/data/service_extension_response.dart new file mode 100644 index 000000000..854526951 --- /dev/null +++ b/dwds/lib/data/service_extension_response.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2025, the Dart project authors. All rights reserved. +// Defines the response for service extension calls over WebSocket. + +import 'dart:convert'; +import 'package:built_value/built_value.dart'; +import 'package:built_value/serializer.dart'; + +part 'service_extension_response.g.dart'; + +abstract class ServiceExtensionResponse + implements + Built { + String get id; + String? + get resultJson; // Store result as JSON string for built_value compatibility + bool get success; + int? get errorCode; + String? get errorMessage; + + // Helper method to get result as Map + Map? get result => + resultJson == null || resultJson!.isEmpty + ? null + : json.decode(resultJson!) as Map; + + ServiceExtensionResponse._(); + factory ServiceExtensionResponse([ + void Function(ServiceExtensionResponseBuilder) updates, + ]) = _$ServiceExtensionResponse; + + // Convenient factory method to create with result Map + factory ServiceExtensionResponse.fromResult({ + required String id, + required bool success, + Map? result, + int? errorCode, + String? errorMessage, + }) => ServiceExtensionResponse( + (b) => + b + ..id = id + ..success = success + ..resultJson = result != null ? json.encode(result) : null + ..errorCode = errorCode + ..errorMessage = errorMessage, + ); + + static Serializer get serializer => + _$serviceExtensionResponseSerializer; +} diff --git a/dwds/lib/data/service_extension_response.g.dart b/dwds/lib/data/service_extension_response.g.dart new file mode 100644 index 000000000..e840cf2b4 --- /dev/null +++ b/dwds/lib/data/service_extension_response.g.dart @@ -0,0 +1,277 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'service_extension_response.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +Serializer _$serviceExtensionResponseSerializer = + new _$ServiceExtensionResponseSerializer(); + +class _$ServiceExtensionResponseSerializer + implements StructuredSerializer { + @override + final Iterable types = const [ + ServiceExtensionResponse, + _$ServiceExtensionResponse, + ]; + @override + final String wireName = 'ServiceExtensionResponse'; + + @override + Iterable serialize( + Serializers serializers, + ServiceExtensionResponse object, { + FullType specifiedType = FullType.unspecified, + }) { + final result = [ + 'id', + serializers.serialize(object.id, specifiedType: const FullType(String)), + 'success', + serializers.serialize( + object.success, + specifiedType: const FullType(bool), + ), + ]; + Object? value; + value = object.resultJson; + if (value != null) { + result + ..add('resultJson') + ..add( + serializers.serialize(value, specifiedType: const FullType(String)), + ); + } + value = object.errorCode; + if (value != null) { + result + ..add('errorCode') + ..add(serializers.serialize(value, specifiedType: const FullType(int))); + } + value = object.errorMessage; + if (value != null) { + result + ..add('errorMessage') + ..add( + serializers.serialize(value, specifiedType: const FullType(String)), + ); + } + return result; + } + + @override + ServiceExtensionResponse deserialize( + Serializers serializers, + Iterable serialized, { + FullType specifiedType = FullType.unspecified, + }) { + final result = new ServiceExtensionResponseBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'id': + result.id = + serializers.deserialize( + value, + specifiedType: const FullType(String), + )! + as String; + break; + case 'resultJson': + result.resultJson = + serializers.deserialize( + value, + specifiedType: const FullType(String), + ) + as String?; + break; + case 'success': + result.success = + serializers.deserialize( + value, + specifiedType: const FullType(bool), + )! + as bool; + break; + case 'errorCode': + result.errorCode = + serializers.deserialize(value, specifiedType: const FullType(int)) + as int?; + break; + case 'errorMessage': + result.errorMessage = + serializers.deserialize( + value, + specifiedType: const FullType(String), + ) + as String?; + break; + } + } + + return result.build(); + } +} + +class _$ServiceExtensionResponse extends ServiceExtensionResponse { + @override + final String id; + @override + final String? resultJson; + @override + final bool success; + @override + final int? errorCode; + @override + final String? errorMessage; + + factory _$ServiceExtensionResponse([ + void Function(ServiceExtensionResponseBuilder)? updates, + ]) => (new ServiceExtensionResponseBuilder()..update(updates))._build(); + + _$ServiceExtensionResponse._({ + required this.id, + this.resultJson, + required this.success, + this.errorCode, + this.errorMessage, + }) : super._() { + BuiltValueNullFieldError.checkNotNull( + id, + r'ServiceExtensionResponse', + 'id', + ); + BuiltValueNullFieldError.checkNotNull( + success, + r'ServiceExtensionResponse', + 'success', + ); + } + + @override + ServiceExtensionResponse rebuild( + void Function(ServiceExtensionResponseBuilder) updates, + ) => (toBuilder()..update(updates)).build(); + + @override + ServiceExtensionResponseBuilder toBuilder() => + new ServiceExtensionResponseBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is ServiceExtensionResponse && + id == other.id && + resultJson == other.resultJson && + success == other.success && + errorCode == other.errorCode && + errorMessage == other.errorMessage; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, id.hashCode); + _$hash = $jc(_$hash, resultJson.hashCode); + _$hash = $jc(_$hash, success.hashCode); + _$hash = $jc(_$hash, errorCode.hashCode); + _$hash = $jc(_$hash, errorMessage.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'ServiceExtensionResponse') + ..add('id', id) + ..add('resultJson', resultJson) + ..add('success', success) + ..add('errorCode', errorCode) + ..add('errorMessage', errorMessage)) + .toString(); + } +} + +class ServiceExtensionResponseBuilder + implements + Builder { + _$ServiceExtensionResponse? _$v; + + String? _id; + String? get id => _$this._id; + set id(String? id) => _$this._id = id; + + String? _resultJson; + String? get resultJson => _$this._resultJson; + set resultJson(String? resultJson) => _$this._resultJson = resultJson; + + bool? _success; + bool? get success => _$this._success; + set success(bool? success) => _$this._success = success; + + int? _errorCode; + int? get errorCode => _$this._errorCode; + set errorCode(int? errorCode) => _$this._errorCode = errorCode; + + String? _errorMessage; + String? get errorMessage => _$this._errorMessage; + set errorMessage(String? errorMessage) => _$this._errorMessage = errorMessage; + + ServiceExtensionResponseBuilder(); + + ServiceExtensionResponseBuilder get _$this { + final $v = _$v; + if ($v != null) { + _id = $v.id; + _resultJson = $v.resultJson; + _success = $v.success; + _errorCode = $v.errorCode; + _errorMessage = $v.errorMessage; + _$v = null; + } + return this; + } + + @override + void replace(ServiceExtensionResponse other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$ServiceExtensionResponse; + } + + @override + void update(void Function(ServiceExtensionResponseBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + ServiceExtensionResponse build() => _build(); + + _$ServiceExtensionResponse _build() { + final _$result = + _$v ?? + new _$ServiceExtensionResponse._( + id: BuiltValueNullFieldError.checkNotNull( + id, + r'ServiceExtensionResponse', + 'id', + ), + resultJson: resultJson, + success: BuiltValueNullFieldError.checkNotNull( + success, + r'ServiceExtensionResponse', + 'success', + ), + errorCode: errorCode, + errorMessage: errorMessage, + ); + replace(_$result); + return _$result; + } +} + +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/dwds/lib/src/connections/debug_connection.dart b/dwds/lib/src/connections/debug_connection.dart index 271331eb3..99fcb9b3e 100644 --- a/dwds/lib/src/connections/debug_connection.dart +++ b/dwds/lib/src/connections/debug_connection.dart @@ -13,7 +13,7 @@ import 'package:vm_service/vm_service.dart'; /// Supports debugging your running application through the Dart VM Service /// Protocol. class DebugConnection { - final AppDebugServices _appDebugServices; + final IAppDebugServices _appDebugServices; final _onDoneCompleter = Completer(); /// Null until [close] is called. @@ -22,9 +22,20 @@ class DebugConnection { Future? _closed; DebugConnection(this._appDebugServices) { - _appDebugServices.chromeProxyService.remoteDebugger.onClose.first.then((_) { - close(); - }); + _setupChromeCloseHandler(); + } + + /// Sets up Chrome remote debugger close handler if available. + void _setupChromeCloseHandler() { + try { + final chromeProxyService = _appDebugServices.chromeProxyService; + if (chromeProxyService != null) { + final remoteDebugger = chromeProxyService.remoteDebugger; + remoteDebugger.onClose.first.then((_) => close()); + } + } catch (_) { + // Chrome proxy service not available in WebSocket-only mode - ignore + } } /// The port of the host Dart VM Service. @@ -41,7 +52,16 @@ class DebugConnection { Future close() => _closed ??= () async { - await _appDebugServices.chromeProxyService.remoteDebugger.close(); + // Close Chrome remote debugger if available + try { + final chromeProxyService = _appDebugServices.chromeProxyService; + if (chromeProxyService != null) { + await chromeProxyService.remoteDebugger.close(); + } + } catch (_) { + // Chrome proxy service not available in WebSocket-only mode - ignore + } + await _appDebugServices.close(); _onDoneCompleter.complete(); }(); diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index 329777540..23817b677 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -15,6 +15,7 @@ import 'package:dwds/data/hot_reload_response.dart'; import 'package:dwds/data/isolate_events.dart'; import 'package:dwds/data/register_event.dart'; import 'package:dwds/data/serializers.dart'; +import 'package:dwds/data/service_extension_response.dart'; import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/connections/app_connection.dart'; import 'package:dwds/src/connections/debug_connection.dart'; @@ -32,7 +33,10 @@ import 'package:dwds/src/servers/extension_debugger.dart'; import 'package:dwds/src/services/app_debug_services.dart'; import 'package:dwds/src/services/debug_service.dart'; import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds/src/services/web_socket_app_debug_services.dart'; +import 'package:dwds/src/services/web_socket_debug_service.dart'; import 'package:dwds/src/utilities/shared.dart'; +import 'package:dwds/src/web_socket_dwds_vm_client.dart'; import 'package:logging/logging.dart'; import 'package:shelf/shelf.dart'; import 'package:sse/server/sse_handler.dart'; @@ -56,7 +60,7 @@ class DevHandler { final AssetReader _assetReader; final String _hostname; final _connectedApps = StreamController.broadcast(); - final _servicesByAppId = {}; + final _servicesByAppId = {}; final _appConnectionByAppId = {}; final Stream buildResults; final Future Function() _chromeConnection; @@ -79,6 +83,8 @@ class DevHandler { Stream get connectedApps => _connectedApps.stream; + final bool useWebSocketConnection; + DevHandler( this._chromeConnection, this.buildResults, @@ -93,8 +99,9 @@ class DevHandler { this._injected, this._spawnDds, this._ddsPort, - this._launchDevToolsInNewWindow, - ) { + this._launchDevToolsInNewWindow, { + this.useWebSocketConnection = false, + }) { _subs.add(buildResults.listen(_emitBuildResults)); _listen(); if (_extensionBackend != null) { @@ -239,7 +246,6 @@ class DevHandler { expressionCompiler: _expressionCompiler, spawnDds: _spawnDds, ddsPort: _ddsPort, - sendClientRequest: _sendRequestToClients, ); } @@ -252,31 +258,67 @@ class DevHandler { ); } - Future loadAppServices(AppConnection appConnection) async { + Future loadAppServices(AppConnection appConnection) async { final appId = appConnection.request.appId; var appServices = _servicesByAppId[appId]; if (appServices == null) { - final debugService = await _startLocalDebugService( - await _chromeConnection(), - appConnection, - ); - appServices = await _createAppDebugServices(debugService); - safeUnawaited( - appServices.chromeProxyService.remoteDebugger.onClose.first - .whenComplete(() async { - await appServices?.close(); - _servicesByAppId.remove(appConnection.request.appId); - _logger.info( - 'Stopped debug service on ' - 'ws://${debugService.hostname}:${debugService.port}\n', - ); - }), - ); + if (useWebSocketConnection) { + appServices = await _createWebSocketAppServices(appConnection); + } else { + appServices = await _createChromeAppServices(appConnection); + _setupChromeServiceCleanup(appServices, appConnection); + } _servicesByAppId[appId] = appServices; } + return appServices; } + /// Creates WebSocket-based app services for hot reload functionality. + Future _createWebSocketAppServices( + AppConnection appConnection, + ) async { + final webSocketDebugService = await WebSocketDebugService.start( + 'localhost', + appConnection, + sendClientRequest: _sendRequestToClients, + ); + return _createAppDebugServicesWebSocketMode( + webSocketDebugService, + appConnection, + ); + } + + /// Creates Chrome-based app services for full debugging capabilities. + Future _createChromeAppServices( + AppConnection appConnection, + ) async { + final debugService = await _startLocalDebugService( + await _chromeConnection(), + appConnection, + ); + return _createAppDebugServices(debugService); + } + + /// Sets up cleanup handling for Chrome-based services. + void _setupChromeServiceCleanup( + IAppDebugServices appServices, + AppConnection appConnection, + ) { + safeUnawaited( + appServices.chromeProxyService.remoteDebugger.onClose.first.whenComplete( + () async { + await appServices.close(); + _servicesByAppId.remove(appConnection.request.appId); + _logger.info( + 'Stopped debug service on ' + 'ws://${appServices.debugService.hostname}:${appServices.debugService.port}\n', + ); + }, + ), + ); + } + void _handleConnection(SocketConnection injectedConnection) { _injectedConnections.add(injectedConnection); AppConnection? appConnection; @@ -294,6 +336,7 @@ class DevHandler { appConnection = await _handleConnectRequest( message, injectedConnection, + isWebSocketMode: useWebSocketConnection, ); } else { final connection = appConnection; @@ -302,23 +345,12 @@ class DevHandler { } if (message is DevToolsRequest) { await _handleDebugRequest(connection, injectedConnection); - } else if (message is HotReloadResponse) { - // The app reload operation has completed. Mark the completer as done. - _servicesByAppId[connection.request.appId]?.chromeProxyService - .completeHotReload(message); - } else if (message is IsolateExit) { - _handleIsolateExit(connection); - } else if (message is IsolateStart) { - await _handleIsolateStart(connection); - } else if (message is BatchedDebugEvents) { - _servicesByAppId[connection.request.appId]?.chromeProxyService - .parseBatchedDebugEvents(message); - } else if (message is DebugEvent) { - _servicesByAppId[connection.request.appId]?.chromeProxyService - .parseDebugEvent(message); - } else if (message is RegisterEvent) { - _servicesByAppId[connection.request.appId]?.chromeProxyService - .parseRegisterEvent(message); + } else if (useWebSocketConnection) { + // Handle WebSocket-specific messages + await _handleWebSocketMessage(connection, message); + } else { + // Handle Chrome-specific messages + await _handleChromeMessage(connection, message); } } } catch (e, s) { @@ -356,7 +388,7 @@ class DevHandler { if (services.connectedInstanceId == null || services.connectedInstanceId == connection.request.instanceId) { services.connectedInstanceId = null; - services.chromeProxyService.destroyIsolate(); + _handleIsolateExit(connection); } } } @@ -364,6 +396,69 @@ class DevHandler { ); } + /// Handles WebSocket-specific messages. + Future _handleWebSocketMessage( + AppConnection connection, + Object? message, + ) async { + if (message == null) return; + + final appId = connection.request.appId; + final wsService = _servicesByAppId[appId]?.webSocketProxyService; + + if (wsService == null) { + _logger.warning( + 'No WebSocketProxyService found for appId: $appId to process $message', + ); + return; + } + if (message is HotReloadResponse) { + wsService.completeHotReload(message); + } else if (message is ServiceExtensionResponse) { + wsService.completeServiceExtension(message); + } else if (message is RegisterEvent) { + wsService.parseRegisterEvent(message); + } else if (message is BatchedDebugEvents) { + wsService.parseBatchedDebugEvents(message); + } else if (message is DebugEvent) { + wsService.parseDebugEvent(message); + } else { + throw UnsupportedError( + 'Message type ${message.runtimeType} is not supported in WebSocket mode', + ); + } + } + + /// Handles Chrome-specific messages. + Future _handleChromeMessage( + AppConnection connection, + Object? message, + ) async { + if (message == null) return; + + if (message is HotReloadResponse) { + _servicesByAppId[connection.request.appId]?.chromeProxyService + .completeHotReload(message); + } else if (message is IsolateExit) { + _handleIsolateExit(connection); + } else if (message is IsolateStart) { + await _handleIsolateStart(connection); + } else if (message is BatchedDebugEvents) { + _servicesByAppId[connection.request.appId]?.chromeProxyService + .parseBatchedDebugEvents(message); + } else if (message is DebugEvent) { + _servicesByAppId[connection.request.appId]?.chromeProxyService + .parseDebugEvent(message); + } else if (message is RegisterEvent) { + _servicesByAppId[connection.request.appId]?.chromeProxyService + .parseRegisterEvent(message); + } else { + throw UnsupportedError( + 'Message type ${message.runtimeType} is not supported in Chrome mode', + ); + } + } + Future _handleDebugRequest( AppConnection appConnection, SocketConnection sseConnection, @@ -388,7 +483,7 @@ class DevHandler { return; } final debuggerStart = DateTime.now(); - AppDebugServices appServices; + IAppDebugServices appServices; try { appServices = await loadAppServices(appConnection); } catch (_) { @@ -469,10 +564,53 @@ class DevHandler { ); } + /// Creates a debug connection for WebSocket mode. + Future createDebugConnectionForWebSocket( + AppConnection appConnection, + ) async { + final appDebugServices = await loadAppServices(appConnection); + + // Initialize WebSocket proxy service + final webSocketProxyService = appDebugServices.webSocketProxyService; + if (webSocketProxyService != null) { + await webSocketProxyService.isInitialized; + _logger.fine('WebSocket proxy service initialized successfully'); + } else { + _logger.warning('WebSocket proxy service is null'); + } + + return DebugConnection(appDebugServices); + } + + /// Creates a debug connection for Chrome mode. + Future createDebugConnectionForChrome( + AppConnection appConnection, + ) async { + final appDebugServices = await loadAppServices(appConnection); + + // Initialize Chrome proxy service + try { + final chromeProxyService = appDebugServices.chromeProxyService; + if (chromeProxyService != null) { + await chromeProxyService.isInitialized; + _logger.fine('Chrome proxy service initialized successfully'); + } else { + _logger.warning('Chrome proxy service is null'); + } + } catch (e) { + _logger.severe('Failed to initialize Chrome proxy service: $e'); + rethrow; + } + + return DebugConnection(appDebugServices); + } + + /// Handles connection requests for both Chrome and WebSocket modes. Future _handleConnectRequest( ConnectRequest message, - SocketConnection sseConnection, - ) async { + SocketConnection sseConnection, { + required bool isWebSocketMode, + }) async { // After a page refresh, reconnect to the same app services if they // were previously launched and create the new isolate. final services = _servicesByAppId[message.appId]; @@ -498,37 +636,96 @@ class DevHandler { existingConnection?.isInKeepAlivePeriod == true); if (canReuseConnection) { - // Disconnect any old connection (eg. those in the keep-alive waiting - // state when reloading the page). - existingConnection?.shutDown(); - services.chromeProxyService.destroyIsolate(); - // Reconnect to existing service. - services.connectedInstanceId = message.instanceId; - - if (services.chromeProxyService.pauseIsolatesOnStart) { - // If the pause-isolates-on-start flag is set, we need to wait for - // the resume event to run the app's main() method. - _waitForResumeEventToRunMain( - services.chromeProxyService.resumeAfterRestartEventsStream, - readyToRunMainCompleter, - ); - } else { - // Otherwise, we can run the app's main() method immediately. - readyToRunMainCompleter.complete(); - } - - await services.chromeProxyService.createIsolate(connection); + await _reconnectToService( + services, + existingConnection, + connection, + message, + readyToRunMainCompleter, + isWebSocketMode, + ); } else { + // Complete the readyToRunMainCompleter immediately since we're + // creating a new connection. // If this is the initial app connection, we can run the app's main() // method immediately. readyToRunMainCompleter.complete(); + + // For WebSocket mode, we need to proactively create and emit a debug connection + // since Flutter tools won't call debugConnection() for WebServerDevice + if (isWebSocketMode) { + try { + // This will call loadAppServices() and initialize the WebSocket service + final debugConnection = await createDebugConnectionForWebSocket( + connection, + ); + + // Emit the debug connection through the extension stream + // This should trigger Flutter tools to pick it up as if it was an extension connection + extensionDebugConnections.add(debugConnection); + } catch (e, s) { + _logger.warning( + 'Failed to create WebSocket debug connection: $e\n$s', + ); + } + } } _appConnectionByAppId[message.appId] = connection; _connectedApps.add(connection); + _logger.fine('App connection established for: ${message.appId}'); return connection; } + /// Handles reconnection to existing services. + Future _reconnectToService( + IAppDebugServices services, + AppConnection? existingConnection, + AppConnection newConnection, + ConnectRequest message, + Completer readyToRunMainCompleter, + bool isWebSocketMode, + ) async { + // Disconnect old connection + existingConnection?.shutDown(); + services.connectedInstanceId = message.instanceId; + + if (isWebSocketMode) { + services.webSocketProxyService?.destroyIsolate(); + _logger.finest('WebSocket service reconnected for app: ${message.appId}'); + + _setupMainExecution( + services.webSocketProxyService?.pauseIsolatesOnStart == true, + services.webSocketProxyService?.resumeAfterRestartEventsStream, + readyToRunMainCompleter, + ); + } else { + services.chromeProxyService.destroyIsolate(); + _logger.finest('Chrome service reconnected for app: ${message.appId}'); + + _setupMainExecution( + services.chromeProxyService.pauseIsolatesOnStart, + services.chromeProxyService.resumeAfterRestartEventsStream, + readyToRunMainCompleter, + ); + } + + await _handleIsolateStart(newConnection); + } + + /// Sets up main() execution timing based on pause settings. + void _setupMainExecution( + bool pauseIsolatesOnStart, + Stream? resumeEventsStream, + Completer readyToRunMainCompleter, + ) { + if (pauseIsolatesOnStart && resumeEventsStream != null) { + _waitForResumeEventToRunMain(resumeEventsStream, readyToRunMainCompleter); + } else { + readyToRunMainCompleter.complete(); + } + } + /// Waits for a resume event to trigger the app's main() method. /// /// The [readyToRunMainCompleter]'s future will be passed to the @@ -545,14 +742,30 @@ class DevHandler { }); } + /// Handles isolate exit events for both WebSocket and Chrome-based debugging. void _handleIsolateExit(AppConnection appConnection) { - _servicesByAppId[appConnection.request.appId]?.chromeProxyService - .destroyIsolate(); + final appId = appConnection.request.appId; + + if (useWebSocketConnection) { + _servicesByAppId[appId]?.webSocketProxyService?.destroyIsolate(); + } else { + _servicesByAppId[appId]?.chromeProxyService.destroyIsolate(); + } } + /// Handles isolate start events for both WebSocket and Chrome-based debugging. Future _handleIsolateStart(AppConnection appConnection) async { - await _servicesByAppId[appConnection.request.appId]?.chromeProxyService - .createIsolate(appConnection); + final appId = appConnection.request.appId; + + if (useWebSocketConnection) { + await _servicesByAppId[appId]?.webSocketProxyService?.createIsolate( + appConnection, + ); + } else { + await _servicesByAppId[appId]?.chromeProxyService.createIsolate( + appConnection, + ); + } } void _listen() { @@ -580,7 +793,7 @@ class DevHandler { ); } - Future _createAppDebugServices( + Future _createAppDebugServices( DebugService debugService, ) async { final dwdsStats = DwdsStats(); @@ -614,6 +827,28 @@ class DevHandler { return appDebugService; } + Future _createAppDebugServicesWebSocketMode( + WebSocketDebugService webSocketDebugService, + AppConnection appConnection, + ) async { + final wsVmClient = await WebSocketDwdsVmClient.create( + webSocketDebugService, + ); + final wsAppDebugService = WebSocketAppDebugServices( + webSocketDebugService, + wsVmClient, + ); + + safeUnawaited(_handleIsolateStart(appConnection)); + final debugServiceUri = webSocketDebugService.uri; + _logger.info('Debug service listening on $debugServiceUri\n'); + + // Notify that DWDS has been launched and a debug connection has been made: + _maybeEmitDwdsLaunchEvent(); + + return wsAppDebugService; + } + Future _listenForDebugExtension() async { final extensionBackend = _extensionBackend; if (extensionBackend == null) { @@ -634,6 +869,7 @@ class DevHandler { extensionDebugger.devToolsRequestStream.listen((devToolsRequest) async { try { await _handleDevToolsRequest(extensionDebugger, devToolsRequest); + _logger.finest('DevTools request processed successfully'); } catch (error) { _logger.severe('Encountered error handling DevTools request.'); extensionDebugger.closeWithError(error); @@ -688,7 +924,6 @@ class DevHandler { expressionCompiler: _expressionCompiler, spawnDds: _spawnDds, ddsPort: _ddsPort, - sendClientRequest: _sendRequestToClients, ); appServices = await _createAppDebugServices(debugService); extensionDebugger.sendEvent('dwds.debugUri', debugService.uri); diff --git a/dwds/lib/src/handlers/injector.dart b/dwds/lib/src/handlers/injector.dart index d55494944..121c3628a 100644 --- a/dwds/lib/src/handlers/injector.dart +++ b/dwds/lib/src/handlers/injector.dart @@ -29,22 +29,12 @@ const _clientScript = 'dwds/src/injected/client'; /// This class is responsible for modifying the served JavaScript files /// to include the injected DWDS client, enabling debugging capabilities /// and source mapping when running in a browser environment. -/// -/// TODO(yjessy): Remove this when the DWDS WebSocket connection is implemented. -/// The `_useDwdsWebSocketConnection` flag determines the communication protocol: -/// - When `true`, uses a socket-based implementation. -/// - When `false`, uses Chrome-based communication protocol. class DwdsInjector { final Future? _extensionUri; final _devHandlerPaths = StreamController(); final _logger = Logger('DwdsInjector'); - final bool _useDwdsWebSocketConnection; - DwdsInjector({ - Future? extensionUri, - bool useDwdsWebSocketConnection = false, - }) : _extensionUri = extensionUri, - _useDwdsWebSocketConnection = useDwdsWebSocketConnection; + DwdsInjector({Future? extensionUri}) : _extensionUri = extensionUri; /// Returns the embedded dev handler paths. /// @@ -111,7 +101,6 @@ class DwdsInjector { devHandlerPath, entrypoint, await _extensionUri, - _useDwdsWebSocketConnection, ); body += await globalToolConfiguration.loadStrategy.bootstrapFor( entrypoint, @@ -148,7 +137,6 @@ Future _injectClientAndHoistMain( String devHandlerPath, String entrypointPath, String? extensionUri, - bool useDwdsWebSocketConnection, ) async { final bodyLines = body.split('\n'); final extensionIndex = bodyLines.indexWhere( @@ -167,7 +155,6 @@ Future _injectClientAndHoistMain( devHandlerPath, entrypointPath, extensionUri, - useDwdsWebSocketConnection, ); result += ''' // Injected by dwds for debugging support. @@ -199,7 +186,6 @@ Future _injectedClientSnippet( String devHandlerPath, String entrypointPath, String? extensionUri, - bool useDwdsWebSocketConnection, ) async { final loadStrategy = globalToolConfiguration.loadStrategy; final buildSettings = loadStrategy.buildSettings; @@ -218,7 +204,6 @@ Future _injectedClientSnippet( 'window.\$dartEmitDebugEvents = ${debugSettings.emitDebugEvents};\n' 'window.\$isInternalBuild = ${appMetadata.isInternalBuild};\n' 'window.\$isFlutterApp = ${buildSettings.isFlutterApp};\n' - 'window.\$useDwdsWebSocketConnection = $useDwdsWebSocketConnection;\n' '${loadStrategy is DdcLibraryBundleStrategy ? 'window.\$hotReloadSourcesPath = "${loadStrategy.hotReloadSourcesUri.toString()}";\n' : ''}' '${loadStrategy.loadClientSnippet(_clientScript)}'; diff --git a/dwds/lib/src/injected/client.js b/dwds/lib/src/injected/client.js index 40bf2fd5d..8ff09194c 100644 --- a/dwds/lib/src/injected/client.js +++ b/dwds/lib/src/injected/client.js @@ -8471,6 +8471,48 @@ }, _$serializers_closure0: function _$serializers_closure0() { }, + ServiceExtensionRequest: function ServiceExtensionRequest() { + }, + _$ServiceExtensionRequestSerializer: function _$ServiceExtensionRequestSerializer() { + }, + _$ServiceExtensionRequest: function _$ServiceExtensionRequest(t0, t1, t2) { + this.id = t0; + this.method = t1; + this.argsJson = t2; + }, + ServiceExtensionRequestBuilder: function ServiceExtensionRequestBuilder() { + var _ = this; + _._argsJson = _._service_extension_request$_method = _._service_extension_request$_id = _._service_extension_request$_$v = null; + }, + ServiceExtensionResponse_ServiceExtensionResponse$fromResult(errorCode, errorMessage, id, result, success) { + var t1 = new A.ServiceExtensionResponseBuilder(); + type$.nullable_void_Function_ServiceExtensionResponseBuilder._as(new A.ServiceExtensionResponse_ServiceExtensionResponse$fromResult_closure(id, success, result, errorCode, errorMessage)).call$1(t1); + return t1._service_extension_response$_build$0(); + }, + ServiceExtensionResponse: function ServiceExtensionResponse() { + }, + ServiceExtensionResponse_ServiceExtensionResponse$fromResult_closure: function ServiceExtensionResponse_ServiceExtensionResponse$fromResult_closure(t0, t1, t2, t3, t4) { + var _ = this; + _.id = t0; + _.success = t1; + _.result = t2; + _.errorCode = t3; + _.errorMessage = t4; + }, + _$ServiceExtensionResponseSerializer: function _$ServiceExtensionResponseSerializer() { + }, + _$ServiceExtensionResponse: function _$ServiceExtensionResponse(t0, t1, t2, t3, t4) { + var _ = this; + _.id = t0; + _.resultJson = t1; + _.success = t2; + _.errorCode = t3; + _.errorMessage = t4; + }, + ServiceExtensionResponseBuilder: function ServiceExtensionResponseBuilder() { + var _ = this; + _._service_extension_response$_errorMessage = _._errorCode = _._service_extension_response$_success = _._resultJson = _._service_extension_response$_id = _._service_extension_response$_$v = null; + }, BatchedStreamController: function BatchedStreamController(t0, t1, t2, t3, t4, t5) { var _ = this; _._checkDelayMilliseconds = t0; @@ -9674,6 +9716,9 @@ _sendResponse(clientSink, builder, requestId, errorMessage, success, $T) { A._trySendEvent(clientSink, B.C_JsonCodec.encode$2$toEncodable($.$get$serializers().serialize$1(builder.call$1(new A._sendResponse_closure(requestId, success, errorMessage))), null), type$.dynamic); }, + _sendServiceExtensionResponse(clientSink, requestId, errorCode, errorMessage, result, success) { + A._trySendEvent(clientSink, B.C_JsonCodec.encode$2$toEncodable($.$get$serializers().serialize$1(A.ServiceExtensionResponse_ServiceExtensionResponse$fromResult(errorCode, errorMessage, requestId, result, success)), null), type$.dynamic); + }, handleWebSocketHotReloadRequest($event, manager, clientSink) { return A.handleWebSocketHotReloadRequest$body($event, manager, clientSink); }, @@ -9731,6 +9776,64 @@ }); return A._asyncStartSync($async$handleWebSocketHotReloadRequest, $async$completer); }, + handleServiceExtensionRequest(request, clientSink, manager) { + return A.handleServiceExtensionRequest$body(request, clientSink, manager); + }, + handleServiceExtensionRequest$body(request, clientSink, manager) { + var $async$goto = 0, + $async$completer = A._makeAsyncAwaitCompleter(type$.void), + $async$handler = 1, $async$errorStack = [], result, e, t1, exception, $async$exception; + var $async$handleServiceExtensionRequest = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) { + $async$errorStack.push($async$result); + $async$goto = $async$handler; + } + while (true) + switch ($async$goto) { + case 0: + // Function start + $async$handler = 3; + t1 = request.argsJson; + t1 = t1.length === 0 ? A.LinkedHashMap_LinkedHashMap$_empty(type$.String, type$.dynamic) : type$.Map_String_dynamic._as(B.C_JsonCodec.decode$1(t1)); + $async$goto = 6; + return A._asyncAwait(manager.handleServiceExtension$2(request.method, t1), $async$handleServiceExtensionRequest); + case 6: + // returning from await. + result = $async$result; + t1 = request.id; + if (result != null) + A._sendServiceExtensionResponse(clientSink, t1, null, null, result, true); + else + A._sendServiceExtensionResponse(clientSink, t1, -32601, "Service extension not supported", null, false); + $async$handler = 1; + // goto after finally + $async$goto = 5; + break; + case 3: + // catch + $async$handler = 2; + $async$exception = $async$errorStack.pop(); + e = A.unwrapException($async$exception); + A._sendServiceExtensionResponse(clientSink, request.id, null, J.toString$0$(e), null, false); + // goto after finally + $async$goto = 5; + break; + case 2: + // uncaught + // goto rethrow + $async$goto = 1; + break; + case 5: + // after finally + // implicit return + return A._asyncReturn(null, $async$completer); + case 1: + // rethrow + return A._asyncRethrow($async$errorStack.at(-1), $async$completer); + } + }); + return A._asyncStartSync($async$handleServiceExtensionRequest, $async$completer); + }, hotReloadSourcesPath() { var path = A._asStringQ(init.G.$hotReloadSourcesPath); if (path == null) @@ -9847,6 +9950,37 @@ }); return A._asyncStartSync($async$_Debugger_maybeInvokeFlutterDisassemble, $async$completer); }, + _Debugger_maybeInvokeFlutterReassemble(_this) { + return A._Debugger_maybeInvokeFlutterReassemble$body(_this); + }, + _Debugger_maybeInvokeFlutterReassemble$body(_this) { + var $async$goto = 0, + $async$completer = A._makeAsyncAwaitCompleter(type$.void), + t1; + var $async$_Debugger_maybeInvokeFlutterReassemble = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return A._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + t1 = type$.JSArray_nullable_Object._as(_this.extensionNames); + $async$goto = J.contains$1$asx(type$.List_String._is(t1) ? t1 : new A.CastList(t1, A._arrayInstanceType(t1)._eval$1("CastList<1,String>")), "ext.flutter.reassemble") ? 2 : 3; + break; + case 2: + // then + $async$goto = 4; + return A._asyncAwait(A.promiseToFuture(type$.JSObject._as(_this.invokeExtension("ext.flutter.reassemble", "{}")), type$.String), $async$_Debugger_maybeInvokeFlutterReassemble); + case 4: + // returning from await. + case 3: + // join + // implicit return + return A._asyncReturn(null, $async$completer); + } + }); + return A._asyncStartSync($async$_Debugger_maybeInvokeFlutterReassemble, $async$completer); + }, DdcLibraryBundleRestarter: function DdcLibraryBundleRestarter() { this.__DdcLibraryBundleRestarter__sourcesAndLibrariesToReload_A = $; }, @@ -11127,6 +11261,10 @@ get$isEmpty(_) { var t1 = this.__internal$_source; return t1.get$isEmpty(t1); + }, + get$isNotEmpty(_) { + var t1 = this.__internal$_source; + return t1.get$isNotEmpty(t1); } }; A.CastMap_forEach_closure.prototype = { @@ -11160,7 +11298,7 @@ call$0() { return A.Future_Future$value(null, type$.void); }, - $signature: 19 + $signature: 16 }; A.SentinelValue.prototype = {}; A.EfficientLengthIterable.prototype = {}; @@ -11647,6 +11785,9 @@ get$isEmpty(_) { return this.get$length(this) === 0; }, + get$isNotEmpty(_) { + return this.get$length(this) !== 0; + }, toString$0(_) { return A.MapBase_mapToString(this); }, @@ -11898,6 +12039,9 @@ get$isEmpty(_) { return this.__js_helper$_length === 0; }, + get$isNotEmpty(_) { + return this.__js_helper$_length !== 0; + }, get$keys() { return new A.LinkedHashMapKeysIterable(this, A._instanceType(this)._eval$1("LinkedHashMapKeysIterable<1>")); }, @@ -12261,13 +12405,13 @@ call$2(o, tag) { return this.getUnknownTag(o, tag); }, - $signature: 66 + $signature: 35 }; A.initHooks_closure1.prototype = { call$1(tag) { return this.prototypeForTag(A._asString(tag)); }, - $signature: 90 + $signature: 49 }; A._Record.prototype = { get$runtimeType(_) { @@ -12855,7 +12999,7 @@ t2 = this.span; t1.firstChild ? t1.removeChild(t2) : t1.appendChild(t2); }, - $signature: 61 + $signature: 37 }; A._AsyncRun__scheduleImmediateJsOverride_internalCallback.prototype = { call$0() { @@ -12961,13 +13105,13 @@ call$2(error, stackTrace) { this.bodyFunction.call$2(1, new A.ExceptionAndStackTrace(error, type$.StackTrace._as(stackTrace))); }, - $signature: 52 + $signature: 47 }; A._wrapJsFunctionForAsync_closure.prototype = { call$2(errorCode, result) { this.$protected(A._asInt(errorCode), result); }, - $signature: 37 + $signature: 57 }; A.AsyncError.prototype = { toString$0(_) { @@ -14778,7 +14922,7 @@ t2._processUncaughtError$3(zone, type$.Object._as(e), t1._as(s)); } }, - $signature: 63 + $signature: 39 }; A._HashMap.prototype = { get$length(_) { @@ -14787,6 +14931,9 @@ get$isEmpty(_) { return this._collection$_length === 0; }, + get$isNotEmpty(_) { + return this._collection$_length !== 0; + }, get$keys() { return new A._HashMapKeyIterable(this, A._instanceType(this)._eval$1("_HashMapKeyIterable<1>")); }, @@ -15000,7 +15147,7 @@ call$1(v) { return this.K._is(v); }, - $signature: 12 + $signature: 14 }; A._HashMapKeyIterable.prototype = { get$length(_) { @@ -15081,7 +15228,7 @@ call$1(v) { return this.K._is(v); }, - $signature: 12 + $signature: 14 }; A._HashSet.prototype = { get$iterator(_) { @@ -15449,7 +15596,7 @@ call$2(k, v) { this.result.$indexSet(0, this.K._as(k), this.V._as(v)); }, - $signature: 23 + $signature: 29 }; A.ListBase.prototype = { get$iterator(receiver) { @@ -15625,6 +15772,10 @@ var t1 = this.get$keys(); return t1.get$isEmpty(t1); }, + get$isNotEmpty(_) { + var t1 = this.get$keys(); + return t1.get$isNotEmpty(t1); + }, toString$0(_) { return A.MapBase_mapToString(this); }, @@ -15643,7 +15794,7 @@ t2 = A.S(v); t1._contents += t2; }, - $signature: 24 + $signature: 31 }; A._UnmodifiableMapMixin.prototype = { $indexSet(_, key, value) { @@ -15674,6 +15825,10 @@ var t1 = this._collection$_map; return t1.get$isEmpty(t1); }, + get$isNotEmpty(_) { + var t1 = this._collection$_map; + return t1.get$isNotEmpty(t1); + }, get$length(_) { var t1 = this._collection$_map; return t1.get$length(t1); @@ -16178,6 +16333,9 @@ get$isEmpty(_) { return this.get$length(0) === 0; }, + get$isNotEmpty(_) { + return this.get$length(0) > 0; + }, get$keys() { if (this._processed == null) { var t1 = this._data; @@ -16296,7 +16454,7 @@ } return null; }, - $signature: 25 + $signature: 21 }; A._Utf8Decoder__decoderNonfatal_closure.prototype = { call$0() { @@ -16308,7 +16466,7 @@ } return null; }, - $signature: 25 + $signature: 21 }; A.AsciiCodec.prototype = { encode$1(source) { @@ -16599,6 +16757,9 @@ var t1 = A._JsonStringStringifier_stringify(value, this.get$encoder()._toEncodable, null); return t1; }, + encode$1(value) { + return this.encode$2$toEncodable(value, null); + }, get$encoder() { return B.JsonEncoder_null; }, @@ -16811,7 +16972,7 @@ B.JSArray_methods.$indexSet(t1, t2.i++, key); B.JSArray_methods.$indexSet(t1, t2.i++, value); }, - $signature: 24 + $signature: 31 }; A._JsonStringStringifier.prototype = { get$_partialResult() { @@ -17493,7 +17654,7 @@ hash = hash + ((hash & 524287) << 10) & 536870911; return hash ^ hash >>> 6; }, - $signature: 26 + $signature: 27 }; A._BigIntImpl_hashCode_finish.prototype = { call$1(hash) { @@ -17501,7 +17662,7 @@ hash ^= hash >>> 11; return hash + ((hash & 16383) << 15) & 536870911; }, - $signature: 27 + $signature: 22 }; A.DateTime.prototype = { $eq(_, other) { @@ -17920,13 +18081,13 @@ call$2(msg, position) { throw A.wrapException(A.FormatException$("Illegal IPv4 address, " + msg, this.host, position)); }, - $signature: 56 + $signature: 38 }; A.Uri_parseIPv6Address_error.prototype = { call$2(msg, position) { throw A.wrapException(A.FormatException$("Illegal IPv6 address, " + msg, this.host, position)); }, - $signature: 53 + $signature: 43 }; A.Uri_parseIPv6Address_parseHex.prototype = { call$2(start, end) { @@ -17938,7 +18099,7 @@ this.error.call$2("each part must be in the range of `0x0..0xFFFF`", start); return value; }, - $signature: 26 + $signature: 27 }; A._Uri.prototype = { get$_text() { @@ -18239,7 +18400,7 @@ call$1(s) { return A._Uri__uriEncode(64, A._asString(s), B.C_Utf8Codec, false); }, - $signature: 13 + $signature: 15 }; A.UriData.prototype = { get$uri() { @@ -18565,7 +18726,7 @@ var t1 = type$.JavaScriptFunction; this._this.then$1$2$onError(new A.FutureOfJSAnyToJSPromise_get_toJS__closure(t1._as(resolve)), new A.FutureOfJSAnyToJSPromise_get_toJS__closure0(t1._as(reject)), type$.nullable_Object); }, - $signature: 29 + $signature: 24 }; A.FutureOfJSAnyToJSPromise_get_toJS__closure.prototype = { call$1(value) { @@ -18591,21 +18752,21 @@ t1.call(t1, wrapper); return wrapper; }, - $signature: 50 + $signature: 51 }; A.FutureOfVoidToJSPromise_get_toJS_closure.prototype = { call$2(resolve, reject) { var t1 = type$.JavaScriptFunction; this._this.then$1$2$onError(new A.FutureOfVoidToJSPromise_get_toJS__closure(t1._as(resolve)), new A.FutureOfVoidToJSPromise_get_toJS__closure0(t1._as(reject)), type$.nullable_Object); }, - $signature: 29 + $signature: 24 }; A.FutureOfVoidToJSPromise_get_toJS__closure.prototype = { call$1(__wc0_formal) { var t1 = this.resolve; return t1.call(t1); }, - $signature: 46 + $signature: 53 }; A.FutureOfVoidToJSPromise_get_toJS__closure0.prototype = { call$2(error, stackTrace) { @@ -18925,7 +19086,7 @@ call$2(h, i) { return A._combine(A._asInt(h), J.get$hashCode$(i)); }, - $signature: 42 + $signature: 62 }; A.BuiltList.prototype = { toBuilder$0() { @@ -19478,7 +19639,7 @@ var t1 = this.$this.$ti; this.replacement.$indexSet(0, t1._precomputed1._as(key), t1._rest[1]._as(value)); }, - $signature: 23 + $signature: 29 }; A.BuiltSet.prototype = { get$hashCode(_) { @@ -19859,7 +20020,7 @@ $._indentingBuiltValueToStringHelperIndent = $._indentingBuiltValueToStringHelperIndent + 2; return new A.IndentingBuiltValueToStringHelper(t1); }, - $signature: 39 + $signature: 64 }; A.IndentingBuiltValueToStringHelper.prototype = { add$2(_, field, value) { @@ -19992,34 +20153,34 @@ call$0() { return A.ListBuilder_ListBuilder(B.List_empty0, type$.Object); }, - $signature: 38 + $signature: 67 }; A.Serializers_Serializers_closure0.prototype = { call$0() { var t1 = type$.Object; return A.ListMultimapBuilder_ListMultimapBuilder(t1, t1); }, - $signature: 36 + $signature: 90 }; A.Serializers_Serializers_closure1.prototype = { call$0() { var t1 = type$.Object; return A.MapBuilder_MapBuilder(t1, t1); }, - $signature: 34 + $signature: 91 }; A.Serializers_Serializers_closure2.prototype = { call$0() { return A.SetBuilder_SetBuilder(type$.Object); }, - $signature: 35 + $signature: 107 }; A.Serializers_Serializers_closure3.prototype = { call$0() { var t1 = type$.Object; return A.SetMultimapBuilder_SetMultimapBuilder(t1, t1); }, - $signature: 89 + $signature: 36 }; A.FullType.prototype = { $eq(_, other) { @@ -21143,6 +21304,9 @@ get$isEmpty(_) { return this._base.__js_helper$_length === 0; }, + get$isNotEmpty(_) { + return this._base.__js_helper$_length !== 0; + }, get$keys() { var t1 = this._base, t2 = A._instanceType(t1)._eval$1("LinkedHashMapValuesIterable<2>"), @@ -23519,95 +23683,357 @@ }, $signature: 41 }; - A.BatchedStreamController.prototype = { - _batchAndSendEvents$0() { - var $async$goto = 0, - $async$completer = A._makeAsyncAwaitCompleter(type$.void), - $async$self = this, t2, t3, t4, t5, t6, t7, t8, lastSendTime0, lastEvent, duration, t1, buffer, lastSendTime, $async$temp1, $async$temp2; - var $async$_batchAndSendEvents$0 = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { - if ($async$errorCode === 1) - return A._asyncRethrow($async$result, $async$completer); - while (true) - switch ($async$goto) { - case 0: - // Function start - duration = A.Duration$(0, $async$self._checkDelayMilliseconds); - t1 = $async$self.$ti; - buffer = A._setArrayType([], t1._eval$1("JSArray<1>")); - lastSendTime = Date.now(); - t2 = $async$self._batchDelayMilliseconds, t3 = $async$self._outputController, t4 = A._instanceType(t3), t1 = t1._precomputed1, t5 = t4._precomputed1, t4 = t4._eval$1("_DelayedData<1>"); - case 2: - // for condition - $async$goto = 4; - return A._asyncAwait($async$self._hasEventOrTimeOut$1(duration), $async$_batchAndSendEvents$0); - case 4: - // returning from await. - if (!$async$result) { - // goto after for - $async$goto = 3; - break; - } - $async$goto = 7; - return A._asyncAwait($async$self._hasEventDuring$1(duration), $async$_batchAndSendEvents$0); - case 7: - // returning from await. - $async$goto = $async$result ? 5 : 6; - break; - case 5: - // then - t6 = $async$self.__BatchedStreamController__inputQueue_A; - t6 === $ && A.throwLateFieldNI("_inputQueue"); - t7 = t6.$ti; - t8 = new A._Future($.Zone__current, t7._eval$1("_Future<1>")); - t6._addRequest$1(new A._NextRequest(new A._AsyncCompleter(t8, t7._eval$1("_AsyncCompleter<1>")), t7._eval$1("_NextRequest<1>"))); - $async$temp1 = B.JSArray_methods; - $async$temp2 = buffer; - $async$goto = 8; - return A._asyncAwait(t8, $async$_batchAndSendEvents$0); - case 8: - // returning from await. - $async$temp1.add$1($async$temp2, $async$result); - case 6: - // join - lastSendTime0 = Date.now(); - if (lastSendTime0 > lastSendTime + t2) { - if (buffer.length !== 0) { - t6 = A.List_List$_of(buffer, t1); - t5._as(t6); - t7 = t3._state; - if (t7 >= 4) - A.throwExpression(t3._badEventState$0()); - if ((t7 & 1) !== 0) - t3._sendData$1(t6); - else if ((t7 & 3) === 0) { - t7 = t3._ensurePendingEvents$0(); - t6 = new A._DelayedData(t6, t4); - lastEvent = t7.lastPendingEvent; - if (lastEvent == null) - t7.firstPendingEvent = t7.lastPendingEvent = t6; - else { - lastEvent.set$next(t6); - t7.lastPendingEvent = t6; - } - } - B.JSArray_methods.clear$0(buffer); - } - lastSendTime = lastSendTime0; - } - // goto for condition - $async$goto = 2; - break; - case 3: - // after for - if (buffer.length !== 0) { - t1 = A.List_List$_of(buffer, t1); - t3.add$1(0, t5._as(t1)); - } - $async$self._completer.complete$1(true); - // implicit return - return A._asyncReturn(null, $async$completer); - } - }); + A.ServiceExtensionRequest.prototype = {}; + A._$ServiceExtensionRequestSerializer.prototype = { + serialize$3$specifiedType(serializers, object, specifiedType) { + type$.ServiceExtensionRequest._as(object); + return ["id", serializers.serialize$2$specifiedType(object.id, B.FullType_PT1), "method", serializers.serialize$2$specifiedType(object.method, B.FullType_PT1), "argsJson", serializers.serialize$2$specifiedType(object.argsJson, B.FullType_PT1)]; + }, + serialize$2(serializers, object) { + return this.serialize$3$specifiedType(serializers, object, B.FullType_null_List_empty_false); + }, + deserialize$3$specifiedType(serializers, serialized, specifiedType) { + var t1, value, _$result, t2, t3, t4, + _s8_ = "argsJson", + _s23_ = "ServiceExtensionRequest", + result = new A.ServiceExtensionRequestBuilder(), + iterator = J.get$iterator$ax(type$.Iterable_nullable_Object._as(serialized)); + for (; iterator.moveNext$0();) { + t1 = iterator.get$current(); + t1.toString; + A._asString(t1); + iterator.moveNext$0(); + value = iterator.get$current(); + switch (t1) { + case "id": + t1 = serializers.deserialize$2$specifiedType(value, B.FullType_PT1); + t1.toString; + A._asString(t1); + result.get$_service_extension_request$_$this()._service_extension_request$_id = t1; + break; + case "method": + t1 = serializers.deserialize$2$specifiedType(value, B.FullType_PT1); + t1.toString; + A._asString(t1); + result.get$_service_extension_request$_$this()._service_extension_request$_method = t1; + break; + case "argsJson": + t1 = serializers.deserialize$2$specifiedType(value, B.FullType_PT1); + t1.toString; + A._asString(t1); + result.get$_service_extension_request$_$this()._argsJson = t1; + break; + } + } + _$result = result._service_extension_request$_$v; + if (_$result == null) { + t1 = type$.String; + t2 = A.BuiltValueNullFieldError_checkNotNull(result.get$_service_extension_request$_$this()._service_extension_request$_id, _s23_, "id", t1); + t3 = A.BuiltValueNullFieldError_checkNotNull(result.get$_service_extension_request$_$this()._service_extension_request$_method, _s23_, "method", t1); + t4 = A.BuiltValueNullFieldError_checkNotNull(result.get$_service_extension_request$_$this()._argsJson, _s23_, _s8_, t1); + _$result = new A._$ServiceExtensionRequest(t2, t3, t4); + A.BuiltValueNullFieldError_checkNotNull(t2, _s23_, "id", t1); + A.BuiltValueNullFieldError_checkNotNull(t3, _s23_, "method", t1); + A.BuiltValueNullFieldError_checkNotNull(t4, _s23_, _s8_, t1); + } + A.ArgumentError_checkNotNull(_$result, "other", type$.ServiceExtensionRequest); + return result._service_extension_request$_$v = _$result; + }, + deserialize$2(serializers, serialized) { + return this.deserialize$3$specifiedType(serializers, serialized, B.FullType_null_List_empty_false); + }, + $isSerializer: 1, + $isStructuredSerializer: 1, + get$types() { + return B.List_4i4; + }, + get$wireName() { + return "ServiceExtensionRequest"; + } + }; + A._$ServiceExtensionRequest.prototype = { + $eq(_, other) { + var _this = this; + if (other == null) + return false; + if (other === _this) + return true; + return other instanceof A._$ServiceExtensionRequest && _this.id === other.id && _this.method === other.method && _this.argsJson === other.argsJson; + }, + get$hashCode(_) { + return A.$jf(A.$jc(A.$jc(A.$jc(0, B.JSString_methods.get$hashCode(this.id)), B.JSString_methods.get$hashCode(this.method)), B.JSString_methods.get$hashCode(this.argsJson))); + }, + toString$0(_) { + var t1 = $.$get$newBuiltValueToStringHelper().call$1("ServiceExtensionRequest"), + t2 = J.getInterceptor$ax(t1); + t2.add$2(t1, "id", this.id); + t2.add$2(t1, "method", this.method); + t2.add$2(t1, "argsJson", this.argsJson); + return t2.toString$0(t1); + } + }; + A.ServiceExtensionRequestBuilder.prototype = { + set$id(id) { + this.get$_service_extension_request$_$this()._service_extension_request$_id = id; + }, + get$_service_extension_request$_$this() { + var _this = this, + $$v = _this._service_extension_request$_$v; + if ($$v != null) { + _this._service_extension_request$_id = $$v.id; + _this._service_extension_request$_method = $$v.method; + _this._argsJson = $$v.argsJson; + _this._service_extension_request$_$v = null; + } + return _this; + } + }; + A.ServiceExtensionResponse.prototype = {}; + A.ServiceExtensionResponse_ServiceExtensionResponse$fromResult_closure.prototype = { + call$1(b) { + var t1, _this = this; + b.get$_service_extension_response$_$this()._service_extension_response$_id = _this.id; + b.get$_service_extension_response$_$this()._service_extension_response$_success = _this.success; + t1 = _this.result; + t1 = t1 != null ? B.C_JsonCodec.encode$1(t1) : null; + b.get$_service_extension_response$_$this()._resultJson = t1; + b.get$_service_extension_response$_$this()._errorCode = _this.errorCode; + b.get$_service_extension_response$_$this()._service_extension_response$_errorMessage = _this.errorMessage; + return b; + }, + $signature: 42 + }; + A._$ServiceExtensionResponseSerializer.prototype = { + serialize$3$specifiedType(serializers, object, specifiedType) { + var result, value; + type$.ServiceExtensionResponse._as(object); + result = ["id", serializers.serialize$2$specifiedType(object.id, B.FullType_PT1), "success", serializers.serialize$2$specifiedType(object.success, B.FullType_R6B)]; + value = object.resultJson; + if (value != null) { + result.push("resultJson"); + result.push(serializers.serialize$2$specifiedType(value, B.FullType_PT1)); + } + value = object.errorCode; + if (value != null) { + result.push("errorCode"); + result.push(serializers.serialize$2$specifiedType(value, B.FullType_rTD)); + } + value = object.errorMessage; + if (value != null) { + result.push("errorMessage"); + result.push(serializers.serialize$2$specifiedType(value, B.FullType_PT1)); + } + return result; + }, + serialize$2(serializers, object) { + return this.serialize$3$specifiedType(serializers, object, B.FullType_null_List_empty_false); + }, + deserialize$3$specifiedType(serializers, serialized, specifiedType) { + var t1, value, + result = new A.ServiceExtensionResponseBuilder(), + iterator = J.get$iterator$ax(type$.Iterable_nullable_Object._as(serialized)); + for (; iterator.moveNext$0();) { + t1 = iterator.get$current(); + t1.toString; + A._asString(t1); + iterator.moveNext$0(); + value = iterator.get$current(); + switch (t1) { + case "id": + t1 = serializers.deserialize$2$specifiedType(value, B.FullType_PT1); + t1.toString; + A._asString(t1); + result.get$_service_extension_response$_$this()._service_extension_response$_id = t1; + break; + case "resultJson": + t1 = A._asStringQ(serializers.deserialize$2$specifiedType(value, B.FullType_PT1)); + result.get$_service_extension_response$_$this()._resultJson = t1; + break; + case "success": + t1 = serializers.deserialize$2$specifiedType(value, B.FullType_R6B); + t1.toString; + A._asBool(t1); + result.get$_service_extension_response$_$this()._service_extension_response$_success = t1; + break; + case "errorCode": + t1 = A._asIntQ(serializers.deserialize$2$specifiedType(value, B.FullType_rTD)); + result.get$_service_extension_response$_$this()._errorCode = t1; + break; + case "errorMessage": + t1 = A._asStringQ(serializers.deserialize$2$specifiedType(value, B.FullType_PT1)); + result.get$_service_extension_response$_$this()._service_extension_response$_errorMessage = t1; + break; + } + } + return result._service_extension_response$_build$0(); + }, + deserialize$2(serializers, serialized) { + return this.deserialize$3$specifiedType(serializers, serialized, B.FullType_null_List_empty_false); + }, + $isSerializer: 1, + $isStructuredSerializer: 1, + get$types() { + return B.List_5rA; + }, + get$wireName() { + return "ServiceExtensionResponse"; + } + }; + A._$ServiceExtensionResponse.prototype = { + $eq(_, other) { + var _this = this; + if (other == null) + return false; + if (other === _this) + return true; + return other instanceof A._$ServiceExtensionResponse && _this.id === other.id && _this.resultJson == other.resultJson && _this.success === other.success && _this.errorCode == other.errorCode && _this.errorMessage == other.errorMessage; + }, + get$hashCode(_) { + var _this = this; + return A.$jf(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(0, B.JSString_methods.get$hashCode(_this.id)), J.get$hashCode$(_this.resultJson)), B.JSBool_methods.get$hashCode(_this.success)), J.get$hashCode$(_this.errorCode)), J.get$hashCode$(_this.errorMessage))); + }, + toString$0(_) { + var _this = this, + t1 = $.$get$newBuiltValueToStringHelper().call$1("ServiceExtensionResponse"), + t2 = J.getInterceptor$ax(t1); + t2.add$2(t1, "id", _this.id); + t2.add$2(t1, "resultJson", _this.resultJson); + t2.add$2(t1, "success", _this.success); + t2.add$2(t1, "errorCode", _this.errorCode); + t2.add$2(t1, "errorMessage", _this.errorMessage); + return t2.toString$0(t1); + } + }; + A.ServiceExtensionResponseBuilder.prototype = { + set$id(id) { + this.get$_service_extension_response$_$this()._service_extension_response$_id = id; + }, + set$success(success) { + this.get$_service_extension_response$_$this()._service_extension_response$_success = success; + }, + set$errorMessage(errorMessage) { + this.get$_service_extension_response$_$this()._service_extension_response$_errorMessage = errorMessage; + }, + get$_service_extension_response$_$this() { + var _this = this, + $$v = _this._service_extension_response$_$v; + if ($$v != null) { + _this._service_extension_response$_id = $$v.id; + _this._resultJson = $$v.resultJson; + _this._service_extension_response$_success = $$v.success; + _this._errorCode = $$v.errorCode; + _this._service_extension_response$_errorMessage = $$v.errorMessage; + _this._service_extension_response$_$v = null; + } + return _this; + }, + _service_extension_response$_build$0() { + var t1, t2, t3, t4, t5, _this = this, + _s24_ = "ServiceExtensionResponse", + _$result = _this._service_extension_response$_$v; + if (_$result == null) { + t1 = type$.String; + t2 = A.BuiltValueNullFieldError_checkNotNull(_this.get$_service_extension_response$_$this()._service_extension_response$_id, _s24_, "id", t1); + t3 = _this.get$_service_extension_response$_$this()._resultJson; + t4 = type$.bool; + t5 = A.BuiltValueNullFieldError_checkNotNull(_this.get$_service_extension_response$_$this()._service_extension_response$_success, _s24_, "success", t4); + _$result = new A._$ServiceExtensionResponse(t2, t3, t5, _this.get$_service_extension_response$_$this()._errorCode, _this.get$_service_extension_response$_$this()._service_extension_response$_errorMessage); + A.BuiltValueNullFieldError_checkNotNull(t2, _s24_, "id", t1); + A.BuiltValueNullFieldError_checkNotNull(t5, _s24_, "success", t4); + } + A.ArgumentError_checkNotNull(_$result, "other", type$.ServiceExtensionResponse); + return _this._service_extension_response$_$v = _$result; + } + }; + A.BatchedStreamController.prototype = { + _batchAndSendEvents$0() { + var $async$goto = 0, + $async$completer = A._makeAsyncAwaitCompleter(type$.void), + $async$self = this, t2, t3, t4, t5, t6, t7, t8, lastSendTime0, lastEvent, duration, t1, buffer, lastSendTime, $async$temp1, $async$temp2; + var $async$_batchAndSendEvents$0 = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return A._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + duration = A.Duration$(0, $async$self._checkDelayMilliseconds); + t1 = $async$self.$ti; + buffer = A._setArrayType([], t1._eval$1("JSArray<1>")); + lastSendTime = Date.now(); + t2 = $async$self._batchDelayMilliseconds, t3 = $async$self._outputController, t4 = A._instanceType(t3), t1 = t1._precomputed1, t5 = t4._precomputed1, t4 = t4._eval$1("_DelayedData<1>"); + case 2: + // for condition + $async$goto = 4; + return A._asyncAwait($async$self._hasEventOrTimeOut$1(duration), $async$_batchAndSendEvents$0); + case 4: + // returning from await. + if (!$async$result) { + // goto after for + $async$goto = 3; + break; + } + $async$goto = 7; + return A._asyncAwait($async$self._hasEventDuring$1(duration), $async$_batchAndSendEvents$0); + case 7: + // returning from await. + $async$goto = $async$result ? 5 : 6; + break; + case 5: + // then + t6 = $async$self.__BatchedStreamController__inputQueue_A; + t6 === $ && A.throwLateFieldNI("_inputQueue"); + t7 = t6.$ti; + t8 = new A._Future($.Zone__current, t7._eval$1("_Future<1>")); + t6._addRequest$1(new A._NextRequest(new A._AsyncCompleter(t8, t7._eval$1("_AsyncCompleter<1>")), t7._eval$1("_NextRequest<1>"))); + $async$temp1 = B.JSArray_methods; + $async$temp2 = buffer; + $async$goto = 8; + return A._asyncAwait(t8, $async$_batchAndSendEvents$0); + case 8: + // returning from await. + $async$temp1.add$1($async$temp2, $async$result); + case 6: + // join + lastSendTime0 = Date.now(); + if (lastSendTime0 > lastSendTime + t2) { + if (buffer.length !== 0) { + t6 = A.List_List$_of(buffer, t1); + t5._as(t6); + t7 = t3._state; + if (t7 >= 4) + A.throwExpression(t3._badEventState$0()); + if ((t7 & 1) !== 0) + t3._sendData$1(t6); + else if ((t7 & 3) === 0) { + t7 = t3._ensurePendingEvents$0(); + t6 = new A._DelayedData(t6, t4); + lastEvent = t7.lastPendingEvent; + if (lastEvent == null) + t7.firstPendingEvent = t7.lastPendingEvent = t6; + else { + lastEvent.set$next(t6); + t7.lastPendingEvent = t6; + } + } + B.JSArray_methods.clear$0(buffer); + } + lastSendTime = lastSendTime0; + } + // goto for condition + $async$goto = 2; + break; + case 3: + // after for + if (buffer.length !== 0) { + t1 = A.List_List$_of(buffer, t1); + t3.add$1(0, t5._as(t1)); + } + $async$self._completer.complete$1(true); + // implicit return + return A._asyncReturn(null, $async$completer); + } + }); return A._asyncStartSync($async$_batchAndSendEvents$0, $async$completer); }, _hasEventOrTimeOut$1(duration) { @@ -23625,13 +24051,13 @@ call$0() { return true; }, - $signature: 33 + $signature: 26 }; A.BatchedStreamController__hasEventDuring_closure.prototype = { call$0() { return false; }, - $signature: 33 + $signature: 26 }; A.SocketClient.prototype = {}; A.SseSocketClient.prototype = { @@ -23673,14 +24099,14 @@ call$1(o) { return J.toString$0$(o); }, - $signature: 43 + $signature: 44 }; A.safeUnawaited_closure.prototype = { call$2(error, stackTrace) { type$.StackTrace._as(stackTrace); return $.$get$_logger().log$4(B.Level_WARNING_900, "Error in unawaited Future:", error, stackTrace); }, - $signature: 21 + $signature: 25 }; A.Int32.prototype = { _toInt$1(val) { @@ -23852,13 +24278,13 @@ call$2(key1, key2) { return A._asString(key1).toLowerCase() === A._asString(key2).toLowerCase(); }, - $signature: 44 + $signature: 45 }; A.BaseRequest_closure0.prototype = { call$1(key) { return B.JSString_methods.get$hashCode(A._asString(key).toLowerCase()); }, - $signature: 45 + $signature: 46 }; A.BaseResponse.prototype = { BaseResponse$7$contentLength$headers$isRedirect$persistentConnection$reasonPhrase$request(statusCode, contentLength, headers, isRedirect, persistentConnection, reasonPhrase, request) { @@ -23996,7 +24422,7 @@ call$1(bytes) { return this.completer.complete$1(new Uint8Array(A._ensureNativeList(type$.List_int._as(bytes)))); }, - $signature: 47 + $signature: 48 }; A.ClientException.prototype = { toString$0(_) { @@ -24084,7 +24510,7 @@ scanner.expectDone$0(); return A.MediaType$(t4, t5, parameters); }, - $signature: 48 + $signature: 34 }; A.MediaType_toString_closure.prototype = { call$2(attribute, value) { @@ -24103,13 +24529,13 @@ } else t1._contents = t3 + value; }, - $signature: 49 + $signature: 50 }; A.MediaType_toString__closure.prototype = { call$1(match) { return "\\" + A.S(match.$index(0, 0)); }, - $signature: 31 + $signature: 28 }; A.expectQuotedString_closure.prototype = { call$1(match) { @@ -24117,7 +24543,7 @@ t1.toString; return t1; }, - $signature: 31 + $signature: 28 }; A.Level.prototype = { $eq(_, other) { @@ -24206,7 +24632,7 @@ $parent._children.$indexSet(0, thisName, t1); return t1; }, - $signature: 51 + $signature: 52 }; A.Context.prototype = { absolute$15(part1, part2, part3, part4, part5, part6, part7, part8, part9, part10, part11, part12, part13, part14, part15) { @@ -24440,20 +24866,20 @@ call$1(part) { return A._asString(part) !== ""; }, - $signature: 30 + $signature: 20 }; A.Context_split_closure.prototype = { call$1(part) { return A._asString(part).length !== 0; }, - $signature: 30 + $signature: 20 }; A._validateArgList_closure.prototype = { call$1(arg) { A._asStringQ(arg); return arg == null ? "null" : '"' + arg + '"'; }, - $signature: 106 + $signature: 54 }; A.InternalStyle.prototype = { getRoot$1(path) { @@ -25348,7 +25774,7 @@ call$0() { return this.color; }, - $signature: 54 + $signature: 55 }; A.Highlighter$__closure.prototype = { call$1(line) { @@ -25356,34 +25782,34 @@ t2 = A._arrayInstanceType(t1); return new A.WhereIterable(t1, t2._eval$1("bool(1)")._as(new A.Highlighter$___closure()), t2._eval$1("WhereIterable<1>")).get$length(0); }, - $signature: 55 + $signature: 56 }; A.Highlighter$___closure.prototype = { call$1(highlight) { var t1 = type$._Highlight._as(highlight).span; return t1.get$start().get$line() !== t1.get$end().get$line(); }, - $signature: 15 + $signature: 19 }; A.Highlighter$__closure0.prototype = { call$1(line) { return type$._Line._as(line).url; }, - $signature: 57 + $signature: 58 }; A.Highlighter__collateLines_closure.prototype = { call$1(highlight) { var t1 = type$._Highlight._as(highlight).span.get$sourceUrl(); return t1 == null ? new A.Object() : t1; }, - $signature: 58 + $signature: 59 }; A.Highlighter__collateLines_closure0.prototype = { call$2(highlight1, highlight2) { var t1 = type$._Highlight; return t1._as(highlight1).span.compareTo$1(0, t1._as(highlight2).span); }, - $signature: 59 + $signature: 60 }; A.Highlighter__collateLines_closure1.prototype = { call$1(entry) { @@ -25426,20 +25852,20 @@ } return lines; }, - $signature: 60 + $signature: 61 }; A.Highlighter__collateLines__closure.prototype = { call$1(highlight) { return type$._Highlight._as(highlight).span.get$end().get$line() < this.line.number; }, - $signature: 15 + $signature: 19 }; A.Highlighter_highlight_closure.prototype = { call$1(highlight) { type$._Highlight._as(highlight); return true; }, - $signature: 15 + $signature: 19 }; A.Highlighter__writeFileStart_closure.prototype = { call$0() { @@ -25540,7 +25966,7 @@ t4 = B.JSString_methods.$mul("^", Math.max(endColumn + (tabsBefore + tabsInside) * 3 - startColumn, 1)); return (t2._contents += t4).length - t3.length; }, - $signature: 22 + $signature: 30 }; A.Highlighter__writeIndicator_closure0.prototype = { call$0() { @@ -25561,7 +25987,7 @@ t1._writeArrow$3$beginning(_this.line, Math.max(_this.highlight.span.get$end().get$column() - 1, 0), false); return t2._contents.length - t3.length; }, - $signature: 22 + $signature: 30 }; A.Highlighter__writeSidebar_closure.prototype = { call$0() { @@ -25597,7 +26023,7 @@ } return A._Highlight__normalizeEndOfLine(A._Highlight__normalizeTrailingNewline(A._Highlight__normalizeNewlines(newSpan))); }, - $signature: 62 + $signature: 63 }; A._Line.prototype = { toString$0(_) { @@ -25966,25 +26392,25 @@ }); return A._asyncStartSync($async$call$0, $async$completer); }, - $signature: 65 + $signature: 66 }; A.generateUuidV4_generateBits.prototype = { call$1(bitCount) { return this.random.nextInt$1(B.JSInt_methods._shlPositive$1(1, bitCount)); }, - $signature: 27 + $signature: 22 }; A.generateUuidV4_printDigits.prototype = { call$2(value, count) { return B.JSString_methods.padLeft$2(B.JSInt_methods.toRadixString$1(value, 16), count, "0"); }, - $signature: 20 + $signature: 32 }; A.generateUuidV4_bitsDigits.prototype = { call$2(bitCount, digitCount) { return this.printDigits.call$2(this.generateBits.call$1(bitCount), digitCount); }, - $signature: 20 + $signature: 32 }; A.GuaranteeChannel.prototype = { GuaranteeChannel$3$allowSinkErrors(innerSink, allowSinkErrors, _box_0, $T) { @@ -26538,7 +26964,7 @@ A._asString(webSocket._webSocket.protocol); t2._readyCompleter.complete$0(); }, - $signature: 67 + $signature: 68 }; A.AdapterWebSocketChannel__closure.prototype = { call$1($event) { @@ -26574,7 +27000,7 @@ } } }, - $signature: 68 + $signature: 69 }; A.AdapterWebSocketChannel__closure0.prototype = { call$1(obj) { @@ -26671,7 +27097,7 @@ }); return A._asyncStartSync($async$call$0, $async$completer); }, - $signature: 19 + $signature: 16 }; A.AdapterWebSocketChannel_closure0.prototype = { call$1(e) { @@ -26689,7 +27115,7 @@ t1 === $ && A.throwLateFieldNI("_sink"); t1.close$0(); }, - $signature: 69 + $signature: 70 }; A._WebSocketSink.prototype = {$isWebSocketSink: 1}; A.WebSocketChannelException.prototype = { @@ -26784,11 +27210,8 @@ A._sendConnectRequest(client.get$sink()); else A.runMain(); - else { + else A._sendConnectRequest(client.get$sink()); - if (A._asBool(t1.$useDwdsWebSocketConnection)) - A.runMain(); - } A._launchCommunicationWithDebugExtension(); // implicit return return A._asyncReturn(null, $async$completer); @@ -26796,7 +27219,7 @@ }); return A._asyncStartSync($async$call$0, $async$completer); }, - $signature: 19 + $signature: 16 }; A.main__closure.prototype = { call$0() { @@ -26826,7 +27249,7 @@ call$1(runId) { return this.call$2(runId, null); }, - $signature: 71 + $signature: 72 }; A.main__closure2.prototype = { call$0() { @@ -26853,7 +27276,7 @@ A._trySendEvent(t1, B.C_JsonCodec.encode$2$toEncodable(t2.serialize$1(t3._debug_event$_build$0()), null), type$.dynamic); } }, - $signature: 72 + $signature: 73 }; A.main___closure2.prototype = { call$1(b) { @@ -26862,7 +27285,7 @@ b.get$_debug_event$_$this().set$_events(t1); return t1; }, - $signature: 73 + $signature: 74 }; A.main__closure4.prototype = { call$2(kind, eventData) { @@ -26876,7 +27299,7 @@ A._trySendEvent(new A._StreamSinkWrapper(t1, A._instanceType(t1)._eval$1("_StreamSinkWrapper<1>")), t2._debug_event$_build$0(), type$.DebugEvent); } }, - $signature: 74 + $signature: 75 }; A.main___closure1.prototype = { call$1(b) { @@ -26886,7 +27309,7 @@ b.get$_debug_event$_$this()._eventData = this.eventData; return b; }, - $signature: 75 + $signature: 76 }; A.main__closure5.prototype = { call$1(eventData) { @@ -26898,7 +27321,7 @@ type$.nullable_void_Function_RegisterEventBuilder._as(new A.main___closure0(eventData)).call$1(t3); A._trySendEvent(t1, B.C_JsonCodec.encode$2$toEncodable(t2.serialize$1(t3._register_event$_build$0()), null), type$.dynamic); }, - $signature: 76 + $signature: 106 }; A.main___closure0.prototype = { call$1(b) { @@ -26907,7 +27330,7 @@ b.get$_register_event$_$this()._register_event$_eventData = this.eventData; return b; }, - $signature: 77 + $signature: 78 }; A.main__closure6.prototype = { call$0() { @@ -26933,7 +27356,7 @@ b.get$_devtools_request$_$this()._devtools_request$_instanceId = t1; return b; }, - $signature: 78 + $signature: 79 }; A.main__closure7.prototype = { call$1(serialized) { @@ -27043,14 +27466,29 @@ break; case 24: // else - $async$goto = $event instanceof A._$HotReloadRequest ? 25 : 26; + $async$goto = $event instanceof A._$HotReloadRequest ? 25 : 27; break; case 25: // then - $async$goto = 27; + $async$goto = 28; return A._asyncAwait(A.handleWebSocketHotReloadRequest($event, $async$self.manager, $async$self.client.get$sink()), $async$call$1); + case 28: + // returning from await. + // goto join + $async$goto = 26; + break; case 27: + // else + $async$goto = $event instanceof A._$ServiceExtensionRequest ? 29 : 30; + break; + case 29: + // then + $async$goto = 31; + return A._asyncAwait(A.handleServiceExtensionRequest($event, $async$self.client.get$sink(), $async$self.manager), $async$call$1); + case 31: // returning from await. + case 30: + // join case 26: // join case 23: @@ -27067,7 +27505,7 @@ }); return A._asyncStartSync($async$call$1, $async$completer); }, - $signature: 79 + $signature: 80 }; A.main__closure8.prototype = { call$1(error) { @@ -27091,7 +27529,7 @@ type$.StackTrace._as(stackTrace); A.print("Unhandled error detected in the injected client.js script.\n\nYou can disable this script in webdev by passing --no-injected-client if it\nis preventing your app from loading, but note that this will also prevent\nall debugging and hot reload/restart functionality from working.\n\nThe original error is below, please file an issue at\nhttps://github.com/dart-lang/webdev/issues/new and attach this output:\n\n" + A.S(error) + "\n" + stackTrace.toString$0(0) + "\n"); }, - $signature: 14 + $signature: 13 }; A._sendConnectRequest_closure.prototype = { call$1(b) { @@ -27104,7 +27542,7 @@ b.get$_connect_request$_$this()._entrypointPath = t1; return b; }, - $signature: 80 + $signature: 81 }; A._launchCommunicationWithDebugExtension_closure.prototype = { call$1(b) { @@ -27134,13 +27572,13 @@ b.get$_$this()._workspaceName = t1; return b; }, - $signature: 81 + $signature: 82 }; A._handleAuthRequest_closure.prototype = { call$1(isAuthenticated) { return A._dispatchEvent("dart-auth-response", "" + A._asBool(isAuthenticated)); }, - $signature: 82 + $signature: 83 }; A._sendResponse_closure.prototype = { call$1(b) { @@ -27297,6 +27735,78 @@ }); return A._asyncStartSync($async$fetchLibrariesForHotReload$1, $async$completer); }, + handleServiceExtension$2(method, args) { + return this.handleServiceExtension$body$DdcLibraryBundleRestarter(method, type$.Map_String_dynamic._as(args)); + }, + handleServiceExtension$body$DdcLibraryBundleRestarter(method, args) { + var $async$goto = 0, + $async$completer = A._makeAsyncAwaitCompleter(type$.nullable_Map_String_dynamic), + $async$returnValue, t1, t2, params, $async$temp1, $async$temp2; + var $async$handleServiceExtension$2 = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return A._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + $async$goto = method === "ext.flutter.reassemble" ? 3 : 5; + break; + case 3: + // then + t1 = type$.JSObject; + $async$goto = 6; + return A._asyncAwait(A._Debugger_maybeInvokeFlutterReassemble(t1._as(t1._as(init.G.dartDevEmbedder).debugger)), $async$handleServiceExtension$2); + case 6: + // returning from await. + $async$returnValue = A.LinkedHashMap_LinkedHashMap$_literal(["status", "reassemble invoked"], type$.String, type$.dynamic); + // goto return + $async$goto = 1; + break; + // goto join + $async$goto = 4; + break; + case 5: + // else + $async$goto = method === "getExtensionRpcs" ? 7 : 9; + break; + case 7: + // then + t1 = type$.JSObject; + t1 = type$.JSArray_nullable_Object._as(t1._as(t1._as(init.G.dartDevEmbedder).debugger).extensionNames); + t1 = type$.List_String._is(t1) ? t1 : new A.CastList(t1, A._arrayInstanceType(t1)._eval$1("CastList<1,String>")); + t2 = type$.String; + $async$returnValue = A.LinkedHashMap_LinkedHashMap$_literal(["rpcs", J.cast$1$0$ax(t1, t2)], t2, type$.dynamic); + // goto return + $async$goto = 1; + break; + // goto join + $async$goto = 8; + break; + case 9: + // else + params = args.get$isNotEmpty(args) ? B.C_JsonCodec.encode$2$toEncodable(args, null) : "{}"; + t1 = type$.JSObject; + $async$temp1 = type$.Map_String_dynamic; + $async$temp2 = B.C_JsonCodec; + $async$goto = 10; + return A._asyncAwait(A.promiseToFuture(t1._as(t1._as(t1._as(init.G.dartDevEmbedder).debugger).invokeExtension(method, params)), type$.String), $async$handleServiceExtension$2); + case 10: + // returning from await. + $async$returnValue = $async$temp1._as($async$temp2.decode$2$reviver($async$result, null)); + // goto return + $async$goto = 1; + break; + case 8: + // join + case 4: + // join + case 1: + // return + return A._asyncReturn($async$returnValue, $async$completer); + } + }); + return A._asyncStartSync($async$handleServiceExtension$2, $async$completer); + }, $isRestarter: 1 }; A.DdcLibraryBundleRestarter_restart_closure.prototype = { @@ -27307,7 +27817,7 @@ t1._as(t1._as(init.G.dartDevEmbedder).config).capturedMainHandler = null; A.safeUnawaited(this.$this._runMainWhenReady$2(this.readyToRunMain, runMain)); }, - $signature: 83 + $signature: 84 }; A.DdcLibraryBundleRestarter_fetchLibrariesForHotReload_closure.prototype = { call$0() { @@ -27369,7 +27879,7 @@ this.sub.cancel$0(); return value; }, - $signature: 84 + $signature: 85 }; A.ReloadingManager.prototype = { hotRestart$2$readyToRunMain$runId(readyToRunMain, runId) { @@ -27430,6 +27940,38 @@ }); return A._asyncStartSync($async$hotReload$0, $async$completer); }, + handleServiceExtension$2(method, args) { + return this.handleServiceExtension$body$ReloadingManager(method, type$.Map_String_dynamic._as(args)); + }, + handleServiceExtension$body$ReloadingManager(method, args) { + var $async$goto = 0, + $async$completer = A._makeAsyncAwaitCompleter(type$.nullable_Map_String_dynamic), + $async$returnValue, $async$self = this, restarter; + var $async$handleServiceExtension$2 = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { + if ($async$errorCode === 1) + return A._asyncRethrow($async$result, $async$completer); + while (true) + switch ($async$goto) { + case 0: + // Function start + restarter = $async$self._restarter; + if (restarter instanceof A.DdcLibraryBundleRestarter) { + $async$returnValue = restarter.handleServiceExtension$2(method, args); + // goto return + $async$goto = 1; + break; + } + $async$returnValue = null; + // goto return + $async$goto = 1; + break; + case 1: + // return + return A._asyncReturn($async$returnValue, $async$completer); + } + }); + return A._asyncStartSync($async$handleServiceExtension$2, $async$completer); + }, _afterRestart$1(succeeded) { var t1, t2; if (!succeeded) @@ -27836,7 +28378,7 @@ call$1(e) { this.completer.completeError$2(new A.HotReloadFailedException(A._asString(type$.JavaScriptObject._as(e).message)), this.stackTrace); }, - $signature: 87 + $signature: 88 }; A._createScript_closure.prototype = { call$0() { @@ -27845,7 +28387,7 @@ return new A._createScript__closure(); return new A._createScript__closure0(nonce); }, - $signature: 88 + $signature: 89 }; A._createScript__closure.prototype = { call$0() { @@ -27910,51 +28452,51 @@ _instance_1_i = hunkHelpers._instance_1i, _instance_0_u = hunkHelpers._instance_0u, _instance_1_u = hunkHelpers._instance_1u; - _static_2(J, "_interceptors_JSArray__compareAny$closure", "JSArray__compareAny", 28); - _static_1(A, "async__AsyncRun__scheduleImmediateJsOverride$closure", "_AsyncRun__scheduleImmediateJsOverride", 16); - _static_1(A, "async__AsyncRun__scheduleImmediateWithSetImmediate$closure", "_AsyncRun__scheduleImmediateWithSetImmediate", 16); - _static_1(A, "async__AsyncRun__scheduleImmediateWithTimer$closure", "_AsyncRun__scheduleImmediateWithTimer", 16); + _static_2(J, "_interceptors_JSArray__compareAny$closure", "JSArray__compareAny", 33); + _static_1(A, "async__AsyncRun__scheduleImmediateJsOverride$closure", "_AsyncRun__scheduleImmediateJsOverride", 12); + _static_1(A, "async__AsyncRun__scheduleImmediateWithSetImmediate$closure", "_AsyncRun__scheduleImmediateWithSetImmediate", 12); + _static_1(A, "async__AsyncRun__scheduleImmediateWithTimer$closure", "_AsyncRun__scheduleImmediateWithTimer", 12); _static_0(A, "async___startMicrotaskLoop$closure", "_startMicrotaskLoop", 0); _static_1(A, "async___nullDataHandler$closure", "_nullDataHandler", 7); - _static_2(A, "async___nullErrorHandler$closure", "_nullErrorHandler", 14); + _static_2(A, "async___nullErrorHandler$closure", "_nullErrorHandler", 13); _static_0(A, "async___nullDoneHandler$closure", "_nullDoneHandler", 0); - _static(A, "async___rootHandleUncaughtError$closure", 5, null, ["call$5"], ["_rootHandleUncaughtError"], 91, 0); + _static(A, "async___rootHandleUncaughtError$closure", 5, null, ["call$5"], ["_rootHandleUncaughtError"], 92, 0); _static(A, "async___rootRun$closure", 4, null, ["call$1$4", "call$4"], ["_rootRun", function($self, $parent, zone, f) { f.toString; return A._rootRun($self, $parent, zone, f, type$.dynamic); - }], 92, 0); + }], 93, 0); _static(A, "async___rootRunUnary$closure", 5, null, ["call$2$5", "call$5"], ["_rootRunUnary", function($self, $parent, zone, f, arg) { var t1 = type$.dynamic; f.toString; return A._rootRunUnary($self, $parent, zone, f, arg, t1, t1); - }], 93, 0); - _static(A, "async___rootRunBinary$closure", 6, null, ["call$3$6"], ["_rootRunBinary"], 94, 0); + }], 94, 0); + _static(A, "async___rootRunBinary$closure", 6, null, ["call$3$6"], ["_rootRunBinary"], 95, 0); _static(A, "async___rootRegisterCallback$closure", 4, null, ["call$1$4", "call$4"], ["_rootRegisterCallback", function($self, $parent, zone, f) { f.toString; return A._rootRegisterCallback($self, $parent, zone, f, type$.dynamic); - }], 95, 0); + }], 96, 0); _static(A, "async___rootRegisterUnaryCallback$closure", 4, null, ["call$2$4", "call$4"], ["_rootRegisterUnaryCallback", function($self, $parent, zone, f) { var t1 = type$.dynamic; f.toString; return A._rootRegisterUnaryCallback($self, $parent, zone, f, t1, t1); - }], 96, 0); + }], 97, 0); _static(A, "async___rootRegisterBinaryCallback$closure", 4, null, ["call$3$4", "call$4"], ["_rootRegisterBinaryCallback", function($self, $parent, zone, f) { var t1 = type$.dynamic; f.toString; return A._rootRegisterBinaryCallback($self, $parent, zone, f, t1, t1, t1); - }], 97, 0); - _static(A, "async___rootErrorCallback$closure", 5, null, ["call$5"], ["_rootErrorCallback"], 98, 0); - _static(A, "async___rootScheduleMicrotask$closure", 4, null, ["call$4"], ["_rootScheduleMicrotask"], 99, 0); - _static(A, "async___rootCreateTimer$closure", 5, null, ["call$5"], ["_rootCreateTimer"], 100, 0); - _static(A, "async___rootCreatePeriodicTimer$closure", 5, null, ["call$5"], ["_rootCreatePeriodicTimer"], 101, 0); - _static(A, "async___rootPrint$closure", 4, null, ["call$4"], ["_rootPrint"], 102, 0); - _static_1(A, "async___printToZone$closure", "_printToZone", 103); - _static(A, "async___rootFork$closure", 5, null, ["call$5"], ["_rootFork"], 104, 0); - _instance(A._Completer.prototype, "get$completeError", 0, 1, null, ["call$2", "call$1"], ["completeError$2", "completeError$1"], 32, 0, 0); - _instance_2_u(A._Future.prototype, "get$_completeError", "_completeError$2", 14); + }], 98, 0); + _static(A, "async___rootErrorCallback$closure", 5, null, ["call$5"], ["_rootErrorCallback"], 99, 0); + _static(A, "async___rootScheduleMicrotask$closure", 4, null, ["call$4"], ["_rootScheduleMicrotask"], 100, 0); + _static(A, "async___rootCreateTimer$closure", 5, null, ["call$5"], ["_rootCreateTimer"], 101, 0); + _static(A, "async___rootCreatePeriodicTimer$closure", 5, null, ["call$5"], ["_rootCreatePeriodicTimer"], 102, 0); + _static(A, "async___rootPrint$closure", 4, null, ["call$4"], ["_rootPrint"], 103, 0); + _static_1(A, "async___printToZone$closure", "_printToZone", 104); + _static(A, "async___rootFork$closure", 5, null, ["call$5"], ["_rootFork"], 105, 0); + _instance(A._Completer.prototype, "get$completeError", 0, 1, null, ["call$2", "call$1"], ["completeError$2", "completeError$1"], 23, 0, 0); + _instance_2_u(A._Future.prototype, "get$_completeError", "_completeError$2", 13); var _; _instance_1_i(_ = A._StreamController.prototype, "get$add", "add$1", 9); - _instance(_, "get$addError", 0, 1, null, ["call$2", "call$1"], ["addError$2", "addError$1"], 32, 0, 0); + _instance(_, "get$addError", 0, 1, null, ["call$2", "call$1"], ["addError$2", "addError$1"], 23, 0, 0); _instance_0_u(_ = A._ControllerSubscription.prototype, "get$_onPause", "_onPause$0", 0); _instance_0_u(_, "get$_onResume", "_onResume$0", 0); _instance_0_u(_ = A._BufferingStreamSubscription.prototype, "get$_onPause", "_onPause$0", 0); @@ -27963,43 +28505,43 @@ _instance_0_u(_ = A._ForwardingStreamSubscription.prototype, "get$_onPause", "_onPause$0", 0); _instance_0_u(_, "get$_onResume", "_onResume$0", 0); _instance_1_u(_, "get$_handleData", "_handleData$1", 9); - _instance_2_u(_, "get$_handleError", "_handleError$2", 21); + _instance_2_u(_, "get$_handleError", "_handleError$2", 25); _instance_0_u(_, "get$_handleDone", "_handleDone$0", 0); - _static_2(A, "collection___defaultEquals$closure", "_defaultEquals0", 18); - _static_1(A, "collection___defaultHashCode$closure", "_defaultHashCode", 17); - _static_2(A, "collection_ListBase__compareAny$closure", "ListBase__compareAny", 28); + _static_2(A, "collection___defaultEquals$closure", "_defaultEquals0", 17); + _static_1(A, "collection___defaultHashCode$closure", "_defaultHashCode", 18); + _static_2(A, "collection_ListBase__compareAny$closure", "ListBase__compareAny", 33); _static_1(A, "convert___defaultToEncodable$closure", "_defaultToEncodable", 4); _instance_1_i(_ = A._ByteCallbackSink.prototype, "get$add", "add$1", 9); _instance_0_u(_, "get$close", "close$0", 0); - _static_1(A, "core__identityHashCode$closure", "identityHashCode", 17); - _static_2(A, "core__identical$closure", "identical", 18); - _static_1(A, "core_Uri_decodeComponent$closure", "Uri_decodeComponent", 13); + _static_1(A, "core__identityHashCode$closure", "identityHashCode", 18); + _static_2(A, "core__identical$closure", "identical", 17); + _static_1(A, "core_Uri_decodeComponent$closure", "Uri_decodeComponent", 15); _static(A, "math__max$closure", 2, null, ["call$1$2", "call$2"], ["max", function(a, b) { a.toString; b.toString; return A.max(a, b, type$.num); - }], 105, 0); - _instance_2_u(_ = A.DeepCollectionEquality.prototype, "get$equals", "equals$2", 18); - _instance_1_u(_, "get$hash", "hash$1", 17); - _instance_1_u(_, "get$isValidKey", "isValidKey$1", 12); + }], 77, 0); + _instance_2_u(_ = A.DeepCollectionEquality.prototype, "get$equals", "equals$2", 17); + _instance_1_u(_, "get$hash", "hash$1", 18); + _instance_1_u(_, "get$isValidKey", "isValidKey$1", 14); _static(A, "hot_reload_response_HotReloadResponse___new_tearOff$closure", 0, null, ["call$1", "call$0"], ["HotReloadResponse___new_tearOff", function() { return A.HotReloadResponse___new_tearOff(null); - }], 70, 0); - _static_1(A, "case_insensitive_map_CaseInsensitiveMap__canonicalizer$closure", "CaseInsensitiveMap__canonicalizer", 13); + }], 71, 0); + _static_1(A, "case_insensitive_map_CaseInsensitiveMap__canonicalizer$closure", "CaseInsensitiveMap__canonicalizer", 15); _instance_1_u(_ = A.SseClient.prototype, "get$_onIncomingControlMessage", "_onIncomingControlMessage$1", 2); _instance_1_u(_, "get$_onIncomingMessage", "_onIncomingMessage$1", 2); _instance_0_u(_, "get$_onOutgoingDone", "_onOutgoingDone$0", 0); - _instance_1_u(_, "get$_onOutgoingMessage", "_onOutgoingMessage$1", 64); + _instance_1_u(_, "get$_onOutgoingMessage", "_onOutgoingMessage$1", 65); _static_1(A, "client___handleAuthRequest$closure", "_handleAuthRequest", 2); - _instance_1_u(_ = A.RequireRestarter.prototype, "get$_moduleParents", "_moduleParents$1", 85); - _instance_2_u(_, "get$_moduleTopologicalCompare", "_moduleTopologicalCompare$2", 86); + _instance_1_u(_ = A.RequireRestarter.prototype, "get$_moduleParents", "_moduleParents$1", 86); + _instance_2_u(_, "get$_moduleTopologicalCompare", "_moduleTopologicalCompare$2", 87); })(); (function inheritance() { var _mixin = hunkHelpers.mixin, _inherit = hunkHelpers.inherit, _inheritMany = hunkHelpers.inheritMany; _inherit(A.Object, null); - _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, J.ArrayIterator, A.Iterable, A.CastIterator, A.Closure, A.MapBase, A.Error, A.ListBase, A.SentinelValue, A.ListIterator, A.MappedIterator, A.WhereIterator, A.ExpandIterator, A.TakeIterator, A.SkipIterator, A.EmptyIterator, A.WhereTypeIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A._Record, A.ConstantMap, A._KeysOrValuesOrElementsIterator, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A.ExceptionAndStackTrace, A._StackTrace, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.LinkedHashMapValueIterator, A.LinkedHashMapEntryIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A._UnmodifiableNativeByteBufferView, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A._AsyncAwaitCompleter, A.AsyncError, A.TimeoutException, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A.Stream, A._StreamController, A._SyncStreamControllerDispatch, A._AsyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._DoneStreamSubscription, A._StreamIterator, A._ZoneFunction, A._ZoneSpecification, A._ZoneDelegate, A._Zone, A._HashMapKeyIterator, A.SetBase, A._HashSetIterator, A._LinkedHashSetCell, A._LinkedHashSetIterator, A._UnmodifiableMapMixin, A.MapView, A._ListQueueIterator, A._SplayTreeNode, A._SplayTree, A._SplayTreeIterator, A.Codec, A.Converter, A._Base64Encoder, A._Base64Decoder, A.ByteConversionSink, A._JsonStringifier, A._Utf8Encoder, A._Utf8Decoder, A._BigIntImpl, A.DateTime, A.Duration, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.IntegerDivisionByZeroException, A.MapEntry, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.NullRejectionException, A._JSRandom, A._JSSecureRandom, A.AsyncMemoizer, A.DelegatingStreamSink, A.ErrorResult, A.ValueResult, A.StreamQueue, A._NextRequest, A._HasNextRequest, A.BuiltList, A.ListBuilder, A.BuiltListMultimap, A.ListMultimapBuilder, A.BuiltMap, A.MapBuilder, A.BuiltSet, A.SetBuilder, A.BuiltSetMultimap, A.SetMultimapBuilder, A.EnumClass, A.IndentingBuiltValueToStringHelper, A.JsonObject, A.FullType, A.BigIntSerializer, A.BoolSerializer, A.BuiltJsonSerializers, A.BuiltJsonSerializersBuilder, A.BuiltListMultimapSerializer, A.BuiltListSerializer, A.BuiltMapSerializer, A.BuiltSetMultimapSerializer, A.BuiltSetSerializer, A.DateTimeSerializer, A.DoubleSerializer, A.DurationSerializer, A.Int32Serializer, A.Int64Serializer, A.IntSerializer, A.JsonObjectSerializer, A.NullSerializer, A.NumSerializer, A.RegExpSerializer, A.StringSerializer, A.Uint8ListSerializer, A.UriSerializer, A.CanonicalizedMap, A.DefaultEquality, A.IterableEquality, A.ListEquality, A._UnorderedEquality, A._MapEntry, A.MapEquality, A.DeepCollectionEquality, A._QueueList_Object_ListMixin, A.BuildResult, A._$BuildStatusSerializer, A._$BuildResultSerializer, A.BuildResultBuilder, A.ConnectRequest, A._$ConnectRequestSerializer, A.ConnectRequestBuilder, A.DebugEvent, A.BatchedDebugEvents, A._$DebugEventSerializer, A._$BatchedDebugEventsSerializer, A.DebugEventBuilder, A.BatchedDebugEventsBuilder, A.DebugInfo, A._$DebugInfoSerializer, A.DebugInfoBuilder, A.DevToolsRequest, A.DevToolsResponse, A._$DevToolsRequestSerializer, A._$DevToolsResponseSerializer, A.DevToolsRequestBuilder, A.DevToolsResponseBuilder, A.ErrorResponse, A._$ErrorResponseSerializer, A.ErrorResponseBuilder, A.ExtensionRequest, A.ExtensionResponse, A.ExtensionEvent, A.BatchedEvents, A._$ExtensionRequestSerializer, A._$ExtensionResponseSerializer, A._$ExtensionEventSerializer, A._$BatchedEventsSerializer, A.ExtensionRequestBuilder, A.ExtensionResponseBuilder, A.ExtensionEventBuilder, A.BatchedEventsBuilder, A.HotReloadRequest, A._$HotReloadRequestSerializer, A.HotReloadRequestBuilder, A.HotReloadResponse, A._$HotReloadResponseSerializer, A.HotReloadResponseBuilder, A.IsolateExit, A.IsolateStart, A._$IsolateExitSerializer, A._$IsolateStartSerializer, A.IsolateExitBuilder, A.IsolateStartBuilder, A.RegisterEvent, A._$RegisterEventSerializer, A.RegisterEventBuilder, A.RunRequest, A._$RunRequestSerializer, A.BatchedStreamController, A.SocketClient, A.Int32, A.Int64, A._StackState, A.BaseClient, A.BaseRequest, A.BaseResponse, A.ClientException, A.MediaType, A.Level, A.LogRecord, A.Logger, A.Context, A.Style, A.ParsedPath, A.PathException, A.Pool, A.PoolResource, A.SourceFile, A.SourceLocationMixin, A.SourceSpanMixin, A.Highlighter, A._Highlight, A._Line, A.SourceLocation, A.SourceSpanException, A.StreamChannelMixin, A._GuaranteeSink, A.StreamChannelController, A.StringScanner, A.RNG, A.UuidV1, A.EventStreamProvider, A._EventStreamSubscription, A.BrowserWebSocket, A.WebSocketEvent, A.WebSocketException, A.WebSocketChannelException, A.DdcLibraryBundleRestarter, A.DdcRestarter, A.ReloadingManager, A.HotReloadFailedException, A.RequireRestarter]); + _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, J.ArrayIterator, A.Iterable, A.CastIterator, A.Closure, A.MapBase, A.Error, A.ListBase, A.SentinelValue, A.ListIterator, A.MappedIterator, A.WhereIterator, A.ExpandIterator, A.TakeIterator, A.SkipIterator, A.EmptyIterator, A.WhereTypeIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A._Record, A.ConstantMap, A._KeysOrValuesOrElementsIterator, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A.ExceptionAndStackTrace, A._StackTrace, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.LinkedHashMapValueIterator, A.LinkedHashMapEntryIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A._UnmodifiableNativeByteBufferView, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A._AsyncAwaitCompleter, A.AsyncError, A.TimeoutException, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A.Stream, A._StreamController, A._SyncStreamControllerDispatch, A._AsyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._DoneStreamSubscription, A._StreamIterator, A._ZoneFunction, A._ZoneSpecification, A._ZoneDelegate, A._Zone, A._HashMapKeyIterator, A.SetBase, A._HashSetIterator, A._LinkedHashSetCell, A._LinkedHashSetIterator, A._UnmodifiableMapMixin, A.MapView, A._ListQueueIterator, A._SplayTreeNode, A._SplayTree, A._SplayTreeIterator, A.Codec, A.Converter, A._Base64Encoder, A._Base64Decoder, A.ByteConversionSink, A._JsonStringifier, A._Utf8Encoder, A._Utf8Decoder, A._BigIntImpl, A.DateTime, A.Duration, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.IntegerDivisionByZeroException, A.MapEntry, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.NullRejectionException, A._JSRandom, A._JSSecureRandom, A.AsyncMemoizer, A.DelegatingStreamSink, A.ErrorResult, A.ValueResult, A.StreamQueue, A._NextRequest, A._HasNextRequest, A.BuiltList, A.ListBuilder, A.BuiltListMultimap, A.ListMultimapBuilder, A.BuiltMap, A.MapBuilder, A.BuiltSet, A.SetBuilder, A.BuiltSetMultimap, A.SetMultimapBuilder, A.EnumClass, A.IndentingBuiltValueToStringHelper, A.JsonObject, A.FullType, A.BigIntSerializer, A.BoolSerializer, A.BuiltJsonSerializers, A.BuiltJsonSerializersBuilder, A.BuiltListMultimapSerializer, A.BuiltListSerializer, A.BuiltMapSerializer, A.BuiltSetMultimapSerializer, A.BuiltSetSerializer, A.DateTimeSerializer, A.DoubleSerializer, A.DurationSerializer, A.Int32Serializer, A.Int64Serializer, A.IntSerializer, A.JsonObjectSerializer, A.NullSerializer, A.NumSerializer, A.RegExpSerializer, A.StringSerializer, A.Uint8ListSerializer, A.UriSerializer, A.CanonicalizedMap, A.DefaultEquality, A.IterableEquality, A.ListEquality, A._UnorderedEquality, A._MapEntry, A.MapEquality, A.DeepCollectionEquality, A._QueueList_Object_ListMixin, A.BuildResult, A._$BuildStatusSerializer, A._$BuildResultSerializer, A.BuildResultBuilder, A.ConnectRequest, A._$ConnectRequestSerializer, A.ConnectRequestBuilder, A.DebugEvent, A.BatchedDebugEvents, A._$DebugEventSerializer, A._$BatchedDebugEventsSerializer, A.DebugEventBuilder, A.BatchedDebugEventsBuilder, A.DebugInfo, A._$DebugInfoSerializer, A.DebugInfoBuilder, A.DevToolsRequest, A.DevToolsResponse, A._$DevToolsRequestSerializer, A._$DevToolsResponseSerializer, A.DevToolsRequestBuilder, A.DevToolsResponseBuilder, A.ErrorResponse, A._$ErrorResponseSerializer, A.ErrorResponseBuilder, A.ExtensionRequest, A.ExtensionResponse, A.ExtensionEvent, A.BatchedEvents, A._$ExtensionRequestSerializer, A._$ExtensionResponseSerializer, A._$ExtensionEventSerializer, A._$BatchedEventsSerializer, A.ExtensionRequestBuilder, A.ExtensionResponseBuilder, A.ExtensionEventBuilder, A.BatchedEventsBuilder, A.HotReloadRequest, A._$HotReloadRequestSerializer, A.HotReloadRequestBuilder, A.HotReloadResponse, A._$HotReloadResponseSerializer, A.HotReloadResponseBuilder, A.IsolateExit, A.IsolateStart, A._$IsolateExitSerializer, A._$IsolateStartSerializer, A.IsolateExitBuilder, A.IsolateStartBuilder, A.RegisterEvent, A._$RegisterEventSerializer, A.RegisterEventBuilder, A.RunRequest, A._$RunRequestSerializer, A.ServiceExtensionRequest, A._$ServiceExtensionRequestSerializer, A.ServiceExtensionRequestBuilder, A.ServiceExtensionResponse, A._$ServiceExtensionResponseSerializer, A.ServiceExtensionResponseBuilder, A.BatchedStreamController, A.SocketClient, A.Int32, A.Int64, A._StackState, A.BaseClient, A.BaseRequest, A.BaseResponse, A.ClientException, A.MediaType, A.Level, A.LogRecord, A.Logger, A.Context, A.Style, A.ParsedPath, A.PathException, A.Pool, A.PoolResource, A.SourceFile, A.SourceLocationMixin, A.SourceSpanMixin, A.Highlighter, A._Highlight, A._Line, A.SourceLocation, A.SourceSpanException, A.StreamChannelMixin, A._GuaranteeSink, A.StreamChannelController, A.StringScanner, A.RNG, A.UuidV1, A.EventStreamProvider, A._EventStreamSubscription, A.BrowserWebSocket, A.WebSocketEvent, A.WebSocketException, A.WebSocketChannelException, A.DdcLibraryBundleRestarter, A.DdcRestarter, A.ReloadingManager, A.HotReloadFailedException, A.RequireRestarter]); _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JavaScriptBigInt, J.JavaScriptSymbol, J.JSNumber, J.JSString]); _inheritMany(J.JavaScriptObject, [J.LegacyJavaScriptObject, J.JSArray, A.NativeByteBuffer, A.NativeTypedData]); _inheritMany(J.LegacyJavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction]); @@ -28009,7 +28551,7 @@ _inheritMany(A._CastIterableBase, [A.CastIterable, A.__CastListBase__CastIterableBase_ListMixin]); _inherit(A._EfficientLengthCastIterable, A.CastIterable); _inherit(A._CastListBase, A.__CastListBase__CastIterableBase_ListMixin); - _inheritMany(A.Closure, [A.Closure2Args, A.Closure0Args, A.Instantiation, A.TearOffClosure, A.initHooks_closure, A.initHooks_closure1, A._AsyncRun__initializeScheduleImmediate_internalCallback, A._AsyncRun__initializeScheduleImmediate_closure, A._awaitOnObject_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure, A._Future_timeout_closure0, A.Stream_length_closure, A.Stream_first_closure0, A._CustomZone_bindUnaryCallback_closure, A._CustomZone_bindUnaryCallbackGuarded_closure, A._RootZone_bindUnaryCallback_closure, A._RootZone_bindUnaryCallbackGuarded_closure, A.runZonedGuarded_closure, A._CustomHashMap_closure, A._LinkedCustomHashMap_closure, A._BigIntImpl_hashCode_finish, A._Uri__makePath_closure, A.FutureOfJSAnyToJSPromise_get_toJS__closure, A.FutureOfVoidToJSPromise_get_toJS__closure, A.jsify__convert, A.promiseToFuture_closure, A.promiseToFuture_closure0, A.dartify_convert, A.StreamQueue__ensureListening_closure, A.BuiltListMultimap_BuiltListMultimap_closure, A.BuiltListMultimap_hashCode_closure, A.ListMultimapBuilder_replace_closure, A.BuiltMap_BuiltMap_closure, A.BuiltMap_hashCode_closure, A.BuiltSet_hashCode_closure, A.BuiltSetMultimap_hashCode_closure, A.SetMultimapBuilder_replace_closure, A.newBuiltValueToStringHelper_closure, A.BuiltListMultimapSerializer_serialize_closure, A.BuiltListMultimapSerializer_deserialize_closure, A.BuiltListSerializer_serialize_closure, A.BuiltListSerializer_deserialize_closure, A.BuiltSetMultimapSerializer_serialize_closure, A.BuiltSetMultimapSerializer_deserialize_closure, A.BuiltSetSerializer_serialize_closure, A.BuiltSetSerializer_deserialize_closure, A.CanonicalizedMap_keys_closure, A.WebSocketClient_stream_closure, A.BaseRequest_closure0, A.BrowserClient_send_closure, A.BrowserClient_send_closure0, A.ByteStream_toBytes_closure, A.MediaType_toString__closure, A.expectQuotedString_closure, A.Context_joinAll_closure, A.Context_split_closure, A._validateArgList_closure, A.Pool__runOnRelease_closure, A.Highlighter$__closure, A.Highlighter$___closure, A.Highlighter$__closure0, A.Highlighter__collateLines_closure, A.Highlighter__collateLines_closure1, A.Highlighter__collateLines__closure, A.Highlighter_highlight_closure, A.SseClient_closure0, A.SseClient_closure1, A.generateUuidV4_generateBits, A._GuaranteeSink__addError_closure, A._EventStreamSubscription_closure, A._EventStreamSubscription_onData_closure, A.BrowserWebSocket_connect_closure, A.BrowserWebSocket_connect_closure0, A.BrowserWebSocket_connect_closure1, A.BrowserWebSocket_connect_closure2, A.AdapterWebSocketChannel_closure, A.AdapterWebSocketChannel__closure, A.AdapterWebSocketChannel__closure0, A.AdapterWebSocketChannel_closure0, A.main__closure1, A.main__closure3, A.main___closure2, A.main___closure1, A.main__closure5, A.main___closure0, A.main___closure, A.main__closure7, A.main__closure8, A.main__closure9, A._sendConnectRequest_closure, A._launchCommunicationWithDebugExtension_closure, A._handleAuthRequest_closure, A._sendResponse_closure, A.DdcLibraryBundleRestarter_restart_closure, A.DdcRestarter_restart_closure0, A.DdcRestarter_restart_closure, A.RequireRestarter__reloadModule_closure0, A.JSArrayExtension_toDartIterable_closure]); + _inheritMany(A.Closure, [A.Closure2Args, A.Closure0Args, A.Instantiation, A.TearOffClosure, A.initHooks_closure, A.initHooks_closure1, A._AsyncRun__initializeScheduleImmediate_internalCallback, A._AsyncRun__initializeScheduleImmediate_closure, A._awaitOnObject_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure, A._Future_timeout_closure0, A.Stream_length_closure, A.Stream_first_closure0, A._CustomZone_bindUnaryCallback_closure, A._CustomZone_bindUnaryCallbackGuarded_closure, A._RootZone_bindUnaryCallback_closure, A._RootZone_bindUnaryCallbackGuarded_closure, A.runZonedGuarded_closure, A._CustomHashMap_closure, A._LinkedCustomHashMap_closure, A._BigIntImpl_hashCode_finish, A._Uri__makePath_closure, A.FutureOfJSAnyToJSPromise_get_toJS__closure, A.FutureOfVoidToJSPromise_get_toJS__closure, A.jsify__convert, A.promiseToFuture_closure, A.promiseToFuture_closure0, A.dartify_convert, A.StreamQueue__ensureListening_closure, A.BuiltListMultimap_BuiltListMultimap_closure, A.BuiltListMultimap_hashCode_closure, A.ListMultimapBuilder_replace_closure, A.BuiltMap_BuiltMap_closure, A.BuiltMap_hashCode_closure, A.BuiltSet_hashCode_closure, A.BuiltSetMultimap_hashCode_closure, A.SetMultimapBuilder_replace_closure, A.newBuiltValueToStringHelper_closure, A.BuiltListMultimapSerializer_serialize_closure, A.BuiltListMultimapSerializer_deserialize_closure, A.BuiltListSerializer_serialize_closure, A.BuiltListSerializer_deserialize_closure, A.BuiltSetMultimapSerializer_serialize_closure, A.BuiltSetMultimapSerializer_deserialize_closure, A.BuiltSetSerializer_serialize_closure, A.BuiltSetSerializer_deserialize_closure, A.CanonicalizedMap_keys_closure, A.ServiceExtensionResponse_ServiceExtensionResponse$fromResult_closure, A.WebSocketClient_stream_closure, A.BaseRequest_closure0, A.BrowserClient_send_closure, A.BrowserClient_send_closure0, A.ByteStream_toBytes_closure, A.MediaType_toString__closure, A.expectQuotedString_closure, A.Context_joinAll_closure, A.Context_split_closure, A._validateArgList_closure, A.Pool__runOnRelease_closure, A.Highlighter$__closure, A.Highlighter$___closure, A.Highlighter$__closure0, A.Highlighter__collateLines_closure, A.Highlighter__collateLines_closure1, A.Highlighter__collateLines__closure, A.Highlighter_highlight_closure, A.SseClient_closure0, A.SseClient_closure1, A.generateUuidV4_generateBits, A._GuaranteeSink__addError_closure, A._EventStreamSubscription_closure, A._EventStreamSubscription_onData_closure, A.BrowserWebSocket_connect_closure, A.BrowserWebSocket_connect_closure0, A.BrowserWebSocket_connect_closure1, A.BrowserWebSocket_connect_closure2, A.AdapterWebSocketChannel_closure, A.AdapterWebSocketChannel__closure, A.AdapterWebSocketChannel__closure0, A.AdapterWebSocketChannel_closure0, A.main__closure1, A.main__closure3, A.main___closure2, A.main___closure1, A.main__closure5, A.main___closure0, A.main___closure, A.main__closure7, A.main__closure8, A.main__closure9, A._sendConnectRequest_closure, A._launchCommunicationWithDebugExtension_closure, A._handleAuthRequest_closure, A._sendResponse_closure, A.DdcLibraryBundleRestarter_restart_closure, A.DdcRestarter_restart_closure0, A.DdcRestarter_restart_closure, A.RequireRestarter__reloadModule_closure0, A.JSArrayExtension_toDartIterable_closure]); _inheritMany(A.Closure2Args, [A._CastListBase_sort_closure, A.CastMap_forEach_closure, A.ConstantMap_map_closure, A.JsLinkedHashMap_addAll_closure, A.initHooks_closure0, A._awaitOnObject_closure0, A._wrapJsFunctionForAsync_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure0, A._Future_timeout_closure1, A._BufferingStreamSubscription_asFuture_closure0, A.LinkedHashMap_LinkedHashMap$from_closure, A.MapBase_mapToString_closure, A._JsonStringifier_writeMap_closure, A._BigIntImpl_hashCode_combine, A.Uri__parseIPv4Address_error, A.Uri_parseIPv6Address_error, A.Uri_parseIPv6Address_parseHex, A.FutureOfJSAnyToJSPromise_get_toJS_closure, A.FutureOfJSAnyToJSPromise_get_toJS__closure0, A.FutureOfVoidToJSPromise_get_toJS_closure, A.FutureOfVoidToJSPromise_get_toJS__closure0, A.StreamQueue__ensureListening_closure1, A.hashObjects_closure, A.MapBuilder_replace_closure, A.CanonicalizedMap_addAll_closure, A.CanonicalizedMap_forEach_closure, A.CanonicalizedMap_map_closure, A.safeUnawaited_closure, A.BaseRequest_closure, A.MediaType_toString_closure, A.Pool__runOnRelease_closure0, A.Highlighter__collateLines_closure0, A.generateUuidV4_printDigits, A.generateUuidV4_bitsDigits, A.main__closure4, A.main_closure0]); _inherit(A.CastList, A._CastListBase); _inheritMany(A.MapBase, [A.CastMap, A.JsLinkedHashMap, A._HashMap, A._JsonMap]); @@ -28094,6 +28636,8 @@ _inherit(A._$IsolateStart, A.IsolateStart); _inherit(A._$RegisterEvent, A.RegisterEvent); _inherit(A._$RunRequest, A.RunRequest); + _inherit(A._$ServiceExtensionRequest, A.ServiceExtensionRequest); + _inherit(A._$ServiceExtensionResponse, A.ServiceExtensionResponse); _inheritMany(A.SocketClient, [A.SseSocketClient, A.WebSocketClient]); _inherit(A.BrowserClient, A.BaseClient); _inherit(A.ByteStream, A.StreamView); @@ -28131,7 +28675,7 @@ typeUniverse: {eC: new Map(), tR: {}, eT: {}, tPV: {}, sEA: []}, mangledGlobalNames: {int: "int", double: "double", num: "num", String: "String", bool: "bool", Null: "Null", List: "List", Object: "Object", Map: "Map"}, mangledNames: {}, - types: ["~()", "Null()", "~(JSObject)", "Object?(@)", "@(@)", "Null(Object,StackTrace)", "Null(@)", "~(@)", "Null(JSObject)", "~(Object?)", "JSObject()", "Object?(Object?)", "bool(Object?)", "String(String)", "~(Object,StackTrace)", "bool(_Highlight)", "~(~())", "int(Object?)", "bool(Object?,Object?)", "Future<~>()", "String(int,int)", "~(@,StackTrace)", "int()", "~(@,@)", "~(Object?,Object?)", "@()", "int(int,int)", "int(int)", "int(@,@)", "Null(JavaScriptFunction,JavaScriptFunction)", "bool(String)", "String(Match)", "~(Object[StackTrace?])", "bool()", "MapBuilder()", "SetBuilder()", "ListMultimapBuilder()", "~(int,@)", "ListBuilder()", "IndentingBuiltValueToStringHelper(String)", "ListBuilder()", "ListBuilder()", "int(int,@)", "String(@)", "bool(String,String)", "int(String)", "Object?(~)", "~(List)", "MediaType()", "~(String,String)", "JSObject(Object,StackTrace)", "Logger()", "Null(@,StackTrace)", "~(String,int?)", "String?()", "int(_Line)", "~(String,int)", "Object(_Line)", "Object(_Highlight)", "int(_Highlight,_Highlight)", "List<_Line>(MapEntry>)", "Null(~())", "SourceSpanWithContext()", "~(Zone,ZoneDelegate,Zone,Object,StackTrace)", "~(String?)", "Future()", "@(@,String)", "Null(WebSocket)", "~(WebSocketEvent)", "Null(Object)", "HotReloadResponse([~(HotReloadResponseBuilder)])", "JSObject(String[bool?])", "~(List)", "ListBuilder(BatchedDebugEventsBuilder)", "Null(String,String)", "DebugEventBuilder(DebugEventBuilder)", "Null(String)", "RegisterEventBuilder(RegisterEventBuilder)", "DevToolsRequestBuilder(DevToolsRequestBuilder)", "Future<~>(String)", "ConnectRequestBuilder(ConnectRequestBuilder)", "DebugInfoBuilder(DebugInfoBuilder)", "~(bool)", "Null(JavaScriptFunction)", "bool(bool)", "List(String)", "int(String,String)", "Null(JavaScriptObject)", "JSObject()()", "SetMultimapBuilder()", "@(String)", "~(Zone?,ZoneDelegate?,Zone,Object,StackTrace)", "0^(Zone?,ZoneDelegate?,Zone,0^())", "0^(Zone?,ZoneDelegate?,Zone,0^(1^),1^)", "0^(Zone?,ZoneDelegate?,Zone,0^(1^,2^),1^,2^)", "0^()(Zone,ZoneDelegate,Zone,0^())", "0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))", "0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))", "AsyncError?(Zone,ZoneDelegate,Zone,Object,StackTrace?)", "~(Zone?,ZoneDelegate?,Zone,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~(Timer))", "~(Zone,ZoneDelegate,Zone,String)", "~(String)", "Zone(Zone?,ZoneDelegate?,Zone,ZoneSpecification?,Map?)", "0^(0^,0^)", "String(String?)"], + types: ["~()", "Null()", "~(JSObject)", "Object?(@)", "@(@)", "Null(Object,StackTrace)", "Null(@)", "~(@)", "Null(JSObject)", "~(Object?)", "JSObject()", "Object?(Object?)", "~(~())", "~(Object,StackTrace)", "bool(Object?)", "String(String)", "Future<~>()", "bool(Object?,Object?)", "int(Object?)", "bool(_Highlight)", "bool(String)", "@()", "int(int)", "~(Object[StackTrace?])", "Null(JavaScriptFunction,JavaScriptFunction)", "~(@,StackTrace)", "bool()", "int(int,int)", "String(Match)", "~(@,@)", "int()", "~(Object?,Object?)", "String(int,int)", "int(@,@)", "MediaType()", "@(@,String)", "SetMultimapBuilder()", "Null(~())", "~(String,int)", "~(Zone,ZoneDelegate,Zone,Object,StackTrace)", "ListBuilder()", "ListBuilder()", "~(ServiceExtensionResponseBuilder)", "~(String,int?)", "String(@)", "bool(String,String)", "int(String)", "Null(@,StackTrace)", "~(List)", "@(String)", "~(String,String)", "JSObject(Object,StackTrace)", "Logger()", "Object?(~)", "String(String?)", "String?()", "int(_Line)", "~(int,@)", "Object(_Line)", "Object(_Highlight)", "int(_Highlight,_Highlight)", "List<_Line>(MapEntry>)", "int(int,@)", "SourceSpanWithContext()", "IndentingBuiltValueToStringHelper(String)", "~(String?)", "Future()", "ListBuilder()", "Null(WebSocket)", "~(WebSocketEvent)", "Null(Object)", "HotReloadResponse([~(HotReloadResponseBuilder)])", "JSObject(String[bool?])", "~(List)", "ListBuilder(BatchedDebugEventsBuilder)", "Null(String,String)", "DebugEventBuilder(DebugEventBuilder)", "0^(0^,0^)", "RegisterEventBuilder(RegisterEventBuilder)", "DevToolsRequestBuilder(DevToolsRequestBuilder)", "Future<~>(String)", "ConnectRequestBuilder(ConnectRequestBuilder)", "DebugInfoBuilder(DebugInfoBuilder)", "~(bool)", "Null(JavaScriptFunction)", "bool(bool)", "List(String)", "int(String,String)", "Null(JavaScriptObject)", "JSObject()()", "ListMultimapBuilder()", "MapBuilder()", "~(Zone?,ZoneDelegate?,Zone,Object,StackTrace)", "0^(Zone?,ZoneDelegate?,Zone,0^())", "0^(Zone?,ZoneDelegate?,Zone,0^(1^),1^)", "0^(Zone?,ZoneDelegate?,Zone,0^(1^,2^),1^,2^)", "0^()(Zone,ZoneDelegate,Zone,0^())", "0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))", "0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))", "AsyncError?(Zone,ZoneDelegate,Zone,Object,StackTrace?)", "~(Zone?,ZoneDelegate?,Zone,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~(Timer))", "~(Zone,ZoneDelegate,Zone,String)", "~(String)", "Zone(Zone?,ZoneDelegate?,Zone,ZoneSpecification?,Map?)", "Null(String)", "SetBuilder()"], interceptorsByTag: null, leafTags: null, arrayRti: Symbol("$ti"), @@ -28139,7 +28683,7 @@ "2;libraries,sources": (t1, t2) => o => o instanceof A._Record_2_libraries_sources && t1._is(o._0) && t2._is(o._1) } }; - A._Universe_addRules(init.typeUniverse, JSON.parse('{"JavaScriptFunction":"LegacyJavaScriptObject","PlainJavaScriptObject":"LegacyJavaScriptObject","UnknownJavaScriptObject":"LegacyJavaScriptObject","JavaScriptObject":{"JSObject":[]},"JSArray":{"List":["1"],"JavaScriptObject":[],"EfficientLengthIterable":["1"],"JSObject":[],"Iterable":["1"],"JSIndexable":["1"],"Iterable.E":"1"},"JSBool":{"bool":[],"TrustedGetRuntimeType":[]},"JSNull":{"Null":[],"TrustedGetRuntimeType":[]},"LegacyJavaScriptObject":{"JavaScriptObject":[],"JSObject":[]},"JSUnmodifiableArray":{"JSArray":["1"],"List":["1"],"JavaScriptObject":[],"EfficientLengthIterable":["1"],"JSObject":[],"Iterable":["1"],"JSIndexable":["1"],"Iterable.E":"1"},"ArrayIterator":{"Iterator":["1"]},"JSNumber":{"double":[],"num":[],"Comparable":["num"]},"JSInt":{"double":[],"int":[],"num":[],"Comparable":["num"],"TrustedGetRuntimeType":[]},"JSNumNotInt":{"double":[],"num":[],"Comparable":["num"],"TrustedGetRuntimeType":[]},"JSString":{"String":[],"Comparable":["String"],"Pattern":[],"JSIndexable":["@"],"TrustedGetRuntimeType":[]},"_CastIterableBase":{"Iterable":["2"]},"CastIterator":{"Iterator":["2"]},"CastIterable":{"_CastIterableBase":["1","2"],"Iterable":["2"],"Iterable.E":"2"},"_EfficientLengthCastIterable":{"CastIterable":["1","2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"_CastListBase":{"ListBase":["2"],"List":["2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"]},"CastList":{"_CastListBase":["1","2"],"ListBase":["2"],"List":["2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListBase.E":"2","Iterable.E":"2"},"CastMap":{"MapBase":["3","4"],"Map":["3","4"],"MapBase.K":"3","MapBase.V":"4"},"LateError":{"Error":[]},"CodeUnits":{"ListBase":["int"],"UnmodifiableListMixin":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"ListBase.E":"int","Iterable.E":"int","UnmodifiableListMixin.E":"int"},"EfficientLengthIterable":{"Iterable":["1"]},"ListIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"SubListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"ListIterator":{"Iterator":["1"]},"MappedIterable":{"Iterable":["2"],"Iterable.E":"2"},"EfficientLengthMappedIterable":{"MappedIterable":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"MappedIterator":{"Iterator":["2"]},"MappedListIterable":{"ListIterable":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListIterable.E":"2","Iterable.E":"2"},"WhereIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereIterator":{"Iterator":["1"]},"ExpandIterable":{"Iterable":["2"],"Iterable.E":"2"},"ExpandIterator":{"Iterator":["2"]},"TakeIterable":{"Iterable":["1"],"Iterable.E":"1"},"EfficientLengthTakeIterable":{"TakeIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"TakeIterator":{"Iterator":["1"]},"SkipIterable":{"Iterable":["1"],"Iterable.E":"1"},"EfficientLengthSkipIterable":{"SkipIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"SkipIterator":{"Iterator":["1"]},"EmptyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"EmptyIterator":{"Iterator":["1"]},"WhereTypeIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereTypeIterator":{"Iterator":["1"]},"UnmodifiableListBase":{"ListBase":["1"],"UnmodifiableListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ReversedListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"_Record_2_libraries_sources":{"_Record2":[],"_Record":[]},"ConstantMap":{"Map":["1","2"]},"ConstantStringMap":{"ConstantMap":["1","2"],"Map":["1","2"]},"_KeysOrValues":{"Iterable":["1"],"Iterable.E":"1"},"_KeysOrValuesOrElementsIterator":{"Iterator":["1"]},"Instantiation":{"Closure":[],"Function":[]},"Instantiation1":{"Closure":[],"Function":[]},"NullError":{"TypeError":[],"Error":[]},"JsNoSuchMethodError":{"Error":[]},"UnknownJsTypeError":{"Error":[]},"NullThrownFromJavaScriptException":{"Exception":[]},"_StackTrace":{"StackTrace":[]},"Closure":{"Function":[]},"Closure0Args":{"Closure":[],"Function":[]},"Closure2Args":{"Closure":[],"Function":[]},"TearOffClosure":{"Closure":[],"Function":[]},"StaticClosure":{"Closure":[],"Function":[]},"BoundClosure":{"Closure":[],"Function":[]},"RuntimeError":{"Error":[]},"JsLinkedHashMap":{"MapBase":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"LinkedHashMapKeysIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapKeyIterator":{"Iterator":["1"]},"LinkedHashMapValuesIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapValueIterator":{"Iterator":["1"]},"LinkedHashMapEntriesIterable":{"EfficientLengthIterable":["MapEntry<1,2>"],"Iterable":["MapEntry<1,2>"],"Iterable.E":"MapEntry<1,2>"},"LinkedHashMapEntryIterator":{"Iterator":["MapEntry<1,2>"]},"JsIdentityLinkedHashMap":{"JsLinkedHashMap":["1","2"],"MapBase":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_Record2":{"_Record":[]},"JSSyntaxRegExp":{"RegExp":[],"Pattern":[]},"_MatchImplementation":{"RegExpMatch":[],"Match":[]},"_AllMatchesIterable":{"Iterable":["RegExpMatch"],"Iterable.E":"RegExpMatch"},"_AllMatchesIterator":{"Iterator":["RegExpMatch"]},"StringMatch":{"Match":[]},"_StringAllMatchesIterable":{"Iterable":["Match"],"Iterable.E":"Match"},"_StringAllMatchesIterator":{"Iterator":["Match"]},"NativeByteBuffer":{"JavaScriptObject":[],"JSObject":[],"ByteBuffer":[],"TrustedGetRuntimeType":[]},"NativeTypedData":{"JavaScriptObject":[],"JSObject":[]},"_UnmodifiableNativeByteBufferView":{"ByteBuffer":[]},"NativeByteData":{"JavaScriptObject":[],"ByteData":[],"JSObject":[],"TrustedGetRuntimeType":[]},"NativeTypedArray":{"JavaScriptIndexingBehavior":["1"],"JavaScriptObject":[],"JSObject":[],"JSIndexable":["1"]},"NativeTypedArrayOfDouble":{"ListBase":["double"],"NativeTypedArray":["double"],"List":["double"],"JavaScriptIndexingBehavior":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"JSObject":[],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"]},"NativeTypedArrayOfInt":{"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"]},"NativeFloat32List":{"Float32List":[],"ListBase":["double"],"NativeTypedArray":["double"],"List":["double"],"JavaScriptIndexingBehavior":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"JSObject":[],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"TrustedGetRuntimeType":[],"ListBase.E":"double","Iterable.E":"double","FixedLengthListMixin.E":"double"},"NativeFloat64List":{"Float64List":[],"ListBase":["double"],"NativeTypedArray":["double"],"List":["double"],"JavaScriptIndexingBehavior":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"JSObject":[],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"TrustedGetRuntimeType":[],"ListBase.E":"double","Iterable.E":"double","FixedLengthListMixin.E":"double"},"NativeInt16List":{"NativeTypedArrayOfInt":[],"Int16List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeInt32List":{"NativeTypedArrayOfInt":[],"Int32List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeInt8List":{"NativeTypedArrayOfInt":[],"Int8List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint16List":{"NativeTypedArrayOfInt":[],"Uint16List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint32List":{"NativeTypedArrayOfInt":[],"Uint32List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint8ClampedList":{"NativeTypedArrayOfInt":[],"Uint8ClampedList":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint8List":{"NativeTypedArrayOfInt":[],"Uint8List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"_Type":{"Type":[]},"_Error":{"Error":[]},"_TypeError":{"TypeError":[],"Error":[]},"AsyncError":{"Error":[]},"_TimerImpl":{"Timer":[]},"_AsyncAwaitCompleter":{"Completer":["1"]},"_Completer":{"Completer":["1"]},"_AsyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_SyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_Future":{"Future":["1"]},"StreamView":{"Stream":["1"]},"_StreamController":{"StreamController":["1"],"StreamSink":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_AsyncStreamController":{"_AsyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_SyncStreamController":{"_SyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_ControllerStream":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_ControllerSubscription":{"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamSinkWrapper":{"StreamSink":["1"]},"_BufferingStreamSubscription":{"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamImpl":{"Stream":["1"]},"_DelayedData":{"_DelayedEvent":["1"]},"_DelayedError":{"_DelayedEvent":["@"]},"_DelayedDone":{"_DelayedEvent":["@"]},"_DoneStreamSubscription":{"StreamSubscription":["1"]},"_EmptyStream":{"Stream":["1"],"Stream.T":"1"},"_ForwardingStream":{"Stream":["2"]},"_ForwardingStreamSubscription":{"_BufferingStreamSubscription":["2"],"StreamSubscription":["2"],"_EventSink":["2"],"_EventDispatch":["2"],"_BufferingStreamSubscription.T":"2"},"_MapStream":{"_ForwardingStream":["1","2"],"Stream":["2"],"Stream.T":"2"},"_ZoneSpecification":{"ZoneSpecification":[]},"_ZoneDelegate":{"ZoneDelegate":[]},"_Zone":{"Zone":[]},"_CustomZone":{"_Zone":[],"Zone":[]},"_RootZone":{"_Zone":[],"Zone":[]},"_SplayTreeSetNode":{"_SplayTreeNode":["1","_SplayTreeSetNode<1>"],"_SplayTreeNode.K":"1","_SplayTreeNode.1":"_SplayTreeSetNode<1>"},"_HashMap":{"MapBase":["1","2"],"HashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_IdentityHashMap":{"_HashMap":["1","2"],"MapBase":["1","2"],"HashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_CustomHashMap":{"_HashMap":["1","2"],"MapBase":["1","2"],"HashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_HashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_HashMapKeyIterator":{"Iterator":["1"]},"_LinkedCustomHashMap":{"JsLinkedHashMap":["1","2"],"MapBase":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_HashSet":{"_SetBase":["1"],"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_HashSetIterator":{"Iterator":["1"]},"_LinkedHashSet":{"_SetBase":["1"],"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_LinkedHashSetIterator":{"Iterator":["1"]},"UnmodifiableListView":{"ListBase":["1"],"UnmodifiableListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListBase.E":"1","Iterable.E":"1","UnmodifiableListMixin.E":"1"},"ListBase":{"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"MapBase":{"Map":["1","2"]},"MapView":{"Map":["1","2"]},"UnmodifiableMapView":{"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ListQueue":{"Queue":["1"],"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"_ListQueueIterator":{"Iterator":["1"]},"SetBase":{"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_SetBase":{"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_SplayTreeIterator":{"Iterator":["3"]},"_SplayTreeKeyIterator":{"_SplayTreeIterator":["1","2","1"],"Iterator":["1"],"_SplayTreeIterator.K":"1","_SplayTreeIterator.T":"1","_SplayTreeIterator.1":"2"},"SplayTreeSet":{"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"_SplayTree":["1","_SplayTreeSetNode<1>"],"Iterable":["1"],"Iterable.E":"1","_SplayTree.1":"_SplayTreeSetNode<1>","_SplayTree.K":"1"},"Encoding":{"Codec":["String","List"]},"_JsonMap":{"MapBase":["String","@"],"Map":["String","@"],"MapBase.K":"String","MapBase.V":"@"},"_JsonMapKeyIterable":{"ListIterable":["String"],"EfficientLengthIterable":["String"],"Iterable":["String"],"ListIterable.E":"String","Iterable.E":"String"},"AsciiCodec":{"Encoding":[],"Codec":["String","List"],"Codec.S":"String"},"_UnicodeSubsetEncoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"AsciiEncoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"_UnicodeSubsetDecoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"AsciiDecoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"Base64Codec":{"Codec":["List","String"],"Codec.S":"List"},"Base64Encoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"Base64Decoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"Converter":{"StreamTransformer":["1","2"]},"JsonUnsupportedObjectError":{"Error":[]},"JsonCyclicError":{"Error":[]},"JsonCodec":{"Codec":["Object?","String"],"Codec.S":"Object?"},"JsonEncoder":{"Converter":["Object?","String"],"StreamTransformer":["Object?","String"]},"JsonDecoder":{"Converter":["String","Object?"],"StreamTransformer":["String","Object?"]},"Latin1Codec":{"Encoding":[],"Codec":["String","List"],"Codec.S":"String"},"Latin1Encoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"Latin1Decoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"Utf8Codec":{"Encoding":[],"Codec":["String","List"],"Codec.S":"String"},"Utf8Encoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"Utf8Decoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"BigInt":{"Comparable":["BigInt"]},"DateTime":{"Comparable":["DateTime"]},"double":{"num":[],"Comparable":["num"]},"Duration":{"Comparable":["Duration"]},"int":{"num":[],"Comparable":["num"]},"List":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"num":{"Comparable":["num"]},"RegExp":{"Pattern":[]},"RegExpMatch":{"Match":[]},"Set":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"String":{"Comparable":["String"],"Pattern":[]},"_BigIntImpl":{"BigInt":[],"Comparable":["BigInt"]},"AssertionError":{"Error":[]},"TypeError":{"Error":[]},"ArgumentError":{"Error":[]},"RangeError":{"Error":[]},"IndexError":{"Error":[]},"UnsupportedError":{"Error":[]},"UnimplementedError":{"Error":[]},"StateError":{"Error":[]},"ConcurrentModificationError":{"Error":[]},"OutOfMemoryError":{"Error":[]},"StackOverflowError":{"Error":[]},"_Exception":{"Exception":[]},"FormatException":{"Exception":[]},"IntegerDivisionByZeroException":{"Exception":[],"Error":[]},"_StringStackTrace":{"StackTrace":[]},"StringBuffer":{"StringSink":[]},"_Uri":{"Uri":[]},"_SimpleUri":{"Uri":[]},"_DataUri":{"Uri":[]},"NullRejectionException":{"Exception":[]},"DelegatingStreamSink":{"StreamSink":["1"]},"ErrorResult":{"Result":["0&"]},"ValueResult":{"Result":["1"]},"_NextRequest":{"_EventRequest":["1"]},"_HasNextRequest":{"_EventRequest":["1"]},"BuiltList":{"Iterable":["1"]},"_BuiltList":{"BuiltList":["1"],"Iterable":["1"],"Iterable.E":"1"},"_BuiltListMultimap":{"BuiltListMultimap":["1","2"]},"_BuiltMap":{"BuiltMap":["1","2"]},"BuiltSet":{"Iterable":["1"]},"_BuiltSet":{"BuiltSet":["1"],"Iterable":["1"],"Iterable.E":"1"},"_BuiltSetMultimap":{"BuiltSetMultimap":["1","2"]},"BuiltValueNullFieldError":{"Error":[]},"BuiltValueNestedFieldError":{"Error":[]},"BoolJsonObject":{"JsonObject":[]},"ListJsonObject":{"JsonObject":[]},"MapJsonObject":{"JsonObject":[]},"NumJsonObject":{"JsonObject":[]},"StringJsonObject":{"JsonObject":[]},"DeserializationError":{"Error":[]},"BigIntSerializer":{"PrimitiveSerializer":["BigInt"],"Serializer":["BigInt"]},"BoolSerializer":{"PrimitiveSerializer":["bool"],"Serializer":["bool"]},"BuiltJsonSerializers":{"Serializers":[]},"BuiltListMultimapSerializer":{"StructuredSerializer":["BuiltListMultimap<@,@>"],"Serializer":["BuiltListMultimap<@,@>"]},"BuiltListSerializer":{"StructuredSerializer":["BuiltList<@>"],"Serializer":["BuiltList<@>"]},"BuiltMapSerializer":{"StructuredSerializer":["BuiltMap<@,@>"],"Serializer":["BuiltMap<@,@>"]},"BuiltSetMultimapSerializer":{"StructuredSerializer":["BuiltSetMultimap<@,@>"],"Serializer":["BuiltSetMultimap<@,@>"]},"BuiltSetSerializer":{"StructuredSerializer":["BuiltSet<@>"],"Serializer":["BuiltSet<@>"]},"DateTimeSerializer":{"PrimitiveSerializer":["DateTime"],"Serializer":["DateTime"]},"DoubleSerializer":{"PrimitiveSerializer":["double"],"Serializer":["double"]},"DurationSerializer":{"PrimitiveSerializer":["Duration"],"Serializer":["Duration"]},"Int32Serializer":{"PrimitiveSerializer":["Int32"],"Serializer":["Int32"]},"Int64Serializer":{"PrimitiveSerializer":["Int64"],"Serializer":["Int64"]},"IntSerializer":{"PrimitiveSerializer":["int"],"Serializer":["int"]},"JsonObjectSerializer":{"PrimitiveSerializer":["JsonObject"],"Serializer":["JsonObject"]},"NullSerializer":{"PrimitiveSerializer":["Null"],"Serializer":["Null"]},"NumSerializer":{"PrimitiveSerializer":["num"],"Serializer":["num"]},"RegExpSerializer":{"PrimitiveSerializer":["RegExp"],"Serializer":["RegExp"]},"StringSerializer":{"PrimitiveSerializer":["String"],"Serializer":["String"]},"Uint8ListSerializer":{"PrimitiveSerializer":["Uint8List"],"Serializer":["Uint8List"]},"UriSerializer":{"PrimitiveSerializer":["Uri"],"Serializer":["Uri"]},"CanonicalizedMap":{"Map":["2","3"]},"DefaultEquality":{"Equality":["1"]},"IterableEquality":{"Equality":["Iterable<1>"]},"ListEquality":{"Equality":["List<1>"]},"_UnorderedEquality":{"Equality":["2"]},"SetEquality":{"_UnorderedEquality":["1","Set<1>"],"Equality":["Set<1>"],"_UnorderedEquality.E":"1","_UnorderedEquality.T":"Set<1>"},"MapEquality":{"Equality":["Map<1,2>"]},"DeepCollectionEquality":{"Equality":["@"]},"QueueList":{"ListBase":["1"],"List":["1"],"Queue":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListBase.E":"1","QueueList.E":"1","Iterable.E":"1"},"_CastQueueList":{"QueueList":["2"],"ListBase":["2"],"List":["2"],"Queue":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListBase.E":"2","QueueList.E":"2","Iterable.E":"2"},"_$BuildStatusSerializer":{"PrimitiveSerializer":["BuildStatus"],"Serializer":["BuildStatus"]},"_$BuildResultSerializer":{"StructuredSerializer":["BuildResult"],"Serializer":["BuildResult"]},"_$BuildResult":{"BuildResult":[]},"_$ConnectRequestSerializer":{"StructuredSerializer":["ConnectRequest"],"Serializer":["ConnectRequest"]},"_$ConnectRequest":{"ConnectRequest":[]},"_$DebugEventSerializer":{"StructuredSerializer":["DebugEvent"],"Serializer":["DebugEvent"]},"_$BatchedDebugEventsSerializer":{"StructuredSerializer":["BatchedDebugEvents"],"Serializer":["BatchedDebugEvents"]},"_$DebugEvent":{"DebugEvent":[]},"_$BatchedDebugEvents":{"BatchedDebugEvents":[]},"_$DebugInfoSerializer":{"StructuredSerializer":["DebugInfo"],"Serializer":["DebugInfo"]},"_$DebugInfo":{"DebugInfo":[]},"_$DevToolsRequestSerializer":{"StructuredSerializer":["DevToolsRequest"],"Serializer":["DevToolsRequest"]},"_$DevToolsResponseSerializer":{"StructuredSerializer":["DevToolsResponse"],"Serializer":["DevToolsResponse"]},"_$DevToolsRequest":{"DevToolsRequest":[]},"_$DevToolsResponse":{"DevToolsResponse":[]},"_$ErrorResponseSerializer":{"StructuredSerializer":["ErrorResponse"],"Serializer":["ErrorResponse"]},"_$ErrorResponse":{"ErrorResponse":[]},"_$ExtensionRequestSerializer":{"StructuredSerializer":["ExtensionRequest"],"Serializer":["ExtensionRequest"]},"_$ExtensionResponseSerializer":{"StructuredSerializer":["ExtensionResponse"],"Serializer":["ExtensionResponse"]},"_$ExtensionEventSerializer":{"StructuredSerializer":["ExtensionEvent"],"Serializer":["ExtensionEvent"]},"_$BatchedEventsSerializer":{"StructuredSerializer":["BatchedEvents"],"Serializer":["BatchedEvents"]},"_$ExtensionRequest":{"ExtensionRequest":[]},"_$ExtensionResponse":{"ExtensionResponse":[]},"_$ExtensionEvent":{"ExtensionEvent":[]},"_$BatchedEvents":{"BatchedEvents":[]},"_$HotReloadRequestSerializer":{"StructuredSerializer":["HotReloadRequest"],"Serializer":["HotReloadRequest"]},"_$HotReloadRequest":{"HotReloadRequest":[]},"_$HotReloadResponseSerializer":{"StructuredSerializer":["HotReloadResponse"],"Serializer":["HotReloadResponse"]},"_$HotReloadResponse":{"HotReloadResponse":[]},"_$IsolateExitSerializer":{"StructuredSerializer":["IsolateExit"],"Serializer":["IsolateExit"]},"_$IsolateStartSerializer":{"StructuredSerializer":["IsolateStart"],"Serializer":["IsolateStart"]},"_$IsolateExit":{"IsolateExit":[]},"_$IsolateStart":{"IsolateStart":[]},"_$RegisterEventSerializer":{"StructuredSerializer":["RegisterEvent"],"Serializer":["RegisterEvent"]},"_$RegisterEvent":{"RegisterEvent":[]},"_$RunRequestSerializer":{"StructuredSerializer":["RunRequest"],"Serializer":["RunRequest"]},"_$RunRequest":{"RunRequest":[]},"SseSocketClient":{"SocketClient":[]},"WebSocketClient":{"SocketClient":[]},"Int32":{"Comparable":["Object"]},"Int64":{"Comparable":["Object"]},"ByteStream":{"StreamView":["List"],"Stream":["List"],"Stream.T":"List","StreamView.T":"List"},"ClientException":{"Exception":[]},"Request":{"BaseRequest":[]},"StreamedResponseV2":{"StreamedResponse":[]},"CaseInsensitiveMap":{"CanonicalizedMap":["String","String","1"],"Map":["String","1"],"CanonicalizedMap.K":"String","CanonicalizedMap.V":"1","CanonicalizedMap.C":"String"},"Level":{"Comparable":["Level"]},"PathException":{"Exception":[]},"PosixStyle":{"InternalStyle":[]},"UrlStyle":{"InternalStyle":[]},"WindowsStyle":{"InternalStyle":[]},"FileLocation":{"SourceLocation":[],"Comparable":["SourceLocation"]},"_FileSpan":{"SourceSpanWithContext":[],"SourceSpan":[],"Comparable":["SourceSpan"]},"SourceLocation":{"Comparable":["SourceLocation"]},"SourceLocationMixin":{"SourceLocation":[],"Comparable":["SourceLocation"]},"SourceSpan":{"Comparable":["SourceSpan"]},"SourceSpanBase":{"SourceSpan":[],"Comparable":["SourceSpan"]},"SourceSpanException":{"Exception":[]},"SourceSpanFormatException":{"FormatException":[],"Exception":[]},"SourceSpanMixin":{"SourceSpan":[],"Comparable":["SourceSpan"]},"SourceSpanWithContext":{"SourceSpan":[],"Comparable":["SourceSpan"]},"SseClient":{"StreamChannel":["String?"]},"GuaranteeChannel":{"StreamChannel":["1"]},"_GuaranteeSink":{"StreamSink":["1"]},"StreamChannelMixin":{"StreamChannel":["1"]},"StringScannerException":{"FormatException":[],"Exception":[]},"_EventStream":{"Stream":["1"],"Stream.T":"1"},"_EventStreamSubscription":{"StreamSubscription":["1"]},"BrowserWebSocket":{"WebSocket":[]},"TextDataReceived":{"WebSocketEvent":[]},"BinaryDataReceived":{"WebSocketEvent":[]},"CloseReceived":{"WebSocketEvent":[]},"WebSocketException":{"Exception":[]},"WebSocketConnectionClosed":{"Exception":[]},"AdapterWebSocketChannel":{"WebSocketChannel":[],"StreamChannel":["@"]},"_WebSocketSink":{"WebSocketSink":[],"DelegatingStreamSink":["@"],"StreamSink":["@"],"DelegatingStreamSink.T":"@"},"WebSocketChannelException":{"Exception":[]},"DdcLibraryBundleRestarter":{"Restarter":[]},"DdcRestarter":{"Restarter":[]},"RequireRestarter":{"Restarter":[]},"HotReloadFailedException":{"Exception":[]},"Int8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8ClampedList":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Float32List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"Float64List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]}}')); + A._Universe_addRules(init.typeUniverse, JSON.parse('{"JavaScriptFunction":"LegacyJavaScriptObject","PlainJavaScriptObject":"LegacyJavaScriptObject","UnknownJavaScriptObject":"LegacyJavaScriptObject","JavaScriptObject":{"JSObject":[]},"JSArray":{"List":["1"],"JavaScriptObject":[],"EfficientLengthIterable":["1"],"JSObject":[],"Iterable":["1"],"JSIndexable":["1"],"Iterable.E":"1"},"JSBool":{"bool":[],"TrustedGetRuntimeType":[]},"JSNull":{"Null":[],"TrustedGetRuntimeType":[]},"LegacyJavaScriptObject":{"JavaScriptObject":[],"JSObject":[]},"JSUnmodifiableArray":{"JSArray":["1"],"List":["1"],"JavaScriptObject":[],"EfficientLengthIterable":["1"],"JSObject":[],"Iterable":["1"],"JSIndexable":["1"],"Iterable.E":"1"},"ArrayIterator":{"Iterator":["1"]},"JSNumber":{"double":[],"num":[],"Comparable":["num"]},"JSInt":{"double":[],"int":[],"num":[],"Comparable":["num"],"TrustedGetRuntimeType":[]},"JSNumNotInt":{"double":[],"num":[],"Comparable":["num"],"TrustedGetRuntimeType":[]},"JSString":{"String":[],"Comparable":["String"],"Pattern":[],"JSIndexable":["@"],"TrustedGetRuntimeType":[]},"_CastIterableBase":{"Iterable":["2"]},"CastIterator":{"Iterator":["2"]},"CastIterable":{"_CastIterableBase":["1","2"],"Iterable":["2"],"Iterable.E":"2"},"_EfficientLengthCastIterable":{"CastIterable":["1","2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"_CastListBase":{"ListBase":["2"],"List":["2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"]},"CastList":{"_CastListBase":["1","2"],"ListBase":["2"],"List":["2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListBase.E":"2","Iterable.E":"2"},"CastMap":{"MapBase":["3","4"],"Map":["3","4"],"MapBase.K":"3","MapBase.V":"4"},"LateError":{"Error":[]},"CodeUnits":{"ListBase":["int"],"UnmodifiableListMixin":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"ListBase.E":"int","Iterable.E":"int","UnmodifiableListMixin.E":"int"},"EfficientLengthIterable":{"Iterable":["1"]},"ListIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"SubListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"ListIterator":{"Iterator":["1"]},"MappedIterable":{"Iterable":["2"],"Iterable.E":"2"},"EfficientLengthMappedIterable":{"MappedIterable":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"MappedIterator":{"Iterator":["2"]},"MappedListIterable":{"ListIterable":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListIterable.E":"2","Iterable.E":"2"},"WhereIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereIterator":{"Iterator":["1"]},"ExpandIterable":{"Iterable":["2"],"Iterable.E":"2"},"ExpandIterator":{"Iterator":["2"]},"TakeIterable":{"Iterable":["1"],"Iterable.E":"1"},"EfficientLengthTakeIterable":{"TakeIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"TakeIterator":{"Iterator":["1"]},"SkipIterable":{"Iterable":["1"],"Iterable.E":"1"},"EfficientLengthSkipIterable":{"SkipIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"SkipIterator":{"Iterator":["1"]},"EmptyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"EmptyIterator":{"Iterator":["1"]},"WhereTypeIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereTypeIterator":{"Iterator":["1"]},"UnmodifiableListBase":{"ListBase":["1"],"UnmodifiableListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ReversedListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"_Record_2_libraries_sources":{"_Record2":[],"_Record":[]},"ConstantMap":{"Map":["1","2"]},"ConstantStringMap":{"ConstantMap":["1","2"],"Map":["1","2"]},"_KeysOrValues":{"Iterable":["1"],"Iterable.E":"1"},"_KeysOrValuesOrElementsIterator":{"Iterator":["1"]},"Instantiation":{"Closure":[],"Function":[]},"Instantiation1":{"Closure":[],"Function":[]},"NullError":{"TypeError":[],"Error":[]},"JsNoSuchMethodError":{"Error":[]},"UnknownJsTypeError":{"Error":[]},"NullThrownFromJavaScriptException":{"Exception":[]},"_StackTrace":{"StackTrace":[]},"Closure":{"Function":[]},"Closure0Args":{"Closure":[],"Function":[]},"Closure2Args":{"Closure":[],"Function":[]},"TearOffClosure":{"Closure":[],"Function":[]},"StaticClosure":{"Closure":[],"Function":[]},"BoundClosure":{"Closure":[],"Function":[]},"RuntimeError":{"Error":[]},"JsLinkedHashMap":{"MapBase":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"LinkedHashMapKeysIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapKeyIterator":{"Iterator":["1"]},"LinkedHashMapValuesIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapValueIterator":{"Iterator":["1"]},"LinkedHashMapEntriesIterable":{"EfficientLengthIterable":["MapEntry<1,2>"],"Iterable":["MapEntry<1,2>"],"Iterable.E":"MapEntry<1,2>"},"LinkedHashMapEntryIterator":{"Iterator":["MapEntry<1,2>"]},"JsIdentityLinkedHashMap":{"JsLinkedHashMap":["1","2"],"MapBase":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_Record2":{"_Record":[]},"JSSyntaxRegExp":{"RegExp":[],"Pattern":[]},"_MatchImplementation":{"RegExpMatch":[],"Match":[]},"_AllMatchesIterable":{"Iterable":["RegExpMatch"],"Iterable.E":"RegExpMatch"},"_AllMatchesIterator":{"Iterator":["RegExpMatch"]},"StringMatch":{"Match":[]},"_StringAllMatchesIterable":{"Iterable":["Match"],"Iterable.E":"Match"},"_StringAllMatchesIterator":{"Iterator":["Match"]},"NativeByteBuffer":{"JavaScriptObject":[],"JSObject":[],"ByteBuffer":[],"TrustedGetRuntimeType":[]},"NativeTypedData":{"JavaScriptObject":[],"JSObject":[]},"_UnmodifiableNativeByteBufferView":{"ByteBuffer":[]},"NativeByteData":{"JavaScriptObject":[],"ByteData":[],"JSObject":[],"TrustedGetRuntimeType":[]},"NativeTypedArray":{"JavaScriptIndexingBehavior":["1"],"JavaScriptObject":[],"JSObject":[],"JSIndexable":["1"]},"NativeTypedArrayOfDouble":{"ListBase":["double"],"NativeTypedArray":["double"],"List":["double"],"JavaScriptIndexingBehavior":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"JSObject":[],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"]},"NativeTypedArrayOfInt":{"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"]},"NativeFloat32List":{"Float32List":[],"ListBase":["double"],"NativeTypedArray":["double"],"List":["double"],"JavaScriptIndexingBehavior":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"JSObject":[],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"TrustedGetRuntimeType":[],"ListBase.E":"double","Iterable.E":"double","FixedLengthListMixin.E":"double"},"NativeFloat64List":{"Float64List":[],"ListBase":["double"],"NativeTypedArray":["double"],"List":["double"],"JavaScriptIndexingBehavior":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"JSObject":[],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"TrustedGetRuntimeType":[],"ListBase.E":"double","Iterable.E":"double","FixedLengthListMixin.E":"double"},"NativeInt16List":{"NativeTypedArrayOfInt":[],"Int16List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeInt32List":{"NativeTypedArrayOfInt":[],"Int32List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeInt8List":{"NativeTypedArrayOfInt":[],"Int8List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint16List":{"NativeTypedArrayOfInt":[],"Uint16List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint32List":{"NativeTypedArrayOfInt":[],"Uint32List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint8ClampedList":{"NativeTypedArrayOfInt":[],"Uint8ClampedList":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"NativeUint8List":{"NativeTypedArrayOfInt":[],"Uint8List":[],"ListBase":["int"],"NativeTypedArray":["int"],"List":["int"],"JavaScriptIndexingBehavior":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"JSObject":[],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int","Iterable.E":"int","FixedLengthListMixin.E":"int"},"_Type":{"Type":[]},"_Error":{"Error":[]},"_TypeError":{"TypeError":[],"Error":[]},"AsyncError":{"Error":[]},"_TimerImpl":{"Timer":[]},"_AsyncAwaitCompleter":{"Completer":["1"]},"_Completer":{"Completer":["1"]},"_AsyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_SyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_Future":{"Future":["1"]},"StreamView":{"Stream":["1"]},"_StreamController":{"StreamController":["1"],"StreamSink":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_AsyncStreamController":{"_AsyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_SyncStreamController":{"_SyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_ControllerStream":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_ControllerSubscription":{"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamSinkWrapper":{"StreamSink":["1"]},"_BufferingStreamSubscription":{"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamImpl":{"Stream":["1"]},"_DelayedData":{"_DelayedEvent":["1"]},"_DelayedError":{"_DelayedEvent":["@"]},"_DelayedDone":{"_DelayedEvent":["@"]},"_DoneStreamSubscription":{"StreamSubscription":["1"]},"_EmptyStream":{"Stream":["1"],"Stream.T":"1"},"_ForwardingStream":{"Stream":["2"]},"_ForwardingStreamSubscription":{"_BufferingStreamSubscription":["2"],"StreamSubscription":["2"],"_EventSink":["2"],"_EventDispatch":["2"],"_BufferingStreamSubscription.T":"2"},"_MapStream":{"_ForwardingStream":["1","2"],"Stream":["2"],"Stream.T":"2"},"_ZoneSpecification":{"ZoneSpecification":[]},"_ZoneDelegate":{"ZoneDelegate":[]},"_Zone":{"Zone":[]},"_CustomZone":{"_Zone":[],"Zone":[]},"_RootZone":{"_Zone":[],"Zone":[]},"_SplayTreeSetNode":{"_SplayTreeNode":["1","_SplayTreeSetNode<1>"],"_SplayTreeNode.K":"1","_SplayTreeNode.1":"_SplayTreeSetNode<1>"},"_HashMap":{"MapBase":["1","2"],"HashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_IdentityHashMap":{"_HashMap":["1","2"],"MapBase":["1","2"],"HashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_CustomHashMap":{"_HashMap":["1","2"],"MapBase":["1","2"],"HashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_HashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_HashMapKeyIterator":{"Iterator":["1"]},"_LinkedCustomHashMap":{"JsLinkedHashMap":["1","2"],"MapBase":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_HashSet":{"_SetBase":["1"],"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_HashSetIterator":{"Iterator":["1"]},"_LinkedHashSet":{"_SetBase":["1"],"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_LinkedHashSetIterator":{"Iterator":["1"]},"UnmodifiableListView":{"ListBase":["1"],"UnmodifiableListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListBase.E":"1","Iterable.E":"1","UnmodifiableListMixin.E":"1"},"ListBase":{"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"MapBase":{"Map":["1","2"]},"MapView":{"Map":["1","2"]},"UnmodifiableMapView":{"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ListQueue":{"Queue":["1"],"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"_ListQueueIterator":{"Iterator":["1"]},"SetBase":{"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_SetBase":{"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_SplayTreeIterator":{"Iterator":["3"]},"_SplayTreeKeyIterator":{"_SplayTreeIterator":["1","2","1"],"Iterator":["1"],"_SplayTreeIterator.K":"1","_SplayTreeIterator.T":"1","_SplayTreeIterator.1":"2"},"SplayTreeSet":{"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"_SplayTree":["1","_SplayTreeSetNode<1>"],"Iterable":["1"],"Iterable.E":"1","_SplayTree.1":"_SplayTreeSetNode<1>","_SplayTree.K":"1"},"Encoding":{"Codec":["String","List"]},"_JsonMap":{"MapBase":["String","@"],"Map":["String","@"],"MapBase.K":"String","MapBase.V":"@"},"_JsonMapKeyIterable":{"ListIterable":["String"],"EfficientLengthIterable":["String"],"Iterable":["String"],"ListIterable.E":"String","Iterable.E":"String"},"AsciiCodec":{"Encoding":[],"Codec":["String","List"],"Codec.S":"String"},"_UnicodeSubsetEncoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"AsciiEncoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"_UnicodeSubsetDecoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"AsciiDecoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"Base64Codec":{"Codec":["List","String"],"Codec.S":"List"},"Base64Encoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"Base64Decoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"Converter":{"StreamTransformer":["1","2"]},"JsonUnsupportedObjectError":{"Error":[]},"JsonCyclicError":{"Error":[]},"JsonCodec":{"Codec":["Object?","String"],"Codec.S":"Object?"},"JsonEncoder":{"Converter":["Object?","String"],"StreamTransformer":["Object?","String"]},"JsonDecoder":{"Converter":["String","Object?"],"StreamTransformer":["String","Object?"]},"Latin1Codec":{"Encoding":[],"Codec":["String","List"],"Codec.S":"String"},"Latin1Encoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"Latin1Decoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"Utf8Codec":{"Encoding":[],"Codec":["String","List"],"Codec.S":"String"},"Utf8Encoder":{"Converter":["String","List"],"StreamTransformer":["String","List"]},"Utf8Decoder":{"Converter":["List","String"],"StreamTransformer":["List","String"]},"BigInt":{"Comparable":["BigInt"]},"DateTime":{"Comparable":["DateTime"]},"double":{"num":[],"Comparable":["num"]},"Duration":{"Comparable":["Duration"]},"int":{"num":[],"Comparable":["num"]},"List":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"num":{"Comparable":["num"]},"RegExp":{"Pattern":[]},"RegExpMatch":{"Match":[]},"Set":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"String":{"Comparable":["String"],"Pattern":[]},"_BigIntImpl":{"BigInt":[],"Comparable":["BigInt"]},"AssertionError":{"Error":[]},"TypeError":{"Error":[]},"ArgumentError":{"Error":[]},"RangeError":{"Error":[]},"IndexError":{"Error":[]},"UnsupportedError":{"Error":[]},"UnimplementedError":{"Error":[]},"StateError":{"Error":[]},"ConcurrentModificationError":{"Error":[]},"OutOfMemoryError":{"Error":[]},"StackOverflowError":{"Error":[]},"_Exception":{"Exception":[]},"FormatException":{"Exception":[]},"IntegerDivisionByZeroException":{"Exception":[],"Error":[]},"_StringStackTrace":{"StackTrace":[]},"StringBuffer":{"StringSink":[]},"_Uri":{"Uri":[]},"_SimpleUri":{"Uri":[]},"_DataUri":{"Uri":[]},"NullRejectionException":{"Exception":[]},"DelegatingStreamSink":{"StreamSink":["1"]},"ErrorResult":{"Result":["0&"]},"ValueResult":{"Result":["1"]},"_NextRequest":{"_EventRequest":["1"]},"_HasNextRequest":{"_EventRequest":["1"]},"BuiltList":{"Iterable":["1"]},"_BuiltList":{"BuiltList":["1"],"Iterable":["1"],"Iterable.E":"1"},"_BuiltListMultimap":{"BuiltListMultimap":["1","2"]},"_BuiltMap":{"BuiltMap":["1","2"]},"BuiltSet":{"Iterable":["1"]},"_BuiltSet":{"BuiltSet":["1"],"Iterable":["1"],"Iterable.E":"1"},"_BuiltSetMultimap":{"BuiltSetMultimap":["1","2"]},"BuiltValueNullFieldError":{"Error":[]},"BuiltValueNestedFieldError":{"Error":[]},"BoolJsonObject":{"JsonObject":[]},"ListJsonObject":{"JsonObject":[]},"MapJsonObject":{"JsonObject":[]},"NumJsonObject":{"JsonObject":[]},"StringJsonObject":{"JsonObject":[]},"DeserializationError":{"Error":[]},"BigIntSerializer":{"PrimitiveSerializer":["BigInt"],"Serializer":["BigInt"]},"BoolSerializer":{"PrimitiveSerializer":["bool"],"Serializer":["bool"]},"BuiltJsonSerializers":{"Serializers":[]},"BuiltListMultimapSerializer":{"StructuredSerializer":["BuiltListMultimap<@,@>"],"Serializer":["BuiltListMultimap<@,@>"]},"BuiltListSerializer":{"StructuredSerializer":["BuiltList<@>"],"Serializer":["BuiltList<@>"]},"BuiltMapSerializer":{"StructuredSerializer":["BuiltMap<@,@>"],"Serializer":["BuiltMap<@,@>"]},"BuiltSetMultimapSerializer":{"StructuredSerializer":["BuiltSetMultimap<@,@>"],"Serializer":["BuiltSetMultimap<@,@>"]},"BuiltSetSerializer":{"StructuredSerializer":["BuiltSet<@>"],"Serializer":["BuiltSet<@>"]},"DateTimeSerializer":{"PrimitiveSerializer":["DateTime"],"Serializer":["DateTime"]},"DoubleSerializer":{"PrimitiveSerializer":["double"],"Serializer":["double"]},"DurationSerializer":{"PrimitiveSerializer":["Duration"],"Serializer":["Duration"]},"Int32Serializer":{"PrimitiveSerializer":["Int32"],"Serializer":["Int32"]},"Int64Serializer":{"PrimitiveSerializer":["Int64"],"Serializer":["Int64"]},"IntSerializer":{"PrimitiveSerializer":["int"],"Serializer":["int"]},"JsonObjectSerializer":{"PrimitiveSerializer":["JsonObject"],"Serializer":["JsonObject"]},"NullSerializer":{"PrimitiveSerializer":["Null"],"Serializer":["Null"]},"NumSerializer":{"PrimitiveSerializer":["num"],"Serializer":["num"]},"RegExpSerializer":{"PrimitiveSerializer":["RegExp"],"Serializer":["RegExp"]},"StringSerializer":{"PrimitiveSerializer":["String"],"Serializer":["String"]},"Uint8ListSerializer":{"PrimitiveSerializer":["Uint8List"],"Serializer":["Uint8List"]},"UriSerializer":{"PrimitiveSerializer":["Uri"],"Serializer":["Uri"]},"CanonicalizedMap":{"Map":["2","3"]},"DefaultEquality":{"Equality":["1"]},"IterableEquality":{"Equality":["Iterable<1>"]},"ListEquality":{"Equality":["List<1>"]},"_UnorderedEquality":{"Equality":["2"]},"SetEquality":{"_UnorderedEquality":["1","Set<1>"],"Equality":["Set<1>"],"_UnorderedEquality.E":"1","_UnorderedEquality.T":"Set<1>"},"MapEquality":{"Equality":["Map<1,2>"]},"DeepCollectionEquality":{"Equality":["@"]},"QueueList":{"ListBase":["1"],"List":["1"],"Queue":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListBase.E":"1","QueueList.E":"1","Iterable.E":"1"},"_CastQueueList":{"QueueList":["2"],"ListBase":["2"],"List":["2"],"Queue":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListBase.E":"2","QueueList.E":"2","Iterable.E":"2"},"_$BuildStatusSerializer":{"PrimitiveSerializer":["BuildStatus"],"Serializer":["BuildStatus"]},"_$BuildResultSerializer":{"StructuredSerializer":["BuildResult"],"Serializer":["BuildResult"]},"_$BuildResult":{"BuildResult":[]},"_$ConnectRequestSerializer":{"StructuredSerializer":["ConnectRequest"],"Serializer":["ConnectRequest"]},"_$ConnectRequest":{"ConnectRequest":[]},"_$DebugEventSerializer":{"StructuredSerializer":["DebugEvent"],"Serializer":["DebugEvent"]},"_$BatchedDebugEventsSerializer":{"StructuredSerializer":["BatchedDebugEvents"],"Serializer":["BatchedDebugEvents"]},"_$DebugEvent":{"DebugEvent":[]},"_$BatchedDebugEvents":{"BatchedDebugEvents":[]},"_$DebugInfoSerializer":{"StructuredSerializer":["DebugInfo"],"Serializer":["DebugInfo"]},"_$DebugInfo":{"DebugInfo":[]},"_$DevToolsRequestSerializer":{"StructuredSerializer":["DevToolsRequest"],"Serializer":["DevToolsRequest"]},"_$DevToolsResponseSerializer":{"StructuredSerializer":["DevToolsResponse"],"Serializer":["DevToolsResponse"]},"_$DevToolsRequest":{"DevToolsRequest":[]},"_$DevToolsResponse":{"DevToolsResponse":[]},"_$ErrorResponseSerializer":{"StructuredSerializer":["ErrorResponse"],"Serializer":["ErrorResponse"]},"_$ErrorResponse":{"ErrorResponse":[]},"_$ExtensionRequestSerializer":{"StructuredSerializer":["ExtensionRequest"],"Serializer":["ExtensionRequest"]},"_$ExtensionResponseSerializer":{"StructuredSerializer":["ExtensionResponse"],"Serializer":["ExtensionResponse"]},"_$ExtensionEventSerializer":{"StructuredSerializer":["ExtensionEvent"],"Serializer":["ExtensionEvent"]},"_$BatchedEventsSerializer":{"StructuredSerializer":["BatchedEvents"],"Serializer":["BatchedEvents"]},"_$ExtensionRequest":{"ExtensionRequest":[]},"_$ExtensionResponse":{"ExtensionResponse":[]},"_$ExtensionEvent":{"ExtensionEvent":[]},"_$BatchedEvents":{"BatchedEvents":[]},"_$HotReloadRequestSerializer":{"StructuredSerializer":["HotReloadRequest"],"Serializer":["HotReloadRequest"]},"_$HotReloadRequest":{"HotReloadRequest":[]},"_$HotReloadResponseSerializer":{"StructuredSerializer":["HotReloadResponse"],"Serializer":["HotReloadResponse"]},"_$HotReloadResponse":{"HotReloadResponse":[]},"_$IsolateExitSerializer":{"StructuredSerializer":["IsolateExit"],"Serializer":["IsolateExit"]},"_$IsolateStartSerializer":{"StructuredSerializer":["IsolateStart"],"Serializer":["IsolateStart"]},"_$IsolateExit":{"IsolateExit":[]},"_$IsolateStart":{"IsolateStart":[]},"_$RegisterEventSerializer":{"StructuredSerializer":["RegisterEvent"],"Serializer":["RegisterEvent"]},"_$RegisterEvent":{"RegisterEvent":[]},"_$RunRequestSerializer":{"StructuredSerializer":["RunRequest"],"Serializer":["RunRequest"]},"_$RunRequest":{"RunRequest":[]},"_$ServiceExtensionRequestSerializer":{"StructuredSerializer":["ServiceExtensionRequest"],"Serializer":["ServiceExtensionRequest"]},"_$ServiceExtensionRequest":{"ServiceExtensionRequest":[]},"_$ServiceExtensionResponseSerializer":{"StructuredSerializer":["ServiceExtensionResponse"],"Serializer":["ServiceExtensionResponse"]},"_$ServiceExtensionResponse":{"ServiceExtensionResponse":[]},"SseSocketClient":{"SocketClient":[]},"WebSocketClient":{"SocketClient":[]},"Int32":{"Comparable":["Object"]},"Int64":{"Comparable":["Object"]},"ByteStream":{"StreamView":["List"],"Stream":["List"],"Stream.T":"List","StreamView.T":"List"},"ClientException":{"Exception":[]},"Request":{"BaseRequest":[]},"StreamedResponseV2":{"StreamedResponse":[]},"CaseInsensitiveMap":{"CanonicalizedMap":["String","String","1"],"Map":["String","1"],"CanonicalizedMap.K":"String","CanonicalizedMap.V":"1","CanonicalizedMap.C":"String"},"Level":{"Comparable":["Level"]},"PathException":{"Exception":[]},"PosixStyle":{"InternalStyle":[]},"UrlStyle":{"InternalStyle":[]},"WindowsStyle":{"InternalStyle":[]},"FileLocation":{"SourceLocation":[],"Comparable":["SourceLocation"]},"_FileSpan":{"SourceSpanWithContext":[],"SourceSpan":[],"Comparable":["SourceSpan"]},"SourceLocation":{"Comparable":["SourceLocation"]},"SourceLocationMixin":{"SourceLocation":[],"Comparable":["SourceLocation"]},"SourceSpan":{"Comparable":["SourceSpan"]},"SourceSpanBase":{"SourceSpan":[],"Comparable":["SourceSpan"]},"SourceSpanException":{"Exception":[]},"SourceSpanFormatException":{"FormatException":[],"Exception":[]},"SourceSpanMixin":{"SourceSpan":[],"Comparable":["SourceSpan"]},"SourceSpanWithContext":{"SourceSpan":[],"Comparable":["SourceSpan"]},"SseClient":{"StreamChannel":["String?"]},"GuaranteeChannel":{"StreamChannel":["1"]},"_GuaranteeSink":{"StreamSink":["1"]},"StreamChannelMixin":{"StreamChannel":["1"]},"StringScannerException":{"FormatException":[],"Exception":[]},"_EventStream":{"Stream":["1"],"Stream.T":"1"},"_EventStreamSubscription":{"StreamSubscription":["1"]},"BrowserWebSocket":{"WebSocket":[]},"TextDataReceived":{"WebSocketEvent":[]},"BinaryDataReceived":{"WebSocketEvent":[]},"CloseReceived":{"WebSocketEvent":[]},"WebSocketException":{"Exception":[]},"WebSocketConnectionClosed":{"Exception":[]},"AdapterWebSocketChannel":{"WebSocketChannel":[],"StreamChannel":["@"]},"_WebSocketSink":{"WebSocketSink":[],"DelegatingStreamSink":["@"],"StreamSink":["@"],"DelegatingStreamSink.T":"@"},"WebSocketChannelException":{"Exception":[]},"DdcLibraryBundleRestarter":{"Restarter":[]},"DdcRestarter":{"Restarter":[]},"RequireRestarter":{"Restarter":[]},"HotReloadFailedException":{"Exception":[]},"Int8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8ClampedList":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Float32List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"Float64List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]}}')); A._Universe_addErasedTypes(init.typeUniverse, JSON.parse('{"UnmodifiableListBase":1,"__CastListBase__CastIterableBase_ListMixin":2,"NativeTypedArray":1,"_DelayedEvent":1,"_SplayTreeSet__SplayTree_Iterable":1,"_SplayTreeSet__SplayTree_Iterable_SetMixin":1,"_QueueList_Object_ListMixin":1,"StreamChannelMixin":1}')); var string$ = { x00_____: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\u03f6\x00\u0404\u03f4 \u03f4\u03f6\u01f6\u01f6\u03f6\u03fc\u01f4\u03ff\u03ff\u0584\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u05d4\u01f4\x00\u01f4\x00\u0504\u05c4\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u0400\x00\u0400\u0200\u03f7\u0200\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u03ff\u0200\u0200\u0200\u03f7\x00", @@ -28250,6 +28794,7 @@ MapEntry_of_Object_and_List__Highlight: findType("MapEntry>"), MapEquality_dynamic_dynamic: findType("MapEquality<@,@>"), Map_String_String: findType("Map"), + Map_String_dynamic: findType("Map"), Map_dynamic_dynamic: findType("Map<@,@>"), Map_of_String_and_nullable_Object: findType("Map"), MappedListIterable_String_dynamic: findType("MappedListIterable"), @@ -28273,6 +28818,8 @@ RunRequest: findType("RunRequest"), SerializerPlugin: findType("SerializerPlugin"), Serializer_dynamic: findType("Serializer<@>"), + ServiceExtensionRequest: findType("ServiceExtensionRequest"), + ServiceExtensionResponse: findType("ServiceExtensionResponse"), SetBuilder_dynamic: findType("SetBuilder<@>"), SetEquality_dynamic: findType("SetEquality<@>"), SetMultimapBuilder_dynamic_dynamic: findType("SetMultimapBuilder<@,@>"), @@ -28349,6 +28896,7 @@ nullable_ListBuilder_DebugEvent: findType("ListBuilder?"), nullable_ListBuilder_ExtensionEvent: findType("ListBuilder?"), nullable_List_dynamic: findType("List<@>?"), + nullable_Map_String_dynamic: findType("Map?"), nullable_Map_of_nullable_Object_and_nullable_Object: findType("Map?"), nullable_Object: findType("Object?"), nullable_Result_DebugEvent: findType("Result?"), @@ -28375,6 +28923,7 @@ nullable_void_Function_HotReloadResponseBuilder: findType("~(HotReloadResponseBuilder)?"), nullable_void_Function_JSObject: findType("~(JSObject)?"), nullable_void_Function_RegisterEventBuilder: findType("~(RegisterEventBuilder)?"), + nullable_void_Function_ServiceExtensionResponseBuilder: findType("~(ServiceExtensionResponseBuilder)?"), num: findType("num"), void: findType("~"), void_Function: findType("~()"), @@ -28595,12 +29144,18 @@ B.Type_ExtensionRequest_9GR = A.typeLiteral("ExtensionRequest"); B.Type__$ExtensionRequest_o1C = A.typeLiteral("_$ExtensionRequest"); B.List_2dD = A._setArrayType(makeConstList([B.Type_ExtensionRequest_9GR, B.Type__$ExtensionRequest_o1C]), type$.JSArray_Type); + B.Type_ServiceExtensionRequest_K8g = A.typeLiteral("ServiceExtensionRequest"); + B.Type__$ServiceExtensionRequest_n9i = A.typeLiteral("_$ServiceExtensionRequest"); + B.List_4i4 = A._setArrayType(makeConstList([B.Type_ServiceExtensionRequest_K8g, B.Type__$ServiceExtensionRequest_n9i]), type$.JSArray_Type); B.Type_DebugInfo_ua9 = A.typeLiteral("DebugInfo"); B.Type__$DebugInfo_ywz = A.typeLiteral("_$DebugInfo"); B.List_55I = A._setArrayType(makeConstList([B.Type_DebugInfo_ua9, B.Type__$DebugInfo_ywz]), type$.JSArray_Type); B.Type_ErrorResponse_WMn = A.typeLiteral("ErrorResponse"); B.Type__$ErrorResponse_9Ps = A.typeLiteral("_$ErrorResponse"); B.List_5LV = A._setArrayType(makeConstList([B.Type_ErrorResponse_WMn, B.Type__$ErrorResponse_9Ps]), type$.JSArray_Type); + B.Type_ServiceExtensionResponse_84R = A.typeLiteral("ServiceExtensionResponse"); + B.Type__$ServiceExtensionResponse_UiR = A.typeLiteral("_$ServiceExtensionResponse"); + B.List_5rA = A._setArrayType(makeConstList([B.Type_ServiceExtensionResponse_84R, B.Type__$ServiceExtensionResponse_UiR]), type$.JSArray_Type); B.Type_HotReloadResponse_Gqc = A.typeLiteral("HotReloadResponse"); B.Type__$HotReloadResponse_56g = A.typeLiteral("_$HotReloadResponse"); B.List_DqJ = A._setArrayType(makeConstList([B.Type_HotReloadResponse_Gqc, B.Type__$HotReloadResponse_56g]), type$.JSArray_Type); @@ -28857,10 +29412,14 @@ t1.add$1(0, $.$get$_$isolateStartSerializer()); t1.add$1(0, $.$get$_$registerEventSerializer()); t1.add$1(0, $.$get$_$runRequestSerializer()); + t1.add$1(0, $.$get$_$serviceExtensionRequestSerializer()); + t1.add$1(0, $.$get$_$serviceExtensionResponseSerializer()); t1.addBuilderFactory$2(B.FullType_3Xm, new A._$serializers_closure()); t1.addBuilderFactory$2(B.FullType_ahP, new A._$serializers_closure0()); return t1.build$0(); }); + _lazy($, "_$serviceExtensionRequestSerializer", "$get$_$serviceExtensionRequestSerializer", () => new A._$ServiceExtensionRequestSerializer()); + _lazy($, "_$serviceExtensionResponseSerializer", "$get$_$serviceExtensionResponseSerializer", () => new A._$ServiceExtensionResponseSerializer()); _lazyFinal($, "_logger", "$get$_logger", () => A.Logger_Logger("Utilities")); _lazyFinal($, "BaseRequest__tokenRE", "$get$BaseRequest__tokenRE", () => A.RegExp_RegExp("^[\\w!#%&'*+\\-.^`|~]+$", true, false)); _lazyFinal($, "_digitRegex", "$get$_digitRegex", () => A.RegExp_RegExp("^\\d+$", true, false)); diff --git a/dwds/lib/src/services/app_debug_services.dart b/dwds/lib/src/services/app_debug_services.dart index fb9d18667..3b5440164 100644 --- a/dwds/lib/src/services/app_debug_services.dart +++ b/dwds/lib/src/services/app_debug_services.dart @@ -8,33 +8,62 @@ import 'package:dwds/src/services/chrome_proxy_service.dart' show ChromeProxyService; import 'package:dwds/src/services/debug_service.dart'; -/// A container for all the services required for debugging an application. -class AppDebugServices { - final DebugService debugService; - final DwdsVmClient dwdsVmClient; - final DwdsStats dwdsStats; - final Uri? ddsUri; - - ChromeProxyService get chromeProxyService => - debugService.chromeProxyService as ChromeProxyService; +/// Common interface for debug service containers. +abstract class IAppDebugServices { + dynamic get debugService; + dynamic get dwdsVmClient; + dynamic get dwdsStats; + Uri? get ddsUri; + String? get connectedInstanceId; + set connectedInstanceId(String? id); + Future close(); + dynamic get chromeProxyService; + dynamic get webSocketProxyService; +} - /// Null until [close] is called. - /// - /// All subsequent calls to [close] will return this future. +/// Chrome-based debug services container. +class AppDebugServices implements IAppDebugServices { + final DebugService _debugService; + final DwdsVmClient _dwdsVmClient; + final DwdsStats _dwdsStats; + final Uri? _ddsUri; Future? _closed; - - /// The instance ID for the currently connected application, if there is one. - /// - /// We only allow a given app to be debugged in a single tab at a time. - String? connectedInstanceId; + String? _connectedInstanceId; AppDebugServices( - this.debugService, - this.dwdsVmClient, - this.dwdsStats, - this.ddsUri, + this._debugService, + this._dwdsVmClient, + this._dwdsStats, + this._ddsUri, ); + @override + DebugService get debugService => _debugService; + + @override + DwdsVmClient get dwdsVmClient => _dwdsVmClient; + + @override + DwdsStats get dwdsStats => _dwdsStats; + + @override + Uri? get ddsUri => _ddsUri; + + @override + String? get connectedInstanceId => _connectedInstanceId; + + @override + set connectedInstanceId(String? id) => _connectedInstanceId = id; + + @override + ChromeProxyService get chromeProxyService => + debugService.chromeProxyService as ChromeProxyService; + + // WebSocket functionality not available in Chrome-based service + @override + dynamic get webSocketProxyService => null; + + @override Future close() => _closed ??= Future.wait([debugService.close(), dwdsVmClient.close()]); } diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 3141d2c57..045c3e9bf 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -7,8 +7,6 @@ import 'dart:convert'; import 'dart:io'; import 'package:dwds/data/debug_event.dart'; -import 'package:dwds/data/hot_reload_request.dart'; -import 'package:dwds/data/hot_reload_response.dart'; import 'package:dwds/data/register_event.dart'; import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/connections/app_connection.dart'; @@ -34,13 +32,8 @@ import 'package:vm_service/vm_service.dart' hide vmServiceVersion; import 'package:vm_service_interface/vm_service_interface.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -/// Defines callbacks for sending messages to the connected client application. -typedef SendClientRequest = void Function(Object request); - /// A proxy from the chrome debug protocol to the dart vm service protocol. class ChromeProxyService implements VmServiceInterface { - final bool useWebSocket; - /// Cache of all existing StreamControllers. /// /// These are all created through [onEvent]. @@ -134,12 +127,6 @@ class ChromeProxyService implements VmServiceInterface { bool terminatingIsolates = false; - /// Callback function to send messages to the connected client application. - final SendClientRequest sendClientRequest; - - /// Pending hot reload request waiting for a response from the client. - Completer? _pendingHotReload; - ChromeProxyService._( this._vm, this.root, @@ -150,9 +137,7 @@ class ChromeProxyService implements VmServiceInterface { this._skipLists, this.executionContext, this._compiler, - this.sendClientRequest, { - this.useWebSocket = false, - }) { + ) { final debugger = Debugger.create( remoteDebugger, _streamNotify, @@ -170,9 +155,7 @@ class ChromeProxyService implements VmServiceInterface { AppConnection appConnection, ExecutionContext executionContext, ExpressionCompiler? expressionCompiler, - SendClientRequest sendClientRequest, { - bool useWebSocket = false, - }) async { + ) async { final vm = VM( name: 'ChromeDebugProxy', operatingSystem: Platform.operatingSystem, @@ -201,32 +184,11 @@ class ChromeProxyService implements VmServiceInterface { skipLists, executionContext, expressionCompiler, - sendClientRequest, - useWebSocket: useWebSocket, ); safeUnawaited(service.createIsolate(appConnection, newConnection: true)); return service; } - /// Completes the hot reload completer associated with the response ID. - void completeHotReload(HotReloadResponse response) { - final completer = _pendingHotReload; - _pendingHotReload = null; - if (completer != null) { - if (response.success) { - completer.complete(response); - } else { - completer.completeError( - response.errorMessage ?? 'Unknown client error during hot reload', - ); - } - } else { - _logger.warning( - 'Received hot reload response but no pending completer was found (id: ${response.id})', - ); - } - } - /// Initializes metadata in [Locations], [Modules], and [ExpressionCompiler]. void _initializeEntrypoint(String entrypoint) { _locations.initialize(entrypoint); @@ -1169,11 +1131,7 @@ class ChromeProxyService implements VmServiceInterface { ], }; try { - if (useWebSocket) { - await _performWebSocketHotReload(); - } else { - await _performClientSideHotReload(); - } + await _performClientSideHotReload(); } catch (e) { _logger.info('Hot reload failed: $e'); return getFailedReloadReport(e.toString()); @@ -1204,37 +1162,6 @@ class ChromeProxyService implements VmServiceInterface { _logger.info('\$dartHotReloadDwds request complete.'); } - /// Performs a WebSocket-based hot reload by sending a request and waiting for a response. - /// If [requestId] is provided, it will be used for the request; otherwise, a new one is generated. - Future _performWebSocketHotReload({String? requestId}) async { - final id = requestId ?? createId(); - if (_pendingHotReload != null) { - throw StateError('A hot reload is already pending.'); - } - final completer = Completer(); - _pendingHotReload = completer; - const timeout = Duration(seconds: 10); - - _logger.info('Issuing HotReloadRequest with ID ($id) to client.'); - sendClientRequest(HotReloadRequest((b) => b.id = id)); - - final response = await completer.future.timeout( - timeout, - onTimeout: - () => - throw TimeoutException( - 'Client did not respond to hot reload request', - timeout, - ), - ); - - if (!response.success) { - throw Exception( - response.errorMessage ?? 'Client reported hot reload failure.', - ); - } - } - @override Future removeBreakpoint(String isolateId, String breakpointId) => wrapInErrorHandlerAsync( diff --git a/dwds/lib/src/services/debug_service.dart b/dwds/lib/src/services/debug_service.dart index ac90a0e17..34202ad09 100644 --- a/dwds/lib/src/services/debug_service.dart +++ b/dwds/lib/src/services/debug_service.dart @@ -231,7 +231,6 @@ class DebugService { int? ddsPort, bool useSse = false, ExpressionCompiler? expressionCompiler, - required SendClientRequest sendClientRequest, }) async { final root = assetReader.basePath; final chromeProxyService = await ChromeProxyService.create( @@ -241,7 +240,6 @@ class DebugService { appConnection, executionContext, expressionCompiler, - sendClientRequest, ); final authToken = _makeAuthToken(); final serviceExtensionRegistry = ServiceExtensionRegistry(); diff --git a/dwds/lib/src/services/web_socket_app_debug_services.dart b/dwds/lib/src/services/web_socket_app_debug_services.dart new file mode 100644 index 000000000..4d8539238 --- /dev/null +++ b/dwds/lib/src/services/web_socket_app_debug_services.dart @@ -0,0 +1,53 @@ +// Copyright (c) 2025, 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 'package:dwds/src/services/app_debug_services.dart'; +import 'package:dwds/src/services/web_socket_debug_service.dart'; +import 'package:dwds/src/web_socket_dwds_vm_client.dart'; + +/// WebSocket-based implementation of app debug services. +/// +/// Provides debugging capabilities without Chrome dependencies. +class WebSocketAppDebugServices implements IAppDebugServices { + final WebSocketDebugService _debugService; + final WebSocketDwdsVmClient _dwdsVmClient; + Future? _closed; + String? _connectedInstanceId; + + WebSocketAppDebugServices(this._debugService, this._dwdsVmClient); + + @override + WebSocketDebugService get debugService => _debugService; + + @override + WebSocketDwdsVmClient get dwdsVmClient => _dwdsVmClient; + + @override + String? get connectedInstanceId => _connectedInstanceId; + + @override + set connectedInstanceId(String? id) => _connectedInstanceId = id; + + // WebSocket-only service - Chrome/DDS features not available + @override + dynamic get dwdsStats => null; + @override + Uri? get ddsUri => null; + @override + dynamic get chromeProxyService => + throw UnsupportedError( + 'Chrome proxy service not available in WebSocket-only mode', + ); + + @override + dynamic get webSocketProxyService => _debugService.webSocketProxyService; + @override + Future close() { + return _closed ??= Future.wait([ + debugService.close(), + dwdsVmClient.close(), + ]); + } +} diff --git a/dwds/lib/src/services/web_socket_debug_service.dart b/dwds/lib/src/services/web_socket_debug_service.dart new file mode 100644 index 000000000..3a3b403ab --- /dev/null +++ b/dwds/lib/src/services/web_socket_debug_service.dart @@ -0,0 +1,178 @@ +// Copyright (c) 2025, 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:convert'; +import 'dart:io'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:dds/dds_launcher.dart'; +import 'package:dwds/src/connections/app_connection.dart'; + +import 'package:dwds/src/services/web_socket_proxy_service.dart'; +import 'package:dwds/src/utilities/server.dart'; +import 'package:logging/logging.dart'; +import 'package:shelf_web_socket/shelf_web_socket.dart'; +import 'package:vm_service_interface/vm_service_interface.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; + +/// Defines callbacks for sending messages to the connected client. +typedef SendClientRequest = void Function(Object request); + +// Connection control for WebSocket clients +bool _acceptNewConnections = true; +int _clientsConnected = 0; + +/// WebSocket-based debug service for web debugging. +/// +/// Provides hot reload and service extension support without Chrome dependencies. +class WebSocketDebugService { + final String hostname; + final int port; + final String authToken; + final HttpServer _server; + final WebSocketProxyService _webSocketProxyService; + final ServiceExtensionRegistry _serviceExtensionRegistry; + + Future? _closed; + DartDevelopmentServiceLauncher? _dds; + + WebSocketDebugService._( + this.hostname, + this.port, + this.authToken, + this._webSocketProxyService, + this._serviceExtensionRegistry, + this._server, + ); + + /// Returns the WebSocketProxyService instance. + WebSocketProxyService get webSocketProxyService => _webSocketProxyService; + + /// Returns the ServiceExtensionRegistry instance. + ServiceExtensionRegistry get serviceExtensionRegistry => + _serviceExtensionRegistry; + + /// Closes the debug service and associated resources. + Future close() => + _closed ??= Future.wait([ + _server.close(), + if (_dds != null) _dds!.shutdown(), + ]); + + /// Starts DDS (Dart Development Service). + Future startDartDevelopmentService({ + int? ddsPort, + }) async { + const timeout = Duration(seconds: 10); + + try { + _dds = await DartDevelopmentServiceLauncher.start( + remoteVmServiceUri: Uri( + scheme: 'http', + host: hostname, + port: port, + path: authToken, + ), + serviceUri: Uri(scheme: 'http', host: hostname, port: ddsPort ?? 0), + ).timeout(timeout); + } catch (e) { + throw Exception('Failed to start DDS: $e'); + } + return _dds!; + } + + String get uri => + Uri(scheme: 'ws', host: hostname, port: port, path: authToken).toString(); + + static Future start( + String hostname, + AppConnection appConnection, { + required SendClientRequest sendClientRequest, + }) async { + final authToken = _makeAuthToken(); + final serviceExtensionRegistry = ServiceExtensionRegistry(); + + final webSocketProxyService = await WebSocketProxyService.create( + sendClientRequest, + appConnection, + ); + + final handler = _createWebSocketHandler( + serviceExtensionRegistry, + webSocketProxyService, + ); + + final server = await startHttpServer(hostname, port: 0); + serveHttpRequests(server, handler, (e, s) { + Logger('WebSocketDebugService').warning('Error serving requests', e); + }); + + return WebSocketDebugService._( + server.address.host, + server.port, + authToken, + webSocketProxyService, + serviceExtensionRegistry, + server, + ); + } + + /// Creates the WebSocket handler for incoming connections. + static dynamic _createWebSocketHandler( + ServiceExtensionRegistry serviceExtensionRegistry, + WebSocketProxyService webSocketProxyService, + ) { + return webSocketHandler((WebSocketChannel webSocket) { + if (!_acceptNewConnections) { + webSocket.sink.add( + jsonEncode({ + 'error': 'Cannot connect: another service has taken control.', + }), + ); + webSocket.sink.close(); + return; + } + + final responseController = StreamController>(); + webSocket.sink.addStream(responseController.stream.map(jsonEncode)); + + final inputStream = webSocket.stream.map((value) { + if (value is List) { + value = utf8.decode(value); + } else if (value is! String) { + throw StateError( + 'Unexpected value type from web socket: ${value.runtimeType}', + ); + } + return Map.from(jsonDecode(value)); + }); + + ++_clientsConnected; + VmServerConnection( + inputStream, + responseController.sink, + serviceExtensionRegistry, + webSocketProxyService, + ).done.whenComplete(() { + --_clientsConnected; + if (!_acceptNewConnections && _clientsConnected == 0) { + _acceptNewConnections = true; + } + }); + }); + } +} + +// Creates a random auth token for more secure connections. +String _makeAuthToken() { + final tokenBytes = 8; + final bytes = Uint8List(tokenBytes); + final random = Random.secure(); + for (var i = 0; i < tokenBytes; i++) { + bytes[i] = random.nextInt(256); + } + return base64Url.encode(bytes); +} diff --git a/dwds/lib/src/services/web_socket_proxy_service.dart b/dwds/lib/src/services/web_socket_proxy_service.dart new file mode 100644 index 000000000..078efe3b2 --- /dev/null +++ b/dwds/lib/src/services/web_socket_proxy_service.dart @@ -0,0 +1,746 @@ +// Copyright (c) 2025, 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:convert'; + +import 'package:dwds/data/debug_event.dart'; +import 'package:dwds/data/hot_reload_request.dart'; +import 'package:dwds/data/hot_reload_response.dart'; +import 'package:dwds/data/register_event.dart'; +import 'package:dwds/data/service_extension_request.dart'; +import 'package:dwds/data/service_extension_response.dart'; +import 'package:dwds/src/connections/app_connection.dart'; +import 'package:dwds/src/events.dart'; +import 'package:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds/src/utilities/shared.dart'; +import 'package:logging/logging.dart'; +// Ensure RPCError and RPCErrorKind are available for error handling +import 'package:pub_semver/pub_semver.dart' as semver; +import 'package:vm_service/vm_service.dart' as vm_service; +import 'package:vm_service/vm_service.dart'; +import 'package:vm_service_interface/vm_service_interface.dart'; + +/// Defines callbacks for sending messages to the connected client. +typedef SendClientRequest = void Function(Object request); + +const _pauseIsolatesOnStartFlag = 'pause_isolates_on_start'; + +/// WebSocket-based VM service proxy for web debugging. +/// +/// Provides hot reload and service extension support via WebSocket communication. +class WebSocketProxyService implements VmServiceInterface { + final _logger = Logger('WebSocketProxyService'); + + /// Signals when the isolate is ready. + Future get isInitialized => _initializedCompleter.future; + Completer _initializedCompleter = Completer(); + + /// Active service extension requests by ID. + final Map> + _pendingServiceExtensions = {}; + + /// Sends messages to the client. + final SendClientRequest sendClientRequest; + + /// App connection for this service. + final AppConnection appConnection; + + /// Current hot reload request (one at a time). + Completer? _pendingHotReload; + + /// App connection cleanup subscription. + StreamSubscription? _appConnectionDoneSubscription; + + /// Event stream controllers. + final Map> _streamControllers = {}; + + /// VM service runtime flags. + final Map _currentVmServiceFlags = { + _pauseIsolatesOnStartFlag: false, + }; + + /// Root VM instance. + final vm_service.VM _vm; + + WebSocketProxyService._( + this.sendClientRequest, + this._vm, + this.appConnection, + ); // Isolate state + vm_service.IsolateRef? _isolateRef; + bool _isolateRunning = false; + vm_service.Event? _currentPauseEvent; + bool _hasResumed = false; + + bool get _isIsolateRunning => _isolateRunning; + + /// Creates a new isolate for WebSocket debugging. + /// + /// Destroys existing isolate first if present. Call [destroyIsolate] on restart. + Future createIsolate([AppConnection? appConnectionOverride]) async { + final appConn = appConnectionOverride ?? appConnection; + + // Clean up existing isolate + if (_isIsolateRunning) { + destroyIsolate(); + await Future.delayed(Duration(milliseconds: 10)); + } + + // Auto-cleanup on connection close + await _appConnectionDoneSubscription?.cancel(); + _appConnectionDoneSubscription = appConn.onDone.asStream().listen((_) { + destroyIsolate(); + }); + + // Create isolate reference + final isolateRef = vm_service.IsolateRef( + id: '1', + name: 'main()', + number: '1', + isSystemIsolate: false, + ); + + _isolateRef = isolateRef; + _isolateRunning = true; + _hasResumed = false; + _vm.isolates?.add(isolateRef); + final timestamp = DateTime.now().millisecondsSinceEpoch; + + // Send lifecycle events + _streamNotify( + vm_service.EventStreams.kIsolate, + vm_service.Event( + kind: vm_service.EventKind.kIsolateStart, + timestamp: timestamp, + isolate: isolateRef, + ), + ); + _streamNotify( + vm_service.EventStreams.kIsolate, + vm_service.Event( + kind: vm_service.EventKind.kIsolateRunnable, + timestamp: timestamp, + isolate: isolateRef, + ), + ); + + if (!_initializedCompleter.isCompleted) _initializedCompleter.complete(); + + // Set up appConnection.onStart listener (like Chrome flow does) + safeUnawaited( + appConn.onStart.then((_) { + // Unlike Chrome flow, we don't have debugger.resumeFromStart(), but we can trigger resume + if (pauseIsolatesOnStart && !_hasResumed) { + final resumeEvent = vm_service.Event( + kind: vm_service.EventKind.kResume, + timestamp: DateTime.now().millisecondsSinceEpoch, + isolate: isolateRef, + ); + _hasResumed = true; + _streamNotify(vm_service.EventStreams.kDebug, resumeEvent); + } + }), + ); + + // Send pause event if enabled + if (pauseIsolatesOnStart) { + final pauseEvent = vm_service.Event( + kind: vm_service.EventKind.kPauseStart, + timestamp: timestamp, + isolate: isolateRef, + ); + _currentPauseEvent = pauseEvent; + _hasResumed = false; + _streamNotify(vm_service.EventStreams.kDebug, pauseEvent); + // Flutter tools will call resume() to start the app + + // Auto-resume after a short delay if no debugger is connected + // This handles the case where the app is run from terminal without debug extension + _scheduleAutoResumeIfNeeded(); + } else { + // If we're not pausing on start, immediately send a resume event + // to ensure the app knows it can start running + _logger.info('Not pausing on start, sending immediate resume event'); + final resumeEvent = vm_service.Event( + kind: vm_service.EventKind.kResume, + timestamp: timestamp, + isolate: isolateRef, + ); + _hasResumed = true; + _streamNotify(vm_service.EventStreams.kDebug, resumeEvent); + } + } + + /// Destroys the isolate and cleans up state. + void destroyIsolate() { + _logger.fine('Destroying isolate'); + if (!_isIsolateRunning) return; + + final isolateRef = _isolateRef; + + _appConnectionDoneSubscription?.cancel(); + _appConnectionDoneSubscription = null; + + // Send exit event + if (isolateRef != null) { + _streamNotify( + vm_service.EventStreams.kIsolate, + vm_service.Event( + kind: vm_service.EventKind.kIsolateExit, + timestamp: DateTime.now().millisecondsSinceEpoch, + isolate: isolateRef, + ), + ); + } + + _vm.isolates?.removeWhere((ref) => ref.id == isolateRef?.id); + + // Reset state + _isolateRef = null; + _isolateRunning = false; + _currentPauseEvent = null; + _hasResumed = false; + + if (_initializedCompleter.isCompleted) { + _initializedCompleter = Completer(); + } + } + + /// Sends events to stream controllers. + void _streamNotify(String streamId, vm_service.Event event) { + final controller = _streamControllers[streamId]; + if (controller == null) return; + controller.add(event); + } + + @override + Future setLibraryDebuggable( + String isolateId, + String libraryId, + bool isDebuggable, + ) { + return _rpcNotSupportedFuture('setLibraryDebuggable'); + } + + @override + Future setIsolatePauseMode( + String isolateId, { + String? exceptionPauseMode, + bool? shouldPauseOnExit, + }) async { + // Not supported in WebSocket mode - return success for compatibility + return Success(); + } + + static Future _rpcNotSupportedFuture(String method) { + return Future.error(_rpcNotSupported(method)); + } + + static RPCError _rpcNotSupported(String method) { + return RPCError( + method, + RPCErrorKind.kMethodNotFound.code, + '$method: Not supported on web devices', + ); + } + + @override + Future getIsolate(String isolateId) => + wrapInErrorHandlerAsync('getIsolate', () => _getIsolate(isolateId)); + + Future _getIsolate(String isolateId) async { + if (!_isIsolateRunning || _isolateRef == null) { + throw vm_service.RPCError( + 'getIsolate', + vm_service.RPCErrorKind.kInvalidParams.code, + 'No running isolate found for id: $isolateId', + ); + } + if (_isolateRef!.id != isolateId) { + throw vm_service.RPCError( + 'getIsolate', + vm_service.RPCErrorKind.kInvalidParams.code, + 'Isolate with id $isolateId not found.', + ); + } + + return vm_service.Isolate( + id: _isolateRef!.id!, + name: _isolateRef!.name, + number: _isolateRef!.number, + startTime: DateTime.now().millisecondsSinceEpoch, + isSystemIsolate: _isolateRef!.isSystemIsolate, + runnable: true, + pauseEvent: _currentPauseEvent, + ); + } + + /// Returns a broadcast stream for the given streamId, creating if needed. + @override + Stream onEvent(String streamId) { + return _streamControllers.putIfAbsent(streamId, () { + switch (streamId) { + case vm_service.EventStreams.kExtension: + case vm_service.EventStreams.kIsolate: + case vm_service.EventStreams.kVM: + case vm_service.EventStreams.kGC: + case vm_service.EventStreams.kTimeline: + case vm_service.EventStreams.kService: + case vm_service.EventStreams.kDebug: + case vm_service.EventStreams.kLogging: + case vm_service.EventStreams.kStdout: + case vm_service.EventStreams.kStderr: + return StreamController.broadcast(); + default: + _logger.warning('Unsupported stream: $streamId'); + throw vm_service.RPCError( + 'streamListen', + vm_service.RPCErrorKind.kInvalidParams.code, + 'Stream `$streamId` not supported on web devices', + ); + } + }).stream; + } + + @override + Future streamListen(String streamId) => + wrapInErrorHandlerAsync('streamListen', () => _streamListen(streamId)); + + Future _streamListen(String streamId) async { + onEvent(streamId); + return vm_service.Success(); + } + + /// Adds events to stream controllers. + void addEvent(String streamId, vm_service.Event event) { + final controller = _streamControllers[streamId]; + if (controller != null && !controller.isClosed) { + controller.add(event); + _logger.fine('Added event to stream $streamId: $event'); + } else { + _logger.warning('Cannot add event to closed/missing stream: $streamId'); + } + } + + static Future create( + SendClientRequest sendClientRequest, + AppConnection appConnection, + ) async { + final vm = vm_service.VM( + name: 'WebSocketDebugProxy', + operatingSystem: 'web', + startTime: DateTime.now().millisecondsSinceEpoch, + version: 'unknown', + isolates: [], + isolateGroups: [], + systemIsolates: [], + systemIsolateGroups: [], + targetCPU: 'Web', + hostCPU: 'DWDS', + architectureBits: -1, + pid: -1, + ); + final service = WebSocketProxyService._( + sendClientRequest, + vm, + appConnection, + ); + safeUnawaited(service.createIsolate(appConnection)); + return service; + } + + /// Returns the root VM object. + @override + Future getVM() => wrapInErrorHandlerAsync('getVM', _getVM); + + Future _getVM() { + // On web, we do not currently support isolates, so isInitialized is not required. + return captureElapsedTime(() async { + return _vm; + }, (result) => DwdsEvent.getVM()); + } + + /// Throws error if remoteDebugger is accessed (not available in WebSocket mode). + dynamic get remoteDebugger { + throw UnsupportedError( + 'remoteDebugger not available in WebSocketProxyService.\n' + 'Called from:\n${StackTrace.current}', + ); + } + + /// Returns supported VM service protocols. + @override + Future getSupportedProtocols() async { + final version = semver.Version.parse(vm_service.vmServiceVersion); + return vm_service.ProtocolList( + protocols: [ + vm_service.Protocol( + protocolName: 'VM Service', + major: version.major, + minor: version.minor, + ), + ], + ); + } + + @override + Future reloadSources( + String isolateId, { + bool? force, + bool? pause, + String? rootLibUri, + String? packagesUri, + }) async { + _logger.info('Attempting a hot reload'); + try { + await _performWebSocketHotReload(); + _logger.info('Hot reload completed successfully'); + return _ReloadReportWithMetadata(success: true); + } catch (e) { + _logger.warning('Hot reload failed: $e'); + return _ReloadReportWithMetadata(success: false, notices: [e.toString()]); + } + } + + /// Completes hot reload with response. + void completeHotReload(HotReloadResponse response) { + final completer = _pendingHotReload; + _pendingHotReload = null; + + if (completer != null) { + if (response.success) { + completer.complete(response); + } else { + completer.completeError( + response.errorMessage ?? 'Unknown client error during hot reload', + ); + } + } else { + _logger.warning( + 'Received hot reload response but no pending completer found (id: ${response.id})', + ); + } + } + + /// Performs WebSocket-based hot reload. + Future _performWebSocketHotReload({String? requestId}) async { + if (_pendingHotReload != null) { + throw StateError('Hot reload already pending'); + } + + final id = requestId ?? createId(); + final completer = Completer(); + _pendingHotReload = completer; + + const timeout = Duration(seconds: 10); + _logger.info('Sending HotReloadRequest with ID ($id) to client'); + + await Future.microtask(() { + sendClientRequest(HotReloadRequest((b) => b.id = id)); + }); + + try { + final response = await completer.future.timeout( + timeout, + onTimeout: () { + _pendingHotReload = null; + throw TimeoutException( + 'Client did not respond to hot reload', + timeout, + ); + }, + ); + + if (!response.success) { + throw Exception(response.errorMessage ?? 'Client reported failure'); + } + } catch (e) { + _pendingHotReload = null; + rethrow; + } + } + + @override + Future callServiceExtension( + String method, { + String? isolateId, + Map? args, + }) => wrapInErrorHandlerAsync( + 'callServiceExtension', + () => _callServiceExtension(method, isolateId: isolateId, args: args), + ); + + /// Calls a service extension on the client. + Future _callServiceExtension( + String method, { + String? isolateId, + Map? args, + }) async { + final requestId = createId(); + if (_pendingServiceExtensions.containsKey(requestId)) { + throw StateError('Service extension call already pending for this ID'); + } + + final completer = Completer(); + _pendingServiceExtensions[requestId] = completer; + + final request = ServiceExtensionRequest.fromArgs( + id: requestId, + method: method, + args: + args != null ? Map.from(args) : {}, + ); + sendClientRequest(request); + + final response = await completer.future.timeout(Duration(seconds: 10)); + _pendingServiceExtensions.remove(requestId); + + if (response.errorMessage != null) { + throw RPCError( + method, + response.errorCode ?? RPCErrorKind.kServerError.code, + response.errorMessage!, + ); + } + return Response()..json = response.result; + } + + /// Completes service extension with response. + void completeServiceExtension(ServiceExtensionResponse response) { + final id = response.id; + final completer = _pendingServiceExtensions.remove(id); + + if (completer != null) { + if (response.success == true) { + completer.complete(response); + } else { + completer.completeError( + response.errorMessage ?? + 'Unknown client error during service extension', + ); + } + } else { + _logger.warning( + 'No pending completer found for service extension (id: $id)', + ); + } + } + + /// Parses the [RegisterEvent] and emits a corresponding Dart VM Service + /// protocol [Event]. + void parseRegisterEvent(RegisterEvent registerEvent) { + _logger.fine('Parsing RegisterEvent: ${registerEvent.eventData}'); + + if (!_isIsolateRunning || _isolateRef == null) { + _logger.warning('Cannot register service extension - no isolate running'); + return; + } + + final service = registerEvent.eventData; + + // Add the service to the isolate's extension RPCs if we had access to the isolate + // In WebSocket mode, we don't maintain the full isolate object like Chrome mode, + // but we can still emit the ServiceExtensionAdded event for tooling + + final event = vm_service.Event( + kind: vm_service.EventKind.kServiceExtensionAdded, + timestamp: DateTime.now().millisecondsSinceEpoch, + isolate: _isolateRef!, + ); + event.extensionRPC = service; + + _streamNotify(vm_service.EventStreams.kIsolate, event); + _logger.fine('Emitted ServiceExtensionAdded event for: $service'); + } + + /// Parses the [BatchedDebugEvents] and emits corresponding Dart VM Service + /// protocol [Event]s. + void parseBatchedDebugEvents(BatchedDebugEvents debugEvents) { + for (final debugEvent in debugEvents.events) { + parseDebugEvent(debugEvent); + } + } + + /// Parses the [DebugEvent] and emits a corresponding Dart VM Service + /// protocol [Event]. + void parseDebugEvent(DebugEvent debugEvent) { + if (!_isIsolateRunning || _isolateRef == null) { + _logger.warning('Cannot parse debug event - no isolate running'); + return; + } + + _streamNotify( + vm_service.EventStreams.kExtension, + vm_service.Event( + kind: vm_service.EventKind.kExtension, + timestamp: DateTime.now().millisecondsSinceEpoch, + isolate: _isolateRef!, + ) + ..extensionKind = debugEvent.kind + ..extensionData = vm_service.ExtensionData.parse( + jsonDecode(debugEvent.eventData) as Map, + ), + ); + } + + @override + Future setFlag(String name, String value) => + wrapInErrorHandlerAsync('setFlag', () => _setFlag(name, value)); + + Future _setFlag(String name, String value) async { + if (!_currentVmServiceFlags.containsKey(name)) { + return _rpcNotSupportedFuture('setFlag'); + } + + assert(value == 'true' || value == 'false'); + final oldValue = _currentVmServiceFlags[name]; + _currentVmServiceFlags[name] = value == 'true'; + + // Handle pause_isolates_on_start flag + if (name == _pauseIsolatesOnStartFlag && + value == 'true' && + oldValue == false) { + // Send pause event for existing isolate if it wasn't paused initially + if (_isIsolateRunning && + _isolateRef != null && + _currentPauseEvent == null) { + final pauseEvent = vm_service.Event( + kind: vm_service.EventKind.kPauseStart, + timestamp: DateTime.now().millisecondsSinceEpoch, + isolate: _isolateRef!, + ); + _currentPauseEvent = pauseEvent; + _hasResumed = false; + _streamNotify(vm_service.EventStreams.kDebug, pauseEvent); + } + } + + return Success(); + } + + @override + Future lookupResolvedPackageUris( + String isolateId, + List uris, { + bool? local, + }) => wrapInErrorHandlerAsync( + 'lookupResolvedPackageUris', + () => _lookupResolvedPackageUris(isolateId, uris), + ); + + Future _lookupResolvedPackageUris( + String isolateId, + List uris, + ) async { + await isInitialized; + return UriList(uris: uris.map(DartUri.toResolvedUri).toList()); + } + + /// Stream controller for resume events after restart. + final _resumeAfterRestartEventsController = + StreamController.broadcast(); + + /// Stream of resume events after restart. + Stream get resumeAfterRestartEventsStream => + _resumeAfterRestartEventsController.stream; + + /// Whether there's a pending restart. + bool get hasPendingRestart => _resumeAfterRestartEventsController.hasListener; + + /// Whether isolates should pause on start. + bool get pauseIsolatesOnStart => + _currentVmServiceFlags[_pauseIsolatesOnStartFlag] ?? false; + + /// Resumes execution of the isolate. + @override + Future resume(String isolateId, {String? step, int? frameIndex}) => + wrapInErrorHandlerAsync( + 'resume', + () => _resume(isolateId, step: step, frameIndex: frameIndex), + ); + + Future _resume( + String isolateId, { + String? step, + int? frameIndex, + }) async { + // Check if we should trigger runMain instead + if (!_hasResumed && _currentPauseEvent != null) { + appConnection.runMain(); + } + + // Prevent multiple resume calls + if (_hasResumed && _currentPauseEvent == null) { + return Success(); + } + + _currentPauseEvent = null; + _hasResumed = true; + + // Send resume event + if (_isolateRef != null) { + final resumeEvent = vm_service.Event( + kind: vm_service.EventKind.kResume, + timestamp: DateTime.now().millisecondsSinceEpoch, + isolate: _isolateRef!, + ); + + _streamNotify(vm_service.EventStreams.kDebug, resumeEvent); + _logger.fine('Sent resume event for isolate ${_isolateRef!.id}'); + } + + // Handle restart events + if (_resumeAfterRestartEventsController.hasListener) { + _resumeAfterRestartEventsController.add(isolateId); + return Success(); + } + + return Success(); + } + + /// Schedules an auto-resume if no debugger connection is detected. + /// This prevents the app from being stuck in a paused state when running from terminal. + void _scheduleAutoResumeIfNeeded() { + _logger.info('Scheduling auto-resume check in 2 seconds'); + // Wait a reasonable amount of time for a debugger to connect + Timer(Duration(seconds: 2), () { + // If we're still paused and no debugger has taken control, auto-resume + if (_currentPauseEvent != null && + _currentPauseEvent!.kind == vm_service.EventKind.kPauseStart && + !_hasResumed) { + _logger.info( + 'Auto-resuming isolate after timeout (no debugger connected)', + ); + // Auto-resume the isolate + safeUnawaited(_resume(_isolateRef?.id ?? '1')); + } else { + _logger.info( + 'Auto-resume check: isolate already resumed or no pause event', + ); + } + }); + } + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +/// Extended ReloadReport that includes additional metadata in JSON output. +class _ReloadReportWithMetadata extends vm_service.ReloadReport { + final List? notices; + _ReloadReportWithMetadata({super.success, this.notices}); + + @override + Map toJson() { + final jsonified = { + 'type': 'ReloadReport', + 'success': success ?? false, + }; + if (notices != null) { + jsonified['notices'] = notices!.map((e) => {'message': e}).toList(); + } + return jsonified; + } +} diff --git a/dwds/lib/src/version.dart b/dwds/lib/src/version.dart index b2c6d5326..b75ef44c9 100644 --- a/dwds/lib/src/version.dart +++ b/dwds/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '24.3.11'; +const packageVersion = '24.3.12-wip'; diff --git a/dwds/lib/src/web_socket_dwds_vm_client.dart b/dwds/lib/src/web_socket_dwds_vm_client.dart new file mode 100644 index 000000000..f4d3e9962 --- /dev/null +++ b/dwds/lib/src/web_socket_dwds_vm_client.dart @@ -0,0 +1,196 @@ +// Copyright (c) 2025, 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:convert'; + +import 'package:dwds/src/services/web_socket_debug_service.dart'; +import 'package:dwds/src/services/web_socket_proxy_service.dart'; +import 'package:logging/logging.dart'; +import 'package:vm_service/vm_service.dart'; +import 'package:vm_service_interface/vm_service_interface.dart'; + +final _logger = Logger('WebSocketDwdsVmClient'); + +typedef VmRequest = Map; +typedef VmResponse = Map; + +enum _NamespacedServiceExtension { + extDwdsEmitEvent(method: 'ext.dwds.emitEvent'), + extDwdsReload(method: 'ext.dwds.reload'), + extDwdsRestart(method: 'ext.dwds.restart'), + extDwdsScreenshot(method: 'ext.dwds.screenshot'), + extDwdsSendEvent(method: 'ext.dwds.sendEvent'), + flutterListViews(method: '_flutter.listViews'); + + const _NamespacedServiceExtension({required this.method}); + final String method; +} + +/// WebSocket-based DWDS VM client. +/// +/// Provides VM service functionality without Chrome dependencies. +class WebSocketDwdsVmClient { + final VmService client; + final StreamController _requestController; + final StreamController _responseController; + Future? _closed; + + WebSocketDwdsVmClient( + this.client, + this._requestController, + this._responseController, + ); + + Future close() => + _closed ??= () async { + await _requestController.close(); + await _responseController.close(); + await client.dispose(); + }(); + + static Future create( + WebSocketDebugService debugService, + ) async { + _logger.fine('Creating WebSocket DWDS VM client'); + final webSocketProxyService = debugService.webSocketProxyService; + final responseController = StreamController(); + final responseSink = responseController.sink; + final responseStream = responseController.stream.asBroadcastStream(); + final requestController = StreamController(); + final requestSink = requestController.sink; + final requestStream = requestController.stream; + + _setUpVmServerConnection( + webSocketProxyService: webSocketProxyService, + debugService: debugService, + responseStream: responseStream, + responseSink: responseSink, + requestStream: requestStream, + requestSink: requestSink, + ); + + final client = _setUpVmClient( + responseStream: responseStream, + requestController: requestController, + requestSink: requestSink, + ); + + _logger.fine('WebSocket DWDS VM client created successfully'); + return WebSocketDwdsVmClient(client, requestController, responseController); + } + + static VmService _setUpVmClient({ + required Stream responseStream, + required StreamSink requestSink, + required StreamController requestController, + }) { + final client = VmService(responseStream.map(jsonEncode), (request) { + if (requestController.isClosed) { + _logger.warning( + 'Attempted to send a request but the connection is closed:\n\n$request', + ); + return; + } + requestSink.add(Map.from(jsonDecode(request))); + }); + return client; + } + + static void _setUpVmServerConnection({ + required WebSocketProxyService webSocketProxyService, + required WebSocketDebugService debugService, + required Stream responseStream, + required StreamSink responseSink, + required Stream requestStream, + required StreamSink requestSink, + }) { + responseStream.listen((request) async { + final response = await _maybeHandleServiceExtensionRequest( + request, + webSocketProxyService: webSocketProxyService, + ); + if (response != null) { + requestSink.add(response); + } + }); + + final vmServerConnection = VmServerConnection( + requestStream, + responseSink, + debugService.serviceExtensionRegistry, + webSocketProxyService, + ); + + // Register service extensions + for (final extension in _NamespacedServiceExtension.values) { + _logger.finest('Registering service extension: ${extension.method}'); + debugService.serviceExtensionRegistry.registerExtension( + extension.method, + vmServerConnection, + ); + } + } + + static Future _maybeHandleServiceExtensionRequest( + VmResponse request, { + required WebSocketProxyService webSocketProxyService, + }) async { + VmRequest? response; + final method = request['method']; + + _logger.finest('Processing service extension method: $method'); + + if (method == _NamespacedServiceExtension.flutterListViews.method) { + response = await _flutterListViewsHandler(webSocketProxyService); + } else if (method == _NamespacedServiceExtension.extDwdsEmitEvent.method) { + response = _extDwdsEmitEventHandler(request); + } else if (method == _NamespacedServiceExtension.extDwdsReload.method) { + response = {'result': 'Reload not implemented'}; + } else if (method == _NamespacedServiceExtension.extDwdsSendEvent.method) { + response = _extDwdsSendEventHandler(request); + } else if (method == _NamespacedServiceExtension.extDwdsScreenshot.method) { + response = {'result': 'Screenshot not implemented'}; + } + + if (response != null) { + response['id'] = request['id'] as String; + response['jsonrpc'] = '2.0'; + } + return response; + } + + static Future> _flutterListViewsHandler( + WebSocketProxyService webSocketProxyService, + ) async { + final vm = await webSocketProxyService.getVM(); + _logger.finest('Retrieved VM with ${vm.isolates?.length ?? 0} isolates'); + final isolates = vm.isolates; + return { + 'result': { + 'views': [ + for (final isolate in isolates ?? []) + {'id': isolate.id, 'isolate': isolate.toJson()}, + ], + }, + }; + } + + static Map _extDwdsEmitEventHandler(VmResponse request) { + final event = request['params'] as Map?; + if (event != null) { + final type = event['type'] as String?; + final payload = event['payload'] as Map?; + if (type != null && payload != null) { + _logger.fine('EmitEvent: $type $payload'); + } + } + return {'result': 'EmitEvent handled'}; + } + + static Map _extDwdsSendEventHandler(VmResponse request) { + _logger.fine('SendEvent: $request'); + return {'result': 'SendEvent handled'}; + } +} diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index ae2f792ab..248b8ffc1 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -1,6 +1,6 @@ name: dwds # Every time this changes you need to run `dart run build_runner build`. -version: 24.3.11 +version: 24.3.12-wip description: >- A service that proxies between the Chrome debug protocol and the Dart VM diff --git a/dwds/web/client.dart b/dwds/web/client.dart index 16daa027a..0c947dd6e 100644 --- a/dwds/web/client.dart +++ b/dwds/web/client.dart @@ -19,6 +19,8 @@ import 'package:dwds/data/hot_reload_response.dart'; import 'package:dwds/data/register_event.dart'; import 'package:dwds/data/run_request.dart'; import 'package:dwds/data/serializers.dart'; +import 'package:dwds/data/service_extension_request.dart'; +import 'package:dwds/data/service_extension_response.dart'; import 'package:dwds/shared/batched_stream.dart'; import 'package:dwds/src/sockets.dart'; import 'package:http/browser_client.dart'; @@ -210,6 +212,8 @@ Future? main() { ); } else if (event is HotReloadRequest) { await handleWebSocketHotReloadRequest(event, manager, client.sink); + } else if (event is ServiceExtensionRequest) { + await handleServiceExtensionRequest(event, client.sink, manager); } }, onError: (error) { @@ -249,10 +253,6 @@ Future? main() { } } else { _sendConnectRequest(client.sink); - // TODO(yjessy): Remove this when the DWDS WebSocket connection is implemented. - if (useDwdsWebSocketConnection) { - runMain(); - } } _launchCommunicationWithDebugExtension(); }, @@ -418,6 +418,30 @@ void _sendHotReloadResponse( ); } +void _sendServiceExtensionResponse( + StreamSink clientSink, + String requestId, { + bool success = true, + String? errorMessage, + int? errorCode, + Map? result, +}) { + _trySendEvent( + clientSink, + jsonEncode( + serializers.serialize( + ServiceExtensionResponse.fromResult( + id: requestId, + success: success, + errorMessage: errorMessage, + errorCode: errorCode, + result: result, + ), + ), + ), + ); +} + Future handleWebSocketHotReloadRequest( HotReloadRequest event, ReloadingManager manager, @@ -438,6 +462,44 @@ Future handleWebSocketHotReloadRequest( } } +Future handleServiceExtensionRequest( + ServiceExtensionRequest request, + StreamSink clientSink, + ReloadingManager manager, +) async { + try { + final result = await manager.handleServiceExtension( + request.method, + request.args, + ); + + if (result != null) { + _sendServiceExtensionResponse( + clientSink, + request.id, + success: true, + result: result, + ); + } else { + // Service extension not supported by this restarter type + _sendServiceExtensionResponse( + clientSink, + request.id, + success: false, + errorMessage: 'Service extension not supported', + errorCode: -32601, // Method not found + ); + } + } catch (e) { + _sendServiceExtensionResponse( + clientSink, + request.id, + success: false, + errorMessage: e.toString(), + ); + } +} + @JS(r'$dartAppId') external String get dartAppId; @@ -490,10 +552,6 @@ external String get reloadConfiguration; @JS(r'$dartEntrypointPath') external String get dartEntrypointPath; -// TODO(yjessy): Remove this when the DWDS WebSocket connection is implemented. -@JS(r'$useDwdsWebSocketConnection') -external bool get useDwdsWebSocketConnection; - @JS(r'$dwdsEnableDevToolsLaunch') external bool get dwdsEnableDevToolsLaunch; diff --git a/dwds/web/reloader/ddc_library_bundle_restarter.dart b/dwds/web/reloader/ddc_library_bundle_restarter.dart index 77f2eab9f..545886782 100644 --- a/dwds/web/reloader/ddc_library_bundle_restarter.dart +++ b/dwds/web/reloader/ddc_library_bundle_restarter.dart @@ -37,6 +37,13 @@ extension type _Debugger._(JSObject _) implements JSObject { await invokeExtension(method, '{}').toDart; } } + + Future maybeInvokeFlutterReassemble() async { + final method = 'ext.flutter.reassemble'; + if (extensionNames.toDart.contains(method.toJS)) { + await invokeExtension(method, '{}').toDart; + } + } } @JS('XMLHttpRequest') @@ -132,4 +139,27 @@ class DdcLibraryBundleRestarter implements Restarter { ); return librariesToReload; } + + /// Handles service extension requests using the dart dev embedder + Future?> handleServiceExtension( + String method, + Map args, + ) async { + if (method == 'ext.flutter.reassemble') { + await _dartDevEmbedder.debugger.maybeInvokeFlutterReassemble(); + return {'status': 'reassemble invoked'}; + } else if (method == 'getExtensionRpcs') { + final rpcs = + _dartDevEmbedder.debugger.extensionNames.toDart.cast(); + return {'rpcs': rpcs}; + } else { + // For other extension methods, delegate to the debugger + final params = args.isNotEmpty ? jsonEncode(args) : '{}'; + final resultJson = + await _dartDevEmbedder.debugger + .invokeExtension(method, params) + .toDart; + return jsonDecode(resultJson.toDart) as Map; + } + } } diff --git a/dwds/web/reloader/manager.dart b/dwds/web/reloader/manager.dart index 1142d8016..8617f777d 100644 --- a/dwds/web/reloader/manager.dart +++ b/dwds/web/reloader/manager.dart @@ -10,6 +10,7 @@ import 'package:dwds/data/serializers.dart'; import 'package:dwds/src/sockets.dart'; import 'package:web/web.dart'; +import 'ddc_library_bundle_restarter.dart'; import 'restarter.dart'; class ReloadingManager { @@ -68,6 +69,19 @@ class ReloadingManager { window.location.reload(); } + /// Handles service extension requests by delegating to the appropriate restarter + Future?> handleServiceExtension( + String method, + Map args, + ) async { + final restarter = _restarter; + if (restarter is DdcLibraryBundleRestarter) { + return restarter.handleServiceExtension(method, args); + } + // For other restarter types, return null to indicate not supported + return null; + } + void _afterRestart(bool succeeded) { if (!succeeded) return; // Notify package:dwds that the isolate has been created.