Skip to content

Conversation

@jonahwilliams
Copy link
Contributor

@jonahwilliams jonahwilliams commented Feb 7, 2020

Description

Updates the implementation of the web runner to use the frontend server (previously, experimental incremental compiler config). This should improve compile times, as well as reduce some of the occurrences of crashes due to us embedding build_runner incorrectly.

Fixes #41951

Closes

Fixes #49838
Fixes #49479
Fixes #49002
Fixes #48481
Fixes #47115
Fixes #46877
Fixes #44698
Fixes #44552
Fixes #43639
Fixes #41544
Fixes #40481
Fixes #38797
Fixes #45798

Might help

#49103
#47732
#44459

@fluttergithubbot fluttergithubbot added c: contributor-productivity Team-specific productivity, code health, technical debt. tool Affects the "flutter" command-line tool. See also t: labels. work in progress; do not review labels Feb 7, 2020
@jonahwilliams jonahwilliams marked this pull request as ready for review February 7, 2020 23:50
@jonahwilliams
Copy link
Contributor Author

Sorry @zanderso

@@ -0,0 +1,249 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

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

Can't think of one, but maybe this file's name should include 'web' somewhere.

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

import 'dart:async';

import 'package:build_daemon/constants.dart' as daemon;
import 'package:build_daemon/client.dart';
Copy link
Member

Choose a reason for hiding this comment

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

Alphabetize

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

.createSync();
final FlutterProject flutterProject = FlutterProject.fromDirectory(projectDirectory);
final bool hasWebPlugins = findPlugins(flutterProject)
.any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
Copy link
Member

Choose a reason for hiding this comment

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

nit: 2 space indent on continued line

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

await for (final BuildResults results in client.buildResults) {
final BuildResult result = results.results.firstWhere((BuildResult result) {
return result.target == 'web';
});
Copy link
Member

Choose a reason for hiding this comment

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

If firstWhere doesn't have an orElse:, it will throw a StateError when it can't find something that matches. Since this code is in an await for, I'd prefer it failing in a more controlled way.

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

break;
}
}
if (success && testOutputDir != null) {
Copy link
Member

Choose a reason for hiding this comment

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

nit: Flip the sense and unindent the larger part.

Alternately, split the test copying code out into a helper function.

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

final DebugConnection debugConnection = useDebugExtension
? await (_cachedExtensionFuture ??= dwds.extensionDebugConnections.stream.first)
: await dwds.debugConnection(appConnection);
if (!firstConnection.isCompleted) {
Copy link
Member

Choose a reason for hiding this comment

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

nit: think positive

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

/// Only calls [AppConnection.runMain] on the subsequent connections.
Future<ConnectionResult> connect(bool useDebugExtension) {
final Completer<ConnectionResult> firstConnection = Completer<ConnectionResult>();
_connectedApps = dwds.connectedApps.listen((AppConnection appConnection) async {
Copy link
Member

Choose a reason for hiding this comment

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

listen should generally have an onError

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

Future<ConnectionResult> connect(bool useDebugExtension) {
final Completer<ConnectionResult> firstConnection = Completer<ConnectionResult>();
_connectedApps = dwds.connectedApps.listen((AppConnection appConnection) async {
final DebugConnection debugConnection = useDebugExtension
Copy link
Member

Choose a reason for hiding this comment

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

If this listen callback throws an exception it will be an unhandled exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to forward the error through the completer

Copy link
Member

Choose a reason for hiding this comment

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

onError handles errors on the stream, but won't run if the listen callback throws.

final String entrypoint = globals.fs.path.basename(mainPath);
webAssetServer.writeFile('/manifest.json', '{"info":"manifest not generated in run mode."}');
webAssetServer.writeFile('/flutter_service_worker.js', '// Service worker not loaded in run mode.');
webAssetServer.writeFile(
Copy link
Member

Choose a reason for hiding this comment

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

2 space indent, paren style.

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

}
return path;
}

Copy link
Member

Choose a reason for hiding this comment

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

extra newline

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

// when(mockWebFs.recompile()).thenAnswer((Invocation _) {
// return Future<bool>.value(false);
// });
// when(mockWebFs.uri).thenReturn('http://localhost:8765/app/');
Copy link
Contributor

Choose a reason for hiding this comment

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

Will the above commented out code be useful in the future?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

});
if (result.status == BuildStatus.failed) {
success = false;
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is break needed? Does the build not stop after this? If so, should it be explicitly stopped?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this particular case, we only want the first success

);
}
return _DwdsResidentWebRunner(
return _ExperimentalResidentWebRunner(
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove "Experimental" from the name?

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

try {
if (fullRestart || !debuggingOptions.buildInfo.isDebug) {
if (!deviceIsDebuggable) {
globals.printStatus('Recompile complete. Page requires refresh.');
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: it's unclear what the use is supposed to do when the page requires a refresh. Perhaps tell them what to do? E.g. "Please refresh the page using browser's reload button"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lets leave this for now since it matches the current behavior

'ignoreCache': !debuggingOptions.buildInfo.isDebug,
});
} else {
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

undo?

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

File _resolveDartFile(String path) {
// If this is a dart file, it must be on the local file system and is
// likely coming from a source map request. Attempt to look in the
// local filesystem for it, and return a 404 if it is not found. The tool
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the comment about 404 move somewhere else? This function cannot return 404.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated comment

if (!firstConnection.isCompleted) {
firstConnection.complete(ConnectionResult(appConnection, debugConnection));
} else {
appConnection.runMain();
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: it's a bit strange to see a method called connect kick off the main.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its how we do --start-paused on the web. If we didn't want to pause we need to tell the "isolate" to start

expect(didSkipDwds, true);
}));
// expect(didSkipDwds, true);
// }));
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

// verify(mockWebFs.connect(true)).called(1);
// // And ensure the debug services was started.
// expect(testLogger.statusText, contains('Debug service listening on'));
// }));
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed


await result;
verify(mockWebFs.stop()).called(1);
// verify(mockWebFs.stop()).called(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this still needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

@jonahwilliams
Copy link
Contributor Author

This currently doesn't work on windows, investigating...

@jonahwilliams
Copy link
Contributor Author

Update to fix on windows, we no longer need to chop off C:/ and friends from the source maps.

@jonahwilliams
Copy link
Contributor Author

Ahh and the package update broke a bunch of stuff ....great

Copy link
Member

@zanderso zanderso left a comment

Choose a reason for hiding this comment

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

lgtm w/ small comment

@jonahwilliams
Copy link
Contributor Author

I added another layer of try-catch

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.