| // Copyright (c) 2020, 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. |
| |
| // @dart = 2.9 |
| |
| import 'dart:async'; |
| import 'dart:convert'; |
| import 'dart:io' show Directory, File, Platform, Process, stderr, stdout; |
| import 'dart:isolate'; |
| |
| import 'package:build_integration/file_system/multi_root.dart'; |
| import 'package:dev_compiler/src/kernel/expression_compiler_worker.dart'; |
| import 'package:front_end/src/api_prototype/standard_file_system.dart'; |
| import 'package:front_end/src/compute_platform_binaries_location.dart'; |
| import 'package:path/path.dart' as p; |
| import 'package:pedantic/pedantic.dart'; |
| import 'package:test/test.dart'; |
| |
| /// Verbose mode for debugging |
| bool get verbose => false; |
| |
| class ModuleConfiguration { |
| final Uri root; |
| final String outputDir; |
| final String libraryUri; |
| final String moduleName; |
| final String jsFileName; |
| final String fullDillFileName; |
| final String summaryDillFileName; |
| |
| ModuleConfiguration( |
| {this.root, |
| this.outputDir, |
| this.moduleName, |
| this.libraryUri, |
| this.jsFileName, |
| this.fullDillFileName, |
| this.summaryDillFileName}); |
| |
| Uri get jsPath => root.resolve('$outputDir/$jsFileName'); |
| Uri get fullDillPath => root.resolve('$outputDir/$fullDillFileName'); |
| Uri get summaryDillPath => root.resolve('$outputDir/$summaryDillFileName'); |
| } |
| |
| class TestProjectConfiguration { |
| final Directory rootDirectory; |
| final String outputDir = 'out'; |
| final bool soundNullSafety; |
| final String moduleFormat; |
| |
| TestProjectConfiguration( |
| this.rootDirectory, this.soundNullSafety, this.moduleFormat); |
| |
| ModuleConfiguration get mainModule => ModuleConfiguration( |
| root: root, |
| outputDir: outputDir, |
| moduleName: 'packages/_testPackage/main', |
| libraryUri: 'org-dartlang-app:/lib/main.dart', |
| jsFileName: 'main.js', |
| fullDillFileName: 'main.full.dill', |
| summaryDillFileName: 'main.dill'); |
| |
| ModuleConfiguration get testModule => ModuleConfiguration( |
| root: root, |
| outputDir: outputDir, |
| moduleName: 'packages/_testPackage/test_library', |
| libraryUri: 'package:_testPackage/test_library.dart', |
| jsFileName: 'test_library.js', |
| fullDillFileName: 'test_library.full.dill', |
| summaryDillFileName: 'test_library.dill'); |
| |
| // TODO(annagrin): E.g. this module should have a file included that's not |
| // directly reachable from the libraryUri (i.e. where "too much" has been |
| // bundled). |
| ModuleConfiguration get testModule2 => ModuleConfiguration( |
| root: root, |
| outputDir: outputDir, |
| moduleName: 'packages/_testPackage/test_library2', |
| libraryUri: 'package:_testPackage/test_library2.dart', |
| jsFileName: 'test_library2.js', |
| fullDillFileName: 'test_library2.full.dill', |
| summaryDillFileName: 'test_library2.dill'); |
| |
| ModuleConfiguration get testModule3 => ModuleConfiguration( |
| root: root, |
| outputDir: outputDir, |
| moduleName: 'packages/_testPackage/test_library3', |
| libraryUri: 'package:_testPackage/test_library3.dart', |
| jsFileName: 'test_library3.js', |
| fullDillFileName: 'test_library3.full.dill', |
| summaryDillFileName: 'test_library3.dill'); |
| |
| String get rootPath => rootDirectory.path; |
| Uri get root => rootDirectory.uri; |
| Uri get outputPath => root.resolve(outputDir); |
| Uri get packagesPath => root.resolve('package_config.json'); |
| |
| Uri get sdkRoot => computePlatformBinariesLocation(); |
| Uri get sdkSummaryPath => soundNullSafety |
| ? sdkRoot.resolve('ddc_outline_sound.dill') |
| : sdkRoot.resolve('ddc_sdk.dill'); |
| Uri get librariesPath => sdkRoot.resolve('lib/libraries.json'); |
| |
| void createTestProject() { |
| var pubspec = root.resolve('pubspec.yaml'); |
| File.fromUri(pubspec) |
| ..createSync() |
| ..writeAsStringSync(''' |
| name: _testPackage |
| version: 1.0.0 |
| |
| environment: |
| sdk: '>=2.8.0 <3.0.0' |
| '''); |
| |
| File.fromUri(packagesPath) |
| ..createSync() |
| ..writeAsStringSync(''' |
| { |
| "configVersion": 2, |
| "packages": [ |
| { |
| "name": "_testPackage", |
| "rootUri": "./lib", |
| "packageUri": "./" |
| } |
| ] |
| } |
| '''); |
| |
| var main = root.resolve('lib/main.dart'); |
| File.fromUri(main) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(''' |
| |
| import 'package:_testPackage/test_library.dart'; |
| import 'package:_testPackage/test_library3.dart'; |
| |
| var global = 0; |
| |
| void main() { |
| var count = 0; |
| // line 9 |
| print('Global is: \${++global}'); |
| print('Count is: \${++count}'); |
| |
| B b = new B(); |
| } |
| |
| extension NumberParsing on String { |
| int parseInt() { |
| var ret = int.parse(this); |
| // line 19 |
| return ret; |
| } |
| } |
| |
| void linkToImports() { |
| testLibraryFunction(42); |
| testLibraryFunction3(42); |
| } |
| '''); |
| |
| var testLibrary = root.resolve('lib/test_library.dart'); |
| File.fromUri(testLibrary) |
| ..createSync() |
| ..writeAsStringSync(''' |
| |
| import 'package:_testPackage/test_library2.dart'; |
| |
| int testLibraryFunction(int formal) { |
| return formal; // line 5 |
| } |
| |
| int callLibraryFunction2(int formal) { |
| return testLibraryFunction2(formal); // line 9 |
| } |
| |
| class B { |
| C c() => new C(); |
| void printNumber() { |
| print(c().getNumber() + 1); |
| } |
| } |
| '''); |
| |
| var testLibrary2 = root.resolve('lib/test_library2.dart'); |
| File.fromUri(testLibrary2) |
| ..createSync() |
| ..writeAsStringSync(''' |
| |
| int testLibraryFunction2(int formal) { |
| return formal; // line 3 |
| } |
| |
| class C { |
| int getNumber() => 42; |
| } |
| '''); |
| |
| var testLibrary3 = root.resolve('lib/test_library3.dart'); |
| File.fromUri(testLibrary3) |
| ..createSync() |
| ..writeAsStringSync(''' |
| |
| int testLibraryFunction3(int formal) { |
| return formal; // line 3 |
| } |
| '''); |
| } |
| } |
| |
| void main() async { |
| for (var moduleFormat in ['amd', 'ddc']) { |
| group('$moduleFormat module format -', () { |
| for (var soundNullSafety in [true, false]) { |
| group('${soundNullSafety ? "sound" : "unsound"} null safety -', () { |
| group('expression compiler worker on startup', () { |
| Directory tempDir; |
| ReceivePort receivePort; |
| |
| setUp(() async { |
| tempDir = Directory.systemTemp.createTempSync('foo bar'); |
| receivePort = ReceivePort(); |
| }); |
| |
| tearDown(() async { |
| tempDir.deleteSync(recursive: true); |
| receivePort.close(); |
| }); |
| |
| test('reports failure to consumer', () async { |
| expect( |
| receivePort, |
| emitsInOrder([ |
| equals(isA<SendPort>()), |
| equals({ |
| 'succeeded': false, |
| 'stackTrace': isNotNull, |
| 'exception': contains('Could not load SDK component'), |
| }), |
| ])); |
| |
| try { |
| var badPath = 'file:///path/does/not/exist'; |
| await ExpressionCompilerWorker.createAndStart( |
| [ |
| '--libraries-file', |
| badPath, |
| '--dart-sdk-summary', |
| badPath, |
| '--module-format', |
| moduleFormat, |
| soundNullSafety |
| ? '--sound-null-safety' |
| : '--no-sound-null-safety', |
| if (verbose) '--verbose', |
| ], |
| sendPort: receivePort.sendPort, |
| ); |
| } catch (e) { |
| throwsA(contains('Could not load SDK component')); |
| } |
| }); |
| }); |
| |
| for (var summarySupport in [true, false]) { |
| group('${summarySupport ? "" : "no "}debugger summary support -', |
| () { |
| group('expression compiler worker', () { |
| ExpressionCompilerWorker worker; |
| Future workerDone; |
| StreamController<Map<String, dynamic>> requestController; |
| StreamController<Map<String, dynamic>> responseController; |
| Directory tempDir; |
| TestProjectConfiguration config; |
| List inputs; |
| |
| setUpAll(() async { |
| tempDir = Directory.systemTemp.createTempSync('foo bar'); |
| config = TestProjectConfiguration( |
| tempDir, soundNullSafety, moduleFormat); |
| |
| // simulate webdev |
| config.createTestProject(); |
| var kernelGenerator = DDCKernelGenerator(config); |
| await kernelGenerator.generate(); |
| |
| inputs = [ |
| { |
| 'path': config.mainModule.fullDillPath.path, |
| if (summarySupport) |
| 'summaryPath': config.mainModule.summaryDillPath.path, |
| 'moduleName': config.mainModule.moduleName |
| }, |
| { |
| 'path': config.testModule.fullDillPath.path, |
| if (summarySupport) |
| 'summaryPath': config.testModule.summaryDillPath.path, |
| 'moduleName': config.testModule.moduleName |
| }, |
| { |
| 'path': config.testModule2.fullDillPath.path, |
| if (summarySupport) |
| 'summaryPath': config.testModule2.summaryDillPath.path, |
| 'moduleName': config.testModule2.moduleName |
| }, |
| { |
| 'path': config.testModule3.fullDillPath.path, |
| if (summarySupport) |
| 'summaryPath': config.testModule3.summaryDillPath.path, |
| 'moduleName': config.testModule3.moduleName |
| }, |
| ]; |
| }); |
| |
| tearDownAll(() async { |
| tempDir.deleteSync(recursive: true); |
| }); |
| |
| setUp(() async { |
| var fileSystem = MultiRootFileSystem('org-dartlang-app', |
| [tempDir.uri], StandardFileSystem.instance); |
| |
| requestController = StreamController<Map<String, dynamic>>(); |
| responseController = StreamController<Map<String, dynamic>>(); |
| worker = await ExpressionCompilerWorker.create( |
| librariesSpecificationUri: config.librariesPath, |
| // We should be able to load everything from dill and not |
| // require source parsing. Webdev and google3 integration |
| // currently rely on that. Make the test fail on source |
| // reading by not providing a packages file. |
| packagesFile: null, |
| sdkSummary: config.sdkSummaryPath, |
| fileSystem: fileSystem, |
| requestStream: requestController.stream, |
| sendResponse: responseController.add, |
| soundNullSafety: soundNullSafety, |
| verbose: verbose, |
| ); |
| workerDone = worker.start(); |
| }); |
| |
| tearDown(() async { |
| unawaited(requestController.close()); |
| await workerDone; |
| unawaited(responseController.close()); |
| }); |
| |
| test('can compile expressions in sdk', () async { |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'other', |
| 'line': 107, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'other': 'other'}, |
| 'libraryUri': 'dart:collection', |
| 'moduleName': 'dart_sdk', |
| }); |
| |
| expect( |
| responseController.stream, |
| emitsInOrder([ |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return other;'), |
| }) |
| ])); |
| }, skip: 'Evaluating expressions in SDK is not supported yet'); |
| |
| test('can compile expressions in a library', () async { |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'formal', |
| 'line': 5, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'formal': 'formal'}, |
| 'libraryUri': config.testModule.libraryUri, |
| 'moduleName': config.testModule.moduleName, |
| }); |
| |
| expect( |
| responseController.stream, |
| emitsInOrder([ |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return formal;'), |
| }) |
| ])); |
| }); |
| |
| test('can compile expressions in main', () async { |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'count', |
| 'line': 9, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'count': 'count'}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| expect( |
| responseController.stream, |
| emitsInOrder([ |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return count;'), |
| }) |
| ])); |
| }); |
| |
| test('can compile expressions in main (extension method)', |
| () async { |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'ret', |
| 'line': 19, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'ret': 'ret'}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| expect( |
| responseController.stream, |
| emitsInOrder([ |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return ret;'), |
| }) |
| ])); |
| }); |
| |
| test('can compile transitive expressions in main', () async { |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'B().c().getNumber()', |
| 'line': 9, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| expect( |
| responseController.stream, |
| emitsInOrder([ |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains( |
| 'new test_library.B.new().c().getNumber()'), |
| }) |
| ])); |
| }); |
| |
| test('can compile series of expressions in various libraries', |
| () async { |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'B().c().getNumber()', |
| 'line': 8, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'formal', |
| 'line': 5, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'formal': 'formal'}, |
| 'libraryUri': config.testModule.libraryUri, |
| 'moduleName': config.testModule.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'formal', |
| 'line': 3, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'formal': 'formal'}, |
| 'libraryUri': config.testModule2.libraryUri, |
| 'moduleName': config.testModule2.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'formal', |
| 'line': 3, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'formal': 'formal'}, |
| 'libraryUri': config.testModule3.libraryUri, |
| 'moduleName': config.testModule3.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'B().printNumber()', |
| 'line': 9, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| expect( |
| responseController.stream, |
| emitsInOrder([ |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains( |
| 'new test_library.B.new().c().getNumber()'), |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return formal;'), |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return formal;'), |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return formal;'), |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': |
| contains('test_library.B.new().printNumber()'), |
| }) |
| ])); |
| }); |
| |
| test('can compile after dependency update', () async { |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'B().c().getNumber()', |
| 'line': 8, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'formal', |
| 'line': 5, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'formal': 'formal'}, |
| 'libraryUri': config.testModule.libraryUri, |
| 'moduleName': config.testModule.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'B().printNumber()', |
| 'line': 9, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'UpdateDeps', |
| 'inputs': inputs, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'B().c().getNumber()', |
| 'line': 8, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {}, |
| 'libraryUri': config.mainModule.libraryUri, |
| 'moduleName': config.mainModule.moduleName, |
| }); |
| |
| requestController.add({ |
| 'command': 'CompileExpression', |
| 'expression': 'formal', |
| 'line': 3, |
| 'column': 1, |
| 'jsModules': {}, |
| 'jsScope': {'formal': 'formal'}, |
| 'libraryUri': config.testModule3.libraryUri, |
| 'moduleName': config.testModule3.moduleName, |
| }); |
| |
| expect( |
| responseController.stream, |
| emitsInOrder([ |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains( |
| 'new test_library.B.new().c().getNumber()'), |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return formal;'), |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': |
| contains('test_library.B.new().printNumber()'), |
| }), |
| equals({ |
| 'succeeded': true, |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains( |
| 'new test_library.B.new().c().getNumber()'), |
| }), |
| equals({ |
| 'succeeded': true, |
| 'errors': isEmpty, |
| 'warnings': isEmpty, |
| 'infos': isEmpty, |
| 'compiledProcedure': contains('return formal;'), |
| }), |
| ])); |
| }); |
| }); |
| }); |
| } |
| }); |
| } |
| }); |
| } |
| } |
| |
| /// Uses DDC to generate kernel from the test code |
| /// in order to simulate webdev environment |
| class DDCKernelGenerator { |
| final TestProjectConfiguration config; |
| |
| DDCKernelGenerator(this.config); |
| |
| Future<int> generate() async { |
| var dart = Platform.resolvedExecutable; |
| var dartdevc = |
| p.join(p.dirname(dart), 'snapshots', 'dartdevc.dart.snapshot'); |
| |
| Directory.fromUri(config.outputPath).createSync(); |
| |
| // generate test_library3.full.dill |
| var args = [ |
| dartdevc, |
| config.testModule3.libraryUri, |
| '-o', |
| config.testModule3.jsPath.toFilePath(), |
| '--source-map', |
| '--experimental-emit-debug-metadata', |
| '--emit-debug-symbols', |
| '--experimental-output-compiled-kernel', |
| '--dart-sdk-summary', |
| config.sdkSummaryPath.path, |
| '--multi-root', |
| '${config.root}', |
| '--multi-root-scheme', |
| 'org-dartlang-app', |
| '--packages', |
| config.packagesPath.path, |
| if (config.soundNullSafety) '--sound-null-safety', |
| if (!config.soundNullSafety) '--no-sound-null-safety', |
| '--modules', |
| '${config.moduleFormat}', |
| ]; |
| |
| var exitCode = await runProcess(dart, args, config.rootPath); |
| if (exitCode != 0) { |
| return exitCode; |
| } |
| |
| // generate test_library2.full.dill |
| args = [ |
| dartdevc, |
| config.testModule2.libraryUri, |
| '-o', |
| config.testModule2.jsPath.toFilePath(), |
| '--source-map', |
| '--experimental-emit-debug-metadata', |
| '--emit-debug-symbols', |
| '--experimental-output-compiled-kernel', |
| '--dart-sdk-summary', |
| config.sdkSummaryPath.path, |
| '--multi-root', |
| '${config.root}', |
| '--multi-root-scheme', |
| 'org-dartlang-app', |
| '--packages', |
| config.packagesPath.path, |
| if (config.soundNullSafety) '--sound-null-safety', |
| if (!config.soundNullSafety) '--no-sound-null-safety', |
| '--modules', |
| '${config.moduleFormat}', |
| ]; |
| |
| exitCode = await runProcess(dart, args, config.rootPath); |
| if (exitCode != 0) { |
| return exitCode; |
| } |
| |
| // generate test_library.full.dill |
| args = [ |
| dartdevc, |
| config.testModule.libraryUri, |
| '--summary', |
| '${config.testModule2.summaryDillPath}=${config.testModule2.moduleName}', |
| '-o', |
| config.testModule.jsPath.toFilePath(), |
| '--source-map', |
| '--experimental-emit-debug-metadata', |
| '--emit-debug-symbols', |
| '--experimental-output-compiled-kernel', |
| '--dart-sdk-summary', |
| config.sdkSummaryPath.path, |
| '--multi-root', |
| '${config.root}', |
| '--multi-root-scheme', |
| 'org-dartlang-app', |
| '--packages', |
| config.packagesPath.path, |
| if (config.soundNullSafety) '--sound-null-safety', |
| if (!config.soundNullSafety) '--no-sound-null-safety', |
| '--modules', |
| '${config.moduleFormat}', |
| ]; |
| |
| exitCode = await runProcess(dart, args, config.rootPath); |
| if (exitCode != 0) { |
| return exitCode; |
| } |
| |
| // generate main.full.dill |
| args = [ |
| dartdevc, |
| config.mainModule.libraryUri, |
| '--summary', |
| '${config.testModule3.summaryDillPath}=${config.testModule3.moduleName}', |
| '--summary', |
| '${config.testModule.summaryDillPath}=${config.testModule.moduleName}', |
| '-o', |
| config.mainModule.jsPath.toFilePath(), |
| '--source-map', |
| '--experimental-emit-debug-metadata', |
| '--emit-debug-symbols', |
| '--experimental-output-compiled-kernel', |
| '--dart-sdk-summary', |
| config.sdkSummaryPath.path, |
| '--multi-root', |
| '${config.root}', |
| '--multi-root-scheme', |
| 'org-dartlang-app', |
| '--packages', |
| config.packagesPath.toFilePath(), |
| if (config.soundNullSafety) '--sound-null-safety', |
| if (!config.soundNullSafety) '--no-sound-null-safety', |
| '--modules', |
| '${config.moduleFormat}', |
| ]; |
| |
| return await runProcess(dart, args, config.rootPath); |
| } |
| } |
| |
| Future<int> runProcess( |
| String command, List<String> args, String workingDirectory) async { |
| if (verbose) { |
| print('Running command in $workingDirectory:' |
| '\n\t $command ${args.join(' ')}, '); |
| } |
| var process = |
| await Process.start(command, args, workingDirectory: workingDirectory) |
| .then((Process process) { |
| process |
| ..stdout.transform(utf8.decoder).listen(stdout.write) |
| ..stderr.transform(utf8.decoder).listen(stderr.write); |
| return process; |
| }); |
| |
| return await process.exitCode; |
| } |