| // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | |
| // 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. | |
| import 'dart:convert' show jsonDecode, utf8; | |
| import 'dart:io' | |
| show Directory, File, FileSystemException, InternetAddress, Socket; | |
| import 'package:path/path.dart' as path; | |
| final class ResidentCompilerInfo { | |
| /// The SDK hash that kernel files compiled using the Resident Frontend | |
| /// Compiler associated with this object will be stamped with. | |
| final String? sdkHash; | |
| /// The address that the Resident Frontend Compiler associated with this | |
| /// object is listening from. | |
| final InternetAddress address; | |
| /// The port number that the Resident Frontend Compiler associated with this | |
| /// object is listening on. | |
| final int port; | |
| /// Extracts the value associated with a key from [entries], where [entries] | |
| /// is a [String] with the format '$key1:$value1 $key2:$value2 ...'. | |
| static String _extractValueAssociatedWithKey(String entries, String key) => | |
| new RegExp( | |
| '$key:' | |
| r'(\S+)(\s|$)', | |
| ).allMatches(entries).first[1]!; | |
| static ResidentCompilerInfo fromFile(File file) { | |
| final String fileContents = file.readAsStringSync(); | |
| return new ResidentCompilerInfo._( | |
| sdkHash: fileContents.contains('sdkHash:') | |
| ? _extractValueAssociatedWithKey(fileContents, 'sdkHash') | |
| : null, | |
| address: new InternetAddress( | |
| _extractValueAssociatedWithKey(fileContents, 'address'), | |
| ), | |
| port: int.parse(_extractValueAssociatedWithKey(fileContents, 'port')), | |
| ); | |
| } | |
| new _({required this.sdkHash, required this.port, required this.address}); | |
| } | |
| typedef CachedDillAndCompilerOptionsPaths = ({ | |
| String cachedDillPath, | |
| String cachedCompilerOptionsPath, | |
| }); | |
| /// Returns the absolute paths to the cached kernel file and the cached compiler | |
| /// options file associated with [canonicalizedLibraryPath]. | |
| CachedDillAndCompilerOptionsPaths computeCachedDillAndCompilerOptionsPaths( | |
| String canonicalizedLibraryPath, | |
| ) { | |
| final String dirname = path.dirname(canonicalizedLibraryPath); | |
| final String basename = path.basename(canonicalizedLibraryPath); | |
| final String cachedKernelDirectoryPath = path.join( | |
| path.join(Directory.systemTemp.path, 'dart_resident_compiler_kernel_cache'), | |
| dirname.replaceAll(new RegExp(r':|\\|\/'), '_'), | |
| ); | |
| try { | |
| new Directory(cachedKernelDirectoryPath).createSync(recursive: true); | |
| } catch (e) { | |
| throw new Exception( | |
| 'Failed to create directory for storing cached kernel files', | |
| ); | |
| } | |
| final String cachedDillPath = path.join( | |
| cachedKernelDirectoryPath, | |
| '$basename.dill', | |
| ); | |
| final String cachedCompilerOptionsPath = path.join( | |
| cachedKernelDirectoryPath, | |
| '${basename}_options.json', | |
| ); | |
| return ( | |
| cachedDillPath: cachedDillPath, | |
| cachedCompilerOptionsPath: cachedCompilerOptionsPath, | |
| ); | |
| } | |
| /// Sends a compilation [request] to the resident frontend compiler associated | |
| /// with [serverInfoFile], and returns the compiler's JSON response. | |
| /// | |
| /// Throws a [FileSystemException] if [serverInfoFile] cannot be accessed. | |
| Future<Map<String, Object?>> sendAndReceiveResponse( | |
| String request, | |
| File serverInfoFile, | |
| ) async { | |
| Socket? client; | |
| Map<String, Object?> jsonResponse; | |
| final ResidentCompilerInfo residentCompilerInfo = | |
| ResidentCompilerInfo.fromFile(serverInfoFile); | |
| try { | |
| client = await Socket.connect( | |
| residentCompilerInfo.address, | |
| residentCompilerInfo.port, | |
| ); | |
| client.write(request); | |
| final String data = utf8.decode(await client.first); | |
| jsonResponse = (jsonDecode(data) as Map<String, Object?>); | |
| } catch (e) { | |
| jsonResponse = <String, Object?>{ | |
| 'success': false, | |
| 'errorMessage': e.toString(), | |
| }; | |
| } | |
| client?.destroy(); | |
| return jsonResponse; | |
| } |