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 {
final Device device;
final FlutterProject flutterProject;
// Only the debug builds of the web support the service protocol.
@override
bool get supportsServiceProtocol => isRunningDebug;
WebFs _webFs;
DebugConnection _debugConnection;
StreamSubscription<vmservice.Event> _stdOutSub;
......
......@@ -25,9 +25,11 @@ import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../cache.dart';
import '../dart/package_map.dart';
import '../globals.dart';
import '../project.dart';
import '../web/chrome.dart';
......@@ -178,6 +180,8 @@ class WebFs {
final Map<String, String> mappedUrls = <String, String>{
'main.dart.js': 'packages/${flutterProject.manifest.appName}/'
'${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',
'${targetBaseName}_web_entrypoint.digests': 'packages/${flutterProject.manifest.appName}/'
......@@ -206,7 +210,7 @@ class WebFs {
.addHandler(dwds.handler);
Cascade cascade = Cascade();
cascade = cascade.add(handler);
cascade = cascade.add(_assetHandler);
cascade = cascade.add(_assetHandler(flutterProject));
final HttpServer server = await httpMultiServerFactory(_kHostName, port);
shelf_io.serveRequests(server, cascade.handler);
final Chrome chrome = await chromeLauncher.launch('http://$_kHostName:$port/');
......@@ -218,46 +222,74 @@ class WebFs {
);
}
static Future<Response> _assetHandler(Request request) async {
if (request.url.path.contains('stack_trace_mapper')) {
final File file = fs.file(fs.path.join(
artifacts.getArtifactPath(Artifact.engineDartSdkPath),
'lib',
'dev_compiler',
'web',
'dart_stack_trace_mapper.js'
));
return Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/javascript',
});
} else if (request.url.path.contains('require.js')) {
final File file = fs.file(fs.path.join(
artifacts.getArtifactPath(Artifact.engineDartSdkPath),
'lib',
'dev_compiler',
'kernel',
'amd',
'require.js'
));
return Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/javascript',
});
} else if (request.url.path.contains('dart_sdk')) {
final File file = fs.file(fs.path.join(
artifacts.getArtifactPath(Artifact.flutterWebSdk),
'kernel',
'amd',
'dart_sdk.js',
));
return Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/javascript',
});
} 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('');
static Future<Response> Function(Request request) _assetHandler(FlutterProject flutterProject) {
final PackageMap packageMap = PackageMap(PackageMap.globalPackagesPath);
return (Request request) async {
if (request.url.path.contains('stack_trace_mapper')) {
final File file = fs.file(fs.path.join(
artifacts.getArtifactPath(Artifact.engineDartSdkPath),
'lib',
'dev_compiler',
'web',
'dart_stack_trace_mapper.js'
));
return Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/javascript',
});
} else if (request.url.path.contains('require.js')) {
final File file = fs.file(fs.path.join(
artifacts.getArtifactPath(Artifact.engineDartSdkPath),
'lib',
'dev_compiler',
'kernel',
'amd',
'require.js'
));
return Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/javascript',
});
} else if (request.url.path.contains('dart_sdk')) {
final File file = fs.file(fs.path.join(
artifacts.getArtifactPath(Artifact.flutterWebSdk),
'kernel',
'amd',
'dart_sdk.js',
));
return Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/javascript',
});
} else if (request.url.path.endsWith('.dart')) {
// This is likely a sourcemap request. The first segment is the
// package name, and the rest is the path to the file relative to
// 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() {
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 {
fs.file('pubspec.yaml').createSync();
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