diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart index 139e55783a8..2c45796c20f 100644 --- a/pkg/frontend_server/lib/frontend_server.dart +++ b/pkg/frontend_server/lib/frontend_server.dart @@ -10,7 +10,11 @@ import 'dart:io' hide FileSystemEntity; import 'package:args/args.dart'; import 'package:dev_compiler/dev_compiler.dart' - show DevCompilerTarget, ExpressionCompiler, parseModuleFormat; + show + DevCompilerTarget, + ExpressionCompiler, + parseModuleFormat, + ProgramCompiler; // front_end/src imports below that require lint `ignore_for_file` // are a temporary state of things until frontend team builds better api @@ -631,7 +635,7 @@ class FrontendCompiler implements CompilerInterface { final sourceMapsFileSink = sourceMapsFile.openWrite(); final metadataFileSink = emitDebugMetadata ? metadataFile.openWrite() : null; - await _bundler.compile( + final kernel2JsCompilers = await _bundler.compile( results.classHierarchy, results.coreTypes, results.loadedLibraries, @@ -639,6 +643,7 @@ class FrontendCompiler implements CompilerInterface { manifestFileSink, sourceMapsFileSink, metadataFileSink); + cachedProgramCompilers.addAll(kernel2JsCompilers); await Future.wait([ sourceFileSink.close(), manifestFileSink.close(), @@ -806,6 +811,12 @@ class FrontendCompiler implements CompilerInterface { } } + /// Program compilers per module. + /// + /// Produced suring initial compilation of the module to JavaScript, + /// cached to be used for expression compilation in [compileExpressionToJs]. + final Map cachedProgramCompilers = {}; + @override Future compileExpressionToJs( String libraryUri, @@ -822,7 +833,7 @@ class FrontendCompiler implements CompilerInterface { reportError('JavaScript bundler is null'); return; } - if (!_bundler.compilers.containsKey(moduleName)) { + if (!cachedProgramCompilers.containsKey(moduleName)) { reportError('Cannot find kernel2js compiler for $moduleName.'); return; } @@ -833,13 +844,13 @@ class FrontendCompiler implements CompilerInterface { _processedOptions.ticker .logMs('Compiling expression to JavaScript in $moduleName'); - var kernel2jsCompiler = _bundler.compilers[moduleName]; + final kernel2jsCompiler = cachedProgramCompilers[moduleName]; Component component = _generator.lastKnownGoodComponent; component.computeCanonicalNames(); _processedOptions.ticker.logMs('Computed component'); - var expressionCompiler = new ExpressionCompiler( + final expressionCompiler = new ExpressionCompiler( _compilerOptions, parseModuleFormat(_options['dartdevc-module-format'] as String), errors, @@ -848,10 +859,10 @@ class FrontendCompiler implements CompilerInterface { component, ); - var procedure = await expressionCompiler.compileExpressionToJs( + final procedure = await expressionCompiler.compileExpressionToJs( libraryUri, line, column, jsFrameValues, expression); - var result = errors.length > 0 ? errors[0] : procedure; + final result = errors.length > 0 ? errors[0] : procedure; // TODO(annagrin): kernelBinaryFilename is too specific // rename to _outputFileName? diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart index 346b4d8d1e3..9829c5750b9 100644 --- a/pkg/frontend_server/lib/src/javascript_bundle.dart +++ b/pkg/frontend_server/lib/src/javascript_bundle.dart @@ -29,8 +29,7 @@ class JavaScriptBundler { this.emitDebugMetadata = false, this.soundNullSafety = false, String moduleFormat}) - : compilers = {}, - _moduleFormat = parseModuleFormat(moduleFormat ?? 'amd') { + : _moduleFormat = parseModuleFormat(moduleFormat ?? 'amd') { _summaries = []; _summaryUris = []; _moduleImportForSummary = {}; @@ -64,7 +63,6 @@ class JavaScriptBundler { final PackageConfig _packageConfig; final bool useDebuggerModuleNames; final bool emitDebugMetadata; - final Map compilers; final ModuleFormat _moduleFormat; final bool soundNullSafety; @@ -75,7 +73,7 @@ class JavaScriptBundler { Map _uriToComponent; /// Compile each component into a single JavaScript module. - Future compile( + Future> compile( ClassHierarchy classHierarchy, CoreTypes coreTypes, Set loadedLibraries, @@ -88,6 +86,7 @@ class JavaScriptBundler { var metadataOffset = 0; final manifest = >>{}; final Set visited = {}; + final Map kernel2JsCompilers = {}; final importToSummary = Map.identity(); final summaryToModule = Map.identity(); @@ -150,9 +149,8 @@ class JavaScriptBundler { // so it can map dart symbols to js symbols // [issue 40273](https://github.com/dart-lang/sdk/issues/40273) - // program compiler is used by ExpressionCompiler to evaluate expressions - // on demand - compilers[moduleName] = compiler; + // Save program compiler to reuse for expression evaluation. + kernel2JsCompilers[moduleName] = compiler; final moduleUrl = urlForComponentUri(moduleUri); String sourceMapBase; @@ -201,6 +199,8 @@ class JavaScriptBundler { }; } manifestSink.add(utf8.encode(json.encode(manifest))); + + return kernel2JsCompilers; } } diff --git a/pkg/frontend_server/test/src/javascript_bundle_test.dart b/pkg/frontend_server/test/src/javascript_bundle_test.dart index 26a7c21c734..02cd81322fe 100644 --- a/pkg/frontend_server/test/src/javascript_bundle_test.dart +++ b/pkg/frontend_server/test/src/javascript_bundle_test.dart @@ -106,8 +106,14 @@ void main() { final metadataSink = _MemorySink(); final coreTypes = CoreTypes(testComponent); - await javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes), - coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink); + final compilers = await javaScriptBundler.compile( + ClassHierarchy(testComponent, coreTypes), + coreTypes, + {}, + codeSink, + manifestSink, + sourcemapSink, + metadataSink); final Map manifest = json.decode(utf8.decode(manifestSink.buffer)); final String code = utf8.decode(codeSink.buffer); @@ -122,6 +128,9 @@ void main() { // verify source map url is correct. expect(code, contains('sourceMappingURL=c.dart.lib.js.map')); + + // verify program compilers are created. + expect(compilers.keys, equals([urlForComponentUri(library.importUri)])); }); test('converts package: uris into /packages/ uris', () async {