From c6ef80d4588f167ac65134821f478c5f1730a964 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 16 Feb 2022 13:58:58 -0800 Subject: [PATCH 01/10] Support lazily created SDK configurations. - Add SdkConfigurationInterface and a default implementation. - Pass SdkConfiguration to dwds and ExpressionCompilerService. - Add tests. --- dwds/lib/dwds.dart | 10 +- dwds/lib/src/debugging/inspector.dart | 6 + dwds/lib/src/handlers/dev_handler.dart | 35 +++-- .../src/services/chrome_proxy_service.dart | 10 ++ dwds/lib/src/services/debug_service.dart | 44 +++--- .../services/expression_compiler_service.dart | 82 ++++------ dwds/lib/src/utilities/dart_uri.dart | 31 ++-- dwds/lib/src/utilities/sdk_configuration.dart | 145 ++++++++++++++++++ dwds/test/dart_uri_test.dart | 17 +- .../expression_compiler_service_test.dart | 4 +- dwds/test/fixtures/context.dart | 36 +++-- dwds/test/sdk_configuration_test.dart | 118 ++++++++++++++ 12 files changed, 411 insertions(+), 127 deletions(-) create mode 100644 dwds/lib/src/utilities/sdk_configuration.dart create mode 100644 dwds/test/sdk_configuration_test.dart diff --git a/dwds/lib/dwds.dart b/dwds/lib/dwds.dart index 785db4a8a..270744cc9 100644 --- a/dwds/lib/dwds.dart +++ b/dwds/lib/dwds.dart @@ -24,7 +24,7 @@ import 'src/readers/asset_reader.dart'; import 'src/servers/devtools.dart'; import 'src/servers/extension_backend.dart'; import 'src/services/expression_compiler.dart'; -import 'src/utilities/dart_uri.dart'; +import 'src/utilities/sdk_configuration.dart'; export 'src/connections/app_connection.dart' show AppConnection; export 'src/connections/debug_connection.dart' show DebugConnection; @@ -50,6 +50,8 @@ export 'src/services/expression_compiler.dart' show ExpressionCompilationResult, ExpressionCompiler, ModuleInfo; export 'src/services/expression_compiler_service.dart' show ExpressionCompilerService; +export 'src/utilities/sdk_configuration.dart' + show SdkConfiguration, SdkConfigurationInterface; typedef ConnectionProvider = Future Function(); typedef UrlEncoder = Future Function(String url); @@ -115,8 +117,7 @@ class Dwds { bool enableDevtoolsLaunch, DevtoolsLauncher devtoolsLauncher, bool launchDevToolsInNewWindow, - Uri sdkDir, - Uri librariesPath, + SdkConfigurationInterface sdkConfiguration, bool emitDebugEvents, }) async { hostname ??= 'localhost'; @@ -131,7 +132,7 @@ class Dwds { globalLoadStrategy = loadStrategy; emitDebugEvents ??= true; - await DartUri.initialize(sdkDir: sdkDir, librariesPath: librariesPath); + sdkConfiguration ??= SdkConfiguration.standard(); DevTools devTools; Future extensionUri; @@ -188,6 +189,7 @@ class Dwds { injected, spawnDds, launchDevToolsInNewWindow, + sdkConfiguration, ); return Dwds._( diff --git a/dwds/lib/src/debugging/inspector.dart b/dwds/lib/src/debugging/inspector.dart index 22ac9d7f3..4508065be 100644 --- a/dwds/lib/src/debugging/inspector.dart +++ b/dwds/lib/src/debugging/inspector.dart @@ -17,6 +17,7 @@ import '../readers/asset_reader.dart'; import '../utilities/conversions.dart'; import '../utilities/dart_uri.dart'; import '../utilities/domain.dart'; +import '../utilities/sdk_configuration.dart'; import '../utilities/shared.dart'; import 'classes.dart'; import 'debugger.dart'; @@ -64,6 +65,7 @@ class AppInspector extends Domain { /// The root URI from which the application is served. final String _root; + final SdkConfigurationInterface _sdkConfiguration; AppInspector._( this.appConnection, @@ -77,6 +79,7 @@ class AppInspector extends Domain { this._locations, this._root, this._executionContext, + this._sdkConfiguration, ) : isolateRef = _toIsolateRef(isolate), super.forInspector(); @@ -91,6 +94,7 @@ class AppInspector extends Domain { var scripts = await scriptRefs; + await DartUri.initialize(_sdkConfiguration); await DartUri.recordAbsoluteUris(libraries.map((lib) => lib.uri)); await DartUri.recordAbsoluteUris(scripts.map((script) => script.uri)); @@ -112,6 +116,7 @@ class AppInspector extends Domain { String root, Debugger debugger, ExecutionContext executionContext, + SdkConfigurationInterface sdkConfiguration, ) async { var id = createId(); var time = DateTime.now().millisecondsSinceEpoch; @@ -156,6 +161,7 @@ class AppInspector extends Domain { locations, root, executionContext, + sdkConfiguration, ); await appInspector._initialize(); return appInspector; diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index 8c1d7251c..ad0d4cd74 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -66,6 +66,7 @@ class DevHandler { final bool _launchDevToolsInNewWindow; final ExpressionCompiler _expressionCompiler; final DwdsInjector _injected; + final SdkConfigurationInterface _sdkConfiguration; /// Null until [close] is called. /// @@ -75,21 +76,23 @@ class DevHandler { Stream get connectedApps => _connectedApps.stream; DevHandler( - this._chromeConnection, - this.buildResults, - this._devTools, - this._assetReader, - this._loadStrategy, - this._hostname, - this._extensionBackend, - this._urlEncoder, - this._useSseForDebugProxy, - this._useSseForInjectedClient, - this._serveDevTools, - this._expressionCompiler, - this._injected, - this._spawnDds, - this._launchDevToolsInNewWindow) { + this._chromeConnection, + this.buildResults, + this._devTools, + this._assetReader, + this._loadStrategy, + this._hostname, + this._extensionBackend, + this._urlEncoder, + this._useSseForDebugProxy, + this._useSseForInjectedClient, + this._serveDevTools, + this._expressionCompiler, + this._injected, + this._spawnDds, + this._launchDevToolsInNewWindow, + this._sdkConfiguration, + ) { _subs.add(buildResults.listen(_emitBuildResults)); _listen(); if (_extensionBackend != null) { @@ -210,6 +213,7 @@ class DevHandler { useSse: false, expressionCompiler: _expressionCompiler, spawnDds: _spawnDds, + sdkConfiguration: _sdkConfiguration, ); } @@ -499,6 +503,7 @@ class DevHandler { useSse: _useSseForDebugProxy, expressionCompiler: _expressionCompiler, spawnDds: _spawnDds, + sdkConfiguration: _sdkConfiguration, ); var appServices = await _createAppDebugServices( devToolsRequest.appId, diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index da93e5275..7e0d3d511 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -94,6 +94,8 @@ class ChromeProxyService implements VmServiceInterface { final ExpressionCompiler _compiler; ExpressionEvaluator _expressionEvaluator; + final SdkConfigurationInterface _sdkConfiguration; + bool terminatingIsolates = false; ChromeProxyService._( @@ -106,6 +108,7 @@ class ChromeProxyService implements VmServiceInterface { this._skipLists, this.executionContext, this._compiler, + this._sdkConfiguration, ) { var debugger = Debugger.create( remoteDebugger, @@ -126,6 +129,7 @@ class ChromeProxyService implements VmServiceInterface { AppConnection appConnection, ExecutionContext executionContext, ExpressionCompiler expressionCompiler, + SdkConfigurationInterface sdkConfiguration, ) async { final vm = VM( name: 'ChromeDebugProxy', @@ -155,6 +159,7 @@ class ChromeProxyService implements VmServiceInterface { skipLists, executionContext, expressionCompiler, + sdkConfiguration, ); unawaited(service.createIsolate(appConnection)); return service; @@ -221,6 +226,7 @@ class ChromeProxyService implements VmServiceInterface { uri, debugger, executionContext, + _sdkConfiguration, ); _expressionEvaluator = _compiler == null @@ -1035,6 +1041,10 @@ ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension( String isolateId, String breakpointId, bool enable) => throw UnimplementedError(); + @override + Future streamCpuSamplesWithUserTag(List userTags) => + throw UnimplementedError(); + /// Prevent DWDS from blocking Dart SDK rolls if changes in package:vm_service /// are unimplemented in DWDS. @override diff --git a/dwds/lib/src/services/debug_service.dart b/dwds/lib/src/services/debug_service.dart index 0581d562b..9d30ef105 100644 --- a/dwds/lib/src/services/debug_service.dart +++ b/dwds/lib/src/services/debug_service.dart @@ -203,28 +203,32 @@ class DebugService { } static Future start( - String hostname, - RemoteDebugger remoteDebugger, - ExecutionContext executionContext, - String tabUrl, - AssetReader assetReader, - LoadStrategy loadStrategy, - AppConnection appConnection, - UrlEncoder urlEncoder, - {void Function(Map) onRequest, - void Function(Map) onResponse, - bool spawnDds = true, - bool useSse, - ExpressionCompiler expressionCompiler}) async { + String hostname, + RemoteDebugger remoteDebugger, + ExecutionContext executionContext, + String tabUrl, + AssetReader assetReader, + LoadStrategy loadStrategy, + AppConnection appConnection, + UrlEncoder urlEncoder, { + void Function(Map) onRequest, + void Function(Map) onResponse, + bool spawnDds = true, + bool useSse, + ExpressionCompiler expressionCompiler, + SdkConfigurationInterface sdkConfiguration, + }) async { useSse ??= false; var chromeProxyService = await ChromeProxyService.create( - remoteDebugger, - tabUrl, - assetReader, - loadStrategy, - appConnection, - executionContext, - expressionCompiler); + remoteDebugger, + tabUrl, + assetReader, + loadStrategy, + appConnection, + executionContext, + expressionCompiler, + sdkConfiguration, + ); var authToken = _makeAuthToken(); var serviceExtensionRegistry = ServiceExtensionRegistry(); Handler handler; diff --git a/dwds/lib/src/services/expression_compiler_service.dart b/dwds/lib/src/services/expression_compiler_service.dart index 719cdb027..4020e99c8 100644 --- a/dwds/lib/src/services/expression_compiler_service.dart +++ b/dwds/lib/src/services/expression_compiler_service.dart @@ -5,15 +5,14 @@ // @dart = 2.9 import 'dart:async'; -import 'dart:io'; import 'dart:isolate'; import 'package:async/async.dart'; import 'package:logging/logging.dart'; -import 'package:path/path.dart' as p; import 'package:shelf/shelf.dart'; import '../utilities/dart_uri.dart'; +import '../utilities/sdk_configuration.dart'; import 'expression_compiler.dart'; final _logger = Logger('ExpressionCompilerService'); @@ -50,10 +49,9 @@ class _Compiler { /// Starts expression compiler worker in an isolate and creates the /// expression compilation service that communicates to the worker. /// - /// [workerPath] is the path for the expression compiler worker, - /// [sdkSummaryPath] is the path to the sdk summary dill file - /// [librariesPath] is the path to libraries definitions file - /// libraries.json. + /// [sdkConfiguration] describes the locations of SDK files used in + /// expression compilation (summaries, libraries spec, compiler worker + /// snapshot). /// /// [soundNullSafety] indiciates if the compioler should support sound null /// safety. @@ -66,35 +64,25 @@ class _Compiler { static Future<_Compiler> start( String address, int port, - String workerPath, - String sdkSummaryPath, - String librariesPath, String moduleFormat, - bool verbose, bool soundNullSafety, + SdkConfigurationInterface sdkConfiguration, + bool verbose, ) async { - final workerUri = p.toUri(p.absolute(workerPath)); - if (!File.fromUri(workerUri).existsSync()) { - _logger.severe('Worker path $workerPath does not exist'); - } + await sdkConfiguration.validate(); - if (!File(sdkSummaryPath).existsSync()) { - _logger.severe('SDK summary path $sdkSummaryPath does not exist'); - } - - if (!File(librariesPath).existsSync()) { - _logger.severe('Libraries path $librariesPath does not exist'); - } - - final sdkSummaryUri = Uri.file(sdkSummaryPath); - final librariesUri = Uri.file(librariesPath); + final librariesUri = await sdkConfiguration.librariesUri; + final workerUri = await sdkConfiguration.compilerWorkerUri; + final sdkSummaryUri = soundNullSafety + ? await sdkConfiguration.soundSdkSummaryPath + : await sdkConfiguration.unsoundSdkSummaryPath; final args = [ '--experimental-expression-compiler', '--libraries-file', '$librariesUri', '--dart-sdk-summary', - '$sdkSummaryUri', + sdkSummaryUri, '--asset-server-address', address, '--asset-server-port', @@ -235,9 +223,9 @@ class _Compiler { /// Uses [_address] and [_port] to communicate and [_assetHandler] to /// redirect asset requests to the asset server. /// -/// [_sdkDir] is the path to the SDK installation directory. -/// [_workerPath] is the path to the DDC worker snapshot. -/// [_librariesPath] is the path to the libraries.json spec. +/// [_sdkConfiguration] describes the locations of SDK files used in +/// expression compilation (summaries, libraries spec, compiler worker +/// snapshot). /// /// Users need to stop the service by calling [stop]. class ExpressionCompilerService implements ExpressionCompiler { @@ -247,16 +235,16 @@ class ExpressionCompilerService implements ExpressionCompiler { final Handler _assetHandler; final bool _verbose; - final String _sdkDir; - final String _workerPath; - final String _librariesPath; + final SdkConfigurationInterface _sdkConfiguration; ExpressionCompilerService( - this._address, this._port, this._assetHandler, this._verbose, - {String sdkDir, String workerPath, String librariesPath}) - : _sdkDir = sdkDir, - _workerPath = workerPath, - _librariesPath = librariesPath; + this._address, + this._port, + this._assetHandler, { + bool verbose = false, + SdkConfigurationInterface sdkConfiguration, + }) : _verbose = verbose, + _sdkConfiguration = sdkConfiguration ?? SdkConfiguration.standard(); @override Future compileExpressionToJs( @@ -276,20 +264,14 @@ class ExpressionCompilerService implements ExpressionCompiler { if (_compiler.isCompleted) return; soundNullSafety ??= false; - final binDir = p.dirname(Platform.resolvedExecutable); - var sdkDir = _sdkDir ?? p.dirname(binDir); - - var sdkSummaryRoot = p.join(sdkDir, 'lib', '_internal'); - var sdkSummaryPath = soundNullSafety - ? p.join(sdkSummaryRoot, 'ddc_outline_sound.dill') - : p.join(sdkSummaryRoot, 'ddc_sdk.dill'); - var librariesPath = - _librariesPath ?? p.join(sdkDir, 'lib', 'libraries.json'); - var workerPath = - _workerPath ?? p.join(binDir, 'snapshots', 'dartdevc.dart.snapshot'); - - var compiler = await _Compiler.start(_address, await _port, workerPath, - sdkSummaryPath, librariesPath, moduleFormat, _verbose, soundNullSafety); + var compiler = await _Compiler.start( + _address, + await _port, + moduleFormat, + soundNullSafety, + _sdkConfiguration, + _verbose, + ); _compiler.complete(compiler); } diff --git a/dwds/lib/src/utilities/dart_uri.dart b/dwds/lib/src/utilities/dart_uri.dart index c84c66253..7fcc362e1 100644 --- a/dwds/lib/src/utilities/dart_uri.dart +++ b/dwds/lib/src/utilities/dart_uri.dart @@ -13,6 +13,7 @@ import 'package:package_config/package_config.dart'; import 'package:path/path.dart' as p; import '../loaders/strategy.dart'; +import 'sdk_configuration.dart'; /// The URI for a particular Dart file, able to canonicalize from various /// different representations. @@ -107,7 +108,7 @@ class DartUri { /// For example: `/Users/me/.dart-sdks/2.15.0` /// /// Used to resolve SDK urls according to vm_service protocol. - static Uri _sdkDir; + static SdkConfigurationInterface _sdkConfiguration; /// All of the known absolute library paths, indexed by their library URL. /// @@ -154,18 +155,15 @@ class DartUri { static String currentDirectoryUri = '${p.toUri(currentDirectory)}'; /// Record library and script uris to enable resolving library and script paths. - static Future initialize({Uri sdkDir, Uri librariesPath}) async { - _sdkDir = - sdkDir ?? p.toUri(p.dirname(p.dirname(Platform.resolvedExecutable))); - - librariesPath ??= - p.toUri(p.join(_sdkDir.toFilePath(), 'lib', 'libraries.json')); - + static Future initialize( + SdkConfigurationInterface sdkConfiguration) async { + await sdkConfiguration.validateSdkDir(); + _sdkConfiguration = sdkConfiguration; var packagesUri = p.toUri(p.join(currentDirectory, '.packages')); clear(); - await _loadLibrariesConfig(librariesPath); - return await _loadPackageConfig(packagesUri); + await _loadLibrariesConfig(await _sdkConfiguration.librariesUri); + await _loadPackageConfig(packagesUri); } /// Clear the uri resolution tables. @@ -178,8 +176,9 @@ class DartUri { /// Record all of the libraries, indexed by their absolute file: URI. static Future recordAbsoluteUris(Iterable libraryUris) async { + var sdkDirectoryUri = await _sdkConfiguration.sdkDirectoryUri; for (var uri in libraryUris) { - _recordAbsoluteUri(uri); + _recordAbsoluteUri(Uri.parse(uri), sdkDirectoryUri); } } @@ -210,20 +209,22 @@ class DartUri { /// Record the library represented by package: or org-dartlang-app: uris /// indexed by absolute file: URI. - static void _recordAbsoluteUri(String libraryUri) { - var uri = Uri.parse(libraryUri); + static void _recordAbsoluteUri(Uri uri, Uri sdkDirectoryUri) { if (uri.scheme.isEmpty && !uri.path.endsWith('.dart')) { // ignore non-dart files return; } + var libraryUri = '$uri'; String libraryPath; switch (uri.scheme) { case 'dart': var libSpec = _librariesSpec?.libraryInfoFor(uri.path); libraryPath = libSpec?.uri?.path; - libraryPath = - libraryPath?.replaceAll(_sdkDir.path, 'org-dartlang-sdk:///sdk'); + if (sdkDirectoryUri != null) { + libraryPath = libraryPath?.replaceAll( + sdkDirectoryUri.path, 'org-dartlang-sdk:///sdk'); + } break; case 'org-dartlang-app': case 'google3': diff --git a/dwds/lib/src/utilities/sdk_configuration.dart b/dwds/lib/src/utilities/sdk_configuration.dart new file mode 100644 index 000000000..14b0d2dfe --- /dev/null +++ b/dwds/lib/src/utilities/sdk_configuration.dart @@ -0,0 +1,145 @@ +// Copyright (c) 2022, 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. + +// @dart=2.9 + +import 'dart:io'; + +import 'package:path/path.dart' as p; + +class InvalidSdkConfigurationException implements Exception { + final String message; + + InvalidSdkConfigurationException([this.message]); + + @override + String toString() { + var message = this.message; + if (message == null) return 'Invalid SDK configuration'; + return 'Invalid SDK configuration: $message'; + } +} + +/// Interface describing the SDK layout. +/// +/// Note: Supports lazily populated configurations. +/// Call [validate] method to make sure the files in the +/// configuration layout exist before reading the files. +abstract class SdkConfigurationInterface { + Future get sdkDirectory; + Future get unsoundSdkSummaryPath; + Future get soundSdkSummaryPath; + Future get librariesPath; + Future get compilerWorkerPath; + + Future get sdkDirectoryUri => + sdkDirectory.then((value) => value == null ? null : Uri.parse(value)); + + Future get librariesUri => + librariesPath.then((value) => value == null ? null : Uri.parse(value)); + + /// Note: has to be ///file: Uri to run in an isolate. + Future get compilerWorkerUri => compilerWorkerPath + .then((value) => value == null ? null : p.toUri(p.absolute(value))); + + /// Throws [InvalidSdkConfigurationException] if configuration does not + /// exist on disk. + Future validate() async { + await validateSdkDir(); + + var libraries = await librariesPath; + if (libraries == null || !File(libraries).existsSync()) { + throw InvalidSdkConfigurationException( + 'Libraries spec $libraries does not exist'); + } + + var unsoundSdkSummary = await unsoundSdkSummaryPath; + if (unsoundSdkSummary == null || !File(unsoundSdkSummary).existsSync()) { + throw InvalidSdkConfigurationException( + 'Sdk summary $unsoundSdkSummary does not exist'); + } + + var soundSdkSummary = await soundSdkSummaryPath; + if (soundSdkSummary == null || !File(soundSdkSummary).existsSync()) { + throw InvalidSdkConfigurationException( + 'Sdk summary $soundSdkSummary does not exist'); + } + + var compilerWorker = await compilerWorkerPath; + if (compilerWorker == null || !File(compilerWorker).existsSync()) { + throw InvalidSdkConfigurationException( + 'Compiler worker $compilerWorker does not exist'); + } + } + + /// Throws [InvalidSdkConfigurationException] if SDK root does not + /// exist on the disk. + Future validateSdkDir() async { + var sdkDir = await sdkDirectory; + if (sdkDir == null || !Directory(sdkDir).existsSync()) { + throw InvalidSdkConfigurationException( + 'Sdk directory $sdkDir does not exist'); + } + } +} + +/// Implementation for the default SDK configuration layout. +class SdkConfiguration extends SdkConfigurationInterface { + final String _sdkDirectory; + final String _unsoundSdkSummaryPath; + final String _soundSdkSummaryPath; + final String _librariesPath; + final String _compilerWorkerPath; + + SdkConfiguration({ + String sdkDirectory, + String unsoundSdkSummaryPath, + String soundSdkSummaryPath, + String librariesPath, + String compilerWorkerPath, + }) : _sdkDirectory = sdkDirectory, + _unsoundSdkSummaryPath = unsoundSdkSummaryPath, + _soundSdkSummaryPath = soundSdkSummaryPath, + _librariesPath = librariesPath, + _compilerWorkerPath = compilerWorkerPath; + + @override + Future get sdkDirectory async => _sdkDirectory; + + @override + Future get unsoundSdkSummaryPath async => _unsoundSdkSummaryPath; + + @override + Future get soundSdkSummaryPath async => _soundSdkSummaryPath; + + @override + Future get librariesPath async => _librariesPath; + + @override + Future get compilerWorkerPath async => _compilerWorkerPath; + + /// Create and validate configuration matching the default SDK layout. + factory SdkConfiguration.standard() { + final binDir = p.dirname(Platform.resolvedExecutable); + final sdkDir = p.dirname(binDir); + + if (sdkDir == null || !Directory(sdkDir).existsSync()) { + throw InvalidSdkConfigurationException( + 'Could not detect default SDK configuration. ' + 'Directory $sdkDir does not exist.'); + } + + var configuration = SdkConfiguration( + sdkDirectory: sdkDir, + unsoundSdkSummaryPath: p.join(sdkDir, 'lib', '_internal', 'ddc_sdk.dill'), + soundSdkSummaryPath: + p.join(sdkDir, 'lib', '_internal', 'ddc_outline_sound.dill'), + librariesPath: p.join(sdkDir, 'lib', 'libraries.json'), + compilerWorkerPath: p.join(binDir, 'snapshots', 'dartdevc.dart.snapshot'), + ); + + configuration.validate(); + return configuration; + } +} diff --git a/dwds/test/dart_uri_test.dart b/dwds/test/dart_uri_test.dart index c15561921..3b668f3b4 100644 --- a/dwds/test/dart_uri_test.dart +++ b/dwds/test/dart_uri_test.dart @@ -7,6 +7,7 @@ @TestOn('vm') import 'dart:io'; +import 'package:dwds/dwds.dart'; import 'package:dwds/src/loaders/strategy.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; import 'package:path/path.dart' as p; @@ -54,7 +55,7 @@ void main() { group('initialized with current SDK directory', () { setUpAll(() async { - await DartUri.initialize(); + await DartUri.initialize(SdkConfiguration.standard()); await DartUri.recordAbsoluteUris(['dart:io', 'dart:html']); }); @@ -90,7 +91,11 @@ void main() { Directory(fakeLibrariesDir).createSync(); File(librariesPath).copySync(fakeLibrariesPath); - await DartUri.initialize(sdkDir: Uri.file(fakeSdkDir)); + var sdkConfiguration = SdkConfiguration( + sdkDirectory: fakeSdkDir, + librariesPath: fakeLibrariesPath, + ); + await DartUri.initialize(sdkConfiguration); await DartUri.recordAbsoluteUris(['dart:io', 'dart:html']); }); @@ -133,9 +138,11 @@ void main() { var fakeLibrariesDir = p.join(fakeSdkDir, 'lib'); var fakeLibrariesPath = p.join(fakeLibrariesDir, 'libraries.json'); - await DartUri.initialize( - sdkDir: Uri.file(fakeSdkDir), - librariesPath: Uri.file(fakeLibrariesPath)); + var sdkConfiguration = SdkConfiguration( + sdkDirectory: fakeSdkDir, + librariesPath: fakeLibrariesPath, + ); + await DartUri.initialize(sdkConfiguration); await DartUri.recordAbsoluteUris(['dart:io', 'dart:html']); expect( diff --git a/dwds/test/expression_compiler_service_test.dart b/dwds/test/expression_compiler_service_test.dart index 3886b1f5e..d7d952284 100644 --- a/dwds/test/expression_compiler_service_test.dart +++ b/dwds/test/expression_compiler_service_test.dart @@ -61,8 +61,8 @@ void main() async { // start expression compilation service Response assetHandler(request) => Response(200, body: File.fromUri(kernel).readAsBytesSync()); - service = - ExpressionCompilerService('localhost', port, assetHandler, false); + service = ExpressionCompilerService('localhost', port, assetHandler, + verbose: false); await service.initialize(moduleFormat: 'amd'); diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 779d8d743..ade6da293 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -105,21 +105,23 @@ class TestContext { _entryContents = _entryFile.readAsStringSync(); } - Future setUp( - {ReloadConfiguration reloadConfiguration, - bool serveDevTools, - bool enableDebugExtension, - bool autoRun, - bool enableDebugging, - bool useSse, - bool spawnDds, - String hostname, - bool waitToDebug, - UrlEncoder urlEncoder, - bool restoreBreakpoints, - CompilationMode compilationMode, - bool enableExpressionEvaluation, - bool verboseCompiler}) async { + Future setUp({ + ReloadConfiguration reloadConfiguration, + bool serveDevTools, + bool enableDebugExtension, + bool autoRun, + bool enableDebugging, + bool useSse, + bool spawnDds, + String hostname, + bool waitToDebug, + UrlEncoder urlEncoder, + bool restoreBreakpoints, + CompilationMode compilationMode, + bool enableExpressionEvaluation, + bool verboseCompiler, + SdkConfigurationInterface sdkConfiguration, + }) async { reloadConfiguration ??= ReloadConfiguration.none; serveDevTools ??= false; enableDebugExtension ??= false; @@ -130,6 +132,7 @@ class TestContext { enableExpressionEvaluation ??= false; spawnDds ??= true; verboseCompiler ??= false; + sdkConfiguration ??= SdkConfiguration.standard(); try { configureLogWriter(); @@ -219,7 +222,8 @@ class TestContext { 'localhost', port, assetHandler, - verboseCompiler, + verbose: verboseCompiler, + sdkConfiguration: sdkConfiguration, ); expressionCompiler = ddcService; } diff --git a/dwds/test/sdk_configuration_test.dart b/dwds/test/sdk_configuration_test.dart new file mode 100644 index 000000000..e0c3feddb --- /dev/null +++ b/dwds/test/sdk_configuration_test.dart @@ -0,0 +1,118 @@ +// Copyright (c) 2019, 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. + +// @dart = 2.9 + +@TestOn('vm') +import 'dart:io'; + +import 'package:dwds/src/utilities/sdk_configuration.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +var _throwsDoesNotExistException = throwsA( + isA() + .having((e) => '$e', 'message', contains('does not exist'))); + +void main() { + group('Basic configuration', () { + test('Can validate default configuration layout', () async { + var defaultConfiguration = SdkConfiguration.standard(); + await defaultConfiguration.validateSdkDir(); + await defaultConfiguration.validate(); + }); + + test('Cannot validate an empty configuration layout', () async { + var emptyConfiguration = SdkConfiguration(); + await expectLater( + emptyConfiguration.validateSdkDir(), _throwsDoesNotExistException); + await expectLater( + emptyConfiguration.validate(), _throwsDoesNotExistException); + }); + }); + + group('Non-standard configuration', () { + Directory outputDir; + + setUp(() async { + var systemTempDir = Directory.systemTemp; + outputDir = systemTempDir.createTempSync('foo bar'); + }); + + tearDown(() async { + await outputDir?.delete(recursive: true); + }); + + test('Can validate existing configuration layout', () async { + var defaultSdkConfiguration = SdkConfiguration.standard(); + + var sdkDirectory = outputDir.path; + var librariesDir = p.join(sdkDirectory, 'specs'); + var librariesPath = p.join(librariesDir, 'libraries.json'); + + Directory(librariesDir).createSync(recursive: true); + File(await defaultSdkConfiguration.librariesPath).copySync(librariesPath); + + var summariesDir = p.join(sdkDirectory, 'summaries'); + var unsoundSdkSummaryPath = p.join(summariesDir, 'ddc_sdk.dill'); + var soundSdkSummaryPath = p.join(summariesDir, 'ddc_outline_sound.dill'); + + Directory(summariesDir).createSync(recursive: true); + File(await defaultSdkConfiguration.unsoundSdkSummaryPath) + .copySync(unsoundSdkSummaryPath); + File(await defaultSdkConfiguration.soundSdkSummaryPath) + .copySync(soundSdkSummaryPath); + + var workerDir = p.join(sdkDirectory, 'snapshots'); + var compilerWorkerPath = p.join(workerDir, 'dartdevc.dart.snapshot'); + + Directory(workerDir).createSync(recursive: true); + File(await defaultSdkConfiguration.compilerWorkerPath) + .copySync(compilerWorkerPath); + + var sdkConfiguration = SdkConfiguration( + sdkDirectory: sdkDirectory, + soundSdkSummaryPath: soundSdkSummaryPath, + unsoundSdkSummaryPath: unsoundSdkSummaryPath, + librariesPath: librariesPath, + compilerWorkerPath: compilerWorkerPath, + ); + + expect(await sdkConfiguration.sdkDirectory, equals(sdkDirectory)); + expect(await sdkConfiguration.unsoundSdkSummaryPath, + equals(unsoundSdkSummaryPath)); + expect(await sdkConfiguration.soundSdkSummaryPath, + equals(soundSdkSummaryPath)); + expect(await sdkConfiguration.librariesPath, equals(librariesPath)); + expect(await sdkConfiguration.compilerWorkerPath, + equals(compilerWorkerPath)); + + await expectLater(sdkConfiguration.validateSdkDir(), completes); + await expectLater(sdkConfiguration.validate(), completes); + }); + + test('Cannot validate non-existing configuration layout', () async { + var sdkDir = outputDir.path; + var librariesDir = p.join(sdkDir, 'fakespecs'); + var librariesPath = p.join(librariesDir, 'libraries.json'); + var summariesDir = p.join(sdkDir, 'fakesummaries'); + var unsoundSdkSummaryPath = p.join(summariesDir, 'ddc_sdk.dill'); + var soundSdkSummaryPath = p.join(summariesDir, 'ddc_outline_sound.dill'); + var workerDir = p.join(sdkDir, 'fakesnapshots'); + var compilerWorkerPath = p.join(workerDir, 'dartdevc.dart.snapshot'); + + var sdkConfiguration = SdkConfiguration( + sdkDirectory: sdkDir, + soundSdkSummaryPath: soundSdkSummaryPath, + unsoundSdkSummaryPath: unsoundSdkSummaryPath, + librariesPath: librariesPath, + compilerWorkerPath: compilerWorkerPath, + ); + + await expectLater(sdkConfiguration.validateSdkDir(), completes); + await expectLater( + sdkConfiguration.validate(), _throwsDoesNotExistException); + }); + }); +} From d5a823e7bd9efe3568b46d137fb04698de11f5bb Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 17 Feb 2022 09:16:31 -0800 Subject: [PATCH 02/10] Fix SDK Uris on Windows --- dwds/lib/src/services/expression_compiler_service.dart | 6 +++--- dwds/lib/src/utilities/sdk_configuration.dart | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dwds/lib/src/services/expression_compiler_service.dart b/dwds/lib/src/services/expression_compiler_service.dart index 4020e99c8..be1e41ec5 100644 --- a/dwds/lib/src/services/expression_compiler_service.dart +++ b/dwds/lib/src/services/expression_compiler_service.dart @@ -74,15 +74,15 @@ class _Compiler { final librariesUri = await sdkConfiguration.librariesUri; final workerUri = await sdkConfiguration.compilerWorkerUri; final sdkSummaryUri = soundNullSafety - ? await sdkConfiguration.soundSdkSummaryPath - : await sdkConfiguration.unsoundSdkSummaryPath; + ? await sdkConfiguration.soundSdkSummaryUri + : await sdkConfiguration.unsoundSdkSummaryUri; final args = [ '--experimental-expression-compiler', '--libraries-file', '$librariesUri', '--dart-sdk-summary', - sdkSummaryUri, + '$sdkSummaryUri', '--asset-server-address', address, '--asset-server-port', diff --git a/dwds/lib/src/utilities/sdk_configuration.dart b/dwds/lib/src/utilities/sdk_configuration.dart index 14b0d2dfe..213124289 100644 --- a/dwds/lib/src/utilities/sdk_configuration.dart +++ b/dwds/lib/src/utilities/sdk_configuration.dart @@ -36,8 +36,14 @@ abstract class SdkConfigurationInterface { Future get sdkDirectoryUri => sdkDirectory.then((value) => value == null ? null : Uri.parse(value)); + Future get soundSdkSummaryUri => soundSdkSummaryPath + .then((value) => value == null ? null : Uri.file(value)); + + Future get unsoundSdkSummaryUri => unsoundSdkSummaryPath + .then((value) => value == null ? null : Uri.file(value)); + Future get librariesUri => - librariesPath.then((value) => value == null ? null : Uri.parse(value)); + librariesPath.then((value) => value == null ? null : Uri.file(value)); /// Note: has to be ///file: Uri to run in an isolate. Future get compilerWorkerUri => compilerWorkerPath From ede9d9c9c54a6ce00b71c7289a5a24deecd64842 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 17 Feb 2022 09:50:24 -0800 Subject: [PATCH 03/10] Fix more Uris on Windows --- dwds/lib/src/utilities/sdk_configuration.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dwds/lib/src/utilities/sdk_configuration.dart b/dwds/lib/src/utilities/sdk_configuration.dart index 213124289..758854de6 100644 --- a/dwds/lib/src/utilities/sdk_configuration.dart +++ b/dwds/lib/src/utilities/sdk_configuration.dart @@ -34,16 +34,16 @@ abstract class SdkConfigurationInterface { Future get compilerWorkerPath; Future get sdkDirectoryUri => - sdkDirectory.then((value) => value == null ? null : Uri.parse(value)); + sdkDirectory.then((value) => value == null ? null : p.toUri(value)); Future get soundSdkSummaryUri => soundSdkSummaryPath - .then((value) => value == null ? null : Uri.file(value)); + .then((value) => value == null ? null : p.toUri(value)); Future get unsoundSdkSummaryUri => unsoundSdkSummaryPath - .then((value) => value == null ? null : Uri.file(value)); + .then((value) => value == null ? null : p.toUri(value)); Future get librariesUri => - librariesPath.then((value) => value == null ? null : Uri.file(value)); + librariesPath.then((value) => value == null ? null : p.toUri(value)); /// Note: has to be ///file: Uri to run in an isolate. Future get compilerWorkerUri => compilerWorkerPath From d8e6d6b1c8b9dfc9999d59d30b2d4093b779c269 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 17 Feb 2022 15:56:48 -0800 Subject: [PATCH 04/10] Reworked SdkConfiguration --- dwds/lib/dwds.dart | 8 +- dwds/lib/src/debugging/inspector.dart | 4 +- dwds/lib/src/handlers/dev_handler.dart | 8 +- .../src/services/chrome_proxy_service.dart | 11 +- dwds/lib/src/services/debug_service.dart | 4 +- .../services/expression_compiler_service.dart | 27 +-- dwds/lib/src/utilities/dart_uri.dart | 23 ++- dwds/lib/src/utilities/sdk_configuration.dart | 170 ++++++++---------- dwds/test/dart_uri_test.dart | 6 +- dwds/test/fixtures/context.dart | 7 +- dwds/test/sdk_configuration_test.dart | 48 +++-- 11 files changed, 151 insertions(+), 165 deletions(-) diff --git a/dwds/lib/dwds.dart b/dwds/lib/dwds.dart index 270744cc9..6e31f60d1 100644 --- a/dwds/lib/dwds.dart +++ b/dwds/lib/dwds.dart @@ -51,7 +51,7 @@ export 'src/services/expression_compiler.dart' export 'src/services/expression_compiler_service.dart' show ExpressionCompilerService; export 'src/utilities/sdk_configuration.dart' - show SdkConfiguration, SdkConfigurationInterface; + show SdkConfiguration, SdkConfigurationProvider; typedef ConnectionProvider = Future Function(); typedef UrlEncoder = Future Function(String url); @@ -117,7 +117,7 @@ class Dwds { bool enableDevtoolsLaunch, DevtoolsLauncher devtoolsLauncher, bool launchDevToolsInNewWindow, - SdkConfigurationInterface sdkConfiguration, + SdkConfigurationProvider sdkConfigurationProvider, bool emitDebugEvents, }) async { hostname ??= 'localhost'; @@ -132,7 +132,7 @@ class Dwds { globalLoadStrategy = loadStrategy; emitDebugEvents ??= true; - sdkConfiguration ??= SdkConfiguration.standard(); + sdkConfigurationProvider ??= DefaultSdkConfigurationProvider(); DevTools devTools; Future extensionUri; @@ -189,7 +189,7 @@ class Dwds { injected, spawnDds, launchDevToolsInNewWindow, - sdkConfiguration, + sdkConfigurationProvider, ); return Dwds._( diff --git a/dwds/lib/src/debugging/inspector.dart b/dwds/lib/src/debugging/inspector.dart index 4508065be..088074f3b 100644 --- a/dwds/lib/src/debugging/inspector.dart +++ b/dwds/lib/src/debugging/inspector.dart @@ -65,7 +65,7 @@ class AppInspector extends Domain { /// The root URI from which the application is served. final String _root; - final SdkConfigurationInterface _sdkConfiguration; + final SdkConfiguration _sdkConfiguration; AppInspector._( this.appConnection, @@ -116,7 +116,7 @@ class AppInspector extends Domain { String root, Debugger debugger, ExecutionContext executionContext, - SdkConfigurationInterface sdkConfiguration, + SdkConfiguration sdkConfiguration, ) async { var id = createId(); var time = DateTime.now().millisecondsSinceEpoch; diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index ad0d4cd74..5f7a68791 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -66,7 +66,7 @@ class DevHandler { final bool _launchDevToolsInNewWindow; final ExpressionCompiler _expressionCompiler; final DwdsInjector _injected; - final SdkConfigurationInterface _sdkConfiguration; + final SdkConfigurationProvider _sdkConfigurationProvider; /// Null until [close] is called. /// @@ -91,7 +91,7 @@ class DevHandler { this._injected, this._spawnDds, this._launchDevToolsInNewWindow, - this._sdkConfiguration, + this._sdkConfigurationProvider, ) { _subs.add(buildResults.listen(_emitBuildResults)); _listen(); @@ -213,7 +213,7 @@ class DevHandler { useSse: false, expressionCompiler: _expressionCompiler, spawnDds: _spawnDds, - sdkConfiguration: _sdkConfiguration, + sdkConfigurationProvider: _sdkConfigurationProvider, ); } @@ -503,7 +503,7 @@ class DevHandler { useSse: _useSseForDebugProxy, expressionCompiler: _expressionCompiler, spawnDds: _spawnDds, - sdkConfiguration: _sdkConfiguration, + sdkConfigurationProvider: _sdkConfigurationProvider, ); var appServices = await _createAppDebugServices( devToolsRequest.appId, diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 7e0d3d511..b7502253a 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -94,7 +94,7 @@ class ChromeProxyService implements VmServiceInterface { final ExpressionCompiler _compiler; ExpressionEvaluator _expressionEvaluator; - final SdkConfigurationInterface _sdkConfiguration; + final SdkConfigurationProvider _sdkConfigurationProvider; bool terminatingIsolates = false; @@ -108,7 +108,7 @@ class ChromeProxyService implements VmServiceInterface { this._skipLists, this.executionContext, this._compiler, - this._sdkConfiguration, + this._sdkConfigurationProvider, ) { var debugger = Debugger.create( remoteDebugger, @@ -129,7 +129,7 @@ class ChromeProxyService implements VmServiceInterface { AppConnection appConnection, ExecutionContext executionContext, ExpressionCompiler expressionCompiler, - SdkConfigurationInterface sdkConfiguration, + SdkConfigurationProvider sdkConfigurationProvider, ) async { final vm = VM( name: 'ChromeDebugProxy', @@ -159,7 +159,7 @@ class ChromeProxyService implements VmServiceInterface { skipLists, executionContext, expressionCompiler, - sdkConfiguration, + sdkConfigurationProvider, ); unawaited(service.createIsolate(appConnection)); return service; @@ -216,6 +216,7 @@ class ChromeProxyService implements VmServiceInterface { // Issue: https://github.com/dart-lang/webdev/issues/1282 var debugger = await _debugger; await _initializeEntrypoint(appConnection.request.entrypointPath); + var sdkConfiguration = await _sdkConfigurationProvider.configuration; debugger.notifyPausedAtStart(); _inspector = await AppInspector.initialize( @@ -226,7 +227,7 @@ class ChromeProxyService implements VmServiceInterface { uri, debugger, executionContext, - _sdkConfiguration, + sdkConfiguration, ); _expressionEvaluator = _compiler == null diff --git a/dwds/lib/src/services/debug_service.dart b/dwds/lib/src/services/debug_service.dart index 9d30ef105..f5997d56f 100644 --- a/dwds/lib/src/services/debug_service.dart +++ b/dwds/lib/src/services/debug_service.dart @@ -216,7 +216,7 @@ class DebugService { bool spawnDds = true, bool useSse, ExpressionCompiler expressionCompiler, - SdkConfigurationInterface sdkConfiguration, + SdkConfigurationProvider sdkConfigurationProvider, }) async { useSse ??= false; var chromeProxyService = await ChromeProxyService.create( @@ -227,7 +227,7 @@ class DebugService { appConnection, executionContext, expressionCompiler, - sdkConfiguration, + sdkConfigurationProvider, ); var authToken = _makeAuthToken(); var serviceExtensionRegistry = ServiceExtensionRegistry(); diff --git a/dwds/lib/src/services/expression_compiler_service.dart b/dwds/lib/src/services/expression_compiler_service.dart index be1e41ec5..eb82bcc37 100644 --- a/dwds/lib/src/services/expression_compiler_service.dart +++ b/dwds/lib/src/services/expression_compiler_service.dart @@ -66,16 +66,16 @@ class _Compiler { int port, String moduleFormat, bool soundNullSafety, - SdkConfigurationInterface sdkConfiguration, + SdkConfiguration sdkConfiguration, bool verbose, ) async { - await sdkConfiguration.validate(); + sdkConfiguration.validate(); - final librariesUri = await sdkConfiguration.librariesUri; - final workerUri = await sdkConfiguration.compilerWorkerUri; + final librariesUri = sdkConfiguration.librariesUri; + final workerUri = sdkConfiguration.compilerWorkerUri; final sdkSummaryUri = soundNullSafety - ? await sdkConfiguration.soundSdkSummaryUri - : await sdkConfiguration.unsoundSdkSummaryUri; + ? sdkConfiguration.soundSdkSummaryUri + : sdkConfiguration.unsoundSdkSummaryUri; final args = [ '--experimental-expression-compiler', @@ -223,9 +223,9 @@ class _Compiler { /// Uses [_address] and [_port] to communicate and [_assetHandler] to /// redirect asset requests to the asset server. /// -/// [_sdkConfiguration] describes the locations of SDK files used in -/// expression compilation (summaries, libraries spec, compiler worker -/// snapshot). +/// Configuration created by [_sdkConfigurationProvider] describes the +/// locations of SDK files used in expression compilation (summaries, +/// libraries spec, compiler worker snapshot). /// /// Users need to stop the service by calling [stop]. class ExpressionCompilerService implements ExpressionCompiler { @@ -235,16 +235,17 @@ class ExpressionCompilerService implements ExpressionCompiler { final Handler _assetHandler; final bool _verbose; - final SdkConfigurationInterface _sdkConfiguration; + final SdkConfigurationProvider _sdkConfigurationProvider; ExpressionCompilerService( this._address, this._port, this._assetHandler, { bool verbose = false, - SdkConfigurationInterface sdkConfiguration, + SdkConfigurationProvider sdkConfigurationProvider, }) : _verbose = verbose, - _sdkConfiguration = sdkConfiguration ?? SdkConfiguration.standard(); + _sdkConfigurationProvider = + sdkConfigurationProvider ?? DefaultSdkConfigurationProvider(); @override Future compileExpressionToJs( @@ -269,7 +270,7 @@ class ExpressionCompilerService implements ExpressionCompiler { await _port, moduleFormat, soundNullSafety, - _sdkConfiguration, + await _sdkConfigurationProvider.configuration, _verbose, ); diff --git a/dwds/lib/src/utilities/dart_uri.dart b/dwds/lib/src/utilities/dart_uri.dart index 7fcc362e1..ac37027b5 100644 --- a/dwds/lib/src/utilities/dart_uri.dart +++ b/dwds/lib/src/utilities/dart_uri.dart @@ -108,7 +108,7 @@ class DartUri { /// For example: `/Users/me/.dart-sdks/2.15.0` /// /// Used to resolve SDK urls according to vm_service protocol. - static SdkConfigurationInterface _sdkConfiguration; + static SdkConfiguration _sdkConfiguration; /// All of the known absolute library paths, indexed by their library URL. /// @@ -155,14 +155,13 @@ class DartUri { static String currentDirectoryUri = '${p.toUri(currentDirectory)}'; /// Record library and script uris to enable resolving library and script paths. - static Future initialize( - SdkConfigurationInterface sdkConfiguration) async { - await sdkConfiguration.validateSdkDir(); + static Future initialize(SdkConfiguration sdkConfiguration) async { + sdkConfiguration.validateSdkDir(); _sdkConfiguration = sdkConfiguration; var packagesUri = p.toUri(p.join(currentDirectory, '.packages')); clear(); - await _loadLibrariesConfig(await _sdkConfiguration.librariesUri); + await _loadLibrariesConfig(_sdkConfiguration.librariesUri); await _loadPackageConfig(packagesUri); } @@ -176,9 +175,8 @@ class DartUri { /// Record all of the libraries, indexed by their absolute file: URI. static Future recordAbsoluteUris(Iterable libraryUris) async { - var sdkDirectoryUri = await _sdkConfiguration.sdkDirectoryUri; for (var uri in libraryUris) { - _recordAbsoluteUri(Uri.parse(uri), sdkDirectoryUri); + _recordAbsoluteUri(uri); } } @@ -209,22 +207,21 @@ class DartUri { /// Record the library represented by package: or org-dartlang-app: uris /// indexed by absolute file: URI. - static void _recordAbsoluteUri(Uri uri, Uri sdkDirectoryUri) { + static void _recordAbsoluteUri(String libraryUri) { + var uri = Uri.parse(libraryUri); if (uri.scheme.isEmpty && !uri.path.endsWith('.dart')) { // ignore non-dart files return; } - var libraryUri = '$uri'; String libraryPath; switch (uri.scheme) { case 'dart': var libSpec = _librariesSpec?.libraryInfoFor(uri.path); libraryPath = libSpec?.uri?.path; - if (sdkDirectoryUri != null) { - libraryPath = libraryPath?.replaceAll( - sdkDirectoryUri.path, 'org-dartlang-sdk:///sdk'); - } + var sdkDir = _sdkConfiguration.sdkDirectoryUri; + libraryPath = + libraryPath?.replaceAll(sdkDir.path, 'org-dartlang-sdk:///sdk'); break; case 'org-dartlang-app': case 'google3': diff --git a/dwds/lib/src/utilities/sdk_configuration.dart b/dwds/lib/src/utilities/sdk_configuration.dart index 758854de6..546fcb40e 100644 --- a/dwds/lib/src/utilities/sdk_configuration.dart +++ b/dwds/lib/src/utilities/sdk_configuration.dart @@ -21,131 +21,117 @@ class InvalidSdkConfigurationException implements Exception { } } -/// Interface describing the SDK layout. +/// SDK configuration provider interface. /// -/// Note: Supports lazily populated configurations. -/// Call [validate] method to make sure the files in the -/// configuration layout exist before reading the files. -abstract class SdkConfigurationInterface { - Future get sdkDirectory; - Future get unsoundSdkSummaryPath; - Future get soundSdkSummaryPath; - Future get librariesPath; - Future get compilerWorkerPath; - - Future get sdkDirectoryUri => - sdkDirectory.then((value) => value == null ? null : p.toUri(value)); - - Future get soundSdkSummaryUri => soundSdkSummaryPath - .then((value) => value == null ? null : p.toUri(value)); +/// Supports lazily populated configurations by allowing to create +/// configuration asyncronously. +abstract class SdkConfigurationProvider { + Future get configuration; +} - Future get unsoundSdkSummaryUri => unsoundSdkSummaryPath - .then((value) => value == null ? null : p.toUri(value)); +/// Data class describing the SDK layout. +/// +/// Provides helpers to convert paths to uris that work on all platforms. +/// +/// Call [validate] method to make sure the files in the configuration +/// layout exist before reading the files. +class SdkConfiguration { + String sdkDirectory; + String unsoundSdkSummaryPath; + String soundSdkSummaryPath; + String librariesPath; + String compilerWorkerPath; - Future get librariesUri => - librariesPath.then((value) => value == null ? null : p.toUri(value)); + SdkConfiguration({ + this.sdkDirectory, + this.unsoundSdkSummaryPath, + this.soundSdkSummaryPath, + this.librariesPath, + this.compilerWorkerPath, + }); + + static Uri _toUri(String path) => path == null ? null : p.toUri(path); + static Uri _toAbsoluteUri(String path) => + path == null ? null : p.toUri(p.absolute(path)); + + Uri get sdkDirectoryUri => _toUri(sdkDirectory); + Uri get soundSdkSummaryUri => _toUri(soundSdkSummaryPath); + Uri get unsoundSdkSummaryUri => _toUri(unsoundSdkSummaryPath); + Uri get librariesUri => _toUri(librariesPath); /// Note: has to be ///file: Uri to run in an isolate. - Future get compilerWorkerUri => compilerWorkerPath - .then((value) => value == null ? null : p.toUri(p.absolute(value))); + Uri get compilerWorkerUri => _toAbsoluteUri(compilerWorkerPath); /// Throws [InvalidSdkConfigurationException] if configuration does not /// exist on disk. - Future validate() async { - await validateSdkDir(); + void validate() { + validateSdkDir(); - var libraries = await librariesPath; - if (libraries == null || !File(libraries).existsSync()) { + if (unsoundSdkSummaryPath == null || + !File(unsoundSdkSummaryPath).existsSync()) { throw InvalidSdkConfigurationException( - 'Libraries spec $libraries does not exist'); + 'Sdk summary $unsoundSdkSummaryPath does not exist'); } - var unsoundSdkSummary = await unsoundSdkSummaryPath; - if (unsoundSdkSummary == null || !File(unsoundSdkSummary).existsSync()) { + if (soundSdkSummaryPath == null || + !File(soundSdkSummaryPath).existsSync()) { throw InvalidSdkConfigurationException( - 'Sdk summary $unsoundSdkSummary does not exist'); + 'Sdk summary $soundSdkSummaryPath does not exist'); } - var soundSdkSummary = await soundSdkSummaryPath; - if (soundSdkSummary == null || !File(soundSdkSummary).existsSync()) { + if (librariesPath == null || !File(librariesPath).existsSync()) { throw InvalidSdkConfigurationException( - 'Sdk summary $soundSdkSummary does not exist'); + 'Libraries spec $librariesPath does not exist'); } - var compilerWorker = await compilerWorkerPath; - if (compilerWorker == null || !File(compilerWorker).existsSync()) { + if (compilerWorkerPath == null || !File(compilerWorkerPath).existsSync()) { throw InvalidSdkConfigurationException( - 'Compiler worker $compilerWorker does not exist'); + 'Compiler worker $compilerWorkerPath does not exist'); } } /// Throws [InvalidSdkConfigurationException] if SDK root does not /// exist on the disk. - Future validateSdkDir() async { - var sdkDir = await sdkDirectory; - if (sdkDir == null || !Directory(sdkDir).existsSync()) { + void validateSdkDir() { + if (sdkDirectory == null || !Directory(sdkDirectory).existsSync()) { throw InvalidSdkConfigurationException( - 'Sdk directory $sdkDir does not exist'); + 'Sdk directory $sdkDirectory does not exist'); } } } /// Implementation for the default SDK configuration layout. -class SdkConfiguration extends SdkConfigurationInterface { - final String _sdkDirectory; - final String _unsoundSdkSummaryPath; - final String _soundSdkSummaryPath; - final String _librariesPath; - final String _compilerWorkerPath; +class DefaultSdkConfigurationProvider extends SdkConfigurationProvider { + SdkConfiguration _configuration; - SdkConfiguration({ - String sdkDirectory, - String unsoundSdkSummaryPath, - String soundSdkSummaryPath, - String librariesPath, - String compilerWorkerPath, - }) : _sdkDirectory = sdkDirectory, - _unsoundSdkSummaryPath = unsoundSdkSummaryPath, - _soundSdkSummaryPath = soundSdkSummaryPath, - _librariesPath = librariesPath, - _compilerWorkerPath = compilerWorkerPath; - - @override - Future get sdkDirectory async => _sdkDirectory; - - @override - Future get unsoundSdkSummaryPath async => _unsoundSdkSummaryPath; - - @override - Future get soundSdkSummaryPath async => _soundSdkSummaryPath; - - @override - Future get librariesPath async => _librariesPath; - - @override - Future get compilerWorkerPath async => _compilerWorkerPath; + DefaultSdkConfigurationProvider(); /// Create and validate configuration matching the default SDK layout. - factory SdkConfiguration.standard() { - final binDir = p.dirname(Platform.resolvedExecutable); - final sdkDir = p.dirname(binDir); - - if (sdkDir == null || !Directory(sdkDir).existsSync()) { - throw InvalidSdkConfigurationException( - 'Could not detect default SDK configuration. ' - 'Directory $sdkDir does not exist.'); + @override + Future get configuration async { + if (_configuration == null) { + final binDir = p.dirname(Platform.resolvedExecutable); + final sdkDir = p.dirname(binDir); + + if (sdkDir == null || !Directory(sdkDir).existsSync()) { + throw InvalidSdkConfigurationException( + 'Could not detect default SDK configuration. ' + 'Directory $sdkDir does not exist.'); + } + + _configuration = SdkConfiguration( + sdkDirectory: sdkDir, + unsoundSdkSummaryPath: + p.join(sdkDir, 'lib', '_internal', 'ddc_sdk.dill'), + soundSdkSummaryPath: + p.join(sdkDir, 'lib', '_internal', 'ddc_outline_sound.dill'), + librariesPath: p.join(sdkDir, 'lib', 'libraries.json'), + compilerWorkerPath: + p.join(binDir, 'snapshots', 'dartdevc.dart.snapshot'), + ); + + _configuration.validate(); } - - var configuration = SdkConfiguration( - sdkDirectory: sdkDir, - unsoundSdkSummaryPath: p.join(sdkDir, 'lib', '_internal', 'ddc_sdk.dill'), - soundSdkSummaryPath: - p.join(sdkDir, 'lib', '_internal', 'ddc_outline_sound.dill'), - librariesPath: p.join(sdkDir, 'lib', 'libraries.json'), - compilerWorkerPath: p.join(binDir, 'snapshots', 'dartdevc.dart.snapshot'), - ); - - configuration.validate(); - return configuration; + return _configuration; } } diff --git a/dwds/test/dart_uri_test.dart b/dwds/test/dart_uri_test.dart index 3b668f3b4..402fe12a6 100644 --- a/dwds/test/dart_uri_test.dart +++ b/dwds/test/dart_uri_test.dart @@ -7,9 +7,9 @@ @TestOn('vm') import 'dart:io'; -import 'package:dwds/dwds.dart'; import 'package:dwds/src/loaders/strategy.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds/src/utilities/sdk_configuration.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; @@ -55,7 +55,9 @@ void main() { group('initialized with current SDK directory', () { setUpAll(() async { - await DartUri.initialize(SdkConfiguration.standard()); + var sdkConfiguration = + await DefaultSdkConfigurationProvider().configuration; + await DartUri.initialize(sdkConfiguration); await DartUri.recordAbsoluteUris(['dart:io', 'dart:html']); }); diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index ade6da293..e0b483713 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -14,6 +14,7 @@ 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/dart_uri.dart'; +import 'package:dwds/src/utilities/sdk_configuration.dart'; import 'package:dwds/src/utilities/shared.dart'; import 'package:frontend_server_common/src/resident_runner.dart'; import 'package:http/http.dart'; @@ -120,7 +121,7 @@ class TestContext { CompilationMode compilationMode, bool enableExpressionEvaluation, bool verboseCompiler, - SdkConfigurationInterface sdkConfiguration, + SdkConfigurationProvider sdkConfigurationProvider, }) async { reloadConfiguration ??= ReloadConfiguration.none; serveDevTools ??= false; @@ -132,7 +133,7 @@ class TestContext { enableExpressionEvaluation ??= false; spawnDds ??= true; verboseCompiler ??= false; - sdkConfiguration ??= SdkConfiguration.standard(); + sdkConfigurationProvider ??= DefaultSdkConfigurationProvider(); try { configureLogWriter(); @@ -223,7 +224,7 @@ class TestContext { port, assetHandler, verbose: verboseCompiler, - sdkConfiguration: sdkConfiguration, + sdkConfigurationProvider: sdkConfigurationProvider, ); expressionCompiler = ddcService; } diff --git a/dwds/test/sdk_configuration_test.dart b/dwds/test/sdk_configuration_test.dart index e0c3feddb..bd2901665 100644 --- a/dwds/test/sdk_configuration_test.dart +++ b/dwds/test/sdk_configuration_test.dart @@ -18,17 +18,17 @@ var _throwsDoesNotExistException = throwsA( void main() { group('Basic configuration', () { test('Can validate default configuration layout', () async { - var defaultConfiguration = SdkConfiguration.standard(); - await defaultConfiguration.validateSdkDir(); - await defaultConfiguration.validate(); + var defaultConfiguration = + await DefaultSdkConfigurationProvider().configuration; + defaultConfiguration.validateSdkDir(); + defaultConfiguration.validate(); }); test('Cannot validate an empty configuration layout', () async { var emptyConfiguration = SdkConfiguration(); - await expectLater( - emptyConfiguration.validateSdkDir(), _throwsDoesNotExistException); - await expectLater( - emptyConfiguration.validate(), _throwsDoesNotExistException); + expect(() => emptyConfiguration.validateSdkDir(), + _throwsDoesNotExistException); + expect(() => emptyConfiguration.validate(), _throwsDoesNotExistException); }); }); @@ -45,30 +45,31 @@ void main() { }); test('Can validate existing configuration layout', () async { - var defaultSdkConfiguration = SdkConfiguration.standard(); + var defaultSdkConfiguration = + await DefaultSdkConfigurationProvider().configuration; var sdkDirectory = outputDir.path; var librariesDir = p.join(sdkDirectory, 'specs'); var librariesPath = p.join(librariesDir, 'libraries.json'); Directory(librariesDir).createSync(recursive: true); - File(await defaultSdkConfiguration.librariesPath).copySync(librariesPath); + File(defaultSdkConfiguration.librariesPath).copySync(librariesPath); var summariesDir = p.join(sdkDirectory, 'summaries'); var unsoundSdkSummaryPath = p.join(summariesDir, 'ddc_sdk.dill'); var soundSdkSummaryPath = p.join(summariesDir, 'ddc_outline_sound.dill'); Directory(summariesDir).createSync(recursive: true); - File(await defaultSdkConfiguration.unsoundSdkSummaryPath) + File(defaultSdkConfiguration.unsoundSdkSummaryPath) .copySync(unsoundSdkSummaryPath); - File(await defaultSdkConfiguration.soundSdkSummaryPath) + File(defaultSdkConfiguration.soundSdkSummaryPath) .copySync(soundSdkSummaryPath); var workerDir = p.join(sdkDirectory, 'snapshots'); var compilerWorkerPath = p.join(workerDir, 'dartdevc.dart.snapshot'); Directory(workerDir).createSync(recursive: true); - File(await defaultSdkConfiguration.compilerWorkerPath) + File(defaultSdkConfiguration.compilerWorkerPath) .copySync(compilerWorkerPath); var sdkConfiguration = SdkConfiguration( @@ -79,17 +80,15 @@ void main() { compilerWorkerPath: compilerWorkerPath, ); - expect(await sdkConfiguration.sdkDirectory, equals(sdkDirectory)); - expect(await sdkConfiguration.unsoundSdkSummaryPath, + expect(sdkConfiguration.sdkDirectory, equals(sdkDirectory)); + expect(sdkConfiguration.unsoundSdkSummaryPath, equals(unsoundSdkSummaryPath)); - expect(await sdkConfiguration.soundSdkSummaryPath, - equals(soundSdkSummaryPath)); - expect(await sdkConfiguration.librariesPath, equals(librariesPath)); - expect(await sdkConfiguration.compilerWorkerPath, - equals(compilerWorkerPath)); - - await expectLater(sdkConfiguration.validateSdkDir(), completes); - await expectLater(sdkConfiguration.validate(), completes); + expect(sdkConfiguration.soundSdkSummaryPath, equals(soundSdkSummaryPath)); + expect(sdkConfiguration.librariesPath, equals(librariesPath)); + expect(sdkConfiguration.compilerWorkerPath, equals(compilerWorkerPath)); + + sdkConfiguration.validateSdkDir(); + sdkConfiguration.validate(); }); test('Cannot validate non-existing configuration layout', () async { @@ -110,9 +109,8 @@ void main() { compilerWorkerPath: compilerWorkerPath, ); - await expectLater(sdkConfiguration.validateSdkDir(), completes); - await expectLater( - sdkConfiguration.validate(), _throwsDoesNotExistException); + sdkConfiguration.validateSdkDir(); + expect(() => sdkConfiguration.validate(), _throwsDoesNotExistException); }); }); } From 70f8e75602347957a0ed3d48f64ded2cf0a24e45 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 17 Feb 2022 17:44:44 -0800 Subject: [PATCH 05/10] Pass filesystem to SdkConfiguration.validate methods for tests --- dwds/lib/src/utilities/sdk_configuration.dart | 48 ++++++++--------- dwds/pubspec.yaml | 1 + dwds/test/sdk_configuration_test.dart | 52 +++++++++++++++++++ 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/dwds/lib/src/utilities/sdk_configuration.dart b/dwds/lib/src/utilities/sdk_configuration.dart index 546fcb40e..5a41191b5 100644 --- a/dwds/lib/src/utilities/sdk_configuration.dart +++ b/dwds/lib/src/utilities/sdk_configuration.dart @@ -4,8 +4,16 @@ // @dart=2.9 +// Copyright (c) 2022, 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. + +// @dart=2.9 + import 'dart:io'; +import 'package:file/file.dart'; +import 'package:file/local.dart'; import 'package:path/path.dart' as p; class InvalidSdkConfigurationException implements Exception { @@ -21,20 +29,15 @@ class InvalidSdkConfigurationException implements Exception { } } -/// SDK configuration provider interface. -/// -/// Supports lazily populated configurations by allowing to create -/// configuration asyncronously. abstract class SdkConfigurationProvider { Future get configuration; } /// Data class describing the SDK layout. /// -/// Provides helpers to convert paths to uris that work on all platforms. -/// -/// Call [validate] method to make sure the files in the configuration -/// layout exist before reading the files. +/// Note: Supports lazily populated configurations. +/// Call [validate] method to make sure the files in the +/// configuration layout exist before reading the files. class SdkConfiguration { String sdkDirectory; String unsoundSdkSummaryPath; @@ -64,27 +67,30 @@ class SdkConfiguration { /// Throws [InvalidSdkConfigurationException] if configuration does not /// exist on disk. - void validate() { - validateSdkDir(); + void validate({FileSystem fileSystem}) { + fileSystem ??= const LocalFileSystem(); + + validateSdkDir(fileSystem: fileSystem); if (unsoundSdkSummaryPath == null || - !File(unsoundSdkSummaryPath).existsSync()) { + !fileSystem.file(unsoundSdkSummaryPath).existsSync()) { throw InvalidSdkConfigurationException( 'Sdk summary $unsoundSdkSummaryPath does not exist'); } if (soundSdkSummaryPath == null || - !File(soundSdkSummaryPath).existsSync()) { + !fileSystem.file(soundSdkSummaryPath).existsSync()) { throw InvalidSdkConfigurationException( 'Sdk summary $soundSdkSummaryPath does not exist'); } - if (librariesPath == null || !File(librariesPath).existsSync()) { + if (librariesPath == null || !fileSystem.file(librariesPath).existsSync()) { throw InvalidSdkConfigurationException( 'Libraries spec $librariesPath does not exist'); } - if (compilerWorkerPath == null || !File(compilerWorkerPath).existsSync()) { + if (compilerWorkerPath == null || + !fileSystem.file(compilerWorkerPath).existsSync()) { throw InvalidSdkConfigurationException( 'Compiler worker $compilerWorkerPath does not exist'); } @@ -92,8 +98,10 @@ class SdkConfiguration { /// Throws [InvalidSdkConfigurationException] if SDK root does not /// exist on the disk. - void validateSdkDir() { - if (sdkDirectory == null || !Directory(sdkDirectory).existsSync()) { + void validateSdkDir({FileSystem fileSystem}) { + fileSystem ??= const LocalFileSystem(); + if (sdkDirectory == null || + !fileSystem.directory(sdkDirectory).existsSync()) { throw InvalidSdkConfigurationException( 'Sdk directory $sdkDirectory does not exist'); } @@ -113,12 +121,6 @@ class DefaultSdkConfigurationProvider extends SdkConfigurationProvider { final binDir = p.dirname(Platform.resolvedExecutable); final sdkDir = p.dirname(binDir); - if (sdkDir == null || !Directory(sdkDir).existsSync()) { - throw InvalidSdkConfigurationException( - 'Could not detect default SDK configuration. ' - 'Directory $sdkDir does not exist.'); - } - _configuration = SdkConfiguration( sdkDirectory: sdkDir, unsoundSdkSummaryPath: @@ -129,8 +131,6 @@ class DefaultSdkConfigurationProvider extends SdkConfigurationProvider { compilerWorkerPath: p.join(binDir, 'snapshots', 'dartdevc.dart.snapshot'), ); - - _configuration.validate(); } return _configuration; } diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index fa279d58d..b6308d5ec 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -16,6 +16,7 @@ dependencies: built_value: '>=6.7.0 <9.0.0' crypto: '>=2.0.6 <4.0.0' dds: ^2.2.0 + file: ^6.1.2 http: '>=0.12.0 <0.14.0' http_multi_server: ^3.0.0 logging: '>=0.11.3 <2.0.0' diff --git a/dwds/test/sdk_configuration_test.dart b/dwds/test/sdk_configuration_test.dart index bd2901665..e270a2897 100644 --- a/dwds/test/sdk_configuration_test.dart +++ b/dwds/test/sdk_configuration_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:dwds/src/utilities/sdk_configuration.dart'; +import 'package:file/memory.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; @@ -113,4 +114,55 @@ void main() { expect(() => sdkConfiguration.validate(), _throwsDoesNotExistException); }); }); + + group('SDK configuration', () { + MemoryFileSystem fs; + + var root = '/root'; + var sdkDirectory = root; + var soundSdkSummaryPath = _dartSoundSdkSummaryPath(sdkDirectory); + var unsoundSdkSummaryPath = _dartUnsoundSdkSummaryPath(sdkDirectory); + var librariesPath = _librariesPath(sdkDirectory); + var compilerWorkerPath = _compilerWorkerPath(root); + + setUp(() async { + fs = MemoryFileSystem(); + await fs.directory(sdkDirectory).create(recursive: true); + await fs.file(soundSdkSummaryPath).create(recursive: true); + await fs.file(unsoundSdkSummaryPath).create(recursive: true); + await fs.file(librariesPath).create(recursive: true); + await fs.file(compilerWorkerPath).create(recursive: true); + }); + + test('Can create and validate default SDK configuration', () async { + var configuration = SdkConfiguration( + sdkDirectory: sdkDirectory, + soundSdkSummaryPath: soundSdkSummaryPath, + unsoundSdkSummaryPath: unsoundSdkSummaryPath, + librariesPath: librariesPath, + compilerWorkerPath: compilerWorkerPath, + ); + + expect(configuration.sdkDirectory, equals(sdkDirectory)); + expect(configuration.soundSdkSummaryPath, equals(soundSdkSummaryPath)); + expect( + configuration.unsoundSdkSummaryPath, equals(unsoundSdkSummaryPath)); + expect(configuration.librariesPath, equals(librariesPath)); + expect(configuration.compilerWorkerPath, equals(compilerWorkerPath)); + + configuration.validateSdkDir(fileSystem: fs); + configuration.validate(fileSystem: fs); + }); + }); } + +String _dartUnsoundSdkSummaryPath(String sdkDir) => + p.join(sdkDir, 'lib', '_internal', 'ddc_sdk.dill'); + +String _dartSoundSdkSummaryPath(String sdkDir) => + p.join(sdkDir, 'lib', '_internal', 'ddc_outline_sound.dill'); + +String _librariesPath(String sdkDir) => p.join(sdkDir, 'lib', 'libraries.json'); + +String _compilerWorkerPath(String binDir) => + p.join(binDir, 'snapshots', 'dartdevc.dart.snapshot'); From bbce0d96b7cec122f5fe2258787c21c8517aca2c Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 17 Feb 2022 17:47:00 -0800 Subject: [PATCH 06/10] Reverted accidental comment changes. --- dwds/lib/src/utilities/sdk_configuration.dart | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/dwds/lib/src/utilities/sdk_configuration.dart b/dwds/lib/src/utilities/sdk_configuration.dart index 5a41191b5..bcb8a16d4 100644 --- a/dwds/lib/src/utilities/sdk_configuration.dart +++ b/dwds/lib/src/utilities/sdk_configuration.dart @@ -4,12 +4,6 @@ // @dart=2.9 -// Copyright (c) 2022, 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. - -// @dart=2.9 - import 'dart:io'; import 'package:file/file.dart'; @@ -29,15 +23,20 @@ class InvalidSdkConfigurationException implements Exception { } } +/// SDK configuration provider interface. +/// +/// Supports lazily populated configurations by allowing to create +/// configuration asyncronously. abstract class SdkConfigurationProvider { Future get configuration; } /// Data class describing the SDK layout. /// -/// Note: Supports lazily populated configurations. -/// Call [validate] method to make sure the files in the -/// configuration layout exist before reading the files. +/// Provides helpers to convert paths to uris that work on all platforms. +/// +/// Call [validate] method to make sure the files in the configuration +/// layout exist before reading the files. class SdkConfiguration { String sdkDirectory; String unsoundSdkSummaryPath; From e03b9436e2c018607de02b586d164b6dd943d06a Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 18 Feb 2022 09:41:31 -0800 Subject: [PATCH 07/10] Disabled flaky test --- dwds/test/debug_extension_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwds/test/debug_extension_test.dart b/dwds/test/debug_extension_test.dart index 9f336b46f..ab85539c8 100644 --- a/dwds/test/debug_extension_test.dart +++ b/dwds/test/debug_extension_test.dart @@ -75,7 +75,7 @@ void main() async { await context.webDriver.driver.switchTo.window(windows.last); expect(await context.webDriver.title, 'Dart DevTools'); }); - }); + }, skip: 'https://github.com/dart-lang/webdev/issues/1512'); group('With a sharded Dart app', () { setUp(() async { From 2d67f4a15b18276533e7d3375dd304f38091e215 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 18 Feb 2022 10:00:12 -0800 Subject: [PATCH 08/10] Enable previously flaky test to test the fix --- dwds/test/debug_extension_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwds/test/debug_extension_test.dart b/dwds/test/debug_extension_test.dart index f8e28305a..a181ad486 100644 --- a/dwds/test/debug_extension_test.dart +++ b/dwds/test/debug_extension_test.dart @@ -81,7 +81,7 @@ void main() async { await context.webDriver.driver.switchTo.window(windows.last); expect(await context.webDriver.title, 'Dart DevTools'); }); - }, skip: 'https://github.com/dart-lang/webdev/issues/1512'); + }); group('With a sharded Dart app', () { setUp(() async { From 6a13cb75ad1be2397b34cc62abe1e60bcba2468f Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 18 Feb 2022 11:00:45 -0800 Subject: [PATCH 09/10] Allow tests to use empty SDK configuration --- dwds/lib/src/utilities/dart_uri.dart | 11 +++++++++-- dwds/test/dart_uri_test.dart | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/dwds/lib/src/utilities/dart_uri.dart b/dwds/lib/src/utilities/dart_uri.dart index ac37027b5..4d3fb35cf 100644 --- a/dwds/lib/src/utilities/dart_uri.dart +++ b/dwds/lib/src/utilities/dart_uri.dart @@ -156,12 +156,19 @@ class DartUri { /// Record library and script uris to enable resolving library and script paths. static Future initialize(SdkConfiguration sdkConfiguration) async { - sdkConfiguration.validateSdkDir(); _sdkConfiguration = sdkConfiguration; var packagesUri = p.toUri(p.join(currentDirectory, '.packages')); clear(); - await _loadLibrariesConfig(_sdkConfiguration.librariesUri); + + // Allow for tests can supplying empty configurations. + if (_sdkConfiguration.sdkDirectory != null) { + _sdkConfiguration.validateSdkDir(); + } + if (_sdkConfiguration.librariesUri != null) { + await _loadLibrariesConfig(_sdkConfiguration.librariesUri); + } + await _loadPackageConfig(packagesUri); } diff --git a/dwds/test/dart_uri_test.dart b/dwds/test/dart_uri_test.dart index 402fe12a6..f52b27ef1 100644 --- a/dwds/test/dart_uri_test.dart +++ b/dwds/test/dart_uri_test.dart @@ -53,6 +53,21 @@ void main() { expect(uri.serverPath, 'web/main.dart'); }); + group('initialized with empty configuration', () { + setUpAll(() async { + var sdkConfiguration = + await FakeSdkConfigurationProvider().configuration; + await DartUri.initialize(sdkConfiguration); + await DartUri.recordAbsoluteUris(['dart:io', 'dart:html']); + }); + + tearDownAll(DartUri.clear); + test('cannot resolve uris', () async { + var resolved = DartUri.toResolvedUri('dart:io'); + expect(resolved, isNull); + }); + }); + group('initialized with current SDK directory', () { setUpAll(() async { var sdkConfiguration = @@ -174,3 +189,8 @@ void main() { }); }); } + +class FakeSdkConfigurationProvider extends SdkConfigurationProvider { + @override + Future get configuration async => SdkConfiguration(); +} From 5738f759b11c5b7f0376e79367743423c3fba8c0 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 18 Feb 2022 11:33:11 -0800 Subject: [PATCH 10/10] Disable flaky tests --- dwds/test/debug_extension_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwds/test/debug_extension_test.dart b/dwds/test/debug_extension_test.dart index a181ad486..b56cdbd94 100644 --- a/dwds/test/debug_extension_test.dart +++ b/dwds/test/debug_extension_test.dart @@ -80,7 +80,7 @@ void main() async { var windows = await context.webDriver.windows.toList(); await context.webDriver.driver.switchTo.window(windows.last); expect(await context.webDriver.title, 'Dart DevTools'); - }); + }, skip: 'https://github.com/dart-lang/webdev/issues/1512'); }); group('With a sharded Dart app', () { @@ -158,7 +158,7 @@ void main() async { var windows = await context.webDriver.windows.toList(); await context.webDriver.driver.switchTo.window(windows.last); expect(await context.webDriver.title, 'Dart DevTools'); - }); + }, skip: 'https://github.com/dart-lang/webdev/issues/1512'); }); }); }