diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index f2e116911..226aa5a9a 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -5,6 +5,8 @@ - Fix pausing starting of `main` after the hot restart. - Updating bootstrapper for DDC library bundler module format + Frontend Server. - Fix setting up breakpoints when handling in-app restarts with attached debugger. +- Fix setting up breakpoints when handling full reloads from attached + debugger / page refreshes. ## 26.2.2 diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index 2a415b0f3..b92a646fb 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -636,21 +636,11 @@ class DevHandler { readyToRunMainCompleter.future, ); - // We can take over a connection if there is no connectedInstanceId (this - // means the client completely disconnected), or if the existing - // AppConnection is in the KeepAlive state (this means it disconnected but - // is still waiting for a possible reconnect - this happens during a page - // reload). - final canReconnect = - services != null && - (services.connectedInstanceId == null || - existingConnection?.isInKeepAlivePeriod == true); - - if (canReconnect) { + if (_canReconnect(existingConnection, message)) { // Disconnect any old connection (eg. those in the keep-alive waiting // state when reloading the page). existingConnection?.shutDown(); - final chromeProxy = services.proxyService; + final chromeProxy = services!.proxyService; if (chromeProxy is ChromeProxyService) { chromeProxy.destroyIsolate(); } @@ -703,24 +693,10 @@ class DevHandler { readyToRunMainCompleter.future, ); - // Allow connection reuse for page refreshes and same instance reconnections - final isSameInstance = - existingConnection?.request.instanceId == message.instanceId; - final isKeepAliveReconnect = - existingConnection?.isInKeepAlivePeriod == true; - final hasNoActiveConnection = services?.connectedInstanceId == null; - final noExistingConnection = existingConnection == null; - - final canReconnect = - services != null && - (isSameInstance || - (isKeepAliveReconnect && hasNoActiveConnection) || - (noExistingConnection && hasNoActiveConnection)); - - if (canReconnect) { + if (_canReconnect(existingConnection, message)) { // Reconnect to existing service. await _reconnectToService( - services, + services!, existingConnection, connection, message, @@ -749,6 +725,30 @@ class DevHandler { return connection; } + /// Allow connection reuse for page refreshes and same instance reconnections + bool _canReconnect( + AppConnection? existingConnection, + ConnectRequest message, + ) { + final services = _servicesByAppId[message.appId]; + + if (services == null) { + return false; + } + + if (existingConnection?.request.instanceId == message.instanceId) { + return true; + } + + final isKeepAliveReconnect = + existingConnection?.isInKeepAlivePeriod == true; + final hasNoActiveConnection = services.connectedInstanceId == null; + final noExistingConnection = existingConnection == null; + + return (isKeepAliveReconnect && hasNoActiveConnection) || + (noExistingConnection && hasNoActiveConnection); + } + /// Handles reconnection to existing services for web-socket mode. Future _reconnectToService( AppDebugServices services, diff --git a/dwds/lib/src/injected/client.js b/dwds/lib/src/injected/client.js index 57b878ba0..6db572f68 100644 --- a/dwds/lib/src/injected/client.js +++ b/dwds/lib/src/injected/client.js @@ -27899,7 +27899,7 @@ $call$body$main_closure() { var $async$goto = 0, $async$completer = A._makeAsyncAwaitCompleter(type$.void), - uri, fixedPath, fixedUri, client, _0_0, t2, manager, t3, t4, t5, debugEventController, t6, _box_0, t1; + storedInstanceId, t2, t3, uri, fixedPath, fixedUri, client, _0_0, manager, t4, t5, debugEventController, t6, _box_0, t1; var $async$call$0 = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) { if ($async$errorCode === 1) return A._asyncRethrow($async$result, $async$completer); @@ -27909,8 +27909,18 @@ // Function start _box_0 = {}; t1 = init.G; - if (A._asStringQ(t1.$dartAppInstanceId) == null) - t1.$dartAppInstanceId = new A.UuidV1(null).generate$1$options(null); + if (A._asStringQ(t1.$dartAppInstanceId) == null) { + storedInstanceId = A._asStringQ(A._asJSObject(A._asJSObject(t1.window).sessionStorage).getItem("dartAppInstanceId")); + if (storedInstanceId != null) + t1.$dartAppInstanceId = storedInstanceId; + else { + t1.$dartAppInstanceId = new A.UuidV1(null).generate$1$options(null); + t2 = A._asJSObject(A._asJSObject(t1.window).sessionStorage); + t3 = A._asStringQ(t1.$dartAppInstanceId); + t3.toString; + t2.setItem("dartAppInstanceId", t3); + } + } uri = A.Uri_parse(A._asString(t1.$dwdsDevHandlerPath)); if (A._asString(A._asJSObject(A._asJSObject(t1.window).location).protocol) === "https:" && uri.get$scheme() === "http" && uri.get$host() !== "localhost") uri = uri.replace$1$scheme("https"); diff --git a/dwds/web/client.dart b/dwds/web/client.dart index 752ea68f2..c691c13ee 100644 --- a/dwds/web/client.dart +++ b/dwds/web/client.dart @@ -47,7 +47,22 @@ Future? main() { () async { // Set the unique id for this instance of the app. // Test apps may already have this set. - dartAppInstanceId ??= const Uuid().v1(); + const dartAppInstanceIdKey = 'dartAppInstanceId'; + if (dartAppInstanceId == null) { + // Check the session storage for the instance id. + final storedInstanceId = window.sessionStorage.getItem( + dartAppInstanceIdKey, + ); + if (storedInstanceId != null) { + dartAppInstanceId = storedInstanceId; + } else { + dartAppInstanceId = const Uuid().v1(); + window.sessionStorage.setItem( + dartAppInstanceIdKey, + dartAppInstanceId!, + ); + } + } final fixedPath = _fixProtocol(dwdsDevHandlerPath); final fixedUri = Uri.parse(fixedPath);