Unverified Commit 2a7ee930 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] Update WebAssetServer to avoid context, fix tests (#60224)

WebAssetServer could fail if some of the global statics it depended on were initialized in a different order. Fix this by removing globals.

Delete dwds startup test that needs to spawn a real server.
parent 15913e5d
...@@ -20,6 +20,7 @@ import '../base/common.dart'; ...@@ -20,6 +20,7 @@ import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/net.dart'; import '../base/net.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';
...@@ -173,7 +174,13 @@ class WebAssetServer implements AssetReader { ...@@ -173,7 +174,13 @@ class WebAssetServer implements AssetReader {
// In release builds deploy a simpler proxy server. // In release builds deploy a simpler proxy server.
if (buildMode != BuildMode.debug) { if (buildMode != BuildMode.debug) {
final ReleaseAssetServer releaseAssetServer = ReleaseAssetServer(entrypoint); final ReleaseAssetServer releaseAssetServer = ReleaseAssetServer(
entrypoint,
fileSystem: globals.fs,
platform: globals.platform,
flutterRoot: Cache.flutterRoot,
webBuildDirectory: getWebBuildDirectory(),
);
shelf.serveRequests(httpServer, releaseAssetServer.handle); shelf.serveRequests(httpServer, releaseAssetServer.handle);
return server; return server;
} }
...@@ -817,17 +824,31 @@ class WebDevFS implements DevFS { ...@@ -817,17 +824,31 @@ class WebDevFS implements DevFS {
} }
class ReleaseAssetServer { class ReleaseAssetServer {
ReleaseAssetServer(this.entrypoint); ReleaseAssetServer(this.entrypoint, {
@required FileSystem fileSystem,
@required String webBuildDirectory,
@required String flutterRoot,
@required Platform platform,
}) : _fileSystem = fileSystem,
_platform = platform,
_flutterRoot = flutterRoot,
_webBuildDirectory = webBuildDirectory,
_fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform);
final Uri entrypoint; final Uri entrypoint;
final String _flutterRoot;
final String _webBuildDirectory;
final FileSystem _fileSystem;
final FileSystemUtils _fileSystemUtils;
final Platform _platform;
// Locations where source files, assets, or source maps may be located. // Locations where source files, assets, or source maps may be located.
final List<Uri> _searchPaths = <Uri>[ List<Uri> _searchPaths() => <Uri>[
globals.fs.directory(getWebBuildDirectory()).uri, _fileSystem.directory(_webBuildDirectory).uri,
globals.fs.directory(Cache.flutterRoot).uri, _fileSystem.directory(_flutterRoot).uri,
globals.fs.directory(Cache.flutterRoot).parent.uri, _fileSystem.directory(_flutterRoot).parent.uri,
globals.fs.currentDirectory.uri, _fileSystem.currentDirectory.uri,
globals.fs.directory(globals.fsUtils.homeDirPath).uri, _fileSystem.directory(_fileSystemUtils.homeDirPath).uri,
]; ];
Future<shelf.Response> handle(shelf.Request request) async { Future<shelf.Response> handle(shelf.Request request) async {
...@@ -835,10 +856,10 @@ class ReleaseAssetServer { ...@@ -835,10 +856,10 @@ class ReleaseAssetServer {
if (request.url.toString() == 'main.dart') { if (request.url.toString() == 'main.dart') {
fileUri = entrypoint; fileUri = entrypoint;
} else { } else {
for (final Uri uri in _searchPaths) { for (final Uri uri in _searchPaths()) {
final Uri potential = uri.resolve(request.url.path); final Uri potential = uri.resolve(request.url.path);
if (potential == null || !globals.fs.isFileSync( if (potential == null || !_fileSystem.isFileSync(
potential.toFilePath(windows: globals.platform.isWindows))) { potential.toFilePath(windows: _platform.isWindows))) {
continue; continue;
} }
fileUri = potential; fileUri = potential;
...@@ -846,7 +867,7 @@ class ReleaseAssetServer { ...@@ -846,7 +867,7 @@ class ReleaseAssetServer {
} }
} }
if (fileUri != null) { if (fileUri != null) {
final File file = globals.fs.file(fileUri); final File file = _fileSystem.file(fileUri);
final Uint8List bytes = file.readAsBytesSync(); final Uint8List bytes = file.readAsBytesSync();
// Fallback to "application/octet-stream" on null which // Fallback to "application/octet-stream" on null which
// makes no claims as to the structure of the data. // makes no claims as to the structure of the data.
...@@ -857,7 +878,7 @@ class ReleaseAssetServer { ...@@ -857,7 +878,7 @@ class ReleaseAssetServer {
}); });
} }
if (request.url.path == '') { if (request.url.path == '') {
final File file = globals.fs.file(globals.fs.path.join(getWebBuildDirectory(), 'index.html')); final File file = _fileSystem.file(_fileSystem.path.join(_webBuildDirectory, 'index.html'));
return shelf.Response.ok(file.readAsBytesSync(), headers: <String, String>{ return shelf.Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/html', 'Content-Type': 'text/html',
}); });
......
...@@ -93,7 +93,9 @@ void main() { ...@@ -93,7 +93,9 @@ void main() {
setUp(() { setUp(() {
testbed = Testbed(setup: () { testbed = Testbed(setup: () {
globals.fs.file(globalPackagesPath).writeAsStringSync('\n'); globals.fs.file(globalPackagesPath)
..createSync(recursive: true)
..writeAsStringSync('\n');
globals.fs.file(globals.fs.path.join('build', 'app.dill')) globals.fs.file(globals.fs.path.join('build', 'app.dill'))
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('ABC'); ..writeAsStringSync('ABC');
......
...@@ -2,14 +2,9 @@ ...@@ -2,14 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:dwds/data/build_result.dart';
import 'package:dwds/dwds.dart'; import 'package:dwds/dwds.dart';
import 'package:dwds/src/loaders/strategy.dart';
import 'package:dwds/src/readers/asset_reader.dart';
import 'package:dwds/src/services/expression_compiler.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
...@@ -18,7 +13,6 @@ import 'package:flutter_tools/src/build_runner/devfs_web.dart'; ...@@ -18,7 +13,6 @@ import 'package:flutter_tools/src/build_runner/devfs_web.dart';
import 'package:flutter_tools/src/compile.dart'; import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:logging/logging.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:package_config/package_config.dart'; import 'package:package_config/package_config.dart';
import 'package:shelf/shelf.dart'; import 'package:shelf/shelf.dart';
...@@ -531,46 +525,6 @@ void main() { ...@@ -531,46 +525,6 @@ void main() {
expect(uri, Uri.http('localhost:0', '')); expect(uri, Uri.http('localhost:0', ''));
await webDevFS.destroy(); await webDevFS.destroy();
})); }));
test('Launches DWDS with the correct arguments', () => testbed.run(() async {
globals.fs.file('.packages').writeAsStringSync('\n');
final WebAssetServer server = await WebAssetServer.start(
null,
'any',
8123,
(String url) => null,
true,
BuildMode.debug,
true,
Uri.file('test.dart'),
null,
dwdsLauncher: ({
AssetReader assetReader,
Stream<BuildResult> buildResults,
ConnectionProvider chromeConnection,
bool enableDebugExtension,
bool enableDebugging,
ExpressionCompiler expressionCompiler,
String hostname,
LoadStrategy loadStrategy,
void Function(Level, String) logWriter,
bool serveDevTools,
UrlEncoder urlEncoder,
bool useSseForDebugProxy,
bool verbose,
}) async {
expect(serveDevTools, false);
expect(verbose, null);
expect(enableDebugging, true);
expect(enableDebugExtension, true);
expect(useSseForDebugProxy, true);
expect(hostname, 'any');
return MockDwds();
});
await server.dispose();
}));
} }
class MockHttpServer extends Mock implements HttpServer {} class MockHttpServer extends Mock implements HttpServer {}
......
...@@ -10,7 +10,6 @@ import 'package:flutter_tools/src/build_runner/devfs_web.dart'; ...@@ -10,7 +10,6 @@ import 'package:flutter_tools/src/build_runner/devfs_web.dart';
import 'package:shelf/shelf.dart'; import 'package:shelf/shelf.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart';
const List<int> kTransparentImage = <int>[ const List<int> kTransparentImage = <int>[
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49,
...@@ -45,8 +44,13 @@ void main() { ...@@ -45,8 +44,13 @@ void main() {
..writeAsBytesSync(<int>[1, 2, 3]); ..writeAsBytesSync(<int>[1, 2, 3]);
}); });
testUsingContext('release asset server serves correct mime type and content length for png', () async { testWithoutContext('release asset server serves correct mime type and content length for png', () async {
final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base); final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base,
fileSystem: fileSystem,
platform: platform,
flutterRoot: '/flutter',
webBuildDirectory: 'build/web',
);
fileSystem.file('build/web/assets/foo.png') fileSystem.file('build/web/assets/foo.png')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsBytesSync(kTransparentImage); ..writeAsBytesSync(kTransparentImage);
...@@ -57,14 +61,15 @@ void main() { ...@@ -57,14 +61,15 @@ void main() {
'Content-Type': 'image/png', 'Content-Type': 'image/png',
'content-length': '64', 'content-length': '64',
}); });
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('release asset server serves correct mime type and content length for JavaScript', () async { testWithoutContext('release asset server serves correct mime type and content length for JavaScript', () async {
final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base); final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base,
fileSystem: fileSystem,
platform: platform,
flutterRoot: '/flutter',
webBuildDirectory: 'build/web',
);
fileSystem.file('build/web/assets/foo.js') fileSystem.file('build/web/assets/foo.js')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('function main() {}'); ..writeAsStringSync('function main() {}');
...@@ -75,14 +80,15 @@ void main() { ...@@ -75,14 +80,15 @@ void main() {
'Content-Type': 'application/javascript', 'Content-Type': 'application/javascript',
'content-length': '18', 'content-length': '18',
}); });
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('release asset server serves correct mime type and content length for html', () async { testWithoutContext('release asset server serves correct mime type and content length for html', () async {
final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base); final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base,
fileSystem: fileSystem,
platform: platform,
flutterRoot: '/flutter',
webBuildDirectory: 'build/web',
);
fileSystem.file('build/web/assets/foo.html') fileSystem.file('build/web/assets/foo.html')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('<!doctype html><html></html>'); ..writeAsStringSync('<!doctype html><html></html>');
...@@ -93,14 +99,15 @@ void main() { ...@@ -93,14 +99,15 @@ void main() {
'Content-Type': 'text/html', 'Content-Type': 'text/html',
'content-length': '28', 'content-length': '28',
}); });
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('release asset server serves content from flutter root', () async { testWithoutContext('release asset server serves content from flutter root', () async {
final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base); final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base,
fileSystem: fileSystem,
platform: platform,
flutterRoot: '/flutter',
webBuildDirectory: 'build/web',
);
fileSystem.file('flutter/bar.dart') fileSystem.file('flutter/bar.dart')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('void main() { }'); ..writeAsStringSync('void main() { }');
...@@ -108,14 +115,15 @@ void main() { ...@@ -108,14 +115,15 @@ void main() {
.handle(Request('GET', Uri.parse('http://localhost:8080/flutter/bar.dart'))); .handle(Request('GET', Uri.parse('http://localhost:8080/flutter/bar.dart')));
expect(response.statusCode, HttpStatus.ok); expect(response.statusCode, HttpStatus.ok);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('release asset server serves content from project directory', () async { testWithoutContext('release asset server serves content from project directory', () async {
final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base); final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base,
fileSystem: fileSystem,
platform: platform,
flutterRoot: '/flutter',
webBuildDirectory: 'build/web',
);
fileSystem.file('bar.dart') fileSystem.file('bar.dart')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('void main() { }'); ..writeAsStringSync('void main() { }');
...@@ -123,9 +131,5 @@ void main() { ...@@ -123,9 +131,5 @@ void main() {
.handle(Request('GET', Uri.parse('http://localhost:8080/bar.dart'))); .handle(Request('GET', Uri.parse('http://localhost:8080/bar.dart')));
expect(response.statusCode, HttpStatus.ok); expect(response.statusCode, HttpStatus.ok);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
}); });
} }
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