Unverified Commit b3a37d02 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] support toggling CanvasKit rendering on with 'k' (#52511)

parent 9666f697
...@@ -153,6 +153,12 @@ class CommandHelp { ...@@ -153,6 +153,12 @@ class CommandHelp {
'Toggle elevation checker.', 'Toggle elevation checker.',
); );
CommandHelpOption _k;
CommandHelpOption get k => _k ??= _makeOption(
'k',
'Toggle CanvasKit rendering.',
);
CommandHelpOption _makeOption(String key, String description, [ CommandHelpOption _makeOption(String key, String description, [
String inParenthesis = '', String inParenthesis = '',
]) { ]) {
......
...@@ -205,8 +205,9 @@ class WebAssetServer implements AssetReader { ...@@ -205,8 +205,9 @@ class WebAssetServer implements AssetReader {
return shelf.Response.notFound(''); return shelf.Response.notFound('');
} }
// For real files, use a serialized file stat as a revision // For real files, use a serialized file stat plus path as a revision.
final String etag = file.lastModifiedSync().toIso8601String(); // This allows us to update between canvaskit and non-canvaskit SDKs.
final String etag = file.lastModifiedSync().toIso8601String() + file.path;
if (ifNoneMatch == etag) { if (ifNoneMatch == etag) {
return shelf.Response.notModified(); return shelf.Response.notModified();
} }
...@@ -291,6 +292,9 @@ class WebAssetServer implements AssetReader { ...@@ -291,6 +292,9 @@ class WebAssetServer implements AssetReader {
return modules; return modules;
} }
/// Whether to use the cavaskit SDK for rendering.
bool canvasKitRendering = false;
@visibleForTesting @visibleForTesting
final File dartSdk = globals.fs.file(globals.fs.path.join( final File dartSdk = globals.fs.file(globals.fs.path.join(
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk), globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
...@@ -299,6 +303,14 @@ class WebAssetServer implements AssetReader { ...@@ -299,6 +303,14 @@ class WebAssetServer implements AssetReader {
'dart_sdk.js', 'dart_sdk.js',
)); ));
@visibleForTesting
final File canvasKitDartSdk = globals.fs.file(globals.fs.path.join(
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
'kernel',
'amd-canvaskit',
'dart_sdk.js',
));
@visibleForTesting @visibleForTesting
final File dartSdkSourcemap = globals.fs.file(globals.fs.path.join( final File dartSdkSourcemap = globals.fs.file(globals.fs.path.join(
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk), globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
...@@ -307,14 +319,26 @@ class WebAssetServer implements AssetReader { ...@@ -307,14 +319,26 @@ class WebAssetServer implements AssetReader {
'dart_sdk.js.map', 'dart_sdk.js.map',
)); ));
@visibleForTesting
final File canvasKitDartSdkSourcemap = globals.fs.file(globals.fs.path.join(
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
'kernel',
'amd-canvaskit',
'dart_sdk.js.map',
));
// Attempt to resolve `path` to a dart file. // Attempt to resolve `path` to a dart file.
File _resolveDartFile(String path) { File _resolveDartFile(String path) {
// Return the actual file objects so that local engine changes are automatically picked up. // Return the actual file objects so that local engine changes are automatically picked up.
switch (path) { switch (path) {
case '/dart_sdk.js': case '/dart_sdk.js':
return dartSdk; return canvasKitRendering
case '.dart_sdk.js.map': ? canvasKitDartSdk
return dartSdkSourcemap; : dartSdk;
case '/dart_sdk.js.map':
return canvasKitRendering
? canvasKitDartSdkSourcemap
: dartSdkSourcemap;
} }
// If this is a dart file, it must be on the local file system and is // If this is a dart file, it must be on the local file system and is
// likely coming from a source map request. The tool doesn't currently // likely coming from a source map request. The tool doesn't currently
...@@ -405,7 +429,6 @@ class WebDevFS implements DevFS { ...@@ -405,7 +429,6 @@ class WebDevFS implements DevFS {
final bool enableDwds; final bool enableDwds;
final bool testMode; final bool testMode;
@visibleForTesting
WebAssetServer webAssetServer; WebAssetServer webAssetServer;
Dwds get dwds => webAssetServer.dwds; Dwds get dwds => webAssetServer.dwds;
......
...@@ -710,6 +710,16 @@ class _ResidentWebRunner extends ResidentWebRunner { ...@@ -710,6 +710,16 @@ class _ResidentWebRunner extends ResidentWebRunner {
return 0; return 0;
} }
@override
bool get supportsCanvasKit => supportsServiceProtocol;
@override
Future<void> toggleCanvaskit() async {
final WebDevFS webDevFS = device.devFS as WebDevFS;
webDevFS.webAssetServer.canvasKitRendering = !webDevFS.webAssetServer.canvasKitRendering;
await _wipConnection?.sendCommand('Page.reload');
}
@override @override
Future<void> exitApp() async { Future<void> exitApp() async {
await device.exitApps(); await device.exitApps();
......
...@@ -665,6 +665,7 @@ abstract class ResidentRunner { ...@@ -665,6 +665,7 @@ abstract class ResidentRunner {
bool get isRunningProfile => debuggingOptions.buildInfo.isProfile; bool get isRunningProfile => debuggingOptions.buildInfo.isProfile;
bool get isRunningRelease => debuggingOptions.buildInfo.isRelease; bool get isRunningRelease => debuggingOptions.buildInfo.isRelease;
bool get supportsServiceProtocol => isRunningDebug || isRunningProfile; bool get supportsServiceProtocol => isRunningDebug || isRunningProfile;
bool get supportsCanvasKit => false;
// Returns the Uri of the first connected device for mobile, // Returns the Uri of the first connected device for mobile,
// and only connected device for web. // and only connected device for web.
...@@ -724,6 +725,13 @@ abstract class ResidentRunner { ...@@ -724,6 +725,13 @@ abstract class ResidentRunner {
throw '${fullRestart ? 'Restart' : 'Reload'} is not supported in $mode mode'; throw '${fullRestart ? 'Restart' : 'Reload'} is not supported in $mode mode';
} }
/// Toggle whether canvaskit is being used for rendering.
///
/// Only supported on the web.
Future<void> toggleCanvaskit() {
throw Exception('Canvaskit not supported by this runner.');
}
/// The resident runner API for interaction with the reloadMethod vmservice /// The resident runner API for interaction with the reloadMethod vmservice
/// request. /// request.
/// ///
...@@ -1043,6 +1051,9 @@ abstract class ResidentRunner { ...@@ -1043,6 +1051,9 @@ abstract class ResidentRunner {
commandHelp.S.print(); commandHelp.S.print();
commandHelp.U.print(); commandHelp.U.print();
} }
if (supportsCanvasKit){
commandHelp.k.print();
}
// `P` should precede `a` // `P` should precede `a`
commandHelp.P.print(); commandHelp.P.print();
commandHelp.a.print(); commandHelp.a.print();
...@@ -1182,6 +1193,12 @@ class TerminalHandler { ...@@ -1182,6 +1193,12 @@ class TerminalHandler {
return true; return true;
} }
return false; return false;
case 'k':
if (residentRunner.supportsCanvasKit) {
await residentRunner.toggleCanvaskit();
return true;
}
return false;
case 'l': case 'l':
final List<FlutterView> views = residentRunner.flutterDevices final List<FlutterView> views = residentRunner.flutterDevices
.expand((FlutterDevice d) => d.views).toList(); .expand((FlutterDevice d) => d.views).toList();
......
...@@ -59,6 +59,7 @@ void _testMessageLength({ ...@@ -59,6 +59,7 @@ void _testMessageLength({
expect(commandHelp.d.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.d.toString().length, lessThanOrEqualTo(expectedWidth));
expect(commandHelp.h.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.h.toString().length, lessThanOrEqualTo(expectedWidth));
expect(commandHelp.i.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.i.toString().length, lessThanOrEqualTo(expectedWidth));
expect(commandHelp.k.toString().length, lessThanOrEqualTo(expectedWidth));
expect(commandHelp.o.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.o.toString().length, lessThanOrEqualTo(expectedWidth));
expect(commandHelp.p.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.p.toString().length, lessThanOrEqualTo(expectedWidth));
expect(commandHelp.q.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.q.toString().length, lessThanOrEqualTo(expectedWidth));
......
...@@ -368,6 +368,8 @@ void main() { ...@@ -368,6 +368,8 @@ void main() {
expect(residentRunner.supportsServiceProtocol, true); expect(residentRunner.supportsServiceProtocol, true);
// isRunningDebug // isRunningDebug
expect(residentRunner.isRunningDebug, true); expect(residentRunner.isRunningDebug, true);
// does not support CanvasKit
expect(residentRunner.supportsCanvasKit, false);
// commands // commands
expect(testLogger.statusText, equals( expect(testLogger.statusText, equals(
<dynamic>[ <dynamic>[
...@@ -395,6 +397,11 @@ void main() { ...@@ -395,6 +397,11 @@ void main() {
)); ));
})); }));
test('ResidentRunner does not support CanvasKit', () => testbed.run(() async {
expect(() => residentRunner.toggleCanvaskit(),
throwsA(isA<Exception>()));
}));
test('ResidentRunner can take screenshot on debug device', () => testbed.run(() async { test('ResidentRunner can take screenshot on debug device', () => testbed.run(() async {
when(mockDevice.supportsScreenshot).thenReturn(true); when(mockDevice.supportsScreenshot).thenReturn(true);
when(mockDevice.takeScreenshot(any)) when(mockDevice.takeScreenshot(any))
......
...@@ -425,6 +425,18 @@ void main() { ...@@ -425,6 +425,18 @@ void main() {
expect(residentWebRunner.debuggingEnabled, true); expect(residentWebRunner.debuggingEnabled, true);
})); }));
test('web resident runner can toggle CanvasKit', () => testbed.run(() async {
final WebAssetServer webAssetServer = WebAssetServer(null, null, null);
when(mockWebDevFS.webAssetServer).thenReturn(webAssetServer);
expect(residentWebRunner.supportsCanvasKit, true);
expect(webAssetServer.canvasKitRendering, false);
await residentWebRunner.toggleCanvaskit();
expect(webAssetServer.canvasKitRendering, true);
}));
test('Exits when initial compile fails', () => testbed.run(() async { test('Exits when initial compile fails', () => testbed.run(() async {
_setupMocks(); _setupMocks();
when(mockWebDevFS.update( when(mockWebDevFS.update(
......
...@@ -357,6 +357,15 @@ void main() { ...@@ -357,6 +357,15 @@ void main() {
webDevFS.webAssetServer.dartSdk webDevFS.webAssetServer.dartSdk
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('HELLO'); ..writeAsStringSync('HELLO');
webDevFS.webAssetServer.dartSdkSourcemap
..createSync(recursive: true)
..writeAsStringSync('THERE');
webDevFS.webAssetServer.canvasKitDartSdk
..createSync(recursive: true)
..writeAsStringSync('OL');
webDevFS.webAssetServer.canvasKitDartSdkSourcemap
..createSync(recursive: true)
..writeAsStringSync('CHUM');
webDevFS.webAssetServer.dartSdkSourcemap.createSync(recursive: true); webDevFS.webAssetServer.dartSdkSourcemap.createSync(recursive: true);
await webDevFS.update( await webDevFS.update(
...@@ -373,6 +382,7 @@ void main() { ...@@ -373,6 +382,7 @@ void main() {
expect(webDevFS.webAssetServer.getFile('/manifest.json'), isNotNull); expect(webDevFS.webAssetServer.getFile('/manifest.json'), isNotNull);
expect(webDevFS.webAssetServer.getFile('/flutter_service_worker.js'), isNotNull); expect(webDevFS.webAssetServer.getFile('/flutter_service_worker.js'), isNotNull);
expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js'), 'HELLO'); expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js'), 'HELLO');
expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js.map'), 'THERE');
// Update to the SDK. // Update to the SDK.
webDevFS.webAssetServer.dartSdk.writeAsStringSync('BELLOW'); webDevFS.webAssetServer.dartSdk.writeAsStringSync('BELLOW');
...@@ -380,6 +390,11 @@ void main() { ...@@ -380,6 +390,11 @@ void main() {
// New SDK should be visible.. // New SDK should be visible..
expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js'), 'BELLOW'); expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js'), 'BELLOW');
// Toggle CanvasKit
webDevFS.webAssetServer.canvasKitRendering = true;
expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js'), 'OL');
expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js.map'), 'CHUM');
await webDevFS.destroy(); await webDevFS.destroy();
})); }));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment