diff --git a/frontend_server_common/CHANGELOG.md b/frontend_server_common/CHANGELOG.md index a2a8ac29e..8eb75a858 100644 --- a/frontend_server_common/CHANGELOG.md +++ b/frontend_server_common/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.2.0 +- Migrate to null safety + ## 0.1.1 - Remove dead code diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index d096875c8..62e4afce9 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.9 - // Note: this is a copy from flutter tools, updated to work with dwds tests import 'dart:async'; @@ -11,7 +9,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:dwds/dwds.dart'; +import 'package:dwds/asset_reader.dart'; import 'package:file/file.dart'; import 'package:logging/logging.dart'; import 'package:mime/mime.dart' as mime; @@ -32,10 +30,10 @@ class TestAssetServer implements AssetReader { static const String _defaultMimeType = 'application/octet-stream'; final FileSystem _fileSystem; final HttpServer _httpServer; - final Map _files = {}; - final Map _sourcemaps = {}; - final Map _metadata = {}; - String _mergedMetadata; + final Map _files = {}; + final Map _sourceMaps = {}; + final Map _metadata = {}; + late String _mergedMetadata; final PackageConfig _packageConfig; final InternetAddress internetAddress; @@ -47,6 +45,15 @@ class TestAssetServer implements AssetReader { this._fileSystem, ) : basePath = _parseBasePathFromIndexHtml(index); + bool hasFile(String path) => _files.containsKey(path); + Uint8List getFile(String path) => _files[path]!; + + bool hasSourceMap(String path) => _sourceMaps.containsKey(path); + Uint8List getSourceMap(String path) => _sourceMaps[path]!; + + bool hasMetadata(String path) => _metadata.containsKey(path); + Uint8List getMetadata(String path) => _metadata[path]!; + /// Start the web asset server on a [hostname] and [port]. /// /// Unhandled exceptions will throw a exception with the error and stack @@ -66,10 +73,6 @@ class TestAssetServer implements AssetReader { return server; } - Uint8List getFile(String path) => _files[path]; - - Uint8List getSourceMap(String path) => _sourcemaps[path]; - // handle requests for JavaScript source, dart sources maps, or asset files. Future handleRequest(shelf.Request request) async { var headers = {}; @@ -94,13 +97,10 @@ class TestAssetServer implements AssetReader { requestPath = _stripBasePath(requestPath, basePath) ?? requestPath; requestPath = requestPath.startsWith('/') ? requestPath : '/$requestPath'; - if (requestPath == null) { - return shelf.Response.notFound(''); - } // If this is a JavaScript file, it must be in the in-memory cache. // Attempt to look up the file by URI. - if (_files.containsKey(requestPath)) { + if (hasFile(requestPath)) { final List bytes = getFile(requestPath); headers[HttpHeaders.contentLengthHeader] = bytes.length.toString(); headers[HttpHeaders.contentTypeHeader] = 'application/javascript'; @@ -108,7 +108,7 @@ class TestAssetServer implements AssetReader { } // If this is a sourcemap file, then it might be in the in-memory cache. // Attempt to lookup the file by URI. - if (_sourcemaps.containsKey(requestPath)) { + if (hasSourceMap(requestPath)) { final List bytes = getSourceMap(requestPath); headers[HttpHeaders.contentLengthHeader] = bytes.length.toString(); headers[HttpHeaders.contentTypeHeader] = 'application/json'; @@ -124,7 +124,7 @@ class TestAssetServer implements AssetReader { // Attempt to determine the file's mime type. if this is not provided some // browsers will refuse to render images/show video et cetera. If the tool // cannot determine a mime type, fall back to application/octet-stream. - String mimeType; + String? mimeType; if (length >= 12) { mimeType = mime.lookupMimeType( file.path, @@ -160,10 +160,6 @@ class TestAssetServer implements AssetReader { var manifest = _castStringKeyedMap(json.decode(manifestFile.readAsStringSync())); for (var filePath in manifest.keys) { - if (filePath == null) { - _logger.severe('Invalid manfiest file: $filePath'); - continue; - } var offsets = _castStringKeyedMap(manifest[filePath]); var codeOffsets = (offsets['code'] as List).cast(); var sourcemapOffsets = @@ -200,7 +196,7 @@ class TestAssetServer implements AssetReader { sourcemapStart, sourcemapEnd - sourcemapStart, ); - _sourcemaps['$filePath.map'] = sourcemapView; + _sourceMaps['$filePath.map'] = sourcemapView; var metadataStart = metadataOffsets[0]; var metadataEnd = metadataOffsets[1]; @@ -259,36 +255,42 @@ class TestAssetServer implements AssetReader { } @override - Future dartSourceContents(String serverPath) { - serverPath = _stripBasePath(serverPath, basePath); - var result = _resolveDartFile(serverPath); - if (result.existsSync()) { - return result.readAsString(); + Future dartSourceContents(String serverPath) async { + final stripped = _stripBasePath(serverPath, basePath); + if (stripped != null) { + var result = _resolveDartFile(stripped); + if (result.existsSync()) { + return result.readAsString(); + } } _logger.severe('Source not found: $serverPath'); return null; } @override - Future sourceMapContents(String serverPath) async { - serverPath = _stripBasePath(serverPath, basePath); - var path = '/$serverPath'; - if (_sourcemaps.containsKey(path)) { - return utf8.decode(_sourcemaps[path]); + Future sourceMapContents(String serverPath) async { + final stripped = _stripBasePath(serverPath, basePath); + if (stripped != null) { + var path = '/$stripped'; + if (hasSourceMap(path)) { + return utf8.decode(getSourceMap(path)); + } } _logger.severe('Source map not found: $serverPath'); return null; } @override - Future metadataContents(String serverPath) async { - serverPath = _stripBasePath(serverPath, basePath); - if (serverPath.endsWith('.ddc_merged_metadata')) { - return _mergedMetadata; - } - var path = '/$serverPath'; - if (_metadata.containsKey(path)) { - return utf8.decode(_metadata[path]); + Future metadataContents(String serverPath) async { + final stripped = _stripBasePath(serverPath, basePath); + if (stripped != null) { + if (stripped.endsWith('.ddc_merged_metadata')) { + return _mergedMetadata; + } + var path = '/$stripped'; + if (hasMetadata(path)) { + return utf8.decode(getMetadata(path)); + } } _logger.severe('Metadata not found: $serverPath'); return null; @@ -299,7 +301,7 @@ class TestAssetServer implements AssetReader { /// the same structure (`Map`) with the correct runtime types. Map _castStringKeyedMap(dynamic untyped) { var map = untyped as Map; - return map?.cast(); + return map.cast(); } String _stripLeadingSlashes(String path) { @@ -309,7 +311,7 @@ String _stripLeadingSlashes(String path) { return path; } -String _stripBasePath(String path, String basePath) { +String? _stripBasePath(String path, String basePath) { path = _stripLeadingSlashes(path); if (path.startsWith(basePath)) { path = path.substring(basePath.length); @@ -327,5 +329,6 @@ String _parseBasePathFromIndexHtml(String index) { } final contents = file.readAsStringSync(); final matches = RegExp(r'').allMatches(contents); - return matches.isEmpty ? '' : matches.first.group(1); + if (matches.isEmpty) return ''; + return matches.first.group(1) ?? ''; } diff --git a/frontend_server_common/lib/src/bootstrap.dart b/frontend_server_common/lib/src/bootstrap.dart index f1a7e01b9..a5d1ba0c4 100644 --- a/frontend_server_common/lib/src/bootstrap.dart +++ b/frontend_server_common/lib/src/bootstrap.dart @@ -2,12 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.9 - // Note: this is a copy from flutter tools, updated to work with dwds tests -import 'package:meta/meta.dart'; - /// The JavaScript bootstrap script to support in-browser hot restart. /// /// The [requireUrl] loads our cached RequireJS script file. The [mapperUrl] @@ -18,9 +14,9 @@ import 'package:meta/meta.dart'; /// and is responsible for bootstrapping the RequireJS modules and attaching /// the hot reload hooks. String generateBootstrapScript({ - @required String requireUrl, - @required String mapperUrl, - @required String entrypoint, + required String requireUrl, + required String mapperUrl, + required String entrypoint, }) { return ''' "use strict"; @@ -53,7 +49,7 @@ document.head.appendChild(requireEl); /// the file `foo/bar/baz.dart` will generate a property named approximately /// `foo__bar__baz`. Rather than attempt to guess, we assume the first property of /// this object is the module. -String generateMainModule({@required String entrypoint}) { +String generateMainModule({required String entrypoint}) { return '''/* ENTRYPOINT_EXTENTION_MARKER */ // Create the main module loaded below. diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart index c9805984e..b7fc30c8e 100644 --- a/frontend_server_common/lib/src/devfs.dart +++ b/frontend_server_common/lib/src/devfs.dart @@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.9 - // Note: this is a copy from flutter tools, updated to work with dwds tests import 'dart:io'; -import 'package:dwds/dwds.dart'; +import 'package:dwds/asset_reader.dart'; import 'package:file/file.dart'; -import 'package:meta/meta.dart'; import 'package:package_config/package_config.dart'; import 'package:path/path.dart' as p; @@ -23,18 +20,18 @@ final String dartWebSdkPath = p.join(dartSdkPath, 'lib', 'dev_compiler'); class WebDevFS { WebDevFS({ - this.fileSystem, - this.hostname, - this.port, - this.projectDirectory, - this.packageConfigFile, - this.index, - this.urlTunneller, - this.soundNullSafety, + required this.fileSystem, + required this.hostname, + required this.port, + required this.projectDirectory, + required this.packageConfigFile, + required this.index, + required this.urlTunneller, + required this.soundNullSafety, }); final FileSystem fileSystem; - TestAssetServer assetServer; + late final TestAssetServer assetServer; final String hostname; final int port; final Uri projectDirectory; @@ -42,9 +39,8 @@ class WebDevFS { final String index; final UrlEncoder urlTunneller; final bool soundNullSafety; - Directory _savedCurrentDirectory; - List sources; - PackageConfig _packageConfig; + late final Directory _savedCurrentDirectory; + late final PackageConfig _packageConfig; Future create() async { _savedCurrentDirectory = fileSystem.currentDirectory; @@ -61,16 +57,15 @@ class WebDevFS { Future dispose() { fileSystem.currentDirectory = _savedCurrentDirectory; - return assetServer?.close(); + return assetServer.close(); } Future update({ - Uri mainUri, - String dillOutputPath, - @required ResidentCompiler generator, - List invalidatedFiles, + required Uri mainUri, + required String dillOutputPath, + required ResidentCompiler generator, + required List invalidatedFiles, }) async { - assert(generator != null); final mainPath = mainUri.toFilePath(); final outputDirectoryPath = fileSystem.file(mainPath).parent.path; final entryPoint = mainUri.toString(); @@ -108,8 +103,6 @@ class WebDevFS { return UpdateFSReport(success: false); } - // list of sources that needs to be monitored are in [compilerOutput.sources] - sources = compilerOutput.sources; File codeFile; File manifestFile; File sourcemapFile; @@ -200,7 +193,7 @@ class UpdateFSReport { /// mode. /// /// Only used for JavaScript compilation. - List invalidatedModules; + List? invalidatedModules; } String _filePathToUriFragment(String path) { diff --git a/frontend_server_common/lib/src/frontend_server_client.dart b/frontend_server_common/lib/src/frontend_server_client.dart index 92dc8ee51..8f5a4a201 100644 --- a/frontend_server_common/lib/src/frontend_server_client.dart +++ b/frontend_server_common/lib/src/frontend_server_client.dart @@ -2,17 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.9 - // Note: this is a copy from flutter tools, updated to work with dwds tests import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:dwds/dwds.dart'; +import 'package:dwds/expression_compiler.dart'; import 'package:logging/logging.dart'; -import 'package:meta/meta.dart'; import 'package:package_config/package_config.dart'; import 'package:path/path.dart' as p; import 'package:usage/uuid/uuid.dart'; @@ -22,7 +19,7 @@ import 'utilities.dart'; Logger _logger = Logger('FrontendServerClient'); Logger _serverLogger = Logger('FrontendServer'); -void defaultConsumer(String message, {StackTrace stackTrace}) => +void defaultConsumer(String message, {StackTrace? stackTrace}) => stackTrace == null ? _serverLogger.info(message) : _serverLogger.severe(message, null, stackTrace); @@ -45,19 +42,20 @@ enum StdoutState { collectDiagnostic, collectDependencies } /// Handles stdin/stdout communication with the frontend server. class StdoutHandler { - StdoutHandler({@required this.consumer}) { + StdoutHandler({required this.consumer}) { reset(); } - bool compilerMessageReceived = false; final CompilerMessageConsumer consumer; - String boundaryKey; - StdoutState state = StdoutState.collectDiagnostic; - Completer compilerOutput; - final List sources = []; + late Completer compilerOutput; + + final List _sources = []; - bool _suppressCompilerMessages; - bool _expectSources; + bool _compilerMessageReceived = false; + String? _boundaryKey; + StdoutState _state = StdoutState.collectDiagnostic; + late bool _suppressCompilerMessages; + late bool _expectSources; bool _badState = false; void handler(String message) { @@ -72,14 +70,14 @@ class StdoutHandler { return; } var kResultPrefix = 'result '; - if (boundaryKey == null && message.startsWith(kResultPrefix)) { - boundaryKey = message.substring(kResultPrefix.length); + if (_boundaryKey == null && message.startsWith(kResultPrefix)) { + _boundaryKey = message.substring(kResultPrefix.length); return; } // Invalid state, see commented issue below for more information. // NB: both the completeError and _badState flags are required to avoid // filling the console with exceptions. - if (boundaryKey == null) { + if (_boundaryKey == null) { // Throwing a synchronous exception via throwToolExit will fail to cancel // the stream. Instead use completeError so that the error is returned // from the awaited future that the compiler consumers are expecting. @@ -90,11 +88,11 @@ class StdoutHandler { 'frontend server client (in dwds tests).' '\n\n' 'Additional debugging information:\n' - ' StdoutState: $state\n' - ' compilerMessageReceived: $compilerMessageReceived\n' + ' StdoutState: $_state\n' + ' compilerMessageReceived: $_compilerMessageReceived\n' ' message: $message\n' ' _expectSources: $_expectSources\n' - ' sources: $sources\n'); + ' sources: $_sources\n'); // There are several event turns before the tool actually exits from a // tool exception. Normally, the stream should be cancelled to prevent // more events from entering the bad state, but because the error @@ -104,10 +102,11 @@ class StdoutHandler { _badState = true; return; } + final boundaryKey = _boundaryKey!; if (message.startsWith(boundaryKey)) { if (_expectSources) { - if (state == StdoutState.collectDiagnostic) { - state = StdoutState.collectDependencies; + if (_state == StdoutState.collectDiagnostic) { + _state = StdoutState.collectDependencies; return; } } @@ -119,25 +118,25 @@ class StdoutHandler { compilerOutput.complete(CompilerOutput( message.substring(boundaryKey.length + 1, spaceDelimiter), int.parse(message.substring(spaceDelimiter + 1).trim()), - sources)); + _sources)); return; } - if (state == StdoutState.collectDiagnostic) { + if (_state == StdoutState.collectDiagnostic) { if (!_suppressCompilerMessages) { - if (compilerMessageReceived == false) { + if (_compilerMessageReceived == false) { consumer('\nCompiler message:'); - compilerMessageReceived = true; + _compilerMessageReceived = true; } consumer(message); } } else { - assert(state == StdoutState.collectDependencies); + assert(_state == StdoutState.collectDependencies); switch (message[0]) { case '+': - sources.add(Uri.parse(message.substring(1))); + _sources.add(Uri.parse(message.substring(1))); break; case '-': - sources.remove(Uri.parse(message.substring(1))); + _sources.remove(Uri.parse(message.substring(1))); break; default: _logger.warning('Unexpected prefix for $message uri - ignoring'); @@ -149,12 +148,12 @@ class StdoutHandler { // with its own boundary key and new completer. void reset( {bool suppressCompilerMessages = false, bool expectSources = true}) { - boundaryKey = null; - compilerMessageReceived = false; - compilerOutput = Completer(); + _boundaryKey = null; + _compilerMessageReceived = false; + compilerOutput = Completer(); _suppressCompilerMessages = suppressCompilerMessages; _expectSources = expectSources; - state = StdoutState.collectDiagnostic; + _state = StdoutState.collectDiagnostic; } } @@ -162,9 +161,9 @@ class StdoutHandler { abstract class _CompilationRequest { _CompilationRequest(this.completer); - Completer completer; + Completer completer; - Future _run(ResidentCompiler compiler); + Future _run(ResidentCompiler compiler); Future run(ResidentCompiler compiler) async { completer.complete(await _run(compiler)); @@ -173,7 +172,7 @@ abstract class _CompilationRequest { class _RecompileRequest extends _CompilationRequest { _RecompileRequest( - Completer completer, + Completer completer, this.mainUri, this.invalidatedFiles, this.outputPath, @@ -186,13 +185,13 @@ class _RecompileRequest extends _CompilationRequest { PackageConfig packageConfig; @override - Future _run(ResidentCompiler compiler) async => + Future _run(ResidentCompiler compiler) async => compiler._recompile(this); } class _CompileExpressionRequest extends _CompilationRequest { _CompileExpressionRequest( - Completer completer, + Completer completer, this.expression, this.definitions, this.typeDefinitions, @@ -204,18 +203,18 @@ class _CompileExpressionRequest extends _CompilationRequest { String expression; List definitions; List typeDefinitions; - String libraryUri; - String klass; - bool isStatic; + String? libraryUri; + String? klass; + bool? isStatic; @override - Future _run(ResidentCompiler compiler) async => + Future _run(ResidentCompiler compiler) async => compiler._compileExpression(this); } class _CompileExpressionToJsRequest extends _CompilationRequest { _CompileExpressionToJsRequest( - Completer completer, + Completer completer, this.libraryUri, this.line, this.column, @@ -234,15 +233,15 @@ class _CompileExpressionToJsRequest extends _CompilationRequest { String expression; @override - Future _run(ResidentCompiler compiler) async => + Future _run(ResidentCompiler compiler) async => compiler._compileExpressionToJs(this); } class _RejectRequest extends _CompilationRequest { - _RejectRequest(Completer completer) : super(completer); + _RejectRequest(Completer completer) : super(completer); @override - Future _run(ResidentCompiler compiler) async => + Future _run(ResidentCompiler compiler) async => compiler._reject(); } @@ -254,15 +253,14 @@ class _RejectRequest extends _CompilationRequest { class ResidentCompiler { ResidentCompiler( this.sdkRoot, { - this.projectDirectory, - this.packageConfigFile, - this.fileSystemRoots, - this.fileSystemScheme, - this.platformDill, - this.verbose, + required this.projectDirectory, + required this.packageConfigFile, + required this.fileSystemRoots, + required this.fileSystemScheme, + required this.platformDill, + this.verbose = false, CompilerMessageConsumer compilerMessageConsumer = defaultConsumer, - }) : assert(sdkRoot != null), - _stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer); + }) : _stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer); final Uri projectDirectory; final Uri packageConfigFile; @@ -274,7 +272,7 @@ class ResidentCompiler { /// The path to the root of the Dart SDK used to compile. final String sdkRoot; - Process _server; + Process? _server; final StdoutHandler _stdoutHandler; bool _compileRequestNeedsConfirmation = false; @@ -288,35 +286,39 @@ class ResidentCompiler { /// point that is used for recompilation. /// Binary file name is returned if compilation was successful, otherwise /// null is returned. - Future recompile(Uri mainUri, List invalidatedFiles, - {@required String outputPath, - @required PackageConfig packageConfig}) async { - assert(outputPath != null); + Future recompile( + Uri mainUri, + List invalidatedFiles, { + required String outputPath, + required PackageConfig packageConfig, + }) async { if (!_controller.hasListener) { _controller.stream.listen(_handleCompilationRequest); } - var completer = Completer(); + var completer = Completer(); _controller.add(_RecompileRequest( completer, mainUri, invalidatedFiles, outputPath, packageConfig)); return completer.future; } - Future _recompile(_RecompileRequest request) async { + Future _recompile(_RecompileRequest request) async { _stdoutHandler.reset(); - final mainUri = - request.packageConfig.toPackageUri(request.mainUri)?.toString() ?? - toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots); + final mainUri = request.packageConfig + .toPackageUri(request.mainUri) + ?.toString() ?? + _toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots); _compileRequestNeedsConfirmation = true; if (_server == null) { return _compile(mainUri, request.outputPath); } + var server = _server!; var inputKey = Uuid().generateV4(); - _server.stdin.writeln('recompile $mainUri$inputKey'); + server.stdin.writeln('recompile $mainUri$inputKey'); _logger.info('<- recompile $mainUri$inputKey'); for (var fileUri in request.invalidatedFiles) { String message; @@ -324,12 +326,12 @@ class ResidentCompiler { message = fileUri.toString(); } else { message = request.packageConfig.toPackageUri(fileUri)?.toString() ?? - toMultiRootPath(fileUri, fileSystemScheme, fileSystemRoots); + _toMultiRootPath(fileUri, fileSystemScheme, fileSystemRoots); } - _server.stdin.writeln(message); + server.stdin.writeln(message); _logger.info(message); } - _server.stdin.writeln(inputKey); + server.stdin.writeln(inputKey); _logger.info('<- $inputKey'); return _stdoutHandler.compilerOutput.future; @@ -352,7 +354,7 @@ class ResidentCompiler { } } - Future _compile( + Future _compile( String scriptUri, String outputFilePath) async { var frontendServer = frontendServerExecutable; var args = [ @@ -364,20 +366,19 @@ class ResidentCompiler { '-Ddart.developer.causal_async_stacks=true', '--output-dill', outputFilePath, - if (packageConfigFile != null) ...[ + ...[ '--packages', '$packageConfigFile', ], - if (fileSystemRoots != null) - for (final root in fileSystemRoots) ...[ - '--filesystem-root', - '$root', - ], - if (fileSystemScheme != null) ...[ + for (final root in fileSystemRoots) ...[ + '--filesystem-root', + '$root', + ], + ...[ '--filesystem-scheme', fileSystemScheme, ], - if (platformDill != null) ...[ + ...[ '--platform', platformDill, ], @@ -390,7 +391,9 @@ class ResidentCompiler { final workingDirectory = projectDirectory.toFilePath(); _server = await Process.start(Platform.resolvedExecutable, args, workingDirectory: workingDirectory); - _server.stdout + + var server = _server!; + server.stdout .transform(utf8.decoder) .transform(const LineSplitter()) .listen(_stdoutHandler.handler, onDone: () { @@ -402,25 +405,25 @@ class ResidentCompiler { } }); - _server.stderr + server.stderr .transform(utf8.decoder) .transform(const LineSplitter()) .listen(_logger.info); - unawaited(_server.exitCode.then((int code) { + unawaited(server.exitCode.then((int code) { if (code != 0) { throw Exception('the Dart compiler exited unexpectedly.'); } })); - _server.stdin.writeln('compile $scriptUri'); + server.stdin.writeln('compile $scriptUri'); _logger.info('<- compile $scriptUri'); return _stdoutHandler.compilerOutput.future; } /// Compile dart expression to kernel. - Future compileExpression( + Future compileExpression( String expression, List definitions, List typeDefinitions, @@ -432,13 +435,13 @@ class ResidentCompiler { _controller.stream.listen(_handleCompilationRequest); } - var completer = Completer(); + var completer = Completer(); _controller.add(_CompileExpressionRequest(completer, expression, definitions, typeDefinitions, libraryUri, klass, isStatic)); return completer.future; } - Future _compileExpression( + Future _compileExpression( _CompileExpressionRequest request) async { _stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false); @@ -447,23 +450,24 @@ class ResidentCompiler { if (_server == null) { return null; } + var server = _server!; var inputKey = Uuid().generateV4(); - _server.stdin.writeln('compile-expression $inputKey'); - _server.stdin.writeln(request.expression); - request.definitions?.forEach(_server.stdin.writeln); - _server.stdin.writeln(inputKey); - request.typeDefinitions?.forEach(_server.stdin.writeln); - _server.stdin.writeln(inputKey); - _server.stdin.writeln(request.libraryUri ?? ''); - _server.stdin.writeln(request.klass ?? ''); - _server.stdin.writeln(request.isStatic ?? false); + server.stdin.writeln('compile-expression $inputKey'); + server.stdin.writeln(request.expression); + request.definitions.forEach(server.stdin.writeln); + server.stdin.writeln(inputKey); + request.typeDefinitions.forEach(server.stdin.writeln); + server.stdin.writeln(inputKey); + server.stdin.writeln(request.libraryUri ?? ''); + server.stdin.writeln(request.klass ?? ''); + server.stdin.writeln(request.isStatic ?? false); return _stdoutHandler.compilerOutput.future; } /// Compiles dart expression to JavaScript. - Future compileExpressionToJs( + Future compileExpressionToJs( String libraryUri, int line, int column, @@ -475,13 +479,13 @@ class ResidentCompiler { _controller.stream.listen(_handleCompilationRequest); } - var completer = Completer(); + var completer = Completer(); _controller.add(_CompileExpressionToJsRequest(completer, libraryUri, line, column, jsModules, jsFrameValues, moduleName, expression)); return completer.future; } - Future _compileExpressionToJs( + Future _compileExpressionToJs( _CompileExpressionToJsRequest request) async { _stdoutHandler.reset( suppressCompilerMessages: !verbose, expectSources: false); @@ -491,22 +495,23 @@ class ResidentCompiler { if (_server == null) { return null; } + var server = _server!; var inputKey = Uuid().generateV4(); - _server.stdin.writeln('compile-expression-to-js $inputKey'); - _server.stdin.writeln(request.libraryUri ?? ''); - _server.stdin.writeln(request.line); - _server.stdin.writeln(request.column); - request.jsModules?.forEach((k, v) { - _server.stdin.writeln('$k:$v'); + server.stdin.writeln('compile-expression-to-js $inputKey'); + server.stdin.writeln(request.libraryUri); + server.stdin.writeln(request.line); + server.stdin.writeln(request.column); + request.jsModules.forEach((k, v) { + server.stdin.writeln('$k:$v'); }); - _server.stdin.writeln(inputKey); - request.jsFrameValues?.forEach((k, v) { - _server.stdin.writeln('$k:$v'); + server.stdin.writeln(inputKey); + request.jsFrameValues.forEach((k, v) { + server.stdin.writeln('$k:$v'); }); - _server.stdin.writeln(inputKey); - _server.stdin.writeln(request.moduleName ?? ''); - _server.stdin.writeln(request.expression ?? ''); + server.stdin.writeln(inputKey); + server.stdin.writeln(request.moduleName); + server.stdin.writeln(request.expression); return _stdoutHandler.compilerOutput.future; } @@ -516,7 +521,7 @@ class ResidentCompiler { /// Either [accept] or [reject] should be called after every [recompile] call. void accept() { if (_compileRequestNeedsConfirmation) { - _server.stdin.writeln('accept'); + _server!.stdin.writeln('accept'); _logger.info('<- accept'); } _compileRequestNeedsConfirmation = false; @@ -525,22 +530,22 @@ class ResidentCompiler { /// Should be invoked when results of compilation are rejected by the client. /// /// Either [accept] or [reject] should be called after every [recompile] call. - Future reject() { + Future reject() { if (!_controller.hasListener) { _controller.stream.listen(_handleCompilationRequest); } - var completer = Completer(); + var completer = Completer(); _controller.add(_RejectRequest(completer)); return completer.future; } - Future _reject() { + Future _reject() { if (!_compileRequestNeedsConfirmation) { - return Future.value(null); + return Future.value(null); } _stdoutHandler.reset(expectSources: false); - _server.stdin.writeln('reject'); + _server!.stdin.writeln('reject'); _logger.info('<- reject'); _compileRequestNeedsConfirmation = false; return _stdoutHandler.compilerOutput.future; @@ -550,14 +555,21 @@ class ResidentCompiler { /// accepted previously so that next call to [recompile] produces complete /// kernel file. void reset() { - _server?.stdin?.writeln('reset'); + // TODO(annagrin): make sure this works when we support hot restart in + // tests using frontend server - for example, throw an error if the + // server is not available. + _server?.stdin.writeln('reset'); _logger.info('<- reset'); } Future quit() async { - _server.stdin.writeln('quit'); + _server?.stdin.writeln('quit'); _logger.info('<- quit'); - return _server.exitCode; + + if (_server == null) { + return 0; + } + return _server!.exitCode; } /// stop the service normally @@ -575,9 +587,10 @@ class ResidentCompiler { return 0; } - _logger.info('killing pid ${_server.pid}'); - _server.kill(); - return _server.exitCode; + var server = _server!; + _logger.info('killing pid ${server.pid}'); + server.kill(); + return server.exitCode; } } @@ -598,7 +611,7 @@ class TestExpressionCompiler implements ExpressionCompiler { var compilerOutput = await _generator.compileExpressionToJs(libraryUri, line, column, jsModules, jsFrameValues, moduleName, expression); - if (compilerOutput != null && compilerOutput.outputFilename != null) { + if (compilerOutput != null) { var content = utf8.decode( fileSystem.file(compilerOutput.outputFilename).readAsBytesSync()); return ExpressionCompilationResult( @@ -614,13 +627,13 @@ class TestExpressionCompiler implements ExpressionCompiler { @override Future initialize( - {String moduleFormat, bool soundNullSafety = false}) async {} + {required String moduleFormat, bool soundNullSafety = false}) async {} } /// Convert a file URI into a multi-root scheme URI if provided, otherwise /// return unmodified. -@visibleForTesting -String toMultiRootPath(Uri fileUri, String scheme, List fileSystemRoots) { +String _toMultiRootPath( + Uri fileUri, String? scheme, List fileSystemRoots) { if (scheme == null || fileSystemRoots.isEmpty || fileUri.scheme != 'file') { return fileUri.toString(); } diff --git a/frontend_server_common/lib/src/resident_runner.dart b/frontend_server_common/lib/src/resident_runner.dart index a49866fb9..e9609c554 100644 --- a/frontend_server_common/lib/src/resident_runner.dart +++ b/frontend_server_common/lib/src/resident_runner.dart @@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.9 - // Note: this is a copy from flutter tools, updated to work with dwds tests, // and some functionality remioved (does not support hot reload yet) import 'dart:async'; -import 'package:dwds/dwds.dart'; +import 'package:dwds/asset_reader.dart'; +import 'package:dwds/expression_compiler.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; @@ -57,18 +56,16 @@ class ResidentWebRunner { final String fileSystemScheme; final bool soundNullSafety; - ResidentCompiler generator; - ExpressionCompiler expressionCompiler; - WebDevFS devFS; - Uri uri; - Iterable modules; - - Future run(String hostname, int port, String index) async { - hostname ??= 'localhost'; + late ResidentCompiler generator; + late ExpressionCompiler expressionCompiler; + late WebDevFS devFS; + late Uri uri; + late Iterable modules; + Future run(String? hostname, int port, String index) async { devFS = WebDevFS( fileSystem: fileSystem, - hostname: hostname, + hostname: hostname ?? 'localhost', port: port, projectDirectory: projectDirectory, packageConfigFile: packageConfigFile, @@ -84,7 +81,7 @@ class ResidentWebRunner { return 1; } - modules = report.invalidatedModules; + modules = report.invalidatedModules!; generator.accept(); return 0; diff --git a/frontend_server_common/lib/src/utilities.dart b/frontend_server_common/lib/src/utilities.dart index 801cc600b..859ab8ad8 100644 --- a/frontend_server_common/lib/src/utilities.dart +++ b/frontend_server_common/lib/src/utilities.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:io'; import 'package:file/file.dart' as fs;