Skip to content

Commit 25a8131

Browse files
author
Jonah Williams
authored
[flutter_tools] reload dart_sdk when sources update (flutter#51067)
1 parent 29306b0 commit 25a8131

File tree

2 files changed

+99
-70
lines changed

2 files changed

+99
-70
lines changed

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

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ class WebAssetServer implements AssetReader {
4545

4646
/// Start the web asset server on a [hostname] and [port].
4747
///
48+
/// If [testMode] is true, do not actually initialize dwds or the shelf static
49+
/// server.
50+
///
4851
/// Unhandled exceptions will throw a [ToolExit] with the error and stack
4952
/// trace.
5053
static Future<WebAssetServer> start(
@@ -53,14 +56,18 @@ class WebAssetServer implements AssetReader {
5356
UrlTunneller urlTunneller,
5457
BuildMode buildMode,
5558
bool enableDwds,
56-
Uri entrypoint,
57-
) async {
59+
Uri entrypoint, {
60+
bool testMode = false,
61+
}) async {
5862
try {
5963
final InternetAddress address = (await InternetAddress.lookup(hostname)).first;
6064
final HttpServer httpServer = await HttpServer.bind(address, port);
6165
final Packages packages = await loadPackagesFile(
6266
Uri.base.resolve('.packages'), loader: (Uri uri) => globals.fs.file(uri).readAsBytes());
6367
final WebAssetServer server = WebAssetServer(httpServer, packages, address);
68+
if (testMode) {
69+
return server;
70+
}
6471

6572
// In release builds deploy a simpler proxy server.
6673
if (buildMode != BuildMode.debug) {
@@ -244,8 +251,31 @@ class WebAssetServer implements AssetReader {
244251
return modules;
245252
}
246253

254+
@visibleForTesting
255+
final File dartSdk = globals.fs.file(globals.fs.path.join(
256+
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
257+
'kernel',
258+
'amd',
259+
'dart_sdk.js',
260+
));
261+
262+
@visibleForTesting
263+
final File dartSdkSourcemap = globals.fs.file(globals.fs.path.join(
264+
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
265+
'kernel',
266+
'amd',
267+
'dart_sdk.js.map',
268+
));
269+
247270
// Attempt to resolve `path` to a dart file.
248271
File _resolveDartFile(String path) {
272+
// Return the actual file objects so that local engine changes are automatically picked up.
273+
switch (path) {
274+
case '/dart_sdk.js':
275+
return dartSdk;
276+
case '.dart_sdk.js.map':
277+
return dartSdkSourcemap;
278+
}
249279
// If this is a dart file, it must be on the local file system and is
250280
// likely coming from a source map request. The tool doesn't currently
251281
// consider the case of Dart files as assets.
@@ -309,7 +339,12 @@ class ConnectionResult {
309339
final DebugConnection debugConnection;
310340
}
311341

342+
/// The web specific DevFS implementation.
312343
class WebDevFS implements DevFS {
344+
/// Create a new [WebDevFS] instance.
345+
///
346+
/// [testMode] is true, do not actually initialize dwds or the shelf static
347+
/// server.
313348
WebDevFS({
314349
@required this.hostname,
315350
@required this.port,
@@ -318,6 +353,7 @@ class WebDevFS implements DevFS {
318353
@required this.buildMode,
319354
@required this.enableDwds,
320355
@required this.entrypoint,
356+
this.testMode = false,
321357
});
322358

323359
final Uri entrypoint;
@@ -327,6 +363,7 @@ class WebDevFS implements DevFS {
327363
final UrlTunneller urlTunneller;
328364
final BuildMode buildMode;
329365
final bool enableDwds;
366+
final bool testMode;
330367

331368
@visibleForTesting
332369
WebAssetServer webAssetServer;
@@ -387,6 +424,7 @@ class WebDevFS implements DevFS {
387424
buildMode,
388425
enableDwds,
389426
entrypoint,
427+
testMode: testMode,
390428
);
391429
return Uri.parse('http://$hostname:$port');
392430
}
@@ -450,8 +488,7 @@ class WebDevFS implements DevFS {
450488
);
451489
// TODO(jonahwilliams): switch to DWDS provided APIs when they are ready.
452490
webAssetServer.writeFile('/basic.digests', '{}');
453-
webAssetServer.writeFile('/dart_sdk.js', dartSdk.readAsStringSync());
454-
webAssetServer.writeFile('/dart_sdk.js.map', dartSdkSourcemap.readAsStringSync());
491+
455492
// TODO(jonahwilliams): refactor the asset code in this and the regular devfs to
456493
// be shared.
457494
if (bundle != null) {
@@ -498,6 +535,7 @@ class WebDevFS implements DevFS {
498535
} on FileSystemException catch (err) {
499536
throwToolExit('Failed to load recompiled sources:\n$err');
500537
}
538+
501539
return UpdateFSReport(
502540
success: true,
503541
syncedBytes: codeFile.lengthSync(),
@@ -515,22 +553,6 @@ class WebDevFS implements DevFS {
515553
'require.js',
516554
));
517555

518-
@visibleForTesting
519-
final File dartSdk = globals.fs.file(globals.fs.path.join(
520-
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
521-
'kernel',
522-
'amd',
523-
'dart_sdk.js',
524-
));
525-
526-
@visibleForTesting
527-
final File dartSdkSourcemap = globals.fs.file(globals.fs.path.join(
528-
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk),
529-
'kernel',
530-
'amd',
531-
'dart_sdk.js.map',
532-
));
533-
534556
@visibleForTesting
535557
final File stackTraceMapper = globals.fs.file(globals.fs.path.join(
536558
globals.artifacts.getArtifactPath(Artifact.engineDartSdkPath),

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

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import 'package:flutter_tools/src/globals.dart' as globals;
1818
import 'package:shelf/shelf.dart';
1919

2020
import '../../src/common.dart';
21-
import '../../src/io.dart';
2221
import '../../src/testbed.dart';
2322

2423
const List<int> kTransparentImage = <int>[
@@ -278,55 +277,63 @@ void main() {
278277
}));
279278

280279
test('Can start web server with specified assets', () => testbed.run(() async {
281-
await IOOverrides.runWithIOOverrides(() async {
282-
final File outputFile = globals.fs.file(globals.fs.path.join('lib', 'main.dart'))
283-
..createSync(recursive: true);
284-
outputFile.parent.childFile('a.sources').writeAsStringSync('');
285-
outputFile.parent.childFile('a.json').writeAsStringSync('{}');
286-
outputFile.parent.childFile('a.map').writeAsStringSync('{}');
287-
outputFile.parent.childFile('.packages').writeAsStringSync('\n');
288-
289-
final ResidentCompiler residentCompiler = MockResidentCompiler();
290-
when(residentCompiler.recompile(
291-
any,
292-
any,
293-
outputPath: anyNamed('outputPath'),
294-
packagesFilePath: anyNamed('packagesFilePath'),
295-
)).thenAnswer((Invocation invocation) async {
296-
return const CompilerOutput('a', 0, <Uri>[]);
297-
});
298-
299-
final WebDevFS webDevFS = WebDevFS(
300-
hostname: 'localhost',
301-
port: 0,
302-
packagesFilePath: '.packages',
303-
urlTunneller: null,
304-
buildMode: BuildMode.debug,
305-
enableDwds: false,
306-
entrypoint: Uri.base,
307-
);
308-
webDevFS.requireJS.createSync(recursive: true);
309-
webDevFS.dartSdk.createSync(recursive: true);
310-
webDevFS.dartSdkSourcemap.createSync(recursive: true);
311-
webDevFS.stackTraceMapper.createSync(recursive: true);
312-
313-
await webDevFS.create();
314-
await webDevFS.update(
315-
mainPath: globals.fs.path.join('lib', 'main.dart'),
316-
generator: residentCompiler,
317-
trackWidgetCreation: true,
318-
bundleFirstUpload: true,
319-
invalidatedFiles: <Uri>[],
320-
);
321-
322-
expect(webDevFS.webAssetServer.getFile('/main.dart'), isNotNull);
323-
expect(webDevFS.webAssetServer.getFile('/manifest.json'), isNotNull);
324-
expect(webDevFS.webAssetServer.getFile('/flutter_service_worker.js'), isNotNull);
325-
326-
await webDevFS.destroy();
327-
await webDevFS.dwds.stop();
328-
}, FlutterIOOverrides(fileSystem: globals.fs));
329-
}), skip: true); // Not clear the best way to test this, since shelf hits the real filesystem.
280+
final File outputFile = globals.fs.file(globals.fs.path.join('lib', 'main.dart'))
281+
..createSync(recursive: true);
282+
outputFile.parent.childFile('a.sources').writeAsStringSync('');
283+
outputFile.parent.childFile('a.json').writeAsStringSync('{}');
284+
outputFile.parent.childFile('a.map').writeAsStringSync('{}');
285+
outputFile.parent.childFile('.packages').writeAsStringSync('\n');
286+
287+
final ResidentCompiler residentCompiler = MockResidentCompiler();
288+
when(residentCompiler.recompile(
289+
any,
290+
any,
291+
outputPath: anyNamed('outputPath'),
292+
packagesFilePath: anyNamed('packagesFilePath'),
293+
)).thenAnswer((Invocation invocation) async {
294+
return const CompilerOutput('a', 0, <Uri>[]);
295+
});
296+
297+
final WebDevFS webDevFS = WebDevFS(
298+
hostname: 'localhost',
299+
port: 0,
300+
packagesFilePath: '.packages',
301+
urlTunneller: null,
302+
buildMode: BuildMode.debug,
303+
enableDwds: false,
304+
entrypoint: Uri.base,
305+
testMode: true,
306+
);
307+
webDevFS.requireJS.createSync(recursive: true);
308+
webDevFS.stackTraceMapper.createSync(recursive: true);
309+
310+
await webDevFS.create();
311+
webDevFS.webAssetServer.dartSdk
312+
..createSync(recursive: true)
313+
..writeAsStringSync('HELLO');
314+
webDevFS.webAssetServer.dartSdkSourcemap.createSync(recursive: true);
315+
316+
await webDevFS.update(
317+
mainPath: globals.fs.path.join('lib', 'main.dart'),
318+
generator: residentCompiler,
319+
trackWidgetCreation: true,
320+
bundleFirstUpload: true,
321+
invalidatedFiles: <Uri>[],
322+
);
323+
324+
expect(webDevFS.webAssetServer.getFile('/main.dart'), isNotNull);
325+
expect(webDevFS.webAssetServer.getFile('/manifest.json'), isNotNull);
326+
expect(webDevFS.webAssetServer.getFile('/flutter_service_worker.js'), isNotNull);
327+
expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js'), 'HELLO');
328+
329+
// Update to the SDK.
330+
webDevFS.webAssetServer.dartSdk.writeAsStringSync('BELLOW');
331+
332+
// New SDK should be visible..
333+
expect(await webDevFS.webAssetServer.dartSourceContents('/dart_sdk.js'), 'BELLOW');
334+
335+
await webDevFS.destroy();
336+
}));
330337
}
331338

332339
class MockHttpServer extends Mock implements HttpServer {}

0 commit comments

Comments
 (0)