| // Copyright 2024 The Dart Authors. 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/debugging/metadata/provider.dart'; |
| import 'package:dwds/src/loaders/ddc.dart'; |
| import 'package:dwds/src/loaders/ddc_library_bundle.dart'; |
| import 'package:dwds/src/loaders/require.dart'; |
| import 'package:dwds/src/loaders/strategy.dart'; |
| import 'package:dwds/src/readers/asset_reader.dart'; |
| import 'package:dwds/src/services/expression_compiler.dart'; |
| import 'package:path/path.dart' as p; |
| |
| abstract class FrontendServerStrategyProvider<T extends LoadStrategy> { |
| final ReloadConfiguration _configuration; |
| final AssetReader _assetReader; |
| final PackageUriMapper _packageUriMapper; |
| final Future<Map<String, String>> Function() _digestsProvider; |
| final String _basePath; |
| final BuildSettings _buildSettings; |
| final String? _packageConfigPath; |
| |
| FrontendServerStrategyProvider( |
| this._configuration, |
| this._assetReader, |
| this._packageUriMapper, |
| this._digestsProvider, |
| this._buildSettings, { |
| String? packageConfigPath, |
| }) : _basePath = _assetReader.basePath, |
| _packageConfigPath = packageConfigPath; |
| |
| T get strategy; |
| |
| String _removeBasePath(String path) { |
| if (_basePath.isEmpty) return path; |
| final stripped = stripLeadingSlashes(path); |
| return stripLeadingSlashes(stripped.substring(_basePath.length)); |
| } |
| |
| String _addBasePath(String serverPath) => |
| _basePath.isEmpty |
| ? stripLeadingSlashes(serverPath) |
| : '$_basePath/${stripLeadingSlashes(serverPath)}'; |
| |
| String _removeJsExtension(String path) => |
| path.endsWith('.js') ? p.withoutExtension(path) : path; |
| |
| Future<Map<String, String>> _moduleProvider( |
| MetadataProvider metadataProvider, |
| ) async => (await metadataProvider.moduleToModulePath).map( |
| (key, value) => |
| MapEntry(key, stripLeadingSlashes(_removeJsExtension(value))), |
| ); |
| |
| Future<String?> _moduleForServerPath( |
| MetadataProvider metadataProvider, |
| String serverPath, |
| ) async { |
| final modulePathToModule = await metadataProvider.modulePathToModule; |
| final relativeServerPath = _removeBasePath(serverPath); |
| return modulePathToModule[relativeServerPath]; |
| } |
| |
| Future<String> _serverPathForModule( |
| MetadataProvider metadataProvider, |
| String module, |
| ) async => |
| _addBasePath((await metadataProvider.moduleToModulePath)[module] ?? ''); |
| |
| Future<String> _sourceMapPathForModule( |
| MetadataProvider metadataProvider, |
| String module, |
| ) async => |
| _addBasePath((await metadataProvider.moduleToSourceMap)[module] ?? ''); |
| |
| String? _serverPathForAppUri(String appUrl) { |
| final appUri = Uri.parse(appUrl); |
| if (appUri.isScheme('org-dartlang-app')) { |
| return _addBasePath(appUri.path); |
| } |
| if (appUri.isScheme('package')) { |
| final resolved = _packageUriMapper.packageUriToServerPath(appUri); |
| if (resolved != null) { |
| return resolved; |
| } |
| } |
| return null; |
| } |
| |
| Future<Map<String, ModuleInfo>> _moduleInfoForProvider( |
| MetadataProvider metadataProvider, |
| ) async { |
| final modules = await metadataProvider.moduleToModulePath; |
| final result = <String, ModuleInfo>{}; |
| for (final module in modules.keys) { |
| final modulePath = modules[module]!; |
| result[module] = ModuleInfo( |
| // TODO: Save locations of full kernel files in ddc metadata. |
| // Issue: https://github.com/dart-lang/sdk/issues/43684 |
| p.setExtension(modulePath, '.full.dill'), |
| p.setExtension(modulePath, '.dill'), |
| ); |
| } |
| return result; |
| } |
| } |
| |
| /// Provides a [DdcStrategy] suitable for use with Frontend Server. |
| class FrontendServerDdcStrategyProvider |
| extends FrontendServerStrategyProvider<DdcStrategy> { |
| late final DdcStrategy _ddcStrategy = DdcStrategy( |
| _configuration, |
| _moduleProvider, |
| (_) => _digestsProvider(), |
| _moduleForServerPath, |
| _serverPathForModule, |
| _sourceMapPathForModule, |
| _serverPathForAppUri, |
| _moduleInfoForProvider, |
| _assetReader, |
| _buildSettings, |
| (String _) => null, |
| packageConfigPath: _packageConfigPath, |
| ); |
| |
| FrontendServerDdcStrategyProvider( |
| super._configuration, |
| super._assetReader, |
| super._packageUriMapper, |
| super._digestsProvider, |
| super._buildSettings, { |
| super.packageConfigPath, |
| }); |
| |
| @override |
| DdcStrategy get strategy => _ddcStrategy; |
| } |
| |
| /// Provides a [DdcLibraryBundleStrategy] suitable for use with the Frontend |
| /// Server. |
| // ignore: prefer-correct-type-name |
| class FrontendServerDdcLibraryBundleStrategyProvider |
| extends FrontendServerStrategyProvider<DdcLibraryBundleStrategy> { |
| late final DdcLibraryBundleStrategy _libraryBundleStrategy; |
| |
| FrontendServerDdcLibraryBundleStrategyProvider( |
| super._configuration, |
| super._assetReader, |
| super._packageUriMapper, |
| super._digestsProvider, |
| super._buildSettings, { |
| super.packageConfigPath, |
| Uri? reloadedSourcesUri, |
| }) { |
| _libraryBundleStrategy = DdcLibraryBundleStrategy( |
| _configuration, |
| _moduleProvider, |
| (_) => _digestsProvider(), |
| _moduleForServerPath, |
| _serverPathForModule, |
| _sourceMapPathForModule, |
| _serverPathForAppUri, |
| _moduleInfoForProvider, |
| _assetReader, |
| _buildSettings, |
| (String _) => null, |
| packageConfigPath: _packageConfigPath, |
| reloadedSourcesUri: reloadedSourcesUri, |
| ); |
| } |
| |
| @override |
| DdcLibraryBundleStrategy get strategy => _libraryBundleStrategy; |
| } |
| |
| /// Provides a [RequireStrategy] suitable for use with Frontend Server. |
| class FrontendServerRequireStrategyProvider |
| extends FrontendServerStrategyProvider<RequireStrategy> { |
| late final RequireStrategy _requireStrategy = RequireStrategy( |
| _configuration, |
| _moduleProvider, |
| (_) => _digestsProvider(), |
| _moduleForServerPath, |
| _serverPathForModule, |
| _sourceMapPathForModule, |
| _serverPathForAppUri, |
| _moduleInfoForProvider, |
| _assetReader, |
| _buildSettings, |
| packageConfigPath: _packageConfigPath, |
| ); |
| |
| FrontendServerRequireStrategyProvider( |
| super._configuration, |
| super._assetReader, |
| super._packageUriMapper, |
| super._digestsProvider, |
| super._buildSettings, { |
| super.packageConfigPath, |
| }); |
| |
| @override |
| RequireStrategy get strategy => _requireStrategy; |
| } |