diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 025cbdaa3..6265b36de 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,4 +1,8 @@ -## 21.1.0-wip +## 22.0.0-wip + +**Breaking changes** + +- Refactor the parameters to `Dwds.start`. - [#2231](https://github.com/dart-lang/webdev/pull/2231). - Update the interface for ChromeProxyService.getSourceReport to match the VM service. - [#2235](https://github.com/dart-lang/webdev/pull/2235) diff --git a/dwds/lib/asset_reader.dart b/dwds/lib/asset_reader.dart index 9066a04b1..578849f30 100644 --- a/dwds/lib/asset_reader.dart +++ b/dwds/lib/asset_reader.dart @@ -3,4 +3,4 @@ // BSD-style license that can be found in the LICENSE file. export 'src/readers/asset_reader.dart' - show AssetReader, UrlEncoder, PackageUriMapper, stripLeadingSlashes; + show AssetReader, PackageUriMapper, stripLeadingSlashes; diff --git a/dwds/lib/config.dart b/dwds/lib/config.dart new file mode 100644 index 000000000..aaf119321 --- /dev/null +++ b/dwds/lib/config.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2023, 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. + +export 'src/config/tool_configuration.dart' + show + AppMetadata, + ToolConfiguration, + UrlEncoder, + DevToolsLauncher, + DebugSettings; diff --git a/dwds/lib/dart_web_debug_service.dart b/dwds/lib/dart_web_debug_service.dart index b68e07416..467e568d1 100644 --- a/dwds/lib/dart_web_debug_service.dart +++ b/dwds/lib/dart_web_debug_service.dart @@ -5,18 +5,16 @@ import 'dart:async'; import 'package:dwds/data/build_result.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'; import 'package:dwds/src/events.dart'; import 'package:dwds/src/handlers/dev_handler.dart'; import 'package:dwds/src/handlers/injector.dart'; import 'package:dwds/src/handlers/socket_connections.dart'; -import 'package:dwds/src/loaders/strategy.dart'; import 'package:dwds/src/readers/asset_reader.dart'; import 'package:dwds/src/servers/devtools.dart'; import 'package:dwds/src/servers/extension_backend.dart'; -import 'package:dwds/src/services/expression_compiler.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:logging/logging.dart'; import 'package:shelf/shelf.dart'; import 'package:sse/server/sse_handler.dart'; @@ -66,36 +64,16 @@ class Dwds { required AssetReader assetReader, required Stream buildResults, required ConnectionProvider chromeConnection, - required LoadStrategy loadStrategy, - required bool enableDebugging, - // TODO(annagrin): make expressionCompiler argument required - // [issue 881](https://github.com/dart-lang/webdev/issues/881) - ExpressionCompiler? expressionCompiler, - bool enableDebugExtension = false, - String hostname = 'localhost', - bool useSseForDebugProxy = true, - bool useSseForDebugBackend = true, - bool useSseForInjectedClient = true, - UrlEncoder? urlEncoder, - bool spawnDds = true, - // TODO(elliette): DevTools is inconsistently capitalized throughout this - // file. Change all occurrences of devtools/Devtools to devTools/DevTools. - bool enableDevtoolsLaunch = true, - DevtoolsLauncher? devtoolsLauncher, - bool launchDevToolsInNewWindow = true, - bool emitDebugEvents = true, - bool isInternalBuild = false, - Future Function()? isFlutterApp, + required ToolConfiguration toolConfiguration, }) async { - globalLoadStrategy = loadStrategy; - globalIsInternalBuild = isInternalBuild; - isFlutterApp ??= () => Future.value(true); - + globalToolConfiguration = toolConfiguration; + final debugSettings = toolConfiguration.debugSettings; + final appMetadata = toolConfiguration.appMetadata; DevTools? devTools; Future? extensionUri; ExtensionBackend? extensionBackend; - if (enableDebugExtension) { - final handler = useSseForDebugBackend + if (debugSettings.enableDebugExtension) { + final handler = debugSettings.useSseForDebugBackend ? SseSocketHandler( SseHandler( Uri.parse('/\$debug'), @@ -108,34 +86,32 @@ class Dwds { ) : WebSocketSocketHandler(); - extensionBackend = await ExtensionBackend.start(handler, hostname); + extensionBackend = + await ExtensionBackend.start(handler, appMetadata.hostname); extensionUri = Future.value( Uri( - scheme: useSseForDebugBackend ? 'http' : 'ws', + scheme: debugSettings.useSseForDebugBackend ? 'http' : 'ws', host: extensionBackend.hostname, port: extensionBackend.port, path: r'$debug', ).toString(), ); - if (urlEncoder != null) extensionUri = urlEncoder(await extensionUri); + final urlEncoder = debugSettings.urlEncoder; + if (urlEncoder != null) { + extensionUri = urlEncoder(await extensionUri); + } } - final serveDevTools = devtoolsLauncher != null; - if (serveDevTools) { - devTools = await devtoolsLauncher(hostname); + final devToolsLauncher = debugSettings.devToolsLauncher; + if (devToolsLauncher != null) { + devTools = await devToolsLauncher(appMetadata.hostname); final uri = Uri(scheme: 'http', host: devTools.hostname, port: devTools.port); _logger.info('Serving DevTools at $uri\n'); } final injected = DwdsInjector( - loadStrategy, - useSseForInjectedClient: useSseForInjectedClient, extensionUri: extensionUri, - enableDevtoolsLaunch: enableDevtoolsLaunch, - emitDebugEvents: emitDebugEvents, - isInternalBuild: isInternalBuild, - isFlutterApp: isFlutterApp, ); final devHandler = DevHandler( @@ -143,15 +119,15 @@ class Dwds { buildResults, devTools, assetReader, - hostname, + appMetadata.hostname, extensionBackend, - urlEncoder, - useSseForDebugProxy, - useSseForInjectedClient, - expressionCompiler, + debugSettings.urlEncoder, + debugSettings.useSseForDebugProxy, + debugSettings.useSseForInjectedClient, + debugSettings.expressionCompiler, injected, - spawnDds, - launchDevToolsInNewWindow, + debugSettings.spawnDds, + debugSettings.launchDevToolsInNewWindow, ); return Dwds._( @@ -159,7 +135,7 @@ class Dwds { devTools, devHandler, assetReader, - enableDebugging, + debugSettings.enableDebugging, ); } } diff --git a/dwds/lib/dwds.dart b/dwds/lib/dwds.dart index 3b67f1a14..7824f2e24 100644 --- a/dwds/lib/dwds.dart +++ b/dwds/lib/dwds.dart @@ -3,6 +3,13 @@ // BSD-style license that can be found in the LICENSE file. export 'dart_web_debug_service.dart' show Dwds, ConnectionProvider; +export 'src/config/tool_configuration.dart' + show + AppMetadata, + UrlEncoder, + DevToolsLauncher, + DebugSettings, + ToolConfiguration; export 'src/connections/app_connection.dart' show AppConnection; export 'src/connections/debug_connection.dart' show DebugConnection; export 'src/debugging/metadata/provider.dart' @@ -17,8 +24,7 @@ export 'src/loaders/frontend_server_require.dart' export 'src/loaders/legacy.dart' show LegacyStrategy; export 'src/loaders/require.dart' show RequireStrategy; export 'src/loaders/strategy.dart' show LoadStrategy, ReloadConfiguration; -export 'src/readers/asset_reader.dart' - show AssetReader, UrlEncoder, PackageUriMapper; +export 'src/readers/asset_reader.dart' show AssetReader, PackageUriMapper; export 'src/readers/frontend_server_asset_reader.dart' show FrontendServerAssetReader; export 'src/readers/proxy_server_asset_reader.dart' show ProxyServerAssetReader; diff --git a/dwds/lib/src/config/tool_configuration.dart b/dwds/lib/src/config/tool_configuration.dart new file mode 100644 index 000000000..17d9fe842 --- /dev/null +++ b/dwds/lib/src/config/tool_configuration.dart @@ -0,0 +1,83 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:dwds/src/loaders/strategy.dart'; +import 'package:dwds/src/servers/devtools.dart'; +import 'package:dwds/src/services/expression_compiler.dart'; + +/// Configuration about the app, debug settings, and file system. +/// +/// This is set by the code runner and passed to DWDS on start up. +class ToolConfiguration { + final LoadStrategy loadStrategy; + final DebugSettings debugSettings; + final AppMetadata appMetadata; + + ToolConfiguration({ + required this.loadStrategy, + required this.debugSettings, + required this.appMetadata, + }); +} + +/// The tool configuration for the connected app. +/// +/// TODO(elliette): Consider making this final (would require updating tests +/// that currently depend on changing the configuration between test cases). +late ToolConfiguration _globalToolConfiguration; +set globalToolConfiguration(ToolConfiguration configuration) => + _globalToolConfiguration = configuration; +ToolConfiguration get globalToolConfiguration => _globalToolConfiguration; + +/// Metadata for the connected app. +/// +/// These are set by the code runner and passed to DWDS on start up. +class AppMetadata { + final String hostname; + final bool isInternalBuild; + Future Function() isFlutterApp; + + AppMetadata({ + this.hostname = 'localhost', + this.isInternalBuild = false, + Future Function()? isFlutterApp, + }) : isFlutterApp = isFlutterApp ?? (() => Future.value(true)); +} + +typedef UrlEncoder = Future Function(String url); + +typedef DevToolsLauncher = Future Function(String hostname); + +/// Debug settings for the connected app. +/// +/// These are set by the code runner and passed to DWDS on start up. +class DebugSettings { + final bool enableDebugging; + final bool enableDebugExtension; + final bool useSseForDebugProxy; + final bool useSseForDebugBackend; + final bool useSseForInjectedClient; + final bool spawnDds; + final bool enableDevToolsLaunch; + final bool launchDevToolsInNewWindow; + final bool emitDebugEvents; + final DevToolsLauncher? devToolsLauncher; + final ExpressionCompiler? expressionCompiler; + final UrlEncoder? urlEncoder; + + DebugSettings({ + this.enableDebugging = true, + this.enableDebugExtension = false, + this.useSseForDebugProxy = true, + this.useSseForDebugBackend = true, + this.useSseForInjectedClient = true, + this.spawnDds = true, + this.enableDevToolsLaunch = true, + this.launchDevToolsInNewWindow = true, + this.emitDebugEvents = true, + this.devToolsLauncher, + this.expressionCompiler, + this.urlEncoder, + }); +} diff --git a/dwds/lib/src/debugging/classes.dart b/dwds/lib/src/debugging/classes.dart index cf24e079f..7f4de281d 100644 --- a/dwds/lib/src/debugging/classes.dart +++ b/dwds/lib/src/debugging/classes.dart @@ -2,10 +2,10 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/metadata/class.dart'; import 'package:dwds/src/services/chrome_debug_exception.dart'; import 'package:dwds/src/utilities/domain.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/shared.dart'; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; @@ -79,7 +79,7 @@ class ClassHelper extends Domain { final expression = ''' (function() { - const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk'); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk'); const dart = sdk.dart; return dart.getClassMetadata('$libraryUri', '$className'); })() diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart index 995f3f580..cdb4a1456 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/dart_scope.dart'; import 'package:dwds/src/debugging/frame_computer.dart'; import 'package:dwds/src/debugging/location.dart'; @@ -12,7 +13,6 @@ import 'package:dwds/src/debugging/skip_list.dart'; import 'package:dwds/src/services/chrome_debug_exception.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; import 'package:dwds/src/utilities/domain.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/objects.dart' show Property; import 'package:dwds/src/utilities/server.dart'; import 'package:dwds/src/utilities/shared.dart'; @@ -585,7 +585,9 @@ class Debugger extends Domain { throw StateError('Stepping failed in script $scriptId'); } - if (url.contains(globalLoadStrategy.loadLibrariesModule)) { + if (url.contains( + globalToolConfiguration.loadStrategy.loadLibrariesModule, + )) { await _remoteDebugger.stepOut(); return; } else if ((await _sourceLocation(e)) == null) { diff --git a/dwds/lib/src/debugging/inspector.dart b/dwds/lib/src/debugging/inspector.dart index c0ad63129..744435de7 100644 --- a/dwds/lib/src/debugging/inspector.dart +++ b/dwds/lib/src/debugging/inspector.dart @@ -6,6 +6,7 @@ import 'dart:math' as math; import 'package:async/async.dart'; import 'package:collection/collection.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/connections/app_connection.dart'; import 'package:dwds/src/debugging/classes.dart'; import 'package:dwds/src/debugging/debugger.dart'; @@ -18,7 +19,6 @@ import 'package:dwds/src/readers/asset_reader.dart'; import 'package:dwds/src/utilities/conversions.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; import 'package:dwds/src/utilities/domain.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/objects.dart'; import 'package:dwds/src/utilities/server.dart'; import 'package:dwds/src/utilities/shared.dart'; @@ -195,7 +195,7 @@ class AppInspector implements AppInspectorInterface { Future loadField(RemoteObject receiver, String fieldName) { final load = ''' function() { - return ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").dart.dloadRepl(this, "$fieldName"); + return ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").dart.dloadRepl(this, "$fieldName"); } '''; return jsCallFunctionOn(receiver, load, []); @@ -217,7 +217,7 @@ class AppInspector implements AppInspectorInterface { final send = ''' function () { if (!(this.__proto__)) { return 'Instance of PlainJavaScriptObject';} - return ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").dart.dsendRepl(this, "$methodName", arguments); + return ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").dart.dsendRepl(this, "$methodName", arguments); } '''; final remote = await jsCallFunctionOn(receiver, send, positionalArgs); @@ -350,7 +350,7 @@ class AppInspector implements AppInspectorInterface { } final findLibrary = ''' (function() { - const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk'); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk'); const dart = sdk.dart; const library = dart.getLibrary('$libraryUri'); if (!library) throw 'cannot find library for $libraryUri'; @@ -637,7 +637,7 @@ class AppInspector implements AppInspectorInterface { // want. To make those alternatives easier in JS, pass both count and end. final expression = ''' function (offset, count) { - const sdk = ${globalLoadStrategy.loadModuleSnippet}("dart_sdk"); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk"); const dart = sdk.dart; return dart.getSubRange(this, offset, count); } @@ -695,7 +695,7 @@ class AppInspector implements AppInspectorInterface { /// Returns the list of scripts refs cached. Future> _populateScriptCaches() { return _scriptCacheMemoizer.runOnce(() async { - final scripts = await globalLoadStrategy + final scripts = await globalToolConfiguration.loadStrategy .metadataProviderFor(appConnection.request.entrypointPath) .scripts; // For all the non-dart: libraries, find their parts and create scriptRefs @@ -746,7 +746,7 @@ class AppInspector implements AppInspectorInterface { /// Runs an eval on the page to compute all existing registered extensions. Future> _getExtensionRpcs() async { final expression = - "${globalLoadStrategy.loadModuleSnippet}('dart_sdk').developer._extensions.keys.toList();"; + "${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk').developer._extensions.keys.toList();"; final extensionRpcs = []; final params = { 'expression': expression, diff --git a/dwds/lib/src/debugging/instance.dart b/dwds/lib/src/debugging/instance.dart index 51eb47318..9db9c78c9 100644 --- a/dwds/lib/src/debugging/instance.dart +++ b/dwds/lib/src/debugging/instance.dart @@ -4,12 +4,12 @@ import 'dart:math'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/inspector.dart'; import 'package:dwds/src/debugging/metadata/class.dart'; import 'package:dwds/src/debugging/metadata/function.dart'; import 'package:dwds/src/utilities/conversions.dart'; import 'package:dwds/src/utilities/domain.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/objects.dart'; import 'package:dwds/src/utilities/shared.dart'; import 'package:logging/logging.dart'; @@ -892,7 +892,7 @@ class InstanceHelper extends Domain { String _jsRuntimeFunctionCall(String expression) => ''' function() { - const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk'); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk'); const dart = sdk.dart; return dart.$expression; } diff --git a/dwds/lib/src/debugging/libraries.dart b/dwds/lib/src/debugging/libraries.dart index 5a1158109..025b57f35 100644 --- a/dwds/lib/src/debugging/libraries.dart +++ b/dwds/lib/src/debugging/libraries.dart @@ -3,10 +3,10 @@ // BSD-style license that can be found in the LICENSE file. import 'package:collection/collection.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/metadata/class.dart'; import 'package:dwds/src/services/chrome_debug_exception.dart'; import 'package:dwds/src/utilities/domain.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:logging/logging.dart'; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; @@ -32,9 +32,11 @@ class LibraryHelper extends Domain { // TODO: read entrypoint from app metadata. // Issue: https://github.com/dart-lang/webdev/issues/1290 final libraries = await libraryRefs; - if (globalLoadStrategy.appEntrypoint != null) { + if (globalToolConfiguration.loadStrategy.appEntrypoint != null) { _rootLib = libraries.firstWhereOrNull( - (lib) => Uri.parse(lib.uri ?? '') == globalLoadStrategy.appEntrypoint, + (lib) => + Uri.parse(lib.uri ?? '') == + globalToolConfiguration.loadStrategy.appEntrypoint, ); } _rootLib = _rootLib ?? @@ -53,7 +55,7 @@ class LibraryHelper extends Domain { /// Note this can return a cached result. Future> get libraryRefs async { if (_libraryRefsById.isNotEmpty) return _libraryRefsById.values.toList(); - final libraries = await globalLoadStrategy + final libraries = await globalToolConfiguration.loadStrategy .metadataProviderFor(inspector.appConnection.request.entrypointPath) .libraries; for (var library in libraries) { @@ -84,7 +86,7 @@ class LibraryHelper extends Domain { // Fetch information about all the classes in this library. final expression = ''' (function() { - const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk'); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk'); const dart = sdk.dart; return dart.getLibraryMetadata('$libraryUri'); })() diff --git a/dwds/lib/src/debugging/location.dart b/dwds/lib/src/debugging/location.dart index e00996561..7895a229c 100644 --- a/dwds/lib/src/debugging/location.dart +++ b/dwds/lib/src/debugging/location.dart @@ -3,10 +3,10 @@ // BSD-style license that can be found in the LICENSE file. import 'package:async/async.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/modules.dart'; import 'package:dwds/src/readers/asset_reader.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; import 'package:source_maps/parser.dart'; @@ -177,8 +177,8 @@ class Locations { final dartUri = DartUri(url, _root); final serverPath = dartUri.serverPath; - final module = - await globalLoadStrategy.moduleForServerPath(_entrypoint, serverPath); + final module = await globalToolConfiguration.loadStrategy + .moduleForServerPath(_entrypoint, serverPath); final cache = _moduleToLocations[module]; if (cache != null) return cache; @@ -301,14 +301,14 @@ class Locations { if (module.endsWith('dart_sdk') || module.endsWith('dart_library')) { return result; } - final modulePath = - await globalLoadStrategy.serverPathForModule(_entrypoint, module); + final modulePath = await globalToolConfiguration.loadStrategy + .serverPathForModule(_entrypoint, module); if (modulePath == null) { _logger.warning('No module path for module: $module'); return result; } - final sourceMapPath = - await globalLoadStrategy.sourceMapPathForModule(_entrypoint, module); + final sourceMapPath = await globalToolConfiguration.loadStrategy + .sourceMapPathForModule(_entrypoint, module); if (sourceMapPath == null) { _logger.warning('No sourceMap path for module: $module'); return result; diff --git a/dwds/lib/src/debugging/metadata/class.dart b/dwds/lib/src/debugging/metadata/class.dart index 8c600c6a0..17bcbbc45 100644 --- a/dwds/lib/src/debugging/metadata/class.dart +++ b/dwds/lib/src/debugging/metadata/class.dart @@ -2,9 +2,9 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/services/chrome_debug_exception.dart'; import 'package:dwds/src/utilities/domain.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:logging/logging.dart'; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; @@ -154,7 +154,7 @@ class ClassMetaDataHelper { try { final evalExpression = ''' function(arg) { - const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk'); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk'); const dart = sdk.dart; return dart.getObjectMetadata(arg); } diff --git a/dwds/lib/src/debugging/metadata/function.dart b/dwds/lib/src/debugging/metadata/function.dart index 297c0e7af..07358cdaf 100644 --- a/dwds/lib/src/debugging/metadata/function.dart +++ b/dwds/lib/src/debugging/metadata/function.dart @@ -2,8 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/remote_debugger.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/server.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; @@ -19,7 +19,7 @@ class FunctionMetaData { ) async { final evalExpression = ''' function() { - const sdk = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk'); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk'); const dart = sdk.dart; return dart.getFunctionMetadata(this); } diff --git a/dwds/lib/src/debugging/modules.dart b/dwds/lib/src/debugging/modules.dart index 03835c583..37b857af1 100644 --- a/dwds/lib/src/debugging/modules.dart +++ b/dwds/lib/src/debugging/modules.dart @@ -3,8 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'package:async/async.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:logging/logging.dart'; /// Tracks modules for the compiled application. @@ -64,7 +64,8 @@ class Modules { /// Initializes [_sourceToModule] and [_sourceToLibrary]. Future _initializeMapping() async { - final provider = globalLoadStrategy.metadataProviderFor(_entrypoint); + final provider = + globalToolConfiguration.loadStrategy.metadataProviderFor(_entrypoint); final libraryToScripts = await provider.scripts; final scriptToModule = await provider.scriptToModule; diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index 51c634ac6..800447fb6 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -14,6 +14,7 @@ import 'package:dwds/data/error_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/src/config/tool_configuration.dart'; import 'package:dwds/src/connections/app_connection.dart'; import 'package:dwds/src/connections/debug_connection.dart'; import 'package:dwds/src/debugging/execution_context.dart'; diff --git a/dwds/lib/src/handlers/injector.dart b/dwds/lib/src/handlers/injector.dart index a8dc6b570..3a170a2a2 100644 --- a/dwds/lib/src/handlers/injector.dart +++ b/dwds/lib/src/handlers/injector.dart @@ -8,7 +8,7 @@ import 'dart:io'; import 'dart:isolate'; import 'package:crypto/crypto.dart'; -import 'package:dwds/src/loaders/strategy.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/version.dart'; import 'package:logging/logging.dart'; import 'package:shelf/shelf.dart'; @@ -28,30 +28,13 @@ const _clientScript = 'dwds/src/injected/client'; /// Handles injecting the DWDS client and embedding debugging related /// information. class DwdsInjector { - final LoadStrategy _loadStrategy; final Future? _extensionUri; final _devHandlerPaths = StreamController(); final _logger = Logger('DwdsInjector'); - final bool _enableDevtoolsLaunch; - final bool _useSseForInjectedClient; - final bool _emitDebugEvents; - final bool _isInternalBuild; - final Future Function() _isFlutterApp; - DwdsInjector( - this._loadStrategy, { - required bool enableDevtoolsLaunch, - required bool useSseForInjectedClient, - required bool emitDebugEvents, - required bool isInternalBuild, - required Future Function() isFlutterApp, + DwdsInjector({ Future? extensionUri, - }) : _extensionUri = extensionUri, - _enableDevtoolsLaunch = enableDevtoolsLaunch, - _useSseForInjectedClient = useSseForInjectedClient, - _emitDebugEvents = emitDebugEvents, - _isInternalBuild = isInternalBuild, - _isFlutterApp = isFlutterApp; + }) : _extensionUri = extensionUri; /// Returns the embedded dev handler paths. /// @@ -97,7 +80,8 @@ class DwdsInjector { final appId = base64 .encode(md5.convert(utf8.encode('$requestedUri')).bytes); var scheme = request.requestedUri.scheme; - if (!_useSseForInjectedClient) { + if (!globalToolConfiguration + .debugSettings.useSseForInjectedClient) { // Switch http->ws and https->wss. scheme = scheme.replaceFirst('http', 'ws'); } @@ -112,20 +96,16 @@ class DwdsInjector { devHandlerPath = '$requestedUriBase/$devHandlerPath'; _devHandlerPaths.add(devHandlerPath); final entrypoint = request.url.path; - _loadStrategy.trackEntrypoint(entrypoint); - body = _injectClientAndHoistMain( + globalToolConfiguration.loadStrategy.trackEntrypoint(entrypoint); + body = await _injectClientAndHoistMain( body, appId, devHandlerPath, entrypoint, await _extensionUri, - _loadStrategy, - _enableDevtoolsLaunch, - _emitDebugEvents, - _isInternalBuild, - await _isFlutterApp(), ); - body += await _loadStrategy.bootstrapFor(entrypoint); + body += await globalToolConfiguration.loadStrategy + .bootstrapFor(entrypoint); _logger.info('Injected debugging metadata for ' 'entrypoint at $requestedUri'); etag = base64.encode(md5.convert(body.codeUnits).bytes); @@ -136,7 +116,8 @@ class DwdsInjector { } return response.change(body: body, headers: newHeaders); } else { - final loadResponse = await _loadStrategy.handler(request); + final loadResponse = + await globalToolConfiguration.loadStrategy.handler(request); if (loadResponse.statusCode != HttpStatus.notFound) { return loadResponse; } @@ -148,18 +129,13 @@ class DwdsInjector { /// Returns the provided body with the main function hoisted into a global /// variable and a snippet of JS that loads the injected client. -String _injectClientAndHoistMain( +Future _injectClientAndHoistMain( String body, String appId, String devHandlerPath, String entrypointPath, String? extensionUri, - LoadStrategy loadStrategy, - bool enableDevtoolsLaunch, - bool emitDebugEvents, - bool isInternalBuild, - bool isFlutterApp, -) { +) async { final bodyLines = body.split('\n'); final extensionIndex = bodyLines.indexWhere((line) => line.contains(mainExtensionMarker)); @@ -171,16 +147,11 @@ String _injectClientAndHoistMain( // We inject the client in the entry point module as the client expects the // application to be in a ready state, that is the main function is hoisted // and the Dart SDK is loaded. - final injectedClientSnippet = _injectedClientSnippet( + final injectedClientSnippet = await _injectedClientSnippet( appId, devHandlerPath, entrypointPath, extensionUri, - loadStrategy, - enableDevtoolsLaunch, - emitDebugEvents, - isInternalBuild, - isFlutterApp, ); result += ''' // Injected by dwds for debugging support. @@ -207,29 +178,25 @@ String _injectClientAndHoistMain( } /// JS snippet which includes global variables required for debugging. -String _injectedClientSnippet( +Future _injectedClientSnippet( String appId, String devHandlerPath, String entrypointPath, String? extensionUri, - LoadStrategy loadStrategy, - bool enableDevtoolsLaunch, - bool emitDebugEvents, - bool isInternalBuild, - bool isFlutterApp, -) { +) async { + final isFlutterApp = await globalToolConfiguration.appMetadata.isFlutterApp(); var injectedBody = 'window.\$dartAppId = "$appId";\n' - 'window.\$dartReloadConfiguration = "${loadStrategy.reloadConfiguration}";\n' - 'window.\$dartModuleStrategy = "${loadStrategy.id}";\n' - 'window.\$loadModuleConfig = ${loadStrategy.loadModuleSnippet};\n' + 'window.\$dartReloadConfiguration = "${globalToolConfiguration.loadStrategy.reloadConfiguration}";\n' + 'window.\$dartModuleStrategy = "${globalToolConfiguration.loadStrategy.id}";\n' + 'window.\$loadModuleConfig = ${globalToolConfiguration.loadStrategy.loadModuleSnippet};\n' 'window.\$dwdsVersion = "$packageVersion";\n' 'window.\$dwdsDevHandlerPath = "$devHandlerPath";\n' - 'window.\$dwdsEnableDevtoolsLaunch = $enableDevtoolsLaunch;\n' + 'window.\$dwdsEnableDevToolsLaunch = ${globalToolConfiguration.debugSettings.enableDevToolsLaunch};\n' 'window.\$dartEntrypointPath = "$entrypointPath";\n' - 'window.\$dartEmitDebugEvents = $emitDebugEvents;\n' - 'window.\$isInternalBuild = $isInternalBuild;\n' + 'window.\$dartEmitDebugEvents = ${globalToolConfiguration.debugSettings.emitDebugEvents};\n' + 'window.\$isInternalBuild = ${globalToolConfiguration.appMetadata.isInternalBuild};\n' 'window.\$isFlutterApp = $isFlutterApp;\n' - '${loadStrategy.loadClientSnippet(_clientScript)}'; + '${globalToolConfiguration.loadStrategy.loadClientSnippet(_clientScript)}'; if (extensionUri != null) { injectedBody += 'window.\$dartExtensionUri = "$extensionUri";\n'; } diff --git a/dwds/lib/src/injected/client.js b/dwds/lib/src/injected/client.js index cf995b3be..62508e0b3 100644 --- a/dwds/lib/src/injected/client.js +++ b/dwds/lib/src/injected/client.js @@ -25487,7 +25487,7 @@ self.$emitRegisterEvent = A.allowInterop(new A.main__closure2(client), type$.void_Function_String); self.$launchDevTools = A.allowInterop(new A.main__closure3(client), type$.void_Function); client.get$stream(client).listen$2$onError(new A.main__closure4(manager), new A.main__closure5()); - if (A.boolConversionCheck(self.$dwdsEnableDevtoolsLaunch)) { + if (A.boolConversionCheck(self.$dwdsEnableDevToolsLaunch)) { t1 = window; t1.toString; A._EventStreamSubscription$(t1, "keydown", type$.nullable_void_Function_KeyboardEvent._as(new A.main__closure6()), false, type$.KeyboardEvent); diff --git a/dwds/lib/src/readers/asset_reader.dart b/dwds/lib/src/readers/asset_reader.dart index 896eb527e..a6a6fa21e 100644 --- a/dwds/lib/src/readers/asset_reader.dart +++ b/dwds/lib/src/readers/asset_reader.dart @@ -7,8 +7,6 @@ import 'package:file/file.dart'; import 'package:logging/logging.dart'; import 'package:package_config/package_config.dart'; -typedef UrlEncoder = Future Function(String url); - /// A reader for Dart sources and related source maps. abstract class AssetReader { /// Base path of the application, for example, set up in the index file: diff --git a/dwds/lib/src/servers/devtools.dart b/dwds/lib/src/servers/devtools.dart index e1deb70e7..579957dff 100644 --- a/dwds/lib/src/servers/devtools.dart +++ b/dwds/lib/src/servers/devtools.dart @@ -4,8 +4,6 @@ import 'dart:io'; -typedef DevtoolsLauncher = Future Function(String hostname); - /// A server for Dart Devtools. class DevTools { final String hostname; diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 44b4bfea4..aff62b637 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:dwds/data/debug_event.dart'; import 'package:dwds/data/register_event.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/connections/app_connection.dart'; import 'package:dwds/src/debugging/debugger.dart'; import 'package:dwds/src/debugging/execution_context.dart'; @@ -23,7 +24,6 @@ import 'package:dwds/src/services/batched_expression_evaluator.dart'; import 'package:dwds/src/services/expression_compiler.dart'; import 'package:dwds/src/services/expression_evaluator.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/shared.dart'; import 'package:logging/logging.dart' hide LogRecord; import 'package:pub_semver/pub_semver.dart' as semver; @@ -173,8 +173,9 @@ class ChromeProxyService implements VmServiceInterface { } Future _updateCompilerDependencies(String entrypoint) async { - final metadataProvider = globalLoadStrategy.metadataProviderFor(entrypoint); - final moduleFormat = globalLoadStrategy.moduleFormat; + final metadataProvider = + globalToolConfiguration.loadStrategy.metadataProviderFor(entrypoint); + final moduleFormat = globalToolConfiguration.loadStrategy.moduleFormat; final soundNullSafety = await metadataProvider.soundNullSafety; _logger.info('Initializing expression compiler for $entrypoint ' @@ -186,8 +187,8 @@ class ChromeProxyService implements VmServiceInterface { moduleFormat: moduleFormat, soundNullSafety: soundNullSafety, ); - final dependencies = - await globalLoadStrategy.moduleInfoForEntrypoint(entrypoint); + final dependencies = await globalToolConfiguration.loadStrategy + .moduleInfoForEntrypoint(entrypoint); await captureElapsedTime( () async { final result = await compiler.updateDependencies(dependencies); @@ -485,7 +486,7 @@ class ChromeProxyService implements VmServiceInterface { ), ); final expression = ''' -${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension( +${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension( "$method", JSON.stringify(${jsonEncode(stringArgs)})); '''; final result = await inspector.jsEvaluate(expression, awaitPromise: true); diff --git a/dwds/lib/src/services/debug_service.dart b/dwds/lib/src/services/debug_service.dart index 5976e7e22..de8e456c1 100644 --- a/dwds/lib/src/services/debug_service.dart +++ b/dwds/lib/src/services/debug_service.dart @@ -9,6 +9,7 @@ import 'dart:math'; import 'dart:typed_data'; import 'package:dds/dds.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/connections/app_connection.dart'; import 'package:dwds/src/debugging/execution_context.dart'; import 'package:dwds/src/debugging/remote_debugger.dart'; diff --git a/dwds/lib/src/services/expression_evaluator.dart b/dwds/lib/src/services/expression_evaluator.dart index 9d76617d2..1aca08c68 100644 --- a/dwds/lib/src/services/expression_evaluator.dart +++ b/dwds/lib/src/services/expression_evaluator.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 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/dart_scope.dart'; import 'package:dwds/src/debugging/debugger.dart'; import 'package:dwds/src/debugging/location.dart'; @@ -10,7 +11,6 @@ import 'package:dwds/src/services/expression_compiler.dart'; import 'package:dwds/src/services/javascript_builder.dart'; import 'package:dwds/src/utilities/conversions.dart'; import 'package:dwds/src/utilities/domain.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/objects.dart' as chrome; import 'package:logging/logging.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; @@ -447,7 +447,7 @@ class ExpressionEvaluator { } else if (error.startsWith('NetworkError: ')) { var modulePath = _loadModuleErrorRegex.firstMatch(error)?.group(1); final module = modulePath != null - ? await globalLoadStrategy.moduleForServerPath( + ? await globalToolConfiguration.loadStrategy.moduleForServerPath( _entrypoint, modulePath, ) diff --git a/dwds/lib/src/utilities/dart_uri.dart b/dwds/lib/src/utilities/dart_uri.dart index 5cdb44f43..f8aa66ab2 100644 --- a/dwds/lib/src/utilities/dart_uri.dart +++ b/dwds/lib/src/utilities/dart_uri.dart @@ -2,7 +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 'package:dwds/src/utilities/globals.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:logging/logging.dart'; import 'package:package_config/package_config.dart'; import 'package:path/path.dart' as p; @@ -56,7 +56,8 @@ class DartUri { /// Construct from a package: URI factory DartUri._fromDartLangUri(String uri) { - var serverPath = globalLoadStrategy.serverPathForAppUri(uri); + var serverPath = + globalToolConfiguration.loadStrategy.serverPathForAppUri(uri); if (serverPath == null) { _logger.severe('Cannot find server path for $uri'); serverPath = uri; @@ -66,7 +67,8 @@ class DartUri { /// Construct from a package: URI factory DartUri._fromPackageUri(String uri, {String? root}) { - var serverPath = globalLoadStrategy.serverPathForAppUri(uri); + var serverPath = + globalToolConfiguration.loadStrategy.serverPathForAppUri(uri); if (serverPath == null) { _logger.severe('Cannot find server path for $uri'); serverPath = uri; @@ -144,7 +146,7 @@ class DartUri { if (packageUri != null) return packageUri; // If this is an internal app, then the given uri might be g3-relative: - if (globalIsInternalBuild) { + if (globalToolConfiguration.appMetadata.isInternalBuild) { // TODO(https://github.com/dart-lang/webdev/issues/2198): Verify if the // intermediary conversion to resolvedUri is causing performance issues. final resolvedUri = _g3RelativeUriToResolvedUri[uri]; @@ -170,7 +172,9 @@ class DartUri { /// Record library and script uris to enable resolving library and script paths. static Future initialize() async { clear(); - await _loadPackageConfig(p.toUri(globalLoadStrategy.packageConfigPath)); + await _loadPackageConfig( + p.toUri(globalToolConfiguration.loadStrategy.packageConfigPath), + ); } /// Clear the uri resolution tables. @@ -185,7 +189,7 @@ class DartUri { static void recordAbsoluteUris(Iterable libraryUris) { for (var uri in libraryUris) { _recordAbsoluteUri(uri); - if (globalIsInternalBuild) { + if (globalToolConfiguration.appMetadata.isInternalBuild) { _recordG3RelativeUri(uri); } } @@ -195,7 +199,8 @@ class DartUri { final absoluteUri = _uriToResolvedUri[libraryUri]; if (absoluteUri == null) return; - final g3RelativeUri = globalLoadStrategy.g3RelativePath(absoluteUri); + final g3RelativeUri = + globalToolConfiguration.loadStrategy.g3RelativePath(absoluteUri); if (g3RelativeUri != null) { _g3RelativeUriToResolvedUri[g3RelativeUri] = absoluteUri; } diff --git a/dwds/lib/src/utilities/globals.dart b/dwds/lib/src/utilities/globals.dart deleted file mode 100644 index d8881dfd2..000000000 --- a/dwds/lib/src/utilities/globals.dart +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'package:dwds/src/loaders/strategy.dart'; - -/// The load strategy for the connected app. -late LoadStrategy _globalLoadStrategy; -set globalLoadStrategy(LoadStrategy strategy) => _globalLoadStrategy = strategy; -LoadStrategy get globalLoadStrategy => _globalLoadStrategy; - -/// Whether or not the connected app is an internal (e.g. google3) app. -bool get globalIsInternalBuild => _isInternalBuild ?? false; -bool? _isInternalBuild; -set globalIsInternalBuild(bool isInternalBuild) => - _isInternalBuild = isInternalBuild; diff --git a/dwds/lib/src/version.dart b/dwds/lib/src/version.dart index b67de3db0..64a096168 100644 --- a/dwds/lib/src/version.dart +++ b/dwds/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '21.1.0-wip'; +const packageVersion = '22.0.0-wip'; diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index defee4632..26766c056 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: 21.1.0-wip +version: 22.0.0-wip description: >- A service that proxies between the Chrome debug protocol and the Dart VM service protocol. diff --git a/dwds/test/chrome_proxy_service_test.dart b/dwds/test/chrome_proxy_service_test.dart index 63b1de556..9e5c830b0 100644 --- a/dwds/test/chrome_proxy_service_test.dart +++ b/dwds/test/chrome_proxy_service_test.dart @@ -9,9 +9,9 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/services/chrome_proxy_service.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/shared.dart'; import 'package:http/http.dart' as http; import 'package:path/path.dart' as path; @@ -668,7 +668,7 @@ void main() { Future createList() { final expr = ''' (function () { - const sdk = ${globalLoadStrategy.loadModuleSnippet}("dart_sdk"); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk"); const list = sdk.dart.dsend(sdk.core.List,"filled", [1001, 5]); list[4] = 100; return list; @@ -680,7 +680,7 @@ void main() { Future createMap() { final expr = ''' (function () { - const sdk = ${globalLoadStrategy.loadModuleSnippet}("dart_sdk"); + const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk"); const iterable = sdk.dart.dsend(sdk.core.Iterable, "generate", [1001]); const list1 = sdk.dart.dsend(iterable, "toList", []); const reversed = sdk.dart.dload(list1, "reversed"); diff --git a/dwds/test/dart_uri_test.dart b/dwds/test/dart_uri_test.dart index 55978ba3b..b2274e6b2 100644 --- a/dwds/test/dart_uri_test.dart +++ b/dwds/test/dart_uri_test.dart @@ -6,13 +6,14 @@ @Timeout(Duration(minutes: 2)) import 'package:dwds/asset_reader.dart'; +import 'package:dwds/config.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; import 'package:test_common/logging.dart'; import 'fixtures/fakes.dart'; +import 'fixtures/utilities.dart'; class TestStrategy extends FakeStrategy { TestStrategy( @@ -48,7 +49,14 @@ class G3TestStrategy extends FakeStrategy { void main() { group('DartUri', () { setUpAll(() { - globalLoadStrategy = TestStrategy(FakeAssetReader()); + final toolConfiguration = createToolConfiguration( + loadStrategy: TestStrategy( + FakeAssetReader(), + ), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); }); test('parses package : paths', () { final uri = DartUri('package:path/path.dart'); @@ -200,20 +208,19 @@ void main() { }); group('initialized to handle g3-relative paths', () { - setUpAll(() { - globalLoadStrategy = G3TestStrategy(FakeAssetReader()); - }); - setUpAll(() async { + final toolConfiguration = createToolConfiguration( + loadStrategy: G3TestStrategy(FakeAssetReader()), + appMetadata: AppMetadata(isInternalBuild: true), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); await DartUri.initialize(); - globalIsInternalBuild = true; DartUri.recordAbsoluteUris(['package:path/path.dart']); }); - tearDownAll(() { - DartUri.clear(); - globalIsInternalBuild = false; - }); + tearDownAll(DartUri.clear); test( 'can resolve g3-relative paths', diff --git a/dwds/test/debugger_test.dart b/dwds/test/debugger_test.dart index 0ea066475..96e8f8321 100644 --- a/dwds/test/debugger_test.dart +++ b/dwds/test/debugger_test.dart @@ -12,7 +12,6 @@ import 'package:dwds/src/debugging/frame_computer.dart'; import 'package:dwds/src/debugging/inspector.dart'; import 'package:dwds/src/debugging/location.dart'; import 'package:dwds/src/debugging/skip_list.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:logging/logging.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart' hide LogRecord; @@ -21,6 +20,7 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' import 'fixtures/debugger_data.dart'; import 'fixtures/fakes.dart'; +import 'fixtures/utilities.dart'; late AppInspector inspector; late Debugger debugger; @@ -87,7 +87,12 @@ void main() async { webkitDebugger = FakeWebkitDebugger(scripts: scripts); pausedController = StreamController(); webkitDebugger.onPaused = pausedController.stream; - globalLoadStrategy = TestStrategy(FakeAssetReader()); + final toolConfiguration = createToolConfiguration( + loadStrategy: TestStrategy(FakeAssetReader()), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); final root = 'fakeRoot'; locations = Locations( FakeAssetReader(sourceMap: sourceMapContents), diff --git a/dwds/test/expression_evaluator_test.dart b/dwds/test/expression_evaluator_test.dart index 498fe90d3..61349d3d1 100644 --- a/dwds/test/expression_evaluator_test.dart +++ b/dwds/test/expression_evaluator_test.dart @@ -11,7 +11,6 @@ import 'package:dwds/src/debugging/location.dart'; import 'package:dwds/src/debugging/skip_list.dart'; import 'package:dwds/src/services/batched_expression_evaluator.dart'; import 'package:dwds/src/services/expression_evaluator.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart' hide LogRecord; @@ -19,6 +18,7 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; import 'fixtures/context.dart'; import 'fixtures/fakes.dart'; +import 'fixtures/utilities.dart'; late ExpressionEvaluator? _evaluator; late ExpressionEvaluator? _batchedEvaluator; @@ -36,8 +36,12 @@ void main() async { late StreamController debugEventController; setUp(() async { final assetReader = FakeAssetReader(sourceMap: ''); - globalLoadStrategy = FakeStrategy(assetReader); - + final toolConfiguration = createToolConfiguration( + loadStrategy: FakeStrategy(assetReader), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); final modules = FakeModules(); final webkitDebugger = FakeWebkitDebugger(); diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index c926ca082..2f07d4b0a 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -10,6 +10,7 @@ import 'package:build_daemon/data/build_status.dart'; import 'package:build_daemon/data/build_target.dart'; import 'package:dwds/asset_reader.dart'; import 'package:dwds/expression_compiler.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'; import 'package:dwds/src/debugging/webkit_debugger.dart'; @@ -155,7 +156,24 @@ class TestContext { bool canaryFeatures = false, }) async { final sdkLayout = sdkConfigurationProvider.sdkLayout; - + final toolConfiguration = createToolConfiguration( + debugSettings: DebugSettings( + enableDebugging: enableDebugging, + enableDebugExtension: enableDebugExtension, + useSseForDebugBackend: useSse, + useSseForDebugProxy: useSse, + useSseForInjectedClient: useSse, + spawnDds: spawnDds, + enableDevToolsLaunch: serveDevTools, + urlEncoder: urlEncoder, + ), + appMetadata: AppMetadata( + hostname: hostname, + isInternalBuild: isInternalBuild, + isFlutterApp: () => Future.value(isFlutterApp), + ), + ); + setGlobalsForTesting(toolConfiguration: toolConfiguration); try { // Make sure configuration was created correctly. final configuration = await sdkConfigurationProvider.configuration; diff --git a/dwds/test/fixtures/fakes.dart b/dwds/test/fixtures/fakes.dart index c981fc97f..262d780d3 100644 --- a/dwds/test/fixtures/fakes.dart +++ b/dwds/test/fixtures/fakes.dart @@ -16,7 +16,6 @@ import 'package:dwds/src/debugging/webkit_debugger.dart'; import 'package:dwds/src/handlers/socket_connections.dart'; import 'package:dwds/src/loaders/require.dart'; import 'package:dwds/src/loaders/strategy.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:dwds/src/utilities/objects.dart'; import 'package:shelf/shelf.dart' as shelf; import 'package:vm_service/vm_service.dart'; @@ -26,6 +25,7 @@ import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; import 'debugger_data.dart'; +import 'utilities.dart'; /// Constructs a trivial Isolate we can use when we need to provide one but /// don't want go through initialization. @@ -180,17 +180,21 @@ class FakeWebkitDebugger implements WebkitDebugger { Future enable() async => null; FakeWebkitDebugger({Map? scripts}) : _scripts = scripts { - globalLoadStrategy = RequireStrategy( - ReloadConfiguration.none, - (_) async => {}, - (_) async => {}, - (_, __) async => null, - (MetadataProvider _, String __) async => '', - (MetadataProvider _, String __) async => '', - (String _) => '', - (MetadataProvider _) async => {}, - FakeAssetReader(), - Uri.parse('package:fakeapp/main.dart'), + setGlobalsForTesting( + toolConfiguration: createToolConfiguration( + loadStrategy: RequireStrategy( + ReloadConfiguration.none, + (_) async => {}, + (_) async => {}, + (_, __) async => null, + (MetadataProvider _, String __) async => '', + (MetadataProvider _, String __) async => '', + (String _) => '', + (MetadataProvider _) async => {}, + FakeAssetReader(), + Uri.parse('package:fakeapp/main.dart'), + ), + ), ); } diff --git a/dwds/test/fixtures/server.dart b/dwds/test/fixtures/server.dart index 6396e8566..9b2ed8a96 100644 --- a/dwds/test/fixtures/server.dart +++ b/dwds/test/fixtures/server.dart @@ -10,6 +10,7 @@ import 'package:dwds/asset_reader.dart'; import 'package:dwds/dart_web_debug_service.dart'; import 'package:dwds/data/build_result.dart'; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/loaders/require.dart'; import 'package:dwds/src/servers/devtools.dart'; import 'package:dwds/src/services/expression_compiler_service.dart'; @@ -103,23 +104,16 @@ class TestServer { throw StateError('Unexpected Daemon build result: $result'); }); - final dwds = await Dwds.start( - assetReader: assetReader, - buildResults: filteredBuildResults, - chromeConnection: chromeConnection, - loadStrategy: strategy, + final debugSettings = DebugSettings( spawnDds: spawnDds, enableDebugExtension: enableDebugExtension, enableDebugging: enableDebugging, useSseForDebugProxy: useSse, useSseForDebugBackend: useSse, useSseForInjectedClient: useSse, - hostname: hostname, urlEncoder: urlEncoder, expressionCompiler: expressionCompiler, - isInternalBuild: isInternalBuild, - isFlutterApp: () => Future.value(isFlutterApp), - devtoolsLauncher: serveDevTools + devToolsLauncher: serveDevTools ? (hostname) async { final server = await DevToolsServer().serveDevTools( hostname: hostname, @@ -134,6 +128,25 @@ class TestServer { : null, ); + final appMetadata = AppMetadata( + hostname: hostname, + isInternalBuild: isInternalBuild, + isFlutterApp: () => Future.value(isFlutterApp), + ); + + final toolConfiguration = ToolConfiguration( + loadStrategy: strategy, + debugSettings: debugSettings, + appMetadata: appMetadata, + ); + + final dwds = await Dwds.start( + assetReader: assetReader, + buildResults: filteredBuildResults, + chromeConnection: chromeConnection, + toolConfiguration: toolConfiguration, + ); + final server = await startHttpServer('localhost', port: port); var cascade = Cascade(); diff --git a/dwds/test/fixtures/utilities.dart b/dwds/test/fixtures/utilities.dart index cc56930aa..5ce25253d 100644 --- a/dwds/test/fixtures/utilities.dart +++ b/dwds/test/fixtures/utilities.dart @@ -7,6 +7,10 @@ import 'dart:io'; import 'package:build_daemon/client.dart'; import 'package:build_daemon/constants.dart'; import 'package:build_daemon/data/server_log.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; +import 'package:dwds/src/loaders/strategy.dart'; + +import 'fakes.dart'; /// Connects to the `build_runner` daemon. Future connectClient( @@ -87,3 +91,22 @@ Future retryFnAsync( failureMessage: failureMessage, ); } + +ToolConfiguration createToolConfiguration({ + LoadStrategy? loadStrategy, + AppMetadata? appMetadata, + DebugSettings? debugSettings, +}) => + ToolConfiguration( + loadStrategy: loadStrategy ?? FakeStrategy(FakeAssetReader()), + debugSettings: debugSettings ?? DebugSettings(), + appMetadata: appMetadata ?? AppMetadata(), + ); + +final defaultToolConfiguration = createToolConfiguration(); + +void setGlobalsForTesting({ + ToolConfiguration? toolConfiguration, +}) { + globalToolConfiguration = toolConfiguration ?? defaultToolConfiguration; +} diff --git a/dwds/test/handlers/injector_test.dart b/dwds/test/handlers/injector_test.dart index 073bffa61..01e92db28 100644 --- a/dwds/test/handlers/injector_test.dart +++ b/dwds/test/handlers/injector_test.dart @@ -6,6 +6,7 @@ import 'dart:io'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/handlers/injector.dart'; import 'package:dwds/src/version.dart'; import 'package:http/http.dart' as http; @@ -13,405 +14,398 @@ import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart' as shelf_io; import 'package:test/test.dart'; -import '../fixtures/fakes.dart'; +import '../fixtures/utilities.dart'; void main() { late HttpServer server; const entryEtag = 'entry etag'; const nonEntryEtag = 'some etag'; - final loadStrategy = FakeStrategy(FakeAssetReader()); - - group('InjectedHandlerWithoutExtension', () { - late DwdsInjector injector; - setUp(() async { - injector = DwdsInjector( - loadStrategy, - useSseForInjectedClient: true, - enableDevtoolsLaunch: true, - emitDebugEvents: true, - isInternalBuild: false, - isFlutterApp: () => Future.value(true), - ); - final pipeline = const Pipeline().addMiddleware(injector.middleware); - server = await shelf_io.serve( - pipeline.addHandler((request) { - if (request.url.path.endsWith(bootstrapJsExtension)) { - return Response.ok( - '$entrypointExtensionMarker\n' - '$mainExtensionMarker\n' - 'app.main.main()', - headers: {HttpHeaders.etagHeader: entryEtag}, - ); - } else if (request.url.path.endsWith('foo.js')) { - return Response.ok( - 'some js', - headers: {HttpHeaders.etagHeader: nonEntryEtag}, - ); - } else { - return Response.notFound('Not found'); - } - }), - 'localhost', - 0, - ); - }); - - tearDown(() async { - await server.close(); - }); - - test('leaves non-entrypoints untouched', () async { - final result = - await http.get(Uri.parse('http://localhost:${server.port}/foo.js')); - expect(result.body, 'some js'); - }); - - test('does not update etags for non-entrypoints', () async { - final result = - await http.get(Uri.parse('http://localhost:${server.port}/foo.js')); - expect(result.headers[HttpHeaders.etagHeader], nonEntryEtag); - }); - - test('replaces main marker with injected client', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('Injected by dwds'), isTrue); - expect(result.body.contains(mainExtensionMarker), isFalse); - }); - - test('prevents main from being called', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('window.\$dartRunMain'), isTrue); - }); - test('updates etags for injected responses', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.headers[HttpHeaders.etagHeader], isNot(entryEtag)); - }); - - test('ignores non-js requests', () async { - final result = await http - .get(Uri.parse('http://localhost:${server.port}/main.dart')); - expect(result.body, 'Not found'); - }); - - test('embeds the devHandlerPath', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect( - result.body.contains('window.\$dwdsDevHandlerPath = "http://'), - isTrue, - ); - }); - - test('emits a devHandlerPath for each entrypoint', () async { - await http.get( - Uri.parse( - 'http://localhost:${server.port}/foo/entrypoint$bootstrapJsExtension', - ), - ); - await http.get( - Uri.parse( - 'http://localhost:${server.port}/blah/entrypoint$bootstrapJsExtension', - ), - ); - expect( - injector.devHandlerPaths, - emitsInOrder([ - 'http://localhost:${server.port}/foo/\$dwdsSseHandler', - 'http://localhost:${server.port}/blah/\$dwdsSseHandler', - ]), - ); - }); - - test( - 'Does not return 304 when if-none-match etag matches the original ' - 'content etag', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - headers: {HttpHeaders.ifNoneMatchHeader: entryEtag}, - ); - expect(result.statusCode, HttpStatus.ok); - }); - - test('Does return 304 when if-none-match etag matches the modified etag', - () async { - final originalResponse = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - - final etagHeader = originalResponse.headers[HttpHeaders.etagHeader]; - expect(etagHeader, isNotNull); - final cachedResponse = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - headers: {HttpHeaders.ifNoneMatchHeader: etagHeader!}, - ); - expect(cachedResponse.statusCode, HttpStatus.notModified); - }); - - test('Does not inject the extension backend port', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('dartExtensionUri'), isFalse); - }); - - test('Has correct DWDS version', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - final expected = r'$dwdsVersion = '; - final index = result.body.indexOf(expected); - expect(index, greaterThan(0)); - final nextBit = result.body.substring(index + expected.length); - final versionPiece = nextBit.split('"')[1]; - expect(versionPiece, packageVersion); - }); - - test('Injects bootstrap', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('dummy_bootstrap'), isTrue); - }); - - test('Injects load strategy id', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('dummy-id'), isTrue); - }); - - test('Injects the entrypoint path', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect( - result.body.contains('dartEntrypointPath = "entrypoint.bootstrap.js"'), - isTrue, - ); - }); - - test('Injects client load snippet', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('dummy-load-client-snippet'), isTrue); - }); - - test('Injects dwds enable devtools launch configuration', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('dwdsEnableDevtoolsLaunch'), isTrue); - }); - - test('Delegates to strategy handler', () async { - final result = await http - .get(Uri.parse('http://localhost:${server.port}/someDummyPath')); - expect(result.body, equals('some dummy response')); - }); - - test('the injected client contains a global \$emitDebugEvents', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/dwds/src/injected/client.js', - ), - ); - expect(result.body, contains('\$dartEmitDebugEvents')); - }); - - test('the injected client contains a global \$emitDebugEvent', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/dwds/src/injected/client.js', - ), - ); - expect(result.body, contains('\$emitDebugEvent')); - }); - - test('the injected client contains a global \$emitRegisterEvent', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/dwds/src/injected/client.js', - ), - ); - expect(result.body, contains('\$emitRegisterEvent')); - }); - - test('the injected client contains a global \$isInternalBuild', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/dwds/src/injected/client.js', - ), - ); - expect(result.body, contains('\$isInternalBuild')); - }); - - test('the injected client contains a global \$isFlutterApp', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/dwds/src/injected/client.js', - ), - ); - expect(result.body, contains('\$isFlutterApp')); - }); - - test('serves the injected client', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/dwds/src/injected/client.js', - ), - ); - expect(result.statusCode, HttpStatus.ok); - }); - }); - - group('InjectedHandlerWithoutExtension using WebSockets', () { - late DwdsInjector injector; - setUp(() async { - injector = DwdsInjector( - loadStrategy, - useSseForInjectedClient: false, - enableDevtoolsLaunch: true, - emitDebugEvents: true, - isInternalBuild: false, - isFlutterApp: () => Future.value(true), - ); - final pipeline = const Pipeline().addMiddleware(injector.middleware); - server = await shelf_io.serve( - pipeline.addHandler((request) { - if (request.url.path.endsWith(bootstrapJsExtension)) { + group('Injector test', () { + setUpAll(setGlobalsForTesting); + + group('InjectedHandlerWithoutExtension', () { + late DwdsInjector injector; + setUp(() async { + injector = DwdsInjector(); + final pipeline = const Pipeline().addMiddleware(injector.middleware); + server = await shelf_io.serve( + pipeline.addHandler((request) { + if (request.url.path.endsWith(bootstrapJsExtension)) { + return Response.ok( + '$entrypointExtensionMarker\n' + '$mainExtensionMarker\n' + 'app.main.main()', + headers: {HttpHeaders.etagHeader: entryEtag}, + ); + } else if (request.url.path.endsWith('foo.js')) { + return Response.ok( + 'some js', + headers: {HttpHeaders.etagHeader: nonEntryEtag}, + ); + } else { + return Response.notFound('Not found'); + } + }), + 'localhost', + 0, + ); + }); + + tearDown(() async { + await server.close(); + }); + + test('leaves non-entrypoints untouched', () async { + final result = + await http.get(Uri.parse('http://localhost:${server.port}/foo.js')); + expect(result.body, 'some js'); + }); + + test('does not update etags for non-entrypoints', () async { + final result = + await http.get(Uri.parse('http://localhost:${server.port}/foo.js')); + expect(result.headers[HttpHeaders.etagHeader], nonEntryEtag); + }); + + test('replaces main marker with injected client', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('Injected by dwds'), isTrue); + expect(result.body.contains(mainExtensionMarker), isFalse); + }); + + test('prevents main from being called', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('window.\$dartRunMain'), isTrue); + }); + + test('updates etags for injected responses', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.headers[HttpHeaders.etagHeader], isNot(entryEtag)); + }); + + test('ignores non-js requests', () async { + final result = await http + .get(Uri.parse('http://localhost:${server.port}/main.dart')); + expect(result.body, 'Not found'); + }); + + test('embeds the devHandlerPath', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect( + result.body.contains('window.\$dwdsDevHandlerPath = "http://'), + isTrue, + ); + }); + + test('emits a devHandlerPath for each entrypoint', () async { + await http.get( + Uri.parse( + 'http://localhost:${server.port}/foo/entrypoint$bootstrapJsExtension', + ), + ); + await http.get( + Uri.parse( + 'http://localhost:${server.port}/blah/entrypoint$bootstrapJsExtension', + ), + ); + expect( + injector.devHandlerPaths, + emitsInOrder([ + 'http://localhost:${server.port}/foo/\$dwdsSseHandler', + 'http://localhost:${server.port}/blah/\$dwdsSseHandler', + ]), + ); + }); + + test( + 'Does not return 304 when if-none-match etag matches the original ' + 'content etag', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + headers: {HttpHeaders.ifNoneMatchHeader: entryEtag}, + ); + expect(result.statusCode, HttpStatus.ok); + }); + + test('Does return 304 when if-none-match etag matches the modified etag', + () async { + final originalResponse = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + + final etagHeader = originalResponse.headers[HttpHeaders.etagHeader]; + expect(etagHeader, isNotNull); + final cachedResponse = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + headers: {HttpHeaders.ifNoneMatchHeader: etagHeader!}, + ); + expect(cachedResponse.statusCode, HttpStatus.notModified); + }); + + test('Does not inject the extension backend port', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('dartExtensionUri'), isFalse); + }); + + test('Has correct DWDS version', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + final expected = r'$dwdsVersion = '; + final index = result.body.indexOf(expected); + expect(index, greaterThan(0)); + final nextBit = result.body.substring(index + expected.length); + final versionPiece = nextBit.split('"')[1]; + expect(versionPiece, packageVersion); + }); + + test('Injects bootstrap', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('dummy_bootstrap'), isTrue); + }); + + test('Injects load strategy id', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('dummy-id'), isTrue); + }); + + test('Injects the entrypoint path', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect( + result.body + .contains('dartEntrypointPath = "entrypoint.bootstrap.js"'), + isTrue, + ); + }); + + test('Injects client load snippet', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('dummy-load-client-snippet'), isTrue); + }); + + test('Injects dwds enable devtools launch configuration', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('dwdsEnableDevToolsLaunch'), isTrue); + }); + + test('Delegates to strategy handler', () async { + final result = await http + .get(Uri.parse('http://localhost:${server.port}/someDummyPath')); + expect(result.body, equals('some dummy response')); + }); + + test('the injected client contains a global \$emitDebugEvents', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/dwds/src/injected/client.js', + ), + ); + expect(result.body, contains('\$dartEmitDebugEvents')); + }); + + test('the injected client contains a global \$emitDebugEvent', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/dwds/src/injected/client.js', + ), + ); + expect(result.body, contains('\$emitDebugEvent')); + }); + + test('the injected client contains a global \$emitRegisterEvent', + () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/dwds/src/injected/client.js', + ), + ); + expect(result.body, contains('\$emitRegisterEvent')); + }); + + test('the injected client contains a global \$isInternalBuild', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/dwds/src/injected/client.js', + ), + ); + expect(result.body, contains('\$isInternalBuild')); + }); + + test('the injected client contains a global \$isFlutterApp', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/dwds/src/injected/client.js', + ), + ); + expect(result.body, contains('\$isFlutterApp')); + }); + + test('serves the injected client', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/dwds/src/injected/client.js', + ), + ); + expect(result.statusCode, HttpStatus.ok); + }); + }); + + group('InjectedHandlerWithoutExtension using WebSockets', () { + late DwdsInjector injector; + setUp(() async { + final toolConfiguration = createToolConfiguration( + debugSettings: DebugSettings( + useSseForInjectedClient: false, + ), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); + injector = DwdsInjector(); + final pipeline = const Pipeline().addMiddleware(injector.middleware); + server = await shelf_io.serve( + pipeline.addHandler((request) { + if (request.url.path.endsWith(bootstrapJsExtension)) { + return Response.ok( + '$entrypointExtensionMarker\n' + '$mainExtensionMarker\n' + 'app.main.main()', + headers: {HttpHeaders.etagHeader: entryEtag}, + ); + } else if (request.url.path.endsWith('foo.js')) { + return Response.ok( + 'some js', + headers: {HttpHeaders.etagHeader: nonEntryEtag}, + ); + } else { + return Response.notFound('Not found'); + } + }), + 'localhost', + 0, + ); + }); + + tearDown(() async { + await server.close(); + }); + + test('embeds the devHandlerPath', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect( + result.body.contains('window.\$dwdsDevHandlerPath = "ws://'), + isTrue, + ); + }); + + test('emits a devHandlerPath for each entrypoint', () async { + await http.get( + Uri.parse( + 'http://localhost:${server.port}/foo/entrypoint$bootstrapJsExtension', + ), + ); + await http.get( + Uri.parse( + 'http://localhost:${server.port}/blah/entrypoint$bootstrapJsExtension', + ), + ); + expect( + injector.devHandlerPaths, + emitsInOrder([ + 'ws://localhost:${server.port}/foo/\$dwdsSseHandler', + 'ws://localhost:${server.port}/blah/\$dwdsSseHandler', + ]), + ); + }); + }); + + group('InjectedHandlerWithExtension', () { + setUp(() async { + final extensionUri = 'http://localhost:4000'; + final pipeline = const Pipeline().addMiddleware( + DwdsInjector( + extensionUri: Future.value(extensionUri), + ).middleware, + ); + server = await shelf_io.serve( + pipeline.addHandler((request) { return Response.ok( '$entrypointExtensionMarker\n' '$mainExtensionMarker\n' 'app.main.main()', headers: {HttpHeaders.etagHeader: entryEtag}, ); - } else if (request.url.path.endsWith('foo.js')) { - return Response.ok( - 'some js', - headers: {HttpHeaders.etagHeader: nonEntryEtag}, - ); - } else { - return Response.notFound('Not found'); - } - }), - 'localhost', - 0, - ); - }); - - tearDown(() async { - await server.close(); - }); - - test('embeds the devHandlerPath', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect( - result.body.contains('window.\$dwdsDevHandlerPath = "ws://'), - isTrue, - ); - }); - - test('emits a devHandlerPath for each entrypoint', () async { - await http.get( - Uri.parse( - 'http://localhost:${server.port}/foo/entrypoint$bootstrapJsExtension', - ), - ); - await http.get( - Uri.parse( - 'http://localhost:${server.port}/blah/entrypoint$bootstrapJsExtension', - ), - ); - expect( - injector.devHandlerPaths, - emitsInOrder([ - 'ws://localhost:${server.port}/foo/\$dwdsSseHandler', - 'ws://localhost:${server.port}/blah/\$dwdsSseHandler', - ]), - ); - }); - }); - - group('InjectedHandlerWithExtension', () { - setUp(() async { - final extensionUri = 'http://localhost:4000'; - final pipeline = const Pipeline().addMiddleware( - DwdsInjector( - loadStrategy, - extensionUri: Future.value(extensionUri), - useSseForInjectedClient: true, - enableDevtoolsLaunch: true, - emitDebugEvents: true, - isInternalBuild: false, - isFlutterApp: () => Future.value(true), - ).middleware, - ); - server = await shelf_io.serve( - pipeline.addHandler((request) { - return Response.ok( - '$entrypointExtensionMarker\n' - '$mainExtensionMarker\n' - 'app.main.main()', - headers: {HttpHeaders.etagHeader: entryEtag}, - ); - }), - 'localhost', - 0, - ); - }); - - tearDown(() async { - await server.close(); - }); - - test('Injects the extension backend port', () async { - final result = await http.get( - Uri.parse( - 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', - ), - ); - expect(result.body.contains('dartExtensionUri'), isTrue); + }), + 'localhost', + 0, + ); + }); + + tearDown(() async { + await server.close(); + }); + + test('Injects the extension backend port', () async { + final result = await http.get( + Uri.parse( + 'http://localhost:${server.port}/entrypoint$bootstrapJsExtension', + ), + ); + expect(result.body.contains('dartExtensionUri'), isTrue); + }); }); }); } diff --git a/dwds/test/inspector_test.dart b/dwds/test/inspector_test.dart index 553e66431..e84cd64ad 100644 --- a/dwds/test/inspector_test.dart +++ b/dwds/test/inspector_test.dart @@ -6,9 +6,9 @@ @Timeout(Duration(minutes: 2)) import 'package:dwds/dwds.dart'; +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/inspector.dart'; import 'package:dwds/src/utilities/conversions.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:test/test.dart'; import 'package:test_common/test_sdk_configuration.dart'; import 'package:vm_service/vm_service.dart'; @@ -40,7 +40,7 @@ void main() { /// A convenient way to get a library variable without boilerplate. String libraryVariableExpression(String variable) => - '${globalLoadStrategy.loadModuleSnippet}("dart_sdk").dart.getModuleLibraries("example/scopes/main")["$url"]["$variable"];'; + '${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").dart.getModuleLibraries("example/scopes/main")["$url"]["$variable"];'; Future libraryPublicFinal() => inspector.jsEvaluate(libraryVariableExpression('libraryPublicFinal')); diff --git a/dwds/test/instances/common/instance_common.dart b/dwds/test/instances/common/instance_common.dart index 01ef9c6df..946b7b60f 100644 --- a/dwds/test/instances/common/instance_common.dart +++ b/dwds/test/instances/common/instance_common.dart @@ -2,8 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/inspector.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:test/test.dart'; import 'package:test_common/logging.dart'; import 'package:test_common/test_sdk_configuration.dart'; @@ -53,7 +53,7 @@ void runTypeSystemVerificationTests({ ) => ''' (function() { - var dart = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk').dart; + var dart = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk').dart; var libraryName = '${libraryName(compilationMode)}'; var library = dart.getModuleLibraries(libraryName)['$url']; var x = library['$variable']; @@ -117,7 +117,7 @@ void runTests({ String variable, CompilationMode compilationMode, ) => - '${globalLoadStrategy.loadModuleSnippet}("dart_sdk").dart.' + '${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").dart.' 'getModuleLibraries("${libraryName(compilationMode)}")' '["$url"]["$variable"];'; diff --git a/dwds/test/location_test.dart b/dwds/test/location_test.dart index d8366e97e..3eb0d2ea6 100644 --- a/dwds/test/location_test.dart +++ b/dwds/test/location_test.dart @@ -7,10 +7,10 @@ import 'package:dwds/asset_reader.dart'; import 'package:dwds/src/debugging/location.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:test/test.dart'; import 'fixtures/fakes.dart'; +import 'fixtures/utilities.dart'; final sourceMapContents = '{"version":3,"sourceRoot":"","sources":["main.dart"],"names":[],' @@ -23,9 +23,13 @@ final sourceMapContents = void main() { const lines = 100; const lineLength = 150; - final assetReader = FakeAssetReader(sourceMap: sourceMapContents); - globalLoadStrategy = MockLoadStrategy(assetReader); + final toolConfiguration = createToolConfiguration( + loadStrategy: MockLoadStrategy(assetReader), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); final dartUri = DartUri('org-dartlang-app://web/main.dart'); final modules = FakeModules(module: _module); diff --git a/dwds/test/metadata_test.dart b/dwds/test/metadata_test.dart index ac6c013dc..3299c040e 100644 --- a/dwds/test/metadata_test.dart +++ b/dwds/test/metadata_test.dart @@ -6,10 +6,10 @@ import 'package:dwds/src/debugging/metadata/module_metadata.dart'; import 'package:dwds/src/debugging/metadata/provider.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:test/test.dart'; import 'fixtures/fakes.dart'; +import 'fixtures/utilities.dart'; const _emptySourceMetadata = '{"version":"1.0.0","name":"web/main","closureName":"load__web__main",' @@ -41,7 +41,12 @@ const _fileUriMetadata = '// intentionally empty: package blah has no dart sources'; void main() { - globalLoadStrategy = FakeStrategy(FakeAssetReader()); + final toolConfiguration = createToolConfiguration( + loadStrategy: FakeStrategy(FakeAssetReader()), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); test('can parse metadata with empty sources', () async { final provider = MetadataProvider( 'foo.bootstrap.js', diff --git a/dwds/test/skip_list_test.dart b/dwds/test/skip_list_test.dart index c3a50304d..3b1adc683 100644 --- a/dwds/test/skip_list_test.dart +++ b/dwds/test/skip_list_test.dart @@ -8,11 +8,11 @@ import 'package:dwds/asset_reader.dart'; import 'package:dwds/src/debugging/location.dart'; import 'package:dwds/src/debugging/skip_list.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/globals.dart'; import 'package:source_maps/parser.dart'; import 'package:test/test.dart'; import 'fixtures/fakes.dart'; +import 'fixtures/utilities.dart'; class TestStrategy extends FakeStrategy { TestStrategy( @@ -26,8 +26,12 @@ class TestStrategy extends FakeStrategy { } void main() { - globalLoadStrategy = TestStrategy(FakeAssetReader()); - + final toolConfiguration = createToolConfiguration( + loadStrategy: TestStrategy(FakeAssetReader()), + ); + setGlobalsForTesting( + toolConfiguration: toolConfiguration, + ); late SkipLists skipLists; final dartUri = DartUri('org-dartlang-app://web/main.dart'); group('SkipLists', () { diff --git a/dwds/web/client.dart b/dwds/web/client.dart index 740688208..51a0a251f 100644 --- a/dwds/web/client.dart +++ b/dwds/web/client.dart @@ -169,7 +169,7 @@ Future? main() { }, ); - if (dwdsEnableDevtoolsLaunch) { + if (dwdsEnableDevToolsLaunch) { window.onKeyDown.listen((Event e) { if (e is KeyboardEvent && const [ @@ -337,8 +337,8 @@ external String get reloadConfiguration; @JS(r'$dartEntrypointPath') external String get dartEntrypointPath; -@JS(r'$dwdsEnableDevtoolsLaunch') -external bool get dwdsEnableDevtoolsLaunch; +@JS(r'$dwdsEnableDevToolsLaunch') +external bool get dwdsEnableDevToolsLaunch; @JS('window.top.document.dispatchEvent') external void dispatchEvent(CustomEvent event); diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index 784e634f9..b63b6e05e 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -10,6 +10,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:dwds/asset_reader.dart'; +import 'package:dwds/config.dart'; import 'package:file/file.dart'; import 'package:logging/logging.dart'; import 'package:mime/mime.dart' as mime; diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart index c0c7f371d..64e3e4512 100644 --- a/frontend_server_common/lib/src/devfs.dart +++ b/frontend_server_common/lib/src/devfs.dart @@ -5,6 +5,7 @@ // Note: this is a copy from flutter tools, updated to work with dwds tests import 'package:dwds/asset_reader.dart'; +import 'package:dwds/config.dart'; import 'package:file/file.dart'; import 'package:path/path.dart' as p; import 'package:test_common/test_sdk_layout.dart'; diff --git a/frontend_server_common/lib/src/resident_runner.dart b/frontend_server_common/lib/src/resident_runner.dart index fdf2e6b1c..e1931fdec 100644 --- a/frontend_server_common/lib/src/resident_runner.dart +++ b/frontend_server_common/lib/src/resident_runner.dart @@ -8,6 +8,7 @@ import 'dart:async'; import 'package:dwds/asset_reader.dart'; +import 'package:dwds/config.dart'; import 'package:dwds/expression_compiler.dart'; import 'package:file/file.dart'; import 'package:logging/logging.dart'; diff --git a/webdev/CHANGELOG.md b/webdev/CHANGELOG.md index 20f62b753..24baf3475 100644 --- a/webdev/CHANGELOG.md +++ b/webdev/CHANGELOG.md @@ -1,5 +1,7 @@ ## 3.1.0-wip +- Update the parameters passed to `Dwds.start`. - [#2231](https://github.com/dart-lang/webdev/pull/2231). + ## 3.0.8 - Hide and deprecate now unsupported `--null-safety` option. - [#2206](https://github.com/dart-lang/webdev/pull/2206) diff --git a/webdev/lib/src/serve/webdev_server.dart b/webdev/lib/src/serve/webdev_server.dart index b4ef287a1..ef3f62f4d 100644 --- a/webdev/lib/src/serve/webdev_server.dart +++ b/webdev/lib/src/serve/webdev_server.dart @@ -144,27 +144,39 @@ class WebDevServer { } var shouldServeDevTools = options.configuration.debug || options.configuration.debugExtension; - dwds = await Dwds.start( - hostname: options.configuration.hostname, - assetReader: assetReader, - buildResults: filteredBuildResults, - chromeConnection: () async => - (await Chrome.connectedInstance).chromeConnection, + + final debugSettings = DebugSettings( + enableDebugExtension: options.configuration.debugExtension, + enableDebugging: options.configuration.debug, + spawnDds: !options.configuration.disableDds, + expressionCompiler: ddcService, + devToolsLauncher: shouldServeDevTools + ? (String hostname) async { + var server = await DevToolsServer().serveDevTools( + hostname: hostname, + enableStdinCommands: false, + customDevToolsPath: devToolsPath, + ); + return DevTools(server!.address.host, server.port, server); + } + : null, + ); + + final appMetadata = AppMetadata( + hostname: options.configuration.hostname, + ); + + final toolConfiguration = ToolConfiguration( loadStrategy: loadStrategy, - enableDebugExtension: options.configuration.debugExtension, - enableDebugging: options.configuration.debug, - spawnDds: !options.configuration.disableDds, - expressionCompiler: ddcService, - devtoolsLauncher: shouldServeDevTools - ? (String hostname) async { - var server = await DevToolsServer().serveDevTools( - hostname: hostname, - enableStdinCommands: false, - customDevToolsPath: devToolsPath, - ); - return DevTools(server!.address.host, server.port, server); - } - : null); + debugSettings: debugSettings, + appMetadata: appMetadata); + dwds = await Dwds.start( + toolConfiguration: toolConfiguration, + assetReader: assetReader, + buildResults: filteredBuildResults, + chromeConnection: () async => + (await Chrome.connectedInstance).chromeConnection, + ); pipeline = pipeline.addMiddleware(dwds.middleware); cascade = cascade.add(dwds.handler); cascade = cascade.add(assetHandler);