From b094cd7eb91a0d51f67ef5f09d3bdb53eee88066 Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 09:52:54 -0700 Subject: [PATCH 1/8] faster launch --- dwds/lib/data/run_request.dart | 8 -- dwds/lib/data/run_request.g.dart | 76 --------------- dwds/lib/data/serializers.dart | 1 - dwds/lib/data/serializers.g.dart | 3 +- dwds/lib/src/connections/app_connection.dart | 13 ++- dwds/lib/src/handlers/dev_handler.dart | 38 +------- dwds/lib/src/injected/client.js | 95 ++----------------- .../src/services/chrome_proxy_service.dart | 76 +++++++++------ dwds/web/client.dart | 1 - 9 files changed, 68 insertions(+), 243 deletions(-) diff --git a/dwds/lib/data/run_request.dart b/dwds/lib/data/run_request.dart index af0780dc7..3204cbf41 100644 --- a/dwds/lib/data/run_request.dart +++ b/dwds/lib/data/run_request.dart @@ -14,11 +14,3 @@ abstract class RunRequest implements Built { RunRequest._(); } - -abstract class RunResponse implements Built { - static Serializer get serializer => _$runResponseSerializer; - - factory RunResponse([Function(RunResponseBuilder) updates]) = _$RunResponse; - - RunResponse._(); -} diff --git a/dwds/lib/data/run_request.g.dart b/dwds/lib/data/run_request.g.dart index 850685957..008cc441b 100644 --- a/dwds/lib/data/run_request.g.dart +++ b/dwds/lib/data/run_request.g.dart @@ -7,7 +7,6 @@ part of 'run_request.dart'; // ************************************************************************** Serializer _$runRequestSerializer = new _$RunRequestSerializer(); -Serializer _$runResponseSerializer = new _$RunResponseSerializer(); class _$RunRequestSerializer implements StructuredSerializer { @override @@ -28,25 +27,6 @@ class _$RunRequestSerializer implements StructuredSerializer { } } -class _$RunResponseSerializer implements StructuredSerializer { - @override - final Iterable types = const [RunResponse, _$RunResponse]; - @override - final String wireName = 'RunResponse'; - - @override - Iterable serialize(Serializers serializers, RunResponse object, - {FullType specifiedType = FullType.unspecified}) { - return []; - } - - @override - RunResponse deserialize(Serializers serializers, Iterable serialized, - {FullType specifiedType = FullType.unspecified}) { - return new RunResponseBuilder().build(); - } -} - class _$RunRequest extends RunRequest { factory _$RunRequest([void Function(RunRequestBuilder) updates]) => (new RunRequestBuilder()..update(updates)).build(); @@ -103,60 +83,4 @@ class RunRequestBuilder implements Builder { } } -class _$RunResponse extends RunResponse { - factory _$RunResponse([void Function(RunResponseBuilder) updates]) => - (new RunResponseBuilder()..update(updates)).build(); - - _$RunResponse._() : super._(); - - @override - RunResponse rebuild(void Function(RunResponseBuilder) updates) => - (toBuilder()..update(updates)).build(); - - @override - RunResponseBuilder toBuilder() => new RunResponseBuilder()..replace(this); - - @override - bool operator ==(Object other) { - if (identical(other, this)) return true; - return other is RunResponse; - } - - @override - int get hashCode { - return 11131040; - } - - @override - String toString() { - return newBuiltValueToStringHelper('RunResponse').toString(); - } -} - -class RunResponseBuilder implements Builder { - _$RunResponse _$v; - - RunResponseBuilder(); - - @override - void replace(RunResponse other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } - _$v = other as _$RunResponse; - } - - @override - void update(void Function(RunResponseBuilder) updates) { - if (updates != null) updates(this); - } - - @override - _$RunResponse build() { - final _$result = _$v ?? new _$RunResponse._(); - replace(_$result); - return _$result; - } -} - // ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/dwds/lib/data/serializers.dart b/dwds/lib/data/serializers.dart index be4d49b5f..19f9b5214 100644 --- a/dwds/lib/data/serializers.dart +++ b/dwds/lib/data/serializers.dart @@ -20,7 +20,6 @@ part 'serializers.g.dart'; DevToolsResponse, ConnectRequest, RunRequest, - RunResponse, DefaultBuildResult, IsolateExit, IsolateStart, diff --git a/dwds/lib/data/serializers.g.dart b/dwds/lib/data/serializers.g.dart index 110a56cce..846cc08e7 100644 --- a/dwds/lib/data/serializers.g.dart +++ b/dwds/lib/data/serializers.g.dart @@ -18,8 +18,7 @@ Serializers _$serializers = (new Serializers().toBuilder() ..add(ExtensionResponse.serializer) ..add(IsolateExit.serializer) ..add(IsolateStart.serializer) - ..add(RunRequest.serializer) - ..add(RunResponse.serializer)) + ..add(RunRequest.serializer)) .build(); // ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/dwds/lib/src/connections/app_connection.dart b/dwds/lib/src/connections/app_connection.dart index 6e7e9511d..2dabe3180 100644 --- a/dwds/lib/src/connections/app_connection.dart +++ b/dwds/lib/src/connections/app_connection.dart @@ -2,6 +2,7 @@ // 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:sse/server/sse_handler.dart'; @@ -14,17 +15,19 @@ import '../../data/serializers.dart'; class AppConnection { /// The initial connection request sent from the application in the browser. final ConnectRequest request; - + final _startCompleter = Completer(); final SseConnection _connection; - var _isStarted = false; AppConnection(this.request, this._connection); - bool get isStarted => _isStarted; + bool get isStarted => _startCompleter.isCompleted; + Future get onStart => _startCompleter.future; void runMain() { - if (_isStarted) throw StateError('Main has already started.'); + if (_startCompleter.isCompleted) { + throw StateError('Main has already started.'); + } _connection.sink.add(jsonEncode(serializers.serialize(RunRequest()))); - _isStarted = true; + _startCompleter.complete(); } } diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index 3cf6b380b..fa9bdb2cd 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -10,7 +10,6 @@ import 'package:build_daemon/data/serializers.dart' as build_daemon; import 'package:dwds/data/error_response.dart'; import 'package:dwds/data/run_request.dart'; import 'package:dwds/src/connections/debug_connection.dart'; -import 'package:dwds/src/debugging/remote_debugger.dart'; import 'package:dwds/src/debugging/webkit_debugger.dart'; import 'package:dwds/src/servers/extension_backend.dart'; import 'package:logging/logging.dart'; @@ -148,9 +147,6 @@ class DevHandler { await startDebugService(await _chromeConnection(), appConnection); var appServices = await _createAppDebugServices( appConnection.request.appId, debugService); - if (appConnection.isStarted) { - await appServices.chromeProxyService.resumeFromStart(); - } unawaited(appServices.chromeProxyService.remoteDebugger.onClose.first .whenComplete(() { appServices.close(); @@ -187,8 +183,6 @@ class DevHandler { await _handleIsolateExit(appConnection); } else if (message is IsolateStart) { await _handleIsolateStart(appConnection, injectedConnection); - } else if (message is RunResponse) { - await _handleRunResponse(appConnection); } } } catch (e, s) { @@ -262,15 +256,6 @@ class DevHandler { return; } - // If you load the same app in a different tab then we need to throw - // away our old services and start new ones. - if (!(await _isCorrectTab(appConnection.request.instanceId, - appServices.chromeProxyService.remoteDebugger))) { - unawaited(appServices.close()); - unawaited(_servicesByAppId.remove(appConnection.request.appId)); - appServices = await loadAppServices(appConnection); - } - sseConnection.sink.add(jsonEncode( serializers.serialize(DevToolsResponse((b) => b..success = true)))); @@ -293,13 +278,9 @@ class DevHandler { var services = await _servicesByAppId[message.appId]; var connection = AppConnection(message, sseConnection); if (services != null && services.connectedInstanceId == null) { - // Re-connect to the previous instance if its in the same tab, - // otherwise do nothing for now. - if (await _isCorrectTab( - message.instanceId, services.chromeProxyService.remoteDebugger)) { - services.connectedInstanceId = message.instanceId; - await services.chromeProxyService.createIsolate(connection); - } + // Reconnect to existing service. + services.connectedInstanceId = message.instanceId; + await services.chromeProxyService.createIsolate(connection); } _appConnectionByAppId[message.appId] = connection; _connectedApps.add(connection); @@ -322,12 +303,6 @@ class DevHandler { sseConnection.sink.add(jsonEncode(serializers.serialize(RunRequest()))); } - Future _handleRunResponse(AppConnection appConnection) async { - await (await _servicesByAppId[appConnection.request.appId]) - ?.chromeProxyService - ?.resumeFromStart(); - } - void _listen() async { var injectedConnections = _sseHandler.connections; while (await injectedConnections.hasNext) { @@ -406,10 +381,3 @@ class DevHandler { }); } } - -/// Checks if connection of [remoteDebugger] is running the app with [instanceId]. -Future _isCorrectTab( - String instanceId, RemoteDebugger remoteDebugger) async { - var result = await remoteDebugger.evaluate(r'window["$dartAppInstanceId"];'); - return result.value == instanceId; -} diff --git a/dwds/lib/src/injected/client.js b/dwds/lib/src/injected/client.js index 51173eb86..5ba27c863 100644 --- a/dwds/lib/src/injected/client.js +++ b/dwds/lib/src/injected/client.js @@ -7249,20 +7249,11 @@ }, RunRequest: function RunRequest() { }, - RunResponse: function RunResponse() { - }, _$RunRequestSerializer: function _$RunRequestSerializer() { }, - _$RunResponseSerializer: function _$RunResponseSerializer() { - }, _$RunRequest: function _$RunRequest() { }, RunRequestBuilder: function RunRequestBuilder() { - }, - _$RunResponse: function _$RunResponse() { - }, - RunResponseBuilder: function RunResponseBuilder() { - this._run_request$_$v = null; } }, L = { @@ -7706,9 +7697,8 @@ }, main___closure: function main___closure() { }, - main__closure1: function main__closure1(t0, t1) { + main__closure1: function main__closure1(t0) { this.manager = t0; - this.client = t1; }, main__closure2: function main__closure2() { }, @@ -21710,7 +21700,6 @@ } }; A.RunRequest.prototype = {}; - A.RunResponse.prototype = {}; A._$RunRequestSerializer.prototype = { serialize$3$specifiedType: function(serializers, object, specifiedType) { H.interceptedTypeCheck(object, "$isRunRequest"); @@ -21741,36 +21730,6 @@ return "RunRequest"; } }; - A._$RunResponseSerializer.prototype = { - serialize$3$specifiedType: function(serializers, object, specifiedType) { - H.interceptedTypeCheck(object, "$isRunResponse"); - return H.setRuntimeTypeInfo([], [P.Object]); - }, - serialize$2: function(serializers, object) { - return this.serialize$3$specifiedType(serializers, object, C.FullType_null_List_empty); - }, - deserialize$3$specifiedType: function(serializers, serialized, specifiedType) { - H.assertSubtype(serialized, "$isIterable", [P.Object], "$asIterable"); - return new A.RunResponseBuilder().build$0(); - }, - deserialize$2: function(serializers, serialized) { - return this.deserialize$3$specifiedType(serializers, serialized, C.FullType_null_List_empty); - }, - $isSerializer: 1, - $asSerializer: function() { - return [A.RunResponse]; - }, - $isStructuredSerializer: 1, - $asStructuredSerializer: function() { - return [A.RunResponse]; - }, - get$types: function() { - return C.List_69t; - }, - get$wireName: function() { - return "RunResponse"; - } - }; A._$RunRequest.prototype = { $eq: function(_, other) { if (other == null) @@ -21787,29 +21746,6 @@ } }; A.RunRequestBuilder.prototype = {}; - A._$RunResponse.prototype = { - $eq: function(_, other) { - if (other == null) - return false; - if (other === this) - return true; - return other instanceof A.RunResponse; - }, - get$hashCode: function(_) { - return 11131040; - }, - toString$0: function(_) { - return J.toString$0$($.$get$newBuiltValueToStringHelper().call$1("RunResponse")); - } - }; - A.RunResponseBuilder.prototype = { - build$0: function() { - var _$result = this._run_request$_$v; - if (_$result == null) - _$result = new A._$RunResponse(); - return this._run_request$_$v = _$result; - } - }; V.Int64.prototype = { $add: function(_, other) { var o = V.Int64__promote(other), @@ -22677,7 +22613,7 @@ self.$dartHotRestart = t4; t4 = P.allowInterop(new D.main__closure0(client), {func: 1, ret: -1}); self.$launchDevTools = t4; - new P._ControllerStream(t2, [H.getTypeArgumentByIndex(t2, 0)]).listen$2$onError(new D.main__closure1(manager, client), new D.main__closure2()); + new P._ControllerStream(t2, [H.getTypeArgumentByIndex(t2, 0)]).listen$2$onError(new D.main__closure1(manager), new D.main__closure2()); t2 = W.KeyboardEvent; W._EventStreamSubscription$(window, "keydown", H.functionTypeCheck(new D.main__closure3(), {func: 1, ret: -1, args: [t2]}), false, t2); if (D._isChrome()) { @@ -22739,7 +22675,7 @@ $call$body$main__closure: function(serialized) { var $async$goto = 0, $async$completer = P._makeAsyncAwaitCompleter(P.Null), - $async$self = this, t1, $event, t2; + $async$self = this, $event, t1; var $async$call$1 = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { if ($async$errorCode === 1) return P._asyncRethrow($async$result, $async$completer); @@ -22747,10 +22683,9 @@ switch ($async$goto) { case 0: // Function start - t1 = $.$get$serializers(); - $event = t1.deserialize$1(C.C_JsonCodec.decode$2$reviver(0, serialized, null)); - t2 = J.getInterceptor$($event); - $async$goto = !!t2.$isDefaultBuildResult ? 2 : 4; + $event = $.$get$serializers().deserialize$1(C.C_JsonCodec.decode$2$reviver(0, serialized, null)); + t1 = J.getInterceptor$($event); + $async$goto = !!t1.$isDefaultBuildResult ? 2 : 4; break; case 2: // then @@ -22788,14 +22723,12 @@ break; case 4: // else - if (!!t2.$isDevToolsResponse) { + if (!!t1.$isDevToolsResponse) { if (!H.boolConversionCheck($event.success)) window.alert("DevTools failed to open with: " + H.S($event.error)); - } else if (!!t2.$isRunRequest) { - t2 = $async$self.client._outgoingController; - t2.add$1(0, H.assertSubtypeOfRuntimeType(C.C_JsonCodec.encode$2$toEncodable(t1.serialize$1(new A.RunResponseBuilder().build$0()), null), H.getTypeArgumentByIndex(t2, 0))); + } else if (!!t1.$isRunRequest) self.$dartRunMain.call$0(); - } else if (!!t2.$isErrorResponse) { + else if (!!t1.$isErrorResponse) { t1 = "Error from backend:\n\nError: " + H.S($event.error) + "\n\nStack Trace:\n" + H.S($event.stackTrace); if (typeof console != "undefined") window.console.error(t1); @@ -23551,7 +23484,7 @@ _inherit = hunkHelpers.inherit, _inheritMany = hunkHelpers.inheritMany; _inherit(P.Object, null); - _inheritMany(P.Object, [H.JS_CONST, J.Interceptor, J.JSObject, J.ArrayIterator, P.Iterable, H.CastIterator, H.Closure, P.MapMixin, P._ListBase_Object_ListMixin, H.ListIterator, P.Iterator, H.FixedLengthListMixin, H.UnmodifiableListMixin, H.Symbol, P.MapView, H.ConstantMap, H.JSInvocationMirror, H.TypeErrorDecoder, P.Error, H.ExceptionAndStackTrace, H._StackTrace, H.TypeImpl, H.LinkedHashMapCell, H.LinkedHashMapKeyIterator, H.JSSyntaxRegExp, H._MatchImplementation, H._AllMatchesIterator, H.StringMatch, H._StringAllMatchesIterator, P._TimerImpl, P._AsyncAwaitCompleter, P.Future, P._Completer, P._FutureListener, P._Future, P._AsyncCallbackEntry, P.Stream, P.StreamSubscription, P.StreamTransformerBase, P._StreamController, P._AsyncStreamControllerDispatch, P._BufferingStreamSubscription, P._StreamSinkWrapper, P._DelayedEvent, P._DelayedDone, P._PendingEvents, P._StreamIterator, P.Timer, P.AsyncError, P._ZoneFunction, P.ZoneSpecification, P._ZoneSpecification, P.ZoneDelegate, P.Zone, P._ZoneDelegate, P._Zone, P._HashMapKeyIterator, P._SetBase, P._HashSetIterator, P._LinkedHashSetCell, P._LinkedHashSetIterator, P.IterableMixin, P.ListMixin, P._UnmodifiableMapMixin, P._ListQueueIterator, P.SetMixin, P._SplayTreeNode, P._SplayTree, P._SplayTreeIterator, P.Codec, P._JsonStringifier, P._Utf8Encoder, P._Utf8Decoder, P._BigIntImpl, P.BigInt, P.bool, P.DateTime, P.num, P.Duration, P.OutOfMemoryError, P.StackOverflowError, P._Exception, P.FormatException, P.IntegerDivisionByZeroException, P.Function, P.List, P.Map, P.MapEntry, P.Null, P.Match, P.RegExp, P.RegExpMatch, P.StackTrace, P.String, P.StringBuffer, P.Symbol0, P.Type, P.Uri, P._Uri, P.UriData, P._SimpleUri, W.CssStyleDeclarationBase, W.ImmutableListMixin, W.FixedSizeListIterator, P._AcceptStructuredClone, P.JsObject, P._JSRandom, P._RectangleBase, P.ByteBuffer, P.ByteData, P.Int8List, P.Uint8List, P.Uint8ClampedList, P.Int16List, P.Uint16List, P.Int32List, P.Uint32List, P.Float32List, P.Float64List, Y.EnumClass, M.DefaultBuildResult, M._$BuildStatusSerializer, M._$DefaultBuildResultSerializer, M.DefaultBuildResultBuilder, S.BuiltList, S.ListBuilder, M.BuiltListMultimap, M.ListMultimapBuilder, A.BuiltMap, A.MapBuilder, L.BuiltSet, L.SetBuilder, E.BuiltSetMultimap, E.SetMultimapBuilder, Y.IndentingBuiltValueToStringHelper, A.JsonObject, U.SerializerPlugin, U.FullType, U.Serializer, O.BigIntSerializer, R.BoolSerializer, Y.BuiltJsonSerializers, Y.BuiltJsonSerializersBuilder, R.BuiltListMultimapSerializer, K.BuiltListSerializer, K.BuiltMapSerializer, R.BuiltSetMultimapSerializer, O.BuiltSetSerializer, Z.DateTimeSerializer, D.DoubleSerializer, K.DurationSerializer, Q.Int64Serializer, B.IntSerializer, O.JsonObjectSerializer, K.NumSerializer, K.RegExpSerializer, M.StringSerializer, O.UriSerializer, U.DefaultEquality, U.IterableEquality, U.ListEquality, U._UnorderedEquality, U._MapEntry, U.MapEquality, U.DeepCollectionEquality, E.ConnectRequest, E._$ConnectRequestSerializer, E.ConnectRequestBuilder, M.DevToolsRequest, M.DevToolsResponse, M._$DevToolsRequestSerializer, M._$DevToolsResponseSerializer, M.DevToolsRequestBuilder, M.DevToolsResponseBuilder, X.ErrorResponse, X._$ErrorResponseSerializer, X.ErrorResponseBuilder, S.ExtensionRequest, S.ExtensionResponse, S.ExtensionEvent, S._$ExtensionRequestSerializer, S._$ExtensionResponseSerializer, S._$ExtensionEventSerializer, S.ExtensionRequestBuilder, S.ExtensionResponseBuilder, S.ExtensionEventBuilder, M.IsolateExit, M.IsolateStart, M._$IsolateExitSerializer, M._$IsolateStartSerializer, M.IsolateExitBuilder, M.IsolateStartBuilder, A.RunRequest, A.RunResponse, A._$RunRequestSerializer, A._$RunResponseSerializer, A.RunRequestBuilder, A.RunResponseBuilder, V.Int64, N.Logger, N.Level, N.LogRecord, M.Context, O.Style, X.ParsedPath, R.StreamChannelMixin, F.Uuid, Z.LegacyRestarter, Q.ReloadingManager, G.Library, G.Module, X.HotReloadFailedException, X.LibraryWrapper, X.RequireRestarter]); + _inheritMany(P.Object, [H.JS_CONST, J.Interceptor, J.JSObject, J.ArrayIterator, P.Iterable, H.CastIterator, H.Closure, P.MapMixin, P._ListBase_Object_ListMixin, H.ListIterator, P.Iterator, H.FixedLengthListMixin, H.UnmodifiableListMixin, H.Symbol, P.MapView, H.ConstantMap, H.JSInvocationMirror, H.TypeErrorDecoder, P.Error, H.ExceptionAndStackTrace, H._StackTrace, H.TypeImpl, H.LinkedHashMapCell, H.LinkedHashMapKeyIterator, H.JSSyntaxRegExp, H._MatchImplementation, H._AllMatchesIterator, H.StringMatch, H._StringAllMatchesIterator, P._TimerImpl, P._AsyncAwaitCompleter, P.Future, P._Completer, P._FutureListener, P._Future, P._AsyncCallbackEntry, P.Stream, P.StreamSubscription, P.StreamTransformerBase, P._StreamController, P._AsyncStreamControllerDispatch, P._BufferingStreamSubscription, P._StreamSinkWrapper, P._DelayedEvent, P._DelayedDone, P._PendingEvents, P._StreamIterator, P.Timer, P.AsyncError, P._ZoneFunction, P.ZoneSpecification, P._ZoneSpecification, P.ZoneDelegate, P.Zone, P._ZoneDelegate, P._Zone, P._HashMapKeyIterator, P._SetBase, P._HashSetIterator, P._LinkedHashSetCell, P._LinkedHashSetIterator, P.IterableMixin, P.ListMixin, P._UnmodifiableMapMixin, P._ListQueueIterator, P.SetMixin, P._SplayTreeNode, P._SplayTree, P._SplayTreeIterator, P.Codec, P._JsonStringifier, P._Utf8Encoder, P._Utf8Decoder, P._BigIntImpl, P.BigInt, P.bool, P.DateTime, P.num, P.Duration, P.OutOfMemoryError, P.StackOverflowError, P._Exception, P.FormatException, P.IntegerDivisionByZeroException, P.Function, P.List, P.Map, P.MapEntry, P.Null, P.Match, P.RegExp, P.RegExpMatch, P.StackTrace, P.String, P.StringBuffer, P.Symbol0, P.Type, P.Uri, P._Uri, P.UriData, P._SimpleUri, W.CssStyleDeclarationBase, W.ImmutableListMixin, W.FixedSizeListIterator, P._AcceptStructuredClone, P.JsObject, P._JSRandom, P._RectangleBase, P.ByteBuffer, P.ByteData, P.Int8List, P.Uint8List, P.Uint8ClampedList, P.Int16List, P.Uint16List, P.Int32List, P.Uint32List, P.Float32List, P.Float64List, Y.EnumClass, M.DefaultBuildResult, M._$BuildStatusSerializer, M._$DefaultBuildResultSerializer, M.DefaultBuildResultBuilder, S.BuiltList, S.ListBuilder, M.BuiltListMultimap, M.ListMultimapBuilder, A.BuiltMap, A.MapBuilder, L.BuiltSet, L.SetBuilder, E.BuiltSetMultimap, E.SetMultimapBuilder, Y.IndentingBuiltValueToStringHelper, A.JsonObject, U.SerializerPlugin, U.FullType, U.Serializer, O.BigIntSerializer, R.BoolSerializer, Y.BuiltJsonSerializers, Y.BuiltJsonSerializersBuilder, R.BuiltListMultimapSerializer, K.BuiltListSerializer, K.BuiltMapSerializer, R.BuiltSetMultimapSerializer, O.BuiltSetSerializer, Z.DateTimeSerializer, D.DoubleSerializer, K.DurationSerializer, Q.Int64Serializer, B.IntSerializer, O.JsonObjectSerializer, K.NumSerializer, K.RegExpSerializer, M.StringSerializer, O.UriSerializer, U.DefaultEquality, U.IterableEquality, U.ListEquality, U._UnorderedEquality, U._MapEntry, U.MapEquality, U.DeepCollectionEquality, E.ConnectRequest, E._$ConnectRequestSerializer, E.ConnectRequestBuilder, M.DevToolsRequest, M.DevToolsResponse, M._$DevToolsRequestSerializer, M._$DevToolsResponseSerializer, M.DevToolsRequestBuilder, M.DevToolsResponseBuilder, X.ErrorResponse, X._$ErrorResponseSerializer, X.ErrorResponseBuilder, S.ExtensionRequest, S.ExtensionResponse, S.ExtensionEvent, S._$ExtensionRequestSerializer, S._$ExtensionResponseSerializer, S._$ExtensionEventSerializer, S.ExtensionRequestBuilder, S.ExtensionResponseBuilder, S.ExtensionEventBuilder, M.IsolateExit, M.IsolateStart, M._$IsolateExitSerializer, M._$IsolateStartSerializer, M.IsolateExitBuilder, M.IsolateStartBuilder, A.RunRequest, A._$RunRequestSerializer, A.RunRequestBuilder, V.Int64, N.Logger, N.Level, N.LogRecord, M.Context, O.Style, X.ParsedPath, R.StreamChannelMixin, F.Uuid, Z.LegacyRestarter, Q.ReloadingManager, G.Library, G.Module, X.HotReloadFailedException, X.LibraryWrapper, X.RequireRestarter]); _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JSArray, J.JSNumber, J.JSString, H.NativeByteBuffer, H.NativeTypedData, W.EventTarget, W.AccessibleNodeList, W.Blob, W.CssStyleValue, W.CssTransformComponent, W.CssRule, W._CssStyleDeclaration_Interceptor_CssStyleDeclarationBase, W.DataTransferItemList, W.DomException, W._DomRectList_Interceptor_ListMixin, W.DomRectReadOnly, W._DomStringList_Interceptor_ListMixin, W.DomTokenList, W.Event, W._FileList_Interceptor_ListMixin, W.Gamepad, W.History, W._HtmlCollection_Interceptor_ListMixin, W.ImageData, W.Location, W.MediaList, W._MidiInputMap_Interceptor_MapMixin, W._MidiOutputMap_Interceptor_MapMixin, W.MimeType, W._MimeTypeArray_Interceptor_ListMixin, W._NodeList_Interceptor_ListMixin, W.Plugin, W._PluginArray_Interceptor_ListMixin, W._RtcStatsReport_Interceptor_MapMixin, W.SpeechGrammar, W._SpeechGrammarList_Interceptor_ListMixin, W.SpeechRecognitionResult, W._Storage_Interceptor_MapMixin, W.StyleSheet, W._TextTrackCueList_Interceptor_ListMixin, W.TimeRanges, W.Touch, W._TouchList_Interceptor_ListMixin, W.TrackDefaultList, W.Url, W.__CssRuleList_Interceptor_ListMixin, W.__GamepadList_Interceptor_ListMixin, W.__NamedNodeMap_Interceptor_ListMixin, W.__SpeechRecognitionResultList_Interceptor_ListMixin, W.__StyleSheetList_Interceptor_ListMixin, P.KeyRange, P.Length, P._LengthList_Interceptor_ListMixin, P.Number, P._NumberList_Interceptor_ListMixin, P.PointList, P._StringList_Interceptor_ListMixin, P.Transform, P._TransformList_Interceptor_ListMixin, P.AudioBuffer, P._AudioParamMap_Interceptor_MapMixin, P._SqlResultSetRowList_Interceptor_ListMixin]); _inheritMany(J.JavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction, S.Promise, X.DartLoader, X.HotReloadableLibrary, X.JsError, X.JsMap]); _inherit(J.JSUnmodifiableArray, J.JSArray); @@ -23699,7 +23632,6 @@ _inherit(M._$IsolateExit, M.IsolateExit); _inherit(M._$IsolateStart, M.IsolateStart); _inherit(A._$RunRequest, A.RunRequest); - _inherit(A._$RunResponse, A.RunResponse); _inherit(B.InternalStyle, O.Style); _inheritMany(B.InternalStyle, [E.PosixStyle, F.UrlStyle, L.WindowsStyle]); _inherit(M.SseClient, R.StreamChannelMixin); @@ -23957,9 +23889,6 @@ C.Type_DevToolsResponse_Hhy = H.createRuntimeType(M.DevToolsResponse); C.Type__$DevToolsResponse_23h = H.createRuntimeType(M._$DevToolsResponse); C.List_41A = H.setRuntimeTypeInfo(makeConstList([C.Type_DevToolsResponse_Hhy, C.Type__$DevToolsResponse_23h]), [P.Type]); - C.Type_RunResponse_mxf = H.createRuntimeType(A.RunResponse); - C.Type__$RunResponse_23h = H.createRuntimeType(A._$RunResponse); - C.List_69t = H.setRuntimeTypeInfo(makeConstList([C.Type_RunResponse_mxf, C.Type__$RunResponse_23h]), [P.Type]); C.Type_IsolateStart_0 = H.createRuntimeType(M.IsolateStart); C.Type__$IsolateStart_o3b = H.createRuntimeType(M._$IsolateStart); C.List_6TA = H.setRuntimeTypeInfo(makeConstList([C.Type_IsolateStart_0, C.Type__$IsolateStart_o3b]), [P.Type]); @@ -24252,9 +24181,6 @@ _lazy($, "_$runRequestSerializer", "$get$_$runRequestSerializer", function() { return new A._$RunRequestSerializer(); }); - _lazy($, "_$runResponseSerializer", "$get$_$runResponseSerializer", function() { - return new A._$RunResponseSerializer(); - }); _lazy($, "serializers", "$get$serializers", function() { return $.$get$_$serializers(); }); @@ -24273,7 +24199,6 @@ t1.add$1(0, $.$get$_$isolateExitSerializer()); t1.add$1(0, $.$get$_$isolateStartSerializer()); t1.add$1(0, $.$get$_$runRequestSerializer()); - t1.add$1(0, $.$get$_$runResponseSerializer()); return t1.build$0(); }); _lazy($, "Logger_root", "$get$Logger_root", function() { diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 963436c7e..4569ed436 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:dwds/src/debugging/instance.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:pub_semver/pub_semver.dart' as semver; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; @@ -42,6 +43,9 @@ class ChromeProxyService implements VmServiceInterface { /// are dynamic and roughly map to chrome tabs. final VM _vm; + // TODO(flutter/devtools/issues/1207) - Remove. + final _vmReadyCompleter = Completer(); + /// The root URI at which we're serving. final String uri; @@ -52,6 +56,17 @@ class ChromeProxyService implements VmServiceInterface { /// Provides debugger-related functionality. Debugger _debugger; + Future get _debuggerFuture async { + return _debugger ??= await Debugger.create( + _assetHandler, + remoteDebugger, + _streamNotify, + appInspectorProvider, + uri, + _logWriter, + ); + } + AppInspector _inspector; /// Public only for testing. @@ -84,22 +99,10 @@ class ChromeProxyService implements VmServiceInterface { ..version = Platform.version; var service = ChromeProxyService._( vm, tabUrl, assetHandler, remoteDebugger, logWriter); - await service._initialize(); - await service.createIsolate(appConnection); + unawaited(service.createIsolate(appConnection)); return service; } - Future _initialize() async { - _debugger = await Debugger.create( - _assetHandler, - remoteDebugger, - _streamNotify, - appInspectorProvider, - uri, - _logWriter, - ); - } - /// Creates a new isolate. /// /// Only one isolate at a time is supported, but they should be cleaned up @@ -111,18 +114,24 @@ class ChromeProxyService implements VmServiceInterface { 'Cannot create multiple isolates for the same app'); } + var debugger = await _debuggerFuture; + var instanceHelper = - InstanceHelper(_debugger, remoteDebugger, appInspectorProvider); + InstanceHelper(debugger, remoteDebugger, appInspectorProvider); _inspector = await AppInspector.initialize( appConnection, remoteDebugger, _assetHandler, - _debugger, + debugger, uri, instanceHelper, ); + unawaited(appConnection.onStart.then((_) { + debugger.resumeFromStart(); + })); + var isolateRef = _inspector.isolateRef; var timestamp = DateTime.now().millisecondsSinceEpoch; @@ -156,6 +165,8 @@ class ChromeProxyService implements VmServiceInterface { isolate: isolateRef) ..extensionRPC = extensionRpc); } + + if (!_vmReadyCompleter.isCompleted) _vmReadyCompleter.complete(); } /// Should be called when there is a hot restart or full page refresh. @@ -178,8 +189,9 @@ class ChromeProxyService implements VmServiceInterface { @override Future addBreakpoint(String isolateId, String scriptId, int line, - {int column}) => - _debugger.addBreakpoint(isolateId, scriptId, line, column: column); + {int column}) async => + (await _debuggerFuture) + .addBreakpoint(isolateId, scriptId, line, column: column); @override Future addBreakpointAtEntry(String isolateId, String functionId) { @@ -192,7 +204,8 @@ class ChromeProxyService implements VmServiceInterface { {int column}) async { var dartUri = DartUri(scriptUri, uri); var ref = await _inspector.scriptRefFor(dartUri.serverPath); - return _debugger.addBreakpoint(isolateId, ref.id, line, column: column); + return (await _debuggerFuture) + .addBreakpoint(isolateId, ref.id, line, column: column); } @override @@ -300,10 +313,14 @@ $loadModule("dart_sdk").developer.invokeExtension( /// /// Returns null if the corresponding isolate is not paused. @override - Future getStack(String isolateId) => _debugger.getStack(isolateId); + Future getStack(String isolateId) async => + (await _debuggerFuture).getStack(isolateId); @override - Future getVM() => Future.value(_vm); + Future getVM() async { + await _vmReadyCompleter.future; + return _vm; + } @override Future getVMTimeline({int timeOriginMicros, int timeExtentMicros}) { @@ -377,7 +394,8 @@ $loadModule("dart_sdk").developer.invokeExtension( } @override - Future pause(String isolateId) => _debugger.pause(); + Future pause(String isolateId) async => + (await _debuggerFuture).pause(); @override Future registerService(String service, String alias) async { @@ -391,15 +409,16 @@ $loadModule("dart_sdk").developer.invokeExtension( } @override - Future removeBreakpoint(String isolateId, String breakpointId) => - _debugger.removeBreakpoint(isolateId, breakpointId); + Future removeBreakpoint( + String isolateId, String breakpointId) async => + (await _debuggerFuture).removeBreakpoint(isolateId, breakpointId); @override Future resume(String isolateId, {String step, int frameIndex}) async { if (_inspector.appConnection.isStarted) { - return await _debugger.resume(isolateId, - step: step, frameIndex: frameIndex); + return await (await _debuggerFuture) + .resume(isolateId, step: step, frameIndex: frameIndex); } else { _inspector.appConnection.runMain(); return Success(); @@ -407,8 +426,8 @@ $loadModule("dart_sdk").developer.invokeExtension( } @override - Future setExceptionPauseMode(String isolateId, String mode) => - _debugger.setExceptionPauseMode(isolateId, mode); + Future setExceptionPauseMode(String isolateId, String mode) async => + (await _debuggerFuture).setExceptionPauseMode(isolateId, mode); @override Future setFlag(String name, String value) { @@ -469,9 +488,6 @@ $loadModule("dart_sdk").developer.invokeExtension( throw UnimplementedError(); } - /// Resumes the [Isolate] from start. - Future resumeFromStart() async => _debugger.resumeFromStart(); - /// Returns a streamController that listens for console logs from chrome and /// adds all events passing [filter] to the stream. StreamController _chromeConsoleStreamController( diff --git a/dwds/web/client.dart b/dwds/web/client.dart index dd6201f00..409af0e29 100644 --- a/dwds/web/client.dart +++ b/dwds/web/client.dart @@ -79,7 +79,6 @@ Future main() { window.alert('DevTools failed to open with: ${event.error}'); } } else if (event is RunRequest) { - client.sink.add(jsonEncode(serializers.serialize(RunResponse()))); runMain(); } else if (event is ErrorResponse) { window.console.error('Error from backend:\n\nError: ${event.error}\n\n' From d872492314465eb36511e7ff4cb0a52f79401469 Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 11:19:17 -0700 Subject: [PATCH 2/8] fix tests --- dwds/lib/src/debugging/debugger.dart | 1 + dwds/test/run_request_test.dart | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart index f88295f71..7c2d01de3 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -473,6 +473,7 @@ class Debugger extends Domain { timestamp: DateTime.now().millisecondsSinceEpoch, isolate: inspector.isolateRef); isolate.pauseEvent = event; + print('NOTIFYING'); _streamNotify('Debug', event); } diff --git a/dwds/test/run_request_test.dart b/dwds/test/run_request_test.dart index 4fa05633a..dc4f7737d 100644 --- a/dwds/test/run_request_test.dart +++ b/dwds/test/run_request_test.dart @@ -2,8 +2,11 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:async'; + import 'package:dwds/src/connections/debug_connection.dart'; import 'package:dwds/src/services/chrome_proxy_service.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; @@ -29,8 +32,15 @@ void main() { var isolate = await service.getIsolate(vm.isolates.first.id); expect(isolate.pauseEvent.kind, EventKind.kPauseStart); var stream = service.onEvent('Debug'); + var resumeCompleter = Completer(); + // The underlying stream is a broadcast stream so we need to add a + // listener before calling resume so that we don't miss events. + unawaited(stream + .firstWhere((event) => event.kind == EventKind.kResume) + .then((_) { + resumeCompleter.complete(); + })); await service.resume(isolate.id); - await stream.firstWhere((event) => event.kind == EventKind.kResume); expect(isolate.pauseEvent.kind, EventKind.kResume); }); From ba29bf1f1534bcb26c401badbf421537baf9a10c Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 12:12:48 -0700 Subject: [PATCH 3/8] changelog --- dwds/CHANGELOG.md | 1 + .../src/services/chrome_proxy_service.dart | 51 +++++++++---------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 6fbafb1ba..4fe34f3ec 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -2,6 +2,7 @@ - Fix an issue where resuming while paused at the start would cause an error. - Expose the `ChromeDebugException` class for error handling purposes. +- DevTools will now launch immediately and lazily sets up necessary state. ## 0.7.4 diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 4569ed436..704f95038 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -53,19 +53,10 @@ class ChromeProxyService implements VmServiceInterface { final AssetHandler _assetHandler; - /// Provides debugger-related functionality. - Debugger _debugger; + final _debuggerCompleter = Completer(); - Future get _debuggerFuture async { - return _debugger ??= await Debugger.create( - _assetHandler, - remoteDebugger, - _streamNotify, - appInspectorProvider, - uri, - _logWriter, - ); - } + /// Provides debugger-related functionality. + Future get _debugger => _debuggerCompleter.future; AppInspector _inspector; @@ -82,7 +73,16 @@ class ChromeProxyService implements VmServiceInterface { this._assetHandler, this.remoteDebugger, this._logWriter, - ); + ) { + _debuggerCompleter.complete(Debugger.create( + _assetHandler, + remoteDebugger, + _streamNotify, + appInspectorProvider, + uri, + _logWriter, + )); + } static Future create( RemoteDebugger remoteDebugger, @@ -114,22 +114,20 @@ class ChromeProxyService implements VmServiceInterface { 'Cannot create multiple isolates for the same app'); } - var debugger = await _debuggerFuture; - var instanceHelper = - InstanceHelper(debugger, remoteDebugger, appInspectorProvider); + InstanceHelper(await _debugger, remoteDebugger, appInspectorProvider); _inspector = await AppInspector.initialize( appConnection, remoteDebugger, _assetHandler, - debugger, + await _debugger, uri, instanceHelper, ); - unawaited(appConnection.onStart.then((_) { - debugger.resumeFromStart(); + unawaited(appConnection.onStart.then((_) async { + unawaited((await _debugger).resumeFromStart()); })); var isolateRef = _inspector.isolateRef; @@ -190,7 +188,7 @@ class ChromeProxyService implements VmServiceInterface { @override Future addBreakpoint(String isolateId, String scriptId, int line, {int column}) async => - (await _debuggerFuture) + (await _debugger) .addBreakpoint(isolateId, scriptId, line, column: column); @override @@ -204,7 +202,7 @@ class ChromeProxyService implements VmServiceInterface { {int column}) async { var dartUri = DartUri(scriptUri, uri); var ref = await _inspector.scriptRefFor(dartUri.serverPath); - return (await _debuggerFuture) + return (await _debugger) .addBreakpoint(isolateId, ref.id, line, column: column); } @@ -314,7 +312,7 @@ $loadModule("dart_sdk").developer.invokeExtension( /// Returns null if the corresponding isolate is not paused. @override Future getStack(String isolateId) async => - (await _debuggerFuture).getStack(isolateId); + (await _debugger).getStack(isolateId); @override Future getVM() async { @@ -394,8 +392,7 @@ $loadModule("dart_sdk").developer.invokeExtension( } @override - Future pause(String isolateId) async => - (await _debuggerFuture).pause(); + Future pause(String isolateId) async => (await _debugger).pause(); @override Future registerService(String service, String alias) async { @@ -411,13 +408,13 @@ $loadModule("dart_sdk").developer.invokeExtension( @override Future removeBreakpoint( String isolateId, String breakpointId) async => - (await _debuggerFuture).removeBreakpoint(isolateId, breakpointId); + (await _debugger).removeBreakpoint(isolateId, breakpointId); @override Future resume(String isolateId, {String step, int frameIndex}) async { if (_inspector.appConnection.isStarted) { - return await (await _debuggerFuture) + return await (await _debugger) .resume(isolateId, step: step, frameIndex: frameIndex); } else { _inspector.appConnection.runMain(); @@ -427,7 +424,7 @@ $loadModule("dart_sdk").developer.invokeExtension( @override Future setExceptionPauseMode(String isolateId, String mode) async => - (await _debuggerFuture).setExceptionPauseMode(isolateId, mode); + (await _debugger).setExceptionPauseMode(isolateId, mode); @override Future setFlag(String name, String value) { From 303ff5eeb5c4a6a9302a12477ecfaa7836fe5a38 Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 12:14:35 -0700 Subject: [PATCH 4/8] remove debugging print --- dwds/lib/src/debugging/debugger.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart index 7c2d01de3..f88295f71 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -473,7 +473,6 @@ class Debugger extends Domain { timestamp: DateTime.now().millisecondsSinceEpoch, isolate: inspector.isolateRef); isolate.pauseEvent = event; - print('NOTIFYING'); _streamNotify('Debug', event); } From e5117451e333d11eb44a39e21db7b0118f54659c Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 12:19:03 -0700 Subject: [PATCH 5/8] rebuild client --- dwds/lib/src/injected/client.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/dwds/lib/src/injected/client.js b/dwds/lib/src/injected/client.js index 189721e64..6e0667240 100644 --- a/dwds/lib/src/injected/client.js +++ b/dwds/lib/src/injected/client.js @@ -22644,23 +22644,13 @@ case 4: // join manager = new Q.ReloadingManager(client, restarter); -<<<<<<< HEAD - t4 = P.allowInterop(new D.main__closure(manager), {func: 1, ret: [S.Promise, -2]}); - self.$dartHotRestart = t4; - t4 = P.allowInterop(new D.main__closure0(client), {func: 1, ret: -1}); - self.$launchDevTools = t4; - new P._ControllerStream(t2, [H.getTypeArgumentByIndex(t2, 0)]).listen$2$onError(new D.main__closure1(manager), new D.main__closure2()); - t2 = W.KeyboardEvent; - W._EventStreamSubscription$(window, "keydown", H.functionTypeCheck(new D.main__closure3(), {func: 1, ret: -1, args: [t2]}), false, t2); -======= t2 = P.allowInterop(new D.main__closure(manager), {func: 1, ret: [S.Promise, -2]}); self.$dartHotRestart = t2; t2 = P.allowInterop(new D.main__closure0(client), {func: 1, ret: -1}); self.$launchDevTools = t2; - new P._ControllerStream(t3, [H.getTypeArgumentByIndex(t3, 0)]).listen$2$onError(new D.main__closure1(manager, client), new D.main__closure2()); + new P._ControllerStream(t3, [H.getTypeArgumentByIndex(t3, 0)]).listen$2$onError(new D.main__closure1(manager), new D.main__closure2()); t3 = W.KeyboardEvent; W._EventStreamSubscription$(window, "keydown", H.functionTypeCheck(new D.main__closure3(), {func: 1, ret: -1, args: [t3]}), false, t3); ->>>>>>> master if (D._isChrome()) { t2 = $.$get$serializers(); t3 = new E.ConnectRequestBuilder(); From 17c8fc35a3d6e1e986c836a6bd76f0163d314447 Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 13:08:01 -0700 Subject: [PATCH 6/8] respond to comments --- dwds/lib/src/connections/app_connection.dart | 10 +++++----- dwds/lib/src/services/chrome_proxy_service.dart | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dwds/lib/src/connections/app_connection.dart b/dwds/lib/src/connections/app_connection.dart index 2dabe3180..6f2e7ec28 100644 --- a/dwds/lib/src/connections/app_connection.dart +++ b/dwds/lib/src/connections/app_connection.dart @@ -15,19 +15,19 @@ import '../../data/serializers.dart'; class AppConnection { /// The initial connection request sent from the application in the browser. final ConnectRequest request; - final _startCompleter = Completer(); + final _startedCompleter = Completer(); final SseConnection _connection; AppConnection(this.request, this._connection); - bool get isStarted => _startCompleter.isCompleted; - Future get onStart => _startCompleter.future; + bool get isStarted => _startedCompleter.isCompleted; + Future get onStart => _startedCompleter.future; void runMain() { - if (_startCompleter.isCompleted) { + if (_startedCompleter.isCompleted) { throw StateError('Main has already started.'); } _connection.sink.add(jsonEncode(serializers.serialize(RunRequest()))); - _startCompleter.complete(); + _startedCompleter.complete(); } } diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 704f95038..4c04b65fb 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -44,7 +44,7 @@ class ChromeProxyService implements VmServiceInterface { final VM _vm; // TODO(flutter/devtools/issues/1207) - Remove. - final _vmReadyCompleter = Completer(); + final _vmReadyCompleter = Completer(); /// The root URI at which we're serving. final String uri; @@ -127,7 +127,7 @@ class ChromeProxyService implements VmServiceInterface { ); unawaited(appConnection.onStart.then((_) async { - unawaited((await _debugger).resumeFromStart()); + await (await _debugger).resumeFromStart(); })); var isolateRef = _inspector.isolateRef; From f05818d31a6fb9381fb4966b69081d77c77752ca Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 13:53:02 -0700 Subject: [PATCH 7/8] fix tests --- dwds/test/fixtures/context.dart | 5 ++++- dwds/test/run_request_test.dart | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 919d59740..8c685ea41 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -11,8 +11,8 @@ import 'package:build_daemon/data/build_status.dart'; import 'package:build_daemon/data/build_target.dart'; import 'package:dwds/dwds.dart'; import 'package:dwds/src/debugging/webkit_debugger.dart'; -import 'package:dwds/src/utilities/shared.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds/src/utilities/shared.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; import 'package:webdriver/io.dart'; @@ -164,6 +164,9 @@ class TestContext { Future startDebugging() async { debugConnection = await testServer.dwds.debugConnection(appConnection); + // Wait for the VM to be ready so that we are guaranteed that the first + // isolate is created. + await debugConnection.vmService.getVM(); webkitDebugger = WebkitDebugger(WipDebugger(tabConnection)); } diff --git a/dwds/test/run_request_test.dart b/dwds/test/run_request_test.dart index dc4f7737d..b0b9ea075 100644 --- a/dwds/test/run_request_test.dart +++ b/dwds/test/run_request_test.dart @@ -41,6 +41,7 @@ void main() { resumeCompleter.complete(); })); await service.resume(isolate.id); + await resumeCompleter.future; expect(isolate.pauseEvent.kind, EventKind.kResume); }); From 76b454de18f2790f434ff422cca23ab1ef1215a2 Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 17 Oct 2019 15:47:02 -0700 Subject: [PATCH 8/8] fix tests --- dwds/lib/dwds.dart | 1 + dwds/lib/src/services/chrome_proxy_service.dart | 10 ++++++---- dwds/test/fixtures/context.dart | 3 --- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dwds/lib/dwds.dart b/dwds/lib/dwds.dart index 1d0229e54..d7eb6c7e1 100644 --- a/dwds/lib/dwds.dart +++ b/dwds/lib/dwds.dart @@ -50,6 +50,7 @@ class Dwds { Future debugConnection(AppConnection appConnection) async { if (!_enableDebugging) throw StateError('Debugging is not enabled.'); var appDebugServices = await _devHandler.loadAppServices(appConnection); + await appDebugServices.chromeProxyService.isInitialized; return DebugConnection(appDebugServices); } diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 4c04b65fb..5ffe410d3 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -43,8 +43,9 @@ class ChromeProxyService implements VmServiceInterface { /// are dynamic and roughly map to chrome tabs. final VM _vm; - // TODO(flutter/devtools/issues/1207) - Remove. - final _vmReadyCompleter = Completer(); + final _initializedCompleter = Completer(); + + Future get isInitialized => _initializedCompleter.future; /// The root URI at which we're serving. final String uri; @@ -164,7 +165,8 @@ class ChromeProxyService implements VmServiceInterface { ..extensionRPC = extensionRpc); } - if (!_vmReadyCompleter.isCompleted) _vmReadyCompleter.complete(); + // The service is considered initialized when the first isolate is created. + if (!_initializedCompleter.isCompleted) _initializedCompleter.complete(); } /// Should be called when there is a hot restart or full page refresh. @@ -316,7 +318,7 @@ $loadModule("dart_sdk").developer.invokeExtension( @override Future getVM() async { - await _vmReadyCompleter.future; + await isInitialized; return _vm; } diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 8c685ea41..f88a69ce7 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -164,9 +164,6 @@ class TestContext { Future startDebugging() async { debugConnection = await testServer.dwds.debugConnection(appConnection); - // Wait for the VM to be ready so that we are guaranteed that the first - // isolate is created. - await debugConnection.vmService.getVM(); webkitDebugger = WebkitDebugger(WipDebugger(tabConnection)); }