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

fix source map loading and service protocol for flutter web (#39189)

parent 2476415b
...@@ -66,6 +66,10 @@ class ResidentWebRunner extends ResidentRunner { ...@@ -66,6 +66,10 @@ class ResidentWebRunner extends ResidentRunner {
final Device device; final Device device;
final FlutterProject flutterProject; final FlutterProject flutterProject;
// Only the debug builds of the web support the service protocol.
@override
bool get supportsServiceProtocol => isRunningDebug;
WebFs _webFs; WebFs _webFs;
DebugConnection _debugConnection; DebugConnection _debugConnection;
StreamSubscription<vmservice.Event> _stdOutSub; StreamSubscription<vmservice.Event> _stdOutSub;
......
...@@ -25,9 +25,11 @@ import '../base/context.dart'; ...@@ -25,9 +25,11 @@ import '../base/context.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/platform.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle.dart';
import '../cache.dart'; import '../cache.dart';
import '../dart/package_map.dart';
import '../globals.dart'; import '../globals.dart';
import '../project.dart'; import '../project.dart';
import '../web/chrome.dart'; import '../web/chrome.dart';
...@@ -178,6 +180,8 @@ class WebFs { ...@@ -178,6 +180,8 @@ class WebFs {
final Map<String, String> mappedUrls = <String, String>{ final Map<String, String> mappedUrls = <String, String>{
'main.dart.js': 'packages/${flutterProject.manifest.appName}/' 'main.dart.js': 'packages/${flutterProject.manifest.appName}/'
'${targetBaseName}_web_entrypoint.dart.js', '${targetBaseName}_web_entrypoint.dart.js',
'${targetBaseName}_web_entrypoint.dart.js.map': 'packages/${flutterProject.manifest.appName}/'
'${targetBaseName}_web_entrypoint.dart.js.map',
'${targetBaseName}_web_entrypoint.dart.bootstrap.js': 'packages/${flutterProject.manifest.appName}/' '${targetBaseName}_web_entrypoint.dart.bootstrap.js': 'packages/${flutterProject.manifest.appName}/'
'${targetBaseName}_web_entrypoint.dart.bootstrap.js', '${targetBaseName}_web_entrypoint.dart.bootstrap.js',
'${targetBaseName}_web_entrypoint.digests': 'packages/${flutterProject.manifest.appName}/' '${targetBaseName}_web_entrypoint.digests': 'packages/${flutterProject.manifest.appName}/'
...@@ -206,7 +210,7 @@ class WebFs { ...@@ -206,7 +210,7 @@ class WebFs {
.addHandler(dwds.handler); .addHandler(dwds.handler);
Cascade cascade = Cascade(); Cascade cascade = Cascade();
cascade = cascade.add(handler); cascade = cascade.add(handler);
cascade = cascade.add(_assetHandler); cascade = cascade.add(_assetHandler(flutterProject));
final HttpServer server = await httpMultiServerFactory(_kHostName, port); final HttpServer server = await httpMultiServerFactory(_kHostName, port);
shelf_io.serveRequests(server, cascade.handler); shelf_io.serveRequests(server, cascade.handler);
final Chrome chrome = await chromeLauncher.launch('http://$_kHostName:$port/'); final Chrome chrome = await chromeLauncher.launch('http://$_kHostName:$port/');
...@@ -218,46 +222,74 @@ class WebFs { ...@@ -218,46 +222,74 @@ class WebFs {
); );
} }
static Future<Response> _assetHandler(Request request) async { static Future<Response> Function(Request request) _assetHandler(FlutterProject flutterProject) {
if (request.url.path.contains('stack_trace_mapper')) { final PackageMap packageMap = PackageMap(PackageMap.globalPackagesPath);
final File file = fs.file(fs.path.join( return (Request request) async {
artifacts.getArtifactPath(Artifact.engineDartSdkPath), if (request.url.path.contains('stack_trace_mapper')) {
'lib', final File file = fs.file(fs.path.join(
'dev_compiler', artifacts.getArtifactPath(Artifact.engineDartSdkPath),
'web', 'lib',
'dart_stack_trace_mapper.js' 'dev_compiler',
)); 'web',
return Response.ok(file.readAsBytesSync(), headers: <String, String>{ 'dart_stack_trace_mapper.js'
'Content-Type': 'text/javascript', ));
}); return Response.ok(file.readAsBytesSync(), headers: <String, String>{
} else if (request.url.path.contains('require.js')) { 'Content-Type': 'text/javascript',
final File file = fs.file(fs.path.join( });
artifacts.getArtifactPath(Artifact.engineDartSdkPath), } else if (request.url.path.contains('require.js')) {
'lib', final File file = fs.file(fs.path.join(
'dev_compiler', artifacts.getArtifactPath(Artifact.engineDartSdkPath),
'kernel', 'lib',
'amd', 'dev_compiler',
'require.js' 'kernel',
)); 'amd',
return Response.ok(file.readAsBytesSync(), headers: <String, String>{ 'require.js'
'Content-Type': 'text/javascript', ));
}); return Response.ok(file.readAsBytesSync(), headers: <String, String>{
} else if (request.url.path.contains('dart_sdk')) { 'Content-Type': 'text/javascript',
final File file = fs.file(fs.path.join( });
artifacts.getArtifactPath(Artifact.flutterWebSdk), } else if (request.url.path.contains('dart_sdk')) {
'kernel', final File file = fs.file(fs.path.join(
'amd', artifacts.getArtifactPath(Artifact.flutterWebSdk),
'dart_sdk.js', 'kernel',
)); 'amd',
return Response.ok(file.readAsBytesSync(), headers: <String, String>{ 'dart_sdk.js',
'Content-Type': 'text/javascript', ));
}); return Response.ok(file.readAsBytesSync(), headers: <String, String>{
} else if (request.url.path.contains('assets')) { 'Content-Type': 'text/javascript',
final String assetPath = request.url.path.replaceFirst('assets/', ''); });
final File file = fs.file(fs.path.join(getAssetBuildDirectory(), assetPath)); } else if (request.url.path.endsWith('.dart')) {
return Response.ok(file.readAsBytesSync()); // This is likely a sourcemap request. The first segment is the
} // package name, and the rest is the path to the file relative to
return Response.notFound(''); // the package uri. For example, `foo/bar.dart` would represent a
// file at a path like `foo/lib/bar.dart`. If there is no leading
// segment, then we assume it is from the current package.
final String packageName = request.url.pathSegments.length == 1
? flutterProject.manifest.appName
: request.url.pathSegments.first;
String filePath = fs.path.joinAll(request.url.pathSegments.length == 1
? request.url.pathSegments
: request.url.pathSegments.skip(1));
String packagePath = packageMap.map[packageName]?.toFilePath(windows: platform.isWindows);
// If the package isn't found, then we have an issue with relative
// paths within the main project.
if (packagePath == null) {
packagePath = packageMap.map[flutterProject.manifest.appName]
.toFilePath(windows: platform.isWindows);
filePath = request.url.path;
}
final File file = fs.file(fs.path.join(packagePath, filePath));
if (file.existsSync()) {
return Response.ok(file.readAsBytesSync());
}
return Response.notFound('');
} else if (request.url.path.contains('assets')) {
final String assetPath = request.url.path.replaceFirst('assets/', '');
final File file = fs.file(fs.path.join(getAssetBuildDirectory(), assetPath));
return Response.ok(file.readAsBytesSync());
}
return Response.notFound('');
};
} }
} }
......
...@@ -74,6 +74,18 @@ void main() { ...@@ -74,6 +74,18 @@ void main() {
when(mockDebugConnection.uri).thenReturn('ws://127.0.0.1/abcd/'); when(mockDebugConnection.uri).thenReturn('ws://127.0.0.1/abcd/');
} }
test('profile does not supportsServiceProtocol', () => testbed.run(() {
final ResidentRunner profileResidentWebRunner = ResidentWebRunner(
MockWebDevice(),
flutterProject: FlutterProject.current(),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
ipv6: true,
);
expect(profileResidentWebRunner.supportsServiceProtocol, false);
expect(residentWebRunner.supportsServiceProtocol, true);
}));
test('Exits on run if application does not support the web', () => testbed.run(() async { test('Exits on run if application does not support the web', () => testbed.run(() async {
fs.file('pubspec.yaml').createSync(); fs.file('pubspec.yaml').createSync();
final BufferLogger bufferLogger = logger; final BufferLogger bufferLogger = logger;
......
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