Skip to content

Commit 497ae83

Browse files
Fix experimental incremental web compiler for Windows (flutter#45286)
1 parent 9f17a43 commit 497ae83

File tree

4 files changed

+70
-14
lines changed

4 files changed

+70
-14
lines changed

packages/flutter_tools/lib/src/resident_runner.dart

+3-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ class FlutterDevice {
8888
fileSystemScheme: fileSystemScheme,
8989
targetModel: TargetModel.dartdevc,
9090
experimentalFlags: experimentalFlags,
91-
platformDill: artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildMode),
91+
platformDill: fs.file(artifacts
92+
.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildMode))
93+
.absolute.uri.toString(),
9294
dartDefines: dartDefines,
9395
);
9496
} else if (flutterProject.hasBuilders) {

packages/flutter_tools/lib/src/web/devfs_web.dart

+37-11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import '../asset.dart';
1212
import '../base/common.dart';
1313
import '../base/file_system.dart';
1414
import '../base/io.dart';
15+
import '../base/platform.dart';
1516
import '../base/utils.dart';
1617
import '../build_info.dart';
1718
import '../bundle.dart';
@@ -61,6 +62,8 @@ class WebAssetServer {
6162
final Map<String, Uint8List> _files = <String, Uint8List>{};
6263
final Map<String, Uint8List> _sourcemaps = <String, Uint8List>{};
6364

65+
final RegExp _drivePath = RegExp(r'\/[A-Z]:\/');
66+
6467
// handle requests for JavaScript source, dart sources maps, or asset files.
6568
Future<void> _handleRequest(HttpRequest request) async {
6669
final HttpResponse response = request.response;
@@ -79,11 +82,17 @@ class WebAssetServer {
7982
await response.close();
8083
return;
8184
}
85+
// TODO(jonahwilliams): better path normalization in frontend_server to remove
86+
// this workaround.
87+
String requestPath = request.uri.path;
88+
if (requestPath.startsWith(_drivePath)) {
89+
requestPath = requestPath.substring(3);
90+
}
8291

8392
// If this is a JavaScript file, it must be in the in-memory cache.
8493
// Attempt to look up the file by URI.
85-
if (_files.containsKey(request.uri.path)) {
86-
final List<int> bytes = _files[request.uri.path];
94+
if (_files.containsKey(requestPath)) {
95+
final List<int> bytes = _files[requestPath];
8796
response.headers
8897
..add('Content-Length', bytes.length)
8998
..add('Content-Type', 'application/javascript');
@@ -93,8 +102,8 @@ class WebAssetServer {
93102
}
94103
// If this is a sourcemap file, then it might be in the in-memory cache.
95104
// Attempt to lookup the file by URI.
96-
if (_sourcemaps.containsKey(request.uri.path)) {
97-
final List<int> bytes = _sourcemaps[request.uri.path];
105+
if (_sourcemaps.containsKey(requestPath)) {
106+
final List<int> bytes = _sourcemaps[requestPath];
98107
response.headers
99108
..add('Content-Length', bytes.length)
100109
..add('Content-Type', 'application/json');
@@ -193,7 +202,7 @@ class WebAssetServer {
193202
codeStart,
194203
codeEnd - codeStart,
195204
);
196-
_files[filePath] = byteView;
205+
_files[_filePathToUriFragment(filePath)] = byteView;
197206

198207
final int sourcemapStart = sourcemapOffsets[0];
199208
final int sourcemapEnd = sourcemapOffsets[1];
@@ -206,7 +215,7 @@ class WebAssetServer {
206215
sourcemapStart,
207216
sourcemapEnd - sourcemapStart ,
208217
);
209-
_sourcemaps['$filePath.map'] = sourcemapView;
218+
_sourcemaps['${_filePathToUriFragment(filePath)}.map'] = sourcemapView;
210219

211220
modules.add(filePath);
212221
}
@@ -303,15 +312,18 @@ class WebDevFS implements DevFS {
303312
'dart_stack_trace_mapper.js',
304313
));
305314
_webAssetServer.writeFile('/main.dart.js', generateBootstrapScript(
306-
requireUrl: requireJS.path,
307-
mapperUrl: stackTraceMapper.path,
308-
entrypoint: '$mainPath.js',
315+
requireUrl: _filePathToUriFragment(requireJS.path),
316+
mapperUrl: _filePathToUriFragment(stackTraceMapper.path),
317+
entrypoint: '${_filePathToUriFragment(mainPath)}.js',
309318
));
310319
_webAssetServer.writeFile('/main_module.js', generateMainModule(
311-
entrypoint: '$mainPath.js',
320+
entrypoint: '${_filePathToUriFragment(mainPath)}.js',
312321
));
313322
_webAssetServer.writeFile('/dart_sdk.js', dartSdk.readAsStringSync());
314323
_webAssetServer.writeFile('/dart_sdk.js.map', dartSdkSourcemap.readAsStringSync());
324+
// TODO(jonahwilliams): refactor the asset code in this and the regular devfs to
325+
// be shared.
326+
await writeBundle(fs.directory(getAssetBuildDirectory()), bundle.entries);
315327
}
316328
final DateTime candidateCompileTime = DateTime.now();
317329
if (fullRestart) {
@@ -344,6 +356,20 @@ class WebDevFS implements DevFS {
344356
}
345357
return UpdateFSReport(success: true, syncedBytes: codeFile.lengthSync(),
346358
invalidatedSourcesCount: invalidatedFiles.length)
347-
..invalidatedModules = modules;
359+
..invalidatedModules = modules.map(_filePathToUriFragment).toList();
360+
}
361+
}
362+
363+
String _filePathToUriFragment(String path) {
364+
if (platform.isWindows) {
365+
final bool startWithSlash = path.startsWith('/');
366+
final String partial = fs.path
367+
.split(path)
368+
.skip(startWithSlash ? 2 : 1).join('/');
369+
if (partial.startsWith('/')) {
370+
return partial;
371+
}
372+
return '/$partial';
348373
}
374+
return path;
349375
}

packages/flutter_tools/test/general.shard/resident_runner_test.dart

+5-2
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,11 @@ void main() {
620620
expect(residentCompiler.targetModel, TargetModel.dartdevc);
621621
expect(residentCompiler.sdkRoot,
622622
artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: BuildMode.debug) + '/');
623-
expect(residentCompiler.platformDill,
624-
artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: BuildMode.debug));
623+
expect(
624+
residentCompiler.platformDill,
625+
fs.file(artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: BuildMode.debug))
626+
.absolute.uri.toString(),
627+
);
625628
}, overrides: <Type, Generator>{
626629
FeatureFlags: () => TestFeatureFlags(isWebIncrementalCompilerEnabled: true),
627630
}));

