Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide an app entrypoint to DWDS #2047

Merged
merged 17 commits into from
Mar 30, 2023
3 changes: 2 additions & 1 deletion dwds/lib/src/debugging/inspector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class AppInspector implements AppInspectorInterface {
String root,
Debugger debugger,
ExecutionContext executionContext,
LoadStrategy loadStrategy,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw we have the load strategy available as a globalLoadStrategy (set on dwds.start so we don't need to pass it around. Can we switch to using the global in this PR as well? Alternatively, we can move to passing load strategy everywhere (not sure the work involved is justifiable though).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks!

) async {
final id = createId();
final time = DateTime.now().millisecondsSinceEpoch;
Expand Down Expand Up @@ -175,7 +176,7 @@ class AppInspector implements AppInspectorInterface {

debugger.updateInspector(inspector);

final libraryHelper = LibraryHelper(inspector);
final libraryHelper = LibraryHelper(inspector, loadStrategy);
final classHelper = ClassHelper(inspector);
final instanceHelper = InstanceHelper(inspector, debugger);

Expand Down
14 changes: 11 additions & 3 deletions dwds/lib/src/debugging/libraries.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,25 @@ class LibraryHelper extends Domain {

LibraryRef? _rootLib;

LibraryHelper(AppInspectorInterface appInspector) {
late final LoadStrategy _loadStrategy;

LibraryHelper(AppInspectorInterface appInspector, LoadStrategy loadStrategy) {
inspector = appInspector;
_loadStrategy = loadStrategy;
}

Future<LibraryRef> get rootLib async {
if (_rootLib != null) return _rootLib!;
// TODO: read entrypoint from app metadata.
// Issue: https://github.com/dart-lang/webdev/issues/1290
final libraries = await libraryRefs;
_rootLib = libraries
.firstWhereOrNull((lib) => lib.name?.contains('org-dartlang') ?? false);
if (_loadStrategy.appEntrypoint != null) {
_rootLib = libraries.firstWhereOrNull(
(lib) => Uri.parse(lib.uri ?? '') == _loadStrategy.appEntrypoint);
}
_rootLib = _rootLib ??
libraries.firstWhereOrNull(
(lib) => lib.name?.contains('org-dartlang') ?? false);
_rootLib = _rootLib ??
libraries
.firstWhereOrNull((lib) => lib.name?.contains('main') ?? false);
Expand Down
10 changes: 8 additions & 2 deletions dwds/lib/src/handlers/dev_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,10 @@ class DevHandler {

// Reconnect to existing service.
services.connectedInstanceId = message.instanceId;
await services.chromeProxyService.createIsolate(connection);
await services.chromeProxyService.createIsolate(
connection,
_loadStrategy,
);
}
_appConnectionByAppId[message.appId] = connection;
_connectedApps.add(connection);
Expand All @@ -429,7 +432,10 @@ class DevHandler {
AppConnection appConnection, SocketConnection sseConnection) async {
await _servicesByAppId[appConnection.request.appId]
?.chromeProxyService
.createIsolate(appConnection);
.createIsolate(
appConnection,
_loadStrategy,
);
}

void _listen() {
Expand Down
8 changes: 7 additions & 1 deletion dwds/lib/src/loaders/build_runner_require.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class BuildRunnerRequireStrategyProvider {
final Handler _assetHandler;
final ReloadConfiguration _configuration;
final AssetReader _assetReader;
final Uri? _appEntrypoint;

late final RequireStrategy _requireStrategy = RequireStrategy(
_configuration,
Expand All @@ -32,10 +33,15 @@ class BuildRunnerRequireStrategyProvider {
_serverPathForAppUri,
_moduleInfoForProvider,
_assetReader,
_appEntrypoint,
);

BuildRunnerRequireStrategyProvider(
this._assetHandler, this._configuration, this._assetReader);
this._assetHandler,
this._configuration,
this._assetReader,
this._appEntrypoint,
);

RequireStrategy get strategy => _requireStrategy;

Expand Down
3 changes: 3 additions & 0 deletions dwds/lib/src/loaders/frontend_server_require.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class FrontendServerRequireStrategyProvider {
final PackageUriMapper _packageUriMapper;
final Future<Map<String, String>> Function() _digestsProvider;
final String _basePath;
final Uri? _appEntrypoint;

late final RequireStrategy _requireStrategy = RequireStrategy(
_configuration,
Expand All @@ -27,6 +28,7 @@ class FrontendServerRequireStrategyProvider {
_serverPathForAppUri,
_moduleInfoForProvider,
_assetReader,
_appEntrypoint,
);

FrontendServerRequireStrategyProvider(
Expand All @@ -35,6 +37,7 @@ class FrontendServerRequireStrategyProvider {
this._packageUriMapper,
this._digestsProvider,
this._basePath,
this._appEntrypoint,
);

RequireStrategy get strategy => _requireStrategy;
Expand Down
6 changes: 6 additions & 0 deletions dwds/lib/src/loaders/legacy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class LegacyStrategy extends LoadStrategy {
/// an app URI.
final String? Function(String appUri) _serverPathForAppUri;

final Uri? _appEntrypoint;

LegacyStrategy(
this.reloadConfiguration,
this._moduleForServerPath,
Expand All @@ -68,6 +70,7 @@ class LegacyStrategy extends LoadStrategy {
this._serverPathForAppUri,
this._moduleInfoForProvider,
AssetReader assetReader,
this._appEntrypoint,
) : super(assetReader);

@override
Expand Down Expand Up @@ -117,4 +120,7 @@ class LegacyStrategy extends LoadStrategy {

@override
String? serverPathForAppUri(String appUri) => _serverPathForAppUri(appUri);

@override
Uri? get appEntrypoint => _appEntrypoint;
}
5 changes: 5 additions & 0 deletions dwds/lib/src/loaders/require.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ class RequireStrategy extends LoadStrategy {
final Future<Map<String, ModuleInfo>> Function(
MetadataProvider metadataProvider) _moduleInfoForProvider;

@override
Uri? get appEntrypoint => _appEntrypoint;
final Uri? _appEntrypoint;

RequireStrategy(
this.reloadConfiguration,
this._moduleProvider,
Expand All @@ -142,6 +146,7 @@ class RequireStrategy extends LoadStrategy {
this._serverPathForAppUri,
this._moduleInfoForProvider,
AssetReader assetReader,
this._appEntrypoint,
) : super(assetReader);

@override
Expand Down
4 changes: 4 additions & 0 deletions dwds/lib/src/loaders/strategy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ abstract class LoadStrategy {
/// The reload configuration for this strategy, e.g. liveReload.
ReloadConfiguration get reloadConfiguration;

/// The URI for the app's entrypoint file, which is usually `main.dart`. It
/// should be a package URI, e.g. `package:myapp/main.dart`.
Uri? get appEntrypoint;

/// Returns a snippet of JS code that initializes a `library` variable that
/// has the actual library object in DDC for [libraryUri].
///
Expand Down
24 changes: 14 additions & 10 deletions dwds/lib/src/services/chrome_proxy_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@ class ChromeProxyService implements VmServiceInterface {
executionContext,
expressionCompiler,
);
safeUnawaited(service.createIsolate(appConnection));
safeUnawaited(service.createIsolate(
appConnection,
loadStrategy,
));
return service;
}

Expand Down Expand Up @@ -229,7 +232,8 @@ class ChromeProxyService implements VmServiceInterface {
/// Only one isolate at a time is supported, but they should be cleaned up
/// with [destroyIsolate] and recreated with this method there is a hot
/// restart or full page refresh.
Future<void> createIsolate(AppConnection appConnection) async {
Future<void> createIsolate(
AppConnection appConnection, LoadStrategy loadStrategy) async {
// Inspector is null if the previous isolate is destroyed.
if (_isIsolateRunning) {
throw UnsupportedError(
Expand All @@ -248,14 +252,14 @@ class ChromeProxyService implements VmServiceInterface {

debugger.notifyPausedAtStart();
_inspector = await AppInspector.create(
appConnection,
remoteDebugger,
_assetReader,
_locations,
root,
debugger,
executionContext,
);
appConnection,
remoteDebugger,
_assetReader,
_locations,
root,
debugger,
executionContext,
loadStrategy);
debugger.updateInspector(inspector);

final compiler = _compiler;
Expand Down
3 changes: 2 additions & 1 deletion dwds/test/chrome_proxy_service_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1942,7 +1942,8 @@ void main() {
event.isolate!.id != initialIsolateId),
])));
service.destroyIsolate();
await service.createIsolate(context.appConnection);
await service.createIsolate(
context.appConnection, globalLoadStrategy);
await eventsDone;
expect((await service.getVM()).isolates!.first.id,
isNot(initialIsolateId));
Expand Down
22 changes: 15 additions & 7 deletions dwds/test/fixtures/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ class TestContext {
),
);

/// The package URI of the Dart entry file, e.g,
/// "org-dartlang-app:example/hello_world/main.dart":
Uri get _dartEntryFilePackageUri => Uri.parse('org-dartlang-app:///${p.join(
annagrin marked this conversation as resolved.
Show resolved Hide resolved
project.webAssetsPath,
project.dartEntryFileName,
)}');

/// The URI for the package_config.json is located in:
/// <project directory>/.dart_tool/package_config
Uri get _packageConfigFile =>
Expand Down Expand Up @@ -284,6 +291,7 @@ class TestContext {
assetHandler,
reloadConfiguration,
assetReader,
_dartEntryFilePackageUri,
).strategy;

buildResults = daemonClient.buildResults;
Expand Down Expand Up @@ -328,14 +336,14 @@ class TestContext {
basePath = webRunner.devFS.assetServer.basePath;
assetReader = webRunner.devFS.assetServer;
_assetHandler = webRunner.devFS.assetServer.handleRequest;

requireStrategy = FrontendServerRequireStrategyProvider(
reloadConfiguration,
assetReader,
packageUriMapper,
() async => {},
basePath)
.strategy;
reloadConfiguration,
assetReader,
packageUriMapper,
() async => {},
basePath,
_dartEntryFilePackageUri,
).strategy;

buildResults = const Stream<BuildResults>.empty();
}
Expand Down
4 changes: 4 additions & 0 deletions dwds/test/fixtures/fakes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ class FakeWebkitDebugger implements WebkitDebugger {
(String _) => '',
(MetadataProvider _) async => <String, ModuleInfo>{},
FakeAssetReader(),
Uri.parse('package:fakeapp/main.dart'),
);
}

Expand Down Expand Up @@ -304,6 +305,9 @@ class FakeStrategy implements LoadStrategy {
@override
String get loadModuleSnippet => '';

@override
Uri? get appEntrypoint => Uri.parse('package:myapp/main.dart');

@override
ReloadConfiguration get reloadConfiguration => ReloadConfiguration.none;

Expand Down
4 changes: 4 additions & 0 deletions dwds/test/inspector_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ void main() {
objectId = instance.objectId!;
});

test('expect rootLib to be the main.dart file', () {
expect(inspector.isolate.rootLib?.uri, equals(url));
});

test('invoke top-level private', () async {
final remote = await inspector.invoke(bootstrapLibrary!.id!,
'_libraryPrivateFunction', [dartIdFor(2), dartIdFor(3)]);
Expand Down
9 changes: 7 additions & 2 deletions webdev/lib/src/serve/webdev_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,13 @@ class WebDevServer {
);

var loadStrategy = BuildRunnerRequireStrategyProvider(
assetHandler, options.configuration.reload, assetReader)
.strategy;
assetHandler,
options.configuration.reload,
assetReader,
// TODO(https://github.com/flutter/devtools/issues/5350): Figure out how
// to determine the app's entrypoint:
/* appEntrypoint */ null,
).strategy;
if (options.configuration.enableExpressionEvaluation) {
ddcService = ExpressionCompilerService(
options.configuration.hostname,
Expand Down