Unverified Commit 497ae83c authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Fix experimental incremental web compiler for Windows (#45286)

parent 9f17a43e
...@@ -88,7 +88,9 @@ class FlutterDevice { ...@@ -88,7 +88,9 @@ class FlutterDevice {
fileSystemScheme: fileSystemScheme, fileSystemScheme: fileSystemScheme,
targetModel: TargetModel.dartdevc, targetModel: TargetModel.dartdevc,
experimentalFlags: experimentalFlags, experimentalFlags: experimentalFlags,
platformDill: artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildMode), platformDill: fs.file(artifacts
.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildMode))
.absolute.uri.toString(),
dartDefines: dartDefines, dartDefines: dartDefines,
); );
} else if (flutterProject.hasBuilders) { } else if (flutterProject.hasBuilders) {
......
...@@ -12,6 +12,7 @@ import '../asset.dart'; ...@@ -12,6 +12,7 @@ import '../asset.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/platform.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle.dart';
...@@ -61,6 +62,8 @@ class WebAssetServer { ...@@ -61,6 +62,8 @@ class WebAssetServer {
final Map<String, Uint8List> _files = <String, Uint8List>{}; final Map<String, Uint8List> _files = <String, Uint8List>{};
final Map<String, Uint8List> _sourcemaps = <String, Uint8List>{}; final Map<String, Uint8List> _sourcemaps = <String, Uint8List>{};
final RegExp _drivePath = RegExp(r'\/[A-Z]:\/');
// handle requests for JavaScript source, dart sources maps, or asset files. // handle requests for JavaScript source, dart sources maps, or asset files.
Future<void> _handleRequest(HttpRequest request) async { Future<void> _handleRequest(HttpRequest request) async {
final HttpResponse response = request.response; final HttpResponse response = request.response;
...@@ -79,11 +82,17 @@ class WebAssetServer { ...@@ -79,11 +82,17 @@ class WebAssetServer {
await response.close(); await response.close();
return; return;
} }
// TODO(jonahwilliams): better path normalization in frontend_server to remove
// this workaround.
String requestPath = request.uri.path;
if (requestPath.startsWith(_drivePath)) {
requestPath = requestPath.substring(3);
}
// If this is a JavaScript file, it must be in the in-memory cache. // If this is a JavaScript file, it must be in the in-memory cache.
// Attempt to look up the file by URI. // Attempt to look up the file by URI.
if (_files.containsKey(request.uri.path)) { if (_files.containsKey(requestPath)) {
final List<int> bytes = _files[request.uri.path]; final List<int> bytes = _files[requestPath];
response.headers response.headers
..add('Content-Length', bytes.length) ..add('Content-Length', bytes.length)
..add('Content-Type', 'application/javascript'); ..add('Content-Type', 'application/javascript');
...@@ -93,8 +102,8 @@ class WebAssetServer { ...@@ -93,8 +102,8 @@ class WebAssetServer {
} }
// If this is a sourcemap file, then it might be in the in-memory cache. // If this is a sourcemap file, then it might be in the in-memory cache.
// Attempt to lookup the file by URI. // Attempt to lookup the file by URI.
if (_sourcemaps.containsKey(request.uri.path)) { if (_sourcemaps.containsKey(requestPath)) {
final List<int> bytes = _sourcemaps[request.uri.path]; final List<int> bytes = _sourcemaps[requestPath];
response.headers response.headers
..add('Content-Length', bytes.length) ..add('Content-Length', bytes.length)
..add('Content-Type', 'application/json'); ..add('Content-Type', 'application/json');
...@@ -193,7 +202,7 @@ class WebAssetServer { ...@@ -193,7 +202,7 @@ class WebAssetServer {
codeStart, codeStart,
codeEnd - codeStart, codeEnd - codeStart,
); );
_files[filePath] = byteView; _files[_filePathToUriFragment(filePath)] = byteView;
final int sourcemapStart = sourcemapOffsets[0]; final int sourcemapStart = sourcemapOffsets[0];
final int sourcemapEnd = sourcemapOffsets[1]; final int sourcemapEnd = sourcemapOffsets[1];
...@@ -206,7 +215,7 @@ class WebAssetServer { ...@@ -206,7 +215,7 @@ class WebAssetServer {
sourcemapStart, sourcemapStart,
sourcemapEnd - sourcemapStart , sourcemapEnd - sourcemapStart ,
); );
_sourcemaps['$filePath.map'] = sourcemapView; _sourcemaps['${_filePathToUriFragment(filePath)}.map'] = sourcemapView;
modules.add(filePath); modules.add(filePath);
} }
...@@ -303,15 +312,18 @@ class WebDevFS implements DevFS { ...@@ -303,15 +312,18 @@ class WebDevFS implements DevFS {
'dart_stack_trace_mapper.js', 'dart_stack_trace_mapper.js',
)); ));
_webAssetServer.writeFile('/main.dart.js', generateBootstrapScript( _webAssetServer.writeFile('/main.dart.js', generateBootstrapScript(
requireUrl: requireJS.path, requireUrl: _filePathToUriFragment(requireJS.path),
mapperUrl: stackTraceMapper.path, mapperUrl: _filePathToUriFragment(stackTraceMapper.path),
entrypoint: '$mainPath.js', entrypoint: '${_filePathToUriFragment(mainPath)}.js',
)); ));
_webAssetServer.writeFile('/main_module.js', generateMainModule( _webAssetServer.writeFile('/main_module.js', generateMainModule(
entrypoint: '$mainPath.js', entrypoint: '${_filePathToUriFragment(mainPath)}.js',
)); ));
_webAssetServer.writeFile('/dart_sdk.js', dartSdk.readAsStringSync()); _webAssetServer.writeFile('/dart_sdk.js', dartSdk.readAsStringSync());
_webAssetServer.writeFile('/dart_sdk.js.map', dartSdkSourcemap.readAsStringSync()); _webAssetServer.writeFile('/dart_sdk.js.map', dartSdkSourcemap.readAsStringSync());
// TODO(jonahwilliams): refactor the asset code in this and the regular devfs to
// be shared.
await writeBundle(fs.directory(getAssetBuildDirectory()), bundle.entries);
} }
final DateTime candidateCompileTime = DateTime.now(); final DateTime candidateCompileTime = DateTime.now();
if (fullRestart) { if (fullRestart) {
...@@ -344,6 +356,20 @@ class WebDevFS implements DevFS { ...@@ -344,6 +356,20 @@ class WebDevFS implements DevFS {
} }
return UpdateFSReport(success: true, syncedBytes: codeFile.lengthSync(), return UpdateFSReport(success: true, syncedBytes: codeFile.lengthSync(),
invalidatedSourcesCount: invalidatedFiles.length) invalidatedSourcesCount: invalidatedFiles.length)
..invalidatedModules = modules; ..invalidatedModules = modules.map(_filePathToUriFragment).toList();
}
}
String _filePathToUriFragment(String path) {
if (platform.isWindows) {
final bool startWithSlash = path.startsWith('/');
final String partial = fs.path
.split(path)
.skip(startWithSlash ? 2 : 1).join('/');
if (partial.startsWith('/')) {
return partial;
}
return '/$partial';
} }
return path;
} }
...@@ -620,8 +620,11 @@ void main() { ...@@ -620,8 +620,11 @@ void main() {
expect(residentCompiler.targetModel, TargetModel.dartdevc); expect(residentCompiler.targetModel, TargetModel.dartdevc);
expect(residentCompiler.sdkRoot, expect(residentCompiler.sdkRoot,
artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: BuildMode.debug) + '/'); artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: BuildMode.debug) + '/');
expect(residentCompiler.platformDill, expect(
artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: BuildMode.debug)); residentCompiler.platformDill,
fs.file(artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: BuildMode.debug))
.absolute.uri.toString(),
);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isWebIncrementalCompilerEnabled: true), FeatureFlags: () => TestFeatureFlags(isWebIncrementalCompilerEnabled: true),
})); }));
......
...@@ -127,6 +127,31 @@ void main() { ...@@ -127,6 +127,31 @@ void main() {
verify(headers.add('Content-Length', source.lengthSync())).called(1); verify(headers.add('Content-Length', source.lengthSync())).called(1);
verify(headers.add('Content-Type', 'application/javascript')).called(1); verify(headers.add('Content-Type', 'application/javascript')).called(1);
verify(response.add(source.readAsBytesSync())).called(1); verify(response.add(source.readAsBytesSync())).called(1);
}, overrides: <Type, Generator>{
Platform: () => linux,
}));
test('serves JavaScript files from in memory cache on Windows', () => testbed.run(() async {
final File source = fs.file('source')
..writeAsStringSync('main() {}');
final File sourcemap = fs.file('sourcemap')
..writeAsStringSync('{}');
final File manifest = fs.file('manifest')
..writeAsStringSync(json.encode(<String, Object>{'/C:/foo.js': <String, Object>{
'code': <int>[0, source.lengthSync()],
'sourcemap': <int>[0, 2],
}}));
webAssetServer.write(source, manifest, sourcemap);
when(request.uri).thenReturn(Uri.parse('http://foobar/C:/foo.js'));
requestController.add(request);
await closeCompleter.future;
verify(headers.add('Content-Length', source.lengthSync())).called(1);
verify(headers.add('Content-Type', 'application/javascript')).called(1);
verify(response.add(source.readAsBytesSync())).called(1);
}, overrides: <Type, Generator>{
Platform: () => windows,
})); }));
test('serves JavaScript files from in memory cache not from manifest', () => testbed.run(() async { test('serves JavaScript files from in memory cache not from manifest', () => testbed.run(() async {
......
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