packages/flutter_tools/test/general.shard/web/devfs_web_test.dart

+25
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,31 @@ void main() {
127127
verify(headers.add('Content-Length', source.lengthSync())).called(1);
128128
verify(headers.add('Content-Type', 'application/javascript')).called(1);
129129
verify(response.add(source.readAsBytesSync())).called(1);
130+
}, overrides: <Type, Generator>{
131+
Platform: () => linux,
132+
}));
133+
134+
test('serves JavaScript files from in memory cache on Windows', () => testbed.run(() async {
135+
final File source = fs.file('source')
136+
..writeAsStringSync('main() {}');
137+
final File sourcemap = fs.file('sourcemap')
138+
..writeAsStringSync('{}');
139+
final File manifest = fs.file('manifest')
140+
..writeAsStringSync(json.encode(<String, Object>{'/C:/foo.js': <String, Object>{
141+
'code': <int>[0, source.lengthSync()],
142+
'sourcemap': <int>[0, 2],
143+
}}));
144+
webAssetServer.write(source, manifest, sourcemap);
145+
146+
when(request.uri).thenReturn(Uri.parse('http://foobar/C:/foo.js'));
147+
requestController.add(request);
148+
await closeCompleter.future;
149+
150+
verify(headers.add('Content-Length', source.lengthSync())).called(1);
151+
verify(headers.add('Content-Type', 'application/javascript')).called(1);
152+
verify(response.add(source.readAsBytesSync())).called(1);
153+
}, overrides: <Type, Generator>{
154+
Platform: () => windows,
130155
}));
131156

132157
test('serves JavaScript files from in memory cache not from manifest', () => testbed.run(() async {

0 commit comments

Comments
 (0)