mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:19:49 +00:00
[ddc] Clean up expression compiler tests
- Allow running the tests with asserts enabled - Allow running the tests in canary mode - Unify common test code and remove duplication - merge expression_compiler/setup_compiler_options.dart into share_compiler_options.dart - Merge TestCompiler code from expression evaluation and expression compilation tests and move into expression_compiler/test_compiler.dart - Rename various TestDrivers so they have more descriptive names - Remove 'golden' JS comparison tests from expression_compiler_test.dart - replace by evaluation tests where needed Closes: https://github.com/dart-lang/sdk/issues/53145 Change-Id: Ic797fa4ee9bfa6b858b924be9f9a53fd10ae1448 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/318080 Commit-Queue: Anna Gringauze <annagrin@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
286e5761e3
commit
67d752aa12
|
@ -35,5 +35,4 @@ dev_dependencies:
|
||||||
stack_trace: any
|
stack_trace: any
|
||||||
test: any
|
test: any
|
||||||
testing: any
|
testing: any
|
||||||
vm: any
|
|
||||||
webkit_inspection_protocol: any
|
webkit_inspection_protocol: any
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
var setup = SetupCompilerOptions(args: args);
|
||||||
|
|
||||||
group('Assertions |', () {
|
group('Asserts', () {
|
||||||
const source = r'''
|
const source = r'''
|
||||||
void main() {
|
void main() {
|
||||||
var b = const bool.fromEnvironment('dart.web.assertions_enabled');
|
var b = const bool.fromEnvironment('dart.web.assertions_enabled');
|
||||||
|
@ -24,60 +25,66 @@ void main(List<String> args) async {
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
|
|
||||||
tearDown(() async {
|
setUpAll(() => driver.initSource(setup, source));
|
||||||
await driver.cleanupTest();
|
|
||||||
});
|
|
||||||
|
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
await driver.cleanupTest();
|
||||||
await driver.finish();
|
await driver.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('dart.web.assertions_enabled is set when asserts are enabled',
|
if (setup.enableAsserts) {
|
||||||
() async {
|
group('enabled |', () {
|
||||||
var setup = SetupCompilerOptions(args: args);
|
test('dart.web.assertions_enabled is set', () async {
|
||||||
await driver.initSource(setup, source);
|
await driver.check(
|
||||||
|
breakpointId: 'bp', expression: 'b', expectedResult: 'true');
|
||||||
|
});
|
||||||
|
|
||||||
await driver.check(
|
test('assert errors in the source code', () async {
|
||||||
breakpointId: 'bp',
|
await driver.check(
|
||||||
expression: 'b',
|
breakpointId: 'bp',
|
||||||
expectedResult: '${setup.enableAsserts}');
|
expression: 'myAssert()',
|
||||||
});
|
expectedResult: allOf(
|
||||||
|
|
||||||
test('assert errors in the source code when asserts are enabled', () async {
|
|
||||||
var setup = SetupCompilerOptions(args: args);
|
|
||||||
await driver.initSource(setup, source);
|
|
||||||
|
|
||||||
await driver.check(
|
|
||||||
breakpointId: 'bp',
|
|
||||||
expression: 'myAssert()',
|
|
||||||
expectedResult: setup.enableAsserts
|
|
||||||
? allOf(
|
|
||||||
contains('Error: Assertion failed:'),
|
contains('Error: Assertion failed:'),
|
||||||
contains('test.dart:8:16'),
|
contains('test.dart:8:16'),
|
||||||
contains('false'),
|
contains('false'),
|
||||||
contains('is not true'),
|
contains('is not true'),
|
||||||
)
|
));
|
||||||
: '0',
|
});
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('assert errors in evaluated expression when asserts are enabled',
|
test('assert errors in evaluated expression', () async {
|
||||||
() async {
|
await driver.check(
|
||||||
var setup = SetupCompilerOptions(args: args);
|
breakpointId: 'bp',
|
||||||
await driver.initSource(setup, source);
|
expression: '() { assert(false); return 0; } ()',
|
||||||
|
expectedResult: allOf(
|
||||||
await driver.check(
|
|
||||||
breakpointId: 'bp',
|
|
||||||
expression: '() { assert(false); return 0; } ()',
|
|
||||||
expectedResult: setup.enableAsserts
|
|
||||||
? allOf(
|
|
||||||
contains('Error: Assertion failed:'),
|
contains('Error: Assertion failed:'),
|
||||||
contains('<unknown source>:-1:-1'),
|
contains('<unknown source>:-1:-1'),
|
||||||
contains('BoolLiteral(false)'),
|
contains('BoolLiteral(false)'),
|
||||||
contains('is not true'),
|
contains('is not true'),
|
||||||
)
|
));
|
||||||
: '0',
|
});
|
||||||
);
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (!setup.enableAsserts) {
|
||||||
|
group('disabled |', () {
|
||||||
|
test('dart.web.assertions_enabled is not set', () async {
|
||||||
|
await driver.check(
|
||||||
|
breakpointId: 'bp', expression: 'b', expectedResult: 'false');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('no assert errors in the source code', () async {
|
||||||
|
await driver.check(
|
||||||
|
breakpointId: 'bp',
|
||||||
|
expression: 'myAssert()',
|
||||||
|
expectedResult: '0');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('no assert errors in evaluated expression', () async {
|
||||||
|
await driver.check(
|
||||||
|
breakpointId: 'bp',
|
||||||
|
expression: '() { assert(false); return 0; } ()',
|
||||||
|
expectedResult: '0');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,15 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
var setup = SetupCompilerOptions(args: args);
|
||||||
|
var mode = setup.canaryFeatures ? 'canary' : 'stable';
|
||||||
|
|
||||||
group('canary', () {
|
group('$mode mode', () {
|
||||||
const source = r'''
|
const source = r'''
|
||||||
void main() {
|
void main() {
|
||||||
print('hello world');
|
print('hello world');
|
||||||
|
@ -28,7 +30,6 @@ void main(List<String> args) async {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('is automatically set to the configuration value', () async {
|
test('is automatically set to the configuration value', () async {
|
||||||
var setup = SetupCompilerOptions(args: args);
|
|
||||||
await driver.initSource(setup, source);
|
await driver.initSource(setup, source);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Sound null safety) (Agnostic code shard 1)', () {
|
group('(Sound null safety) (Agnostic code shard 1)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Sound null safety) (Agnostic code shard 2)', () {
|
group('(Sound null safety) (Agnostic code shard 2)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Unsound null safety) (Agnostic code shard 1)', () {
|
group('(Unsound null safety) (Agnostic code shard 1)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Unsound null safety) (Agnostic code shard 2)', () {
|
group('(Unsound null safety) (Agnostic code shard 2)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Legacy code shard 1)', () {
|
group('(Legacy code shard 1)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Legacy code shard 2)', () {
|
group('(Legacy code shard 2)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,14 +6,14 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
// Set to `true` for debug output.
|
// Set to `true` for debug output.
|
||||||
final debug = false;
|
final debug = false;
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Sound null safety)', () {
|
group('(Sound null safety)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Unsound null safety)', () {
|
group('(Unsound null safety)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,11 +6,11 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('Dart 2.17 language features', () {
|
group('Dart 2.17 language features', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
@ -64,7 +64,8 @@ void main(List<String> args) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shared tests for language features introduced in version 2.17.0.
|
/// Shared tests for language features introduced in version 2.17.0.
|
||||||
void runSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
void runSharedTests(
|
||||||
|
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||||
group('Named arguments anywhere', () {
|
group('Named arguments anywhere', () {
|
||||||
var source = r'''
|
var source = r'''
|
||||||
String topLevelMethod(int param1, String param2,
|
String topLevelMethod(int param1, String param2,
|
||||||
|
|
|
@ -6,11 +6,11 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('Dart 3.0 language features', () {
|
group('Dart 3.0 language features', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
@ -64,7 +64,8 @@ void main(List<String> args) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shared tests for language features introduced in version 3.0.0.
|
/// Shared tests for language features introduced in version 3.0.0.
|
||||||
void runSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
void runSharedTests(
|
||||||
|
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||||
group('Records', () {
|
group('Records', () {
|
||||||
const recordsSource = '''
|
const recordsSource = '''
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Sound null safety) (Agnostic code shard 1)', () {
|
group('(Sound null safety) (Agnostic code shard 1)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Sound null safety) (Agnostic code shard 2)', () {
|
group('(Sound null safety) (Agnostic code shard 2)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Unsound null safety) (Agnostic code shard 1)', () {
|
group('(Unsound null safety) (Agnostic code shard 1)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Unsound null safety) (Agnostic code shard 2)', () {
|
group('(Unsound null safety) (Agnostic code shard 2)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Legacy code shard 1)', () {
|
group('(Legacy code shard 1)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Legacy code shard 2)', () {
|
group('(Legacy code shard 2)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Sound null safety)', () {
|
group('(Sound null safety)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_shared.dart';
|
import 'expression_compiler_e2e_shared.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
group('(Unsound null safety)', () {
|
group('(Unsound null safety)', () {
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
const simpleClassSource = '''
|
const simpleClassSource = '''
|
||||||
extension NumberParsing on String {
|
extension NumberParsing on String {
|
||||||
|
@ -64,7 +64,8 @@ main() {
|
||||||
/// Shared tests that require a language version >=2.12.0 <2.17.0.
|
/// Shared tests that require a language version >=2.12.0 <2.17.0.
|
||||||
// TODO(nshahan) Merge with [runAgnosticSharedTests] after we no longer need to
|
// TODO(nshahan) Merge with [runAgnosticSharedTests] after we no longer need to
|
||||||
// test support for evaluation in legacy (pre-null safety) code.
|
// test support for evaluation in legacy (pre-null safety) code.
|
||||||
void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
void runNullSafeSharedTests(
|
||||||
|
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||||
group('Exceptions', () {
|
group('Exceptions', () {
|
||||||
const exceptionSource = r'''
|
const exceptionSource = r'''
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -207,6 +208,17 @@ void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
||||||
expectedResult: 'test.C.new { Symbol(_unusedField): 4, '
|
expectedResult: 'test.C.new { Symbol(_unusedField): 4, '
|
||||||
'Symbol(C.field): 42, Symbol(_field): 0}');
|
'Symbol(C.field): 42, Symbol(_field): 0}');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('map access', () async {
|
||||||
|
await driver.check(
|
||||||
|
breakpointId: 'methodBP',
|
||||||
|
expression: '''
|
||||||
|
(Map<String, String> params) {
|
||||||
|
return params["a"];
|
||||||
|
}({"a":"b"})
|
||||||
|
''',
|
||||||
|
expectedResult: 'b');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('Expression compiler tests in global function:', () {
|
group('Expression compiler tests in global function:', () {
|
||||||
|
@ -470,7 +482,7 @@ void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
||||||
/// This group of tests has been sharded manually. The others are in
|
/// This group of tests has been sharded manually. The others are in
|
||||||
/// [runAgnosticSharedTestsShard2].
|
/// [runAgnosticSharedTestsShard2].
|
||||||
void runAgnosticSharedTestsShard1(
|
void runAgnosticSharedTestsShard1(
|
||||||
SetupCompilerOptions setup, TestDriver driver) {
|
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||||
group('Correct null safety mode used', () {
|
group('Correct null safety mode used', () {
|
||||||
var source = '''
|
var source = '''
|
||||||
const soundNullSafety = !(<Null>[] is List<int>);
|
const soundNullSafety = !(<Null>[] is List<int>);
|
||||||
|
@ -956,7 +968,7 @@ void runAgnosticSharedTestsShard1(
|
||||||
/// This group of tests has been sharded manually. The others are in
|
/// This group of tests has been sharded manually. The others are in
|
||||||
/// [runAgnosticSharedTestsShard1].
|
/// [runAgnosticSharedTestsShard1].
|
||||||
void runAgnosticSharedTestsShard2(
|
void runAgnosticSharedTestsShard2(
|
||||||
SetupCompilerOptions setup, TestDriver driver) {
|
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||||
group('Expression compiler tests in constructor:', () {
|
group('Expression compiler tests in constructor:', () {
|
||||||
var source = simpleClassSource;
|
var source = simpleClassSource;
|
||||||
|
|
||||||
|
|
|
@ -10,182 +10,20 @@ import 'dart:math';
|
||||||
import 'package:async/async.dart';
|
import 'package:async/async.dart';
|
||||||
import 'package:browser_launcher/browser_launcher.dart' as browser;
|
import 'package:browser_launcher/browser_launcher.dart' as browser;
|
||||||
import 'package:dev_compiler/src/compiler/module_builder.dart';
|
import 'package:dev_compiler/src/compiler/module_builder.dart';
|
||||||
import 'package:dev_compiler/src/compiler/shared_command.dart'
|
|
||||||
show SharedCompilerOptions;
|
|
||||||
import 'package:dev_compiler/src/kernel/command.dart';
|
|
||||||
import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler;
|
|
||||||
import 'package:dev_compiler/src/kernel/expression_compiler.dart'
|
|
||||||
show ExpressionCompiler;
|
|
||||||
import 'package:dev_compiler/src/kernel/module_metadata.dart';
|
|
||||||
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
|
||||||
import 'package:front_end/src/fasta/incremental_serializer.dart' as fe;
|
|
||||||
import 'package:kernel/ast.dart' show Component, Library;
|
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
import 'package:source_maps/source_maps.dart' as source_maps;
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
|
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
|
||||||
as wip;
|
as wip;
|
||||||
|
|
||||||
import 'setup_compiler_options.dart';
|
import '../shared_test_options.dart';
|
||||||
|
import 'test_compiler.dart';
|
||||||
|
|
||||||
class DevelopmentIncrementalCompiler extends fe.IncrementalCompiler {
|
class ExpressionEvaluationTestDriver {
|
||||||
Uri entryPoint;
|
|
||||||
|
|
||||||
DevelopmentIncrementalCompiler(fe.CompilerOptions options, this.entryPoint,
|
|
||||||
[Uri? initializeFrom,
|
|
||||||
bool? outlineOnly,
|
|
||||||
fe.IncrementalSerializer? incrementalSerializer])
|
|
||||||
: super(
|
|
||||||
fe.CompilerContext(
|
|
||||||
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
|
||||||
initializeFrom,
|
|
||||||
outlineOnly,
|
|
||||||
incrementalSerializer);
|
|
||||||
|
|
||||||
DevelopmentIncrementalCompiler.fromComponent(fe.CompilerOptions options,
|
|
||||||
this.entryPoint, Component componentToInitializeFrom,
|
|
||||||
[bool? outlineOnly, fe.IncrementalSerializer? incrementalSerializer])
|
|
||||||
: super.fromComponent(
|
|
||||||
fe.CompilerContext(
|
|
||||||
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
|
||||||
componentToInitializeFrom,
|
|
||||||
outlineOnly,
|
|
||||||
incrementalSerializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestCompilationResult {
|
|
||||||
final String? result;
|
|
||||||
final bool isSuccess;
|
|
||||||
|
|
||||||
TestCompilationResult(this.result, this.isSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestCompiler {
|
|
||||||
final SetupCompilerOptions setup;
|
|
||||||
final Component component;
|
|
||||||
final ExpressionCompiler evaluator;
|
|
||||||
final ModuleMetadata? metadata;
|
|
||||||
final source_maps.SingleMapping sourceMap;
|
|
||||||
|
|
||||||
TestCompiler._(this.setup, this.component, this.evaluator, this.metadata,
|
|
||||||
this.sourceMap);
|
|
||||||
|
|
||||||
static Future<TestCompiler> init(SetupCompilerOptions setup,
|
|
||||||
{required Uri input,
|
|
||||||
required Uri output,
|
|
||||||
Uri? packages,
|
|
||||||
Map<String, bool> experiments = const {}}) async {
|
|
||||||
// Initialize the incremental compiler and module component.
|
|
||||||
// TODO: extend this for multi-module compilations by storing separate
|
|
||||||
// compilers/components/names per module.
|
|
||||||
setup.options.packagesFileUri = packages;
|
|
||||||
setup.options.explicitExperimentalFlags.addAll(fe.parseExperimentalFlags(
|
|
||||||
experiments,
|
|
||||||
onError: (message) => throw Exception(message)));
|
|
||||||
var compiler = DevelopmentIncrementalCompiler(setup.options, input);
|
|
||||||
var compilerResult = await compiler.computeDelta();
|
|
||||||
var component = compilerResult.component;
|
|
||||||
component.computeCanonicalNames();
|
|
||||||
// Initialize DDC.
|
|
||||||
var moduleName = p.basenameWithoutExtension(output.toFilePath());
|
|
||||||
|
|
||||||
var classHierarchy = compilerResult.classHierarchy!;
|
|
||||||
var compilerOptions = SharedCompilerOptions(
|
|
||||||
replCompile: true,
|
|
||||||
moduleName: moduleName,
|
|
||||||
experiments: experiments,
|
|
||||||
soundNullSafety: setup.soundNullSafety,
|
|
||||||
emitDebugMetadata: true,
|
|
||||||
canaryFeatures: setup.canaryFeatures,
|
|
||||||
enableAsserts: setup.enableAsserts,
|
|
||||||
);
|
|
||||||
var coreTypes = compilerResult.coreTypes;
|
|
||||||
|
|
||||||
final importToSummary = Map<Library, Component>.identity();
|
|
||||||
final summaryToModule = Map<Component, String>.identity();
|
|
||||||
for (var lib in component.libraries) {
|
|
||||||
importToSummary[lib] = component;
|
|
||||||
}
|
|
||||||
summaryToModule[component] = moduleName;
|
|
||||||
|
|
||||||
var kernel2jsCompiler = ProgramCompiler(component, classHierarchy,
|
|
||||||
compilerOptions, importToSummary, summaryToModule,
|
|
||||||
coreTypes: coreTypes);
|
|
||||||
var module = kernel2jsCompiler.emitModule(component);
|
|
||||||
|
|
||||||
// Perform a full compile, writing the compiled JS + sourcemap.
|
|
||||||
var code = jsProgramToCode(
|
|
||||||
module,
|
|
||||||
setup.moduleFormat,
|
|
||||||
inlineSourceMap: compilerOptions.inlineSourceMap,
|
|
||||||
buildSourceMap: compilerOptions.sourceMap,
|
|
||||||
emitDebugMetadata: compilerOptions.emitDebugMetadata,
|
|
||||||
emitDebugSymbols: compilerOptions.emitDebugSymbols,
|
|
||||||
jsUrl: '$output',
|
|
||||||
mapUrl: '$output.map',
|
|
||||||
compiler: kernel2jsCompiler,
|
|
||||||
component: component,
|
|
||||||
);
|
|
||||||
var codeBytes = utf8.encode(code.code);
|
|
||||||
var sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
|
|
||||||
|
|
||||||
File(output.toFilePath()).writeAsBytesSync(codeBytes);
|
|
||||||
File('${output.toFilePath()}.map').writeAsBytesSync(sourceMapBytes);
|
|
||||||
|
|
||||||
// Save the expression evaluator for future evaluations.
|
|
||||||
var evaluator = ExpressionCompiler(
|
|
||||||
setup.options,
|
|
||||||
setup.moduleFormat,
|
|
||||||
setup.errors,
|
|
||||||
compiler,
|
|
||||||
kernel2jsCompiler,
|
|
||||||
component,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (setup.errors.isNotEmpty) {
|
|
||||||
throw Exception('Compilation failed with: ${setup.errors}');
|
|
||||||
}
|
|
||||||
setup.diagnosticMessages.clear();
|
|
||||||
|
|
||||||
var sourceMap = source_maps.SingleMapping.fromJson(
|
|
||||||
code.sourceMap!.cast<String, dynamic>());
|
|
||||||
return TestCompiler._(
|
|
||||||
setup, component, evaluator, code.metadata, sourceMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<TestCompilationResult> compileExpression(
|
|
||||||
{required Uri input,
|
|
||||||
required int line,
|
|
||||||
required int column,
|
|
||||||
required Map<String, String> scope,
|
|
||||||
required String expression}) async {
|
|
||||||
var libraryUri = metadataForLibraryUri(input);
|
|
||||||
var jsExpression = await evaluator.compileExpressionToJs(
|
|
||||||
libraryUri.importUri, line, column, scope, expression);
|
|
||||||
if (setup.errors.isNotEmpty) {
|
|
||||||
jsExpression = setup.errors.toString().replaceAll(
|
|
||||||
RegExp(
|
|
||||||
r'org-dartlang-debug:synthetic_debug_expression:[0-9]*:[0-9]*:'),
|
|
||||||
'');
|
|
||||||
|
|
||||||
return TestCompilationResult(jsExpression, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TestCompilationResult(jsExpression, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
LibraryMetadata metadataForLibraryUri(Uri libraryUri) =>
|
|
||||||
metadata!.libraries.entries
|
|
||||||
.firstWhere((entry) => entry.value.fileUri == '$libraryUri')
|
|
||||||
.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestDriver {
|
|
||||||
final browser.Chrome chrome;
|
final browser.Chrome chrome;
|
||||||
final Directory chromeDir;
|
final Directory chromeDir;
|
||||||
final wip.WipConnection connection;
|
final wip.WipConnection connection;
|
||||||
final wip.WipDebugger debugger;
|
final wip.WipDebugger debugger;
|
||||||
late TestCompiler compiler;
|
late TestExpressionCompiler compiler;
|
||||||
late Uri htmlBootstrapper;
|
late Uri htmlBootstrapper;
|
||||||
late Uri input;
|
late Uri input;
|
||||||
late Uri output;
|
late Uri output;
|
||||||
|
@ -196,10 +34,11 @@ class TestDriver {
|
||||||
late Directory testDir;
|
late Directory testDir;
|
||||||
late String dartSdkPath;
|
late String dartSdkPath;
|
||||||
|
|
||||||
TestDriver._(this.chrome, this.chromeDir, this.connection, this.debugger);
|
ExpressionEvaluationTestDriver._(
|
||||||
|
this.chrome, this.chromeDir, this.connection, this.debugger);
|
||||||
|
|
||||||
/// Initializes a Chrome browser instance, tab connection, and debugger.
|
/// Initializes a Chrome browser instance, tab connection, and debugger.
|
||||||
static Future<TestDriver> init() async {
|
static Future<ExpressionEvaluationTestDriver> init() async {
|
||||||
// Create a temporary directory for holding Chrome tests.
|
// Create a temporary directory for holding Chrome tests.
|
||||||
var chromeDir = Directory.systemTemp.createTempSync('ddc_eval_test_anchor');
|
var chromeDir = Directory.systemTemp.createTempSync('ddc_eval_test_anchor');
|
||||||
|
|
||||||
|
@ -243,7 +82,8 @@ class TestDriver {
|
||||||
var debugger = connection.debugger;
|
var debugger = connection.debugger;
|
||||||
await debugger.enable().timeout(Duration(seconds: 5),
|
await debugger.enable().timeout(Duration(seconds: 5),
|
||||||
onTimeout: (() => throw Exception('Unable to enable WIP debugger')));
|
onTimeout: (() => throw Exception('Unable to enable WIP debugger')));
|
||||||
return TestDriver._(chrome, chromeDir, connection, debugger);
|
return ExpressionEvaluationTestDriver._(
|
||||||
|
chrome, chromeDir, connection, debugger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Must be called when testing a new Dart program.
|
/// Must be called when testing a new Dart program.
|
||||||
|
@ -288,7 +128,7 @@ class TestDriver {
|
||||||
''');
|
''');
|
||||||
|
|
||||||
// Initialize DDC and the incremental compiler, then perform a full compile.
|
// Initialize DDC and the incremental compiler, then perform a full compile.
|
||||||
compiler = await TestCompiler.init(setup,
|
compiler = await TestExpressionCompiler.init(setup,
|
||||||
input: input,
|
input: input,
|
||||||
output: output,
|
output: output,
|
||||||
packages: packagesFile,
|
packages: packagesFile,
|
||||||
|
@ -660,14 +500,10 @@ class TestDriver {
|
||||||
}) async {
|
}) async {
|
||||||
var frame = event.getCallFrames().first;
|
var frame = event.getCallFrames().first;
|
||||||
|
|
||||||
var loadModule = setup.moduleFormat == ModuleFormat.amd
|
|
||||||
? 'require'
|
|
||||||
: 'dart_library.import';
|
|
||||||
|
|
||||||
var jsExpression = '''
|
var jsExpression = '''
|
||||||
(function () {
|
(function () {
|
||||||
try {
|
try {
|
||||||
var sdk = $loadModule('dart_sdk');
|
var sdk = ${setup.loadModule}('dart_sdk');
|
||||||
var dart = sdk.dart;
|
var dart = sdk.dart;
|
||||||
var interceptors = sdk._interceptors;
|
var interceptors = sdk._interceptors;
|
||||||
return $expression;
|
return $expression;
|
||||||
|
@ -685,23 +521,28 @@ class TestDriver {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<TestCompilationResult> _compileDartExpression(
|
||||||
|
wip.WipCallFrame frame, String expression, int dartLine) async {
|
||||||
|
// Retrieve the call frame and its scope variables.
|
||||||
|
var scope = await _collectScopeVariables(frame);
|
||||||
|
|
||||||
|
// Perform an incremental compile.
|
||||||
|
return await compiler.compileExpression(
|
||||||
|
input: input,
|
||||||
|
line: dartLine,
|
||||||
|
column: 1,
|
||||||
|
scope: scope,
|
||||||
|
expression: expression);
|
||||||
|
}
|
||||||
|
|
||||||
Future<wip.RemoteObject> _evaluateDartExpression(
|
Future<wip.RemoteObject> _evaluateDartExpression(
|
||||||
wip.DebuggerPausedEvent event,
|
wip.DebuggerPausedEvent event,
|
||||||
String expression,
|
String expression,
|
||||||
int dartLine, {
|
int dartLine, {
|
||||||
bool returnByValue = false,
|
bool returnByValue = false,
|
||||||
}) async {
|
}) async {
|
||||||
// Retrieve the call frame and its scope variables.
|
|
||||||
var frame = event.getCallFrames().first;
|
var frame = event.getCallFrames().first;
|
||||||
var scope = await _collectScopeVariables(frame);
|
var result = await _compileDartExpression(frame, expression, dartLine);
|
||||||
|
|
||||||
// Perform an incremental compile.
|
|
||||||
var result = await compiler.compileExpression(
|
|
||||||
input: input,
|
|
||||||
line: dartLine,
|
|
||||||
column: 1,
|
|
||||||
scope: scope,
|
|
||||||
expression: expression);
|
|
||||||
|
|
||||||
if (!result.isSuccess) {
|
if (!result.isSuccess) {
|
||||||
setup.diagnosticMessages.clear();
|
setup.diagnosticMessages.clear();
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
// Copyright (c) 2023, 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:io' show Directory, File;
|
||||||
|
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
|
import 'test_compiler.dart';
|
||||||
|
|
||||||
|
class ExpressionCompilerTestDriver {
|
||||||
|
final SetupCompilerOptions setup;
|
||||||
|
late Directory testDir;
|
||||||
|
String source;
|
||||||
|
late Uri input;
|
||||||
|
late Uri output;
|
||||||
|
late Uri packages;
|
||||||
|
late int line;
|
||||||
|
|
||||||
|
ExpressionCompilerTestDriver(this.setup, this.source) {
|
||||||
|
source = '${setup.dartLangComment}\n\n$source';
|
||||||
|
line = _getEvaluationLine(source);
|
||||||
|
var systemTempDir = Directory.systemTemp;
|
||||||
|
testDir = systemTempDir.createTempSync('foo bar');
|
||||||
|
|
||||||
|
output = testDir.uri.resolve('test.js');
|
||||||
|
input = testDir.uri.resolve('test.dart');
|
||||||
|
File.fromUri(input)
|
||||||
|
..createSync()
|
||||||
|
..writeAsStringSync(source);
|
||||||
|
|
||||||
|
packages = testDir.uri.resolve('package_config.json');
|
||||||
|
File.fromUri(packages)
|
||||||
|
..createSync()
|
||||||
|
..writeAsStringSync('''
|
||||||
|
{
|
||||||
|
"configVersion": 2,
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "foo",
|
||||||
|
"rootUri": "./",
|
||||||
|
"packageUri": "./"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
''');
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete() {
|
||||||
|
testDir.deleteSync(recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TestExpressionCompiler> createCompiler() =>
|
||||||
|
TestExpressionCompiler.init(setup,
|
||||||
|
input: input, output: output, packages: packages);
|
||||||
|
|
||||||
|
Future<TestCompilationResult> compile({
|
||||||
|
required TestExpressionCompiler compiler,
|
||||||
|
required Map<String, String> scope,
|
||||||
|
required String expression,
|
||||||
|
}) async {
|
||||||
|
return compiler.compileExpression(
|
||||||
|
input: input,
|
||||||
|
line: line,
|
||||||
|
column: 1,
|
||||||
|
scope: scope,
|
||||||
|
expression: expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkResult(
|
||||||
|
TestCompilationResult result, {
|
||||||
|
String? expectedError,
|
||||||
|
dynamic expectedResult,
|
||||||
|
}) {
|
||||||
|
var success = expectedError == null;
|
||||||
|
var message = success ? expectedResult! : expectedError;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
result,
|
||||||
|
const TypeMatcher<TestCompilationResult>()
|
||||||
|
.having((r) => r.result!, 'result', _matches(message))
|
||||||
|
.having((r) => r.isSuccess, 'isSuccess', success));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> check({
|
||||||
|
TestExpressionCompiler? compiler,
|
||||||
|
required Map<String, String> scope,
|
||||||
|
required String expression,
|
||||||
|
String? expectedError,
|
||||||
|
dynamic expectedResult,
|
||||||
|
}) async {
|
||||||
|
compiler ??= await createCompiler();
|
||||||
|
var result =
|
||||||
|
await compile(compiler: compiler, scope: scope, expression: expression);
|
||||||
|
|
||||||
|
checkResult(result,
|
||||||
|
expectedError: expectedError, expectedResult: expectedResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher _matches(dynamic matcher) {
|
||||||
|
if (matcher is Matcher) return matcher;
|
||||||
|
if (matcher is! String) throw StateError('Unsupported matcher $matcher');
|
||||||
|
|
||||||
|
var unIndented = RegExp.escape(matcher).replaceAll(RegExp('[ ]+'), '[ ]*');
|
||||||
|
return matches(RegExp(unIndented, multiLine: true));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _getEvaluationLine(String source) {
|
||||||
|
var placeholderRegExp = RegExp(r'// Breakpoint');
|
||||||
|
|
||||||
|
var lines = source.split('\n');
|
||||||
|
for (var line = 0; line < lines.length; line++) {
|
||||||
|
var content = lines[line];
|
||||||
|
if (placeholderRegExp.firstMatch(content) != null) {
|
||||||
|
return line + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,284 +2,21 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// 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.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:io' show Directory, File;
|
|
||||||
|
|
||||||
import 'package:dev_compiler/src/compiler/js_names.dart';
|
|
||||||
import 'package:dev_compiler/src/compiler/module_builder.dart';
|
import 'package:dev_compiler/src/compiler/module_builder.dart';
|
||||||
import 'package:dev_compiler/src/compiler/shared_command.dart'
|
|
||||||
show SharedCompilerOptions;
|
|
||||||
import 'package:dev_compiler/src/js_ast/js_ast.dart';
|
|
||||||
import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler;
|
|
||||||
import 'package:dev_compiler/src/kernel/expression_compiler.dart'
|
|
||||||
show ExpressionCompiler;
|
|
||||||
import 'package:kernel/ast.dart' show Component, Library;
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:vm/transformations/type_flow/utils.dart';
|
|
||||||
|
|
||||||
import '../shared_test_options.dart';
|
import '../shared_test_options.dart';
|
||||||
|
import 'expression_compiler_suite.dart';
|
||||||
|
|
||||||
// TODO(annagrin): Replace javascript matching in tests below with evaluating
|
void main(List<String> args) {
|
||||||
// the javascript and checking the result.
|
|
||||||
// See https://github.com/dart-lang/sdk/issues/41959
|
|
||||||
|
|
||||||
/// Convenience class describing JavaScript module
|
|
||||||
/// to ensure we have normalized module names
|
|
||||||
class Module {
|
|
||||||
/// variable name used in JavaScript output to load the module
|
|
||||||
/// example: file
|
|
||||||
final String name;
|
|
||||||
|
|
||||||
/// JavaScript module name used in trackLibraries
|
|
||||||
/// example: packages/package/file.dart
|
|
||||||
final String path;
|
|
||||||
|
|
||||||
/// URI where the contents of the library that produces this module
|
|
||||||
/// can be found
|
|
||||||
/// example: /Users/../package/file.dart
|
|
||||||
final Uri fileUri;
|
|
||||||
|
|
||||||
/// Import URI for the library that generates this module.
|
|
||||||
/// example: packages:package/file.dart
|
|
||||||
final Uri importUri;
|
|
||||||
|
|
||||||
Module(this.importUri, this.fileUri)
|
|
||||||
: name = libraryUriToJsIdentifier(importUri),
|
|
||||||
path = importUri.isScheme('package')
|
|
||||||
? 'packages/${importUri.path}'
|
|
||||||
: importUri.path;
|
|
||||||
|
|
||||||
String get package => importUri.toString();
|
|
||||||
String get file => fileUri.path;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() =>
|
|
||||||
'Name: \$name, File: \$file, Package: \$package, path: \$path';
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestCompilationResult {
|
|
||||||
final String result;
|
|
||||||
final bool isSuccess;
|
|
||||||
|
|
||||||
TestCompilationResult(this.result, this.isSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestCompiler {
|
|
||||||
final SetupCompilerOptions setup;
|
|
||||||
final Map<Uri, Module> _modules = {};
|
|
||||||
late final ExpressionCompiler compiler;
|
|
||||||
|
|
||||||
TestCompiler._(this.setup);
|
|
||||||
|
|
||||||
static Future<TestCompiler> create(
|
|
||||||
SetupCompilerOptions setup, Uri input, Uri packages) async {
|
|
||||||
final testCompiler = TestCompiler._(setup);
|
|
||||||
await testCompiler._createCompiler(input, packages);
|
|
||||||
return testCompiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<TestCompilationResult> compile(
|
|
||||||
{required Uri input,
|
|
||||||
required int line,
|
|
||||||
required int column,
|
|
||||||
required Map<String, String> scope,
|
|
||||||
required String expression}) async {
|
|
||||||
// clear previous errors
|
|
||||||
setup.errors.clear();
|
|
||||||
|
|
||||||
// compile
|
|
||||||
var jsExpression = await compiler.compileExpressionToJs(
|
|
||||||
_libraryUriFor(input), line, column, scope, expression);
|
|
||||||
|
|
||||||
if (setup.errors.isNotEmpty) {
|
|
||||||
jsExpression = setup.errors.toString().replaceAll(
|
|
||||||
RegExp(
|
|
||||||
r'org-dartlang-debug:synthetic_debug_expression:[0-9]*:[0-9]*:'),
|
|
||||||
'');
|
|
||||||
|
|
||||||
return TestCompilationResult(jsExpression, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TestCompilationResult(jsExpression!, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _createCompiler(Uri input, Uri packages) async {
|
|
||||||
// initialize incremental compiler and create component
|
|
||||||
setup.options.packagesFileUri = packages;
|
|
||||||
var frontend = DevelopmentIncrementalCompiler(setup.options, input);
|
|
||||||
var compilerResult = await frontend.computeDelta();
|
|
||||||
var component = compilerResult.component;
|
|
||||||
component.computeCanonicalNames();
|
|
||||||
|
|
||||||
// initialize ddc
|
|
||||||
var moduleName = 'foo.dart';
|
|
||||||
var classHierarchy = compilerResult.classHierarchy;
|
|
||||||
var compilerOptions = SharedCompilerOptions(
|
|
||||||
replCompile: true,
|
|
||||||
moduleName: moduleName,
|
|
||||||
soundNullSafety: setup.soundNullSafety,
|
|
||||||
moduleFormats: [setup.moduleFormat],
|
|
||||||
canaryFeatures: false,
|
|
||||||
);
|
|
||||||
var coreTypes = compilerResult.coreTypes;
|
|
||||||
|
|
||||||
final importToSummary = Map<Library, Component>.identity();
|
|
||||||
final summaryToModule = Map<Component, String>.identity();
|
|
||||||
for (var lib in component.libraries) {
|
|
||||||
importToSummary[lib] = component;
|
|
||||||
}
|
|
||||||
summaryToModule[component] = moduleName;
|
|
||||||
|
|
||||||
var kernel2jsCompiler = ProgramCompiler(component, classHierarchy!,
|
|
||||||
compilerOptions, importToSummary, summaryToModule,
|
|
||||||
coreTypes: coreTypes);
|
|
||||||
var moduleTree = kernel2jsCompiler.emitModule(component);
|
|
||||||
|
|
||||||
{
|
|
||||||
var opts = JavaScriptPrintingOptions(
|
|
||||||
allowKeywordsInProperties: true, allowSingleLineIfStatements: true);
|
|
||||||
var printer = SimpleJavaScriptPrintingContext();
|
|
||||||
|
|
||||||
var tree = transformModuleFormat(setup.moduleFormat, moduleTree);
|
|
||||||
tree.accept(Printer(opts, printer, localNamer: TemporaryNamer(tree)));
|
|
||||||
var printed = printer.getText();
|
|
||||||
debugPrint(printed);
|
|
||||||
}
|
|
||||||
|
|
||||||
_collectModules(component);
|
|
||||||
|
|
||||||
// create expression compiler
|
|
||||||
compiler = ExpressionCompiler(
|
|
||||||
setup.options,
|
|
||||||
setup.moduleFormat,
|
|
||||||
setup.errors,
|
|
||||||
frontend,
|
|
||||||
kernel2jsCompiler,
|
|
||||||
component,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _collectModules(Component component) {
|
|
||||||
for (var library in component.libraries) {
|
|
||||||
_modules[library.fileUri] = Module(library.importUri, library.fileUri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String _libraryUriFor(Uri input) => _modules[input]!.package;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestDriver {
|
|
||||||
final SetupCompilerOptions options;
|
|
||||||
late Directory tempDir;
|
|
||||||
final String source;
|
|
||||||
late Uri input;
|
|
||||||
late Uri packages;
|
|
||||||
late File file;
|
|
||||||
int line;
|
|
||||||
|
|
||||||
TestDriver(this.options, this.source) : line = _getEvaluationLine(source) {
|
|
||||||
var systemTempDir = Directory.systemTemp;
|
|
||||||
tempDir = systemTempDir.createTempSync('foo bar');
|
|
||||||
|
|
||||||
input = tempDir.uri.resolve('foo.dart');
|
|
||||||
file = File.fromUri(input)..createSync();
|
|
||||||
file.writeAsStringSync(source);
|
|
||||||
|
|
||||||
packages = tempDir.uri.resolve('package_config.json');
|
|
||||||
file = File.fromUri(packages)..createSync();
|
|
||||||
file.writeAsStringSync('''
|
|
||||||
{
|
|
||||||
"configVersion": 2,
|
|
||||||
"packages": [
|
|
||||||
{
|
|
||||||
"name": "foo",
|
|
||||||
"rootUri": "./",
|
|
||||||
"packageUri": "./"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
''');
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete() {
|
|
||||||
tempDir.delete(recursive: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<TestCompiler> createCompiler() =>
|
|
||||||
TestCompiler.create(options, input, packages);
|
|
||||||
|
|
||||||
Future<TestCompilationResult> compile({
|
|
||||||
required TestCompiler compiler,
|
|
||||||
required Map<String, String> scope,
|
|
||||||
required String expression,
|
|
||||||
}) async {
|
|
||||||
return compiler.compile(
|
|
||||||
input: input,
|
|
||||||
line: line,
|
|
||||||
column: 1,
|
|
||||||
scope: scope,
|
|
||||||
expression: expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkResult(
|
|
||||||
TestCompilationResult result, {
|
|
||||||
String? expectedError,
|
|
||||||
String? expectedResult,
|
|
||||||
}) {
|
|
||||||
var success = expectedError == null;
|
|
||||||
var message = success ? expectedResult! : expectedError;
|
|
||||||
|
|
||||||
expect(
|
|
||||||
result,
|
|
||||||
const TypeMatcher<TestCompilationResult>()
|
|
||||||
.having((r) => _normalize(r.result), 'result', _matches(message))
|
|
||||||
.having((r) => r.isSuccess, 'isSuccess', success));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> check({
|
|
||||||
TestCompiler? compiler,
|
|
||||||
required Map<String, String> scope,
|
|
||||||
required String expression,
|
|
||||||
String? expectedError,
|
|
||||||
String? expectedResult,
|
|
||||||
}) async {
|
|
||||||
compiler ??= await createCompiler();
|
|
||||||
var result =
|
|
||||||
await compile(compiler: compiler, scope: scope, expression: expression);
|
|
||||||
|
|
||||||
checkResult(result,
|
|
||||||
expectedError: expectedError, expectedResult: expectedResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
String _normalize(String text) {
|
|
||||||
return text
|
|
||||||
.replaceAll(RegExp('\'.*foo.dart\''), '\'foo.dart\'')
|
|
||||||
.replaceAll(RegExp('".*foo.dart"'), '\'foo.dart\'');
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher _matches(String text) {
|
|
||||||
var unIndented = RegExp.escape(text).replaceAll(RegExp('[ ]+'), '[ ]*');
|
|
||||||
return matches(RegExp(unIndented, multiLine: true));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _getEvaluationLine(String source) {
|
|
||||||
var placeholderRegExp = RegExp(r'/\* evaluation placeholder \*/');
|
|
||||||
|
|
||||||
var lines = source.split('\n');
|
|
||||||
for (var line = 0; line < lines.length; line++) {
|
|
||||||
var content = lines[line];
|
|
||||||
if (placeholderRegExp.firstMatch(content) != null) {
|
|
||||||
return line + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
for (var moduleFormat in [ModuleFormat.amd, ModuleFormat.ddc]) {
|
for (var moduleFormat in [ModuleFormat.amd, ModuleFormat.ddc]) {
|
||||||
group('Module format: $moduleFormat |', () {
|
group('Module format: $moduleFormat |', () {
|
||||||
group('Unsound null safety |', () {
|
group('Unsound null safety |', () {
|
||||||
runUnsoundTests(moduleFormat);
|
runTests(SetupCompilerOptions(
|
||||||
|
soundNullSafety: false,
|
||||||
|
moduleFormat: moduleFormat,
|
||||||
|
args: args,
|
||||||
|
));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -287,33 +24,31 @@ void main() {
|
||||||
for (var moduleFormat in [ModuleFormat.amd, ModuleFormat.ddc]) {
|
for (var moduleFormat in [ModuleFormat.amd, ModuleFormat.ddc]) {
|
||||||
group('Module format: $moduleFormat |', () {
|
group('Module format: $moduleFormat |', () {
|
||||||
group('Sound null safety |', () {
|
group('Sound null safety |', () {
|
||||||
runSoundTests(moduleFormat);
|
runTests(SetupCompilerOptions(
|
||||||
|
soundNullSafety: true,
|
||||||
|
moduleFormat: moduleFormat,
|
||||||
|
args: args,
|
||||||
|
));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void runUnsoundTests(ModuleFormat moduleFormat) {
|
void runTests(SetupCompilerOptions setup) {
|
||||||
var options = SetupCompilerOptions(
|
|
||||||
soundNullSafety: false,
|
|
||||||
moduleFormat: moduleFormat,
|
|
||||||
);
|
|
||||||
|
|
||||||
group('Expression compilations on the same expression compiler |', () {
|
group('Expression compilations on the same expression compiler |', () {
|
||||||
var source = '''
|
var source = '''
|
||||||
${options.dartLangComment}
|
main() {
|
||||||
main() {
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void foo() {
|
void foo() {
|
||||||
/* evaluation placeholder */
|
// Breakpoint
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
|
|
||||||
late TestDriver driver;
|
late ExpressionCompilerTestDriver driver;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
driver = TestDriver(options, source);
|
driver = ExpressionCompilerTestDriver(setup, source);
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
|
@ -326,24 +61,12 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
||||||
compiler: compiler,
|
compiler: compiler,
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
expression: 'true',
|
expression: 'true',
|
||||||
expectedResult: '''
|
expectedResult: contains('return true;'));
|
||||||
(function() {
|
|
||||||
return true;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
await driver.check(
|
await driver.check(
|
||||||
compiler: compiler,
|
compiler: compiler,
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
expression: 'false',
|
expression: 'false',
|
||||||
expectedResult: '''
|
expectedResult: contains('return false;'));
|
||||||
(function() {
|
|
||||||
return false;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('some successful expression compilations', () async {
|
test('some successful expression compilations', () async {
|
||||||
|
@ -352,13 +75,7 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
||||||
compiler: compiler,
|
compiler: compiler,
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
expression: 'true',
|
expression: 'true',
|
||||||
expectedResult: '''
|
expectedResult: contains('return true;'));
|
||||||
(function() {
|
|
||||||
return true;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
await driver.check(
|
await driver.check(
|
||||||
compiler: compiler,
|
compiler: compiler,
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
|
@ -369,13 +86,7 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
||||||
compiler: compiler,
|
compiler: compiler,
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
expression: 'false',
|
expression: 'false',
|
||||||
expectedResult: '''
|
expectedResult: contains('return false;'));
|
||||||
(function() {
|
|
||||||
return false;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('failing expression compilations', () async {
|
test('failing expression compilations', () async {
|
||||||
|
@ -397,26 +108,25 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
||||||
|
|
||||||
group('Expression compiler import tests', () {
|
group('Expression compiler import tests', () {
|
||||||
var source = '''
|
var source = '''
|
||||||
${options.dartLangComment}
|
import 'dart:io' show Directory;
|
||||||
import 'dart:io' show Directory;
|
import 'dart:io' as p;
|
||||||
import 'dart:io' as p;
|
import 'dart:convert' as p;
|
||||||
import 'dart:convert' as p;
|
|
||||||
|
|
||||||
main() {
|
|
||||||
print(Directory.systemTemp);
|
|
||||||
print(p.Directory.systemTemp);
|
|
||||||
print(p.utf.decoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void foo() {
|
main() {
|
||||||
/* evaluation placeholder */
|
print(Directory.systemTemp);
|
||||||
}
|
print(p.Directory.systemTemp);
|
||||||
''';
|
print(p.utf8.decoder);
|
||||||
|
}
|
||||||
|
|
||||||
late TestDriver driver;
|
void foo() {
|
||||||
|
// Breakpoint
|
||||||
|
}
|
||||||
|
''';
|
||||||
|
|
||||||
|
late ExpressionCompilerTestDriver driver;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
driver = TestDriver(options, source);
|
driver = ExpressionCompilerTestDriver(setup, source);
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
|
@ -427,30 +137,14 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
||||||
await driver.check(
|
await driver.check(
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
expression: 'Directory.systemTemp',
|
expression: 'Directory.systemTemp',
|
||||||
expectedResult: '''
|
expectedResult: contains('return io.Directory.systemTemp;'));
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const io = dart_sdk.io;
|
|
||||||
return io.Directory.systemTemp;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('expression referencing named import', () async {
|
test('expression referencing named import', () async {
|
||||||
await driver.check(
|
await driver.check(
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
expression: 'p.Directory.systemTemp',
|
expression: 'p.Directory.systemTemp',
|
||||||
expectedResult: '''
|
expectedResult: contains('return io.Directory.systemTemp;'));
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const io = dart_sdk.io;
|
|
||||||
return io.Directory.systemTemp;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('expression referencing another library with the same named import',
|
test('expression referencing another library with the same named import',
|
||||||
|
@ -458,412 +152,7 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
||||||
await driver.check(
|
await driver.check(
|
||||||
scope: <String, String>{},
|
scope: <String, String>{},
|
||||||
expression: 'p.utf8.decoder',
|
expression: 'p.utf8.decoder',
|
||||||
expectedResult: '''
|
expectedResult: contains('return convert.utf8.decoder;'));
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const convert = dart_sdk.convert;
|
|
||||||
return convert.utf8.decoder;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('Expression compiler tests for interactions with module containers:',
|
|
||||||
() {
|
|
||||||
var source = '''
|
|
||||||
${options.dartLangComment}
|
|
||||||
class A {
|
|
||||||
const A();
|
|
||||||
}
|
|
||||||
class B {
|
|
||||||
const B();
|
|
||||||
}
|
|
||||||
void foo() {
|
|
||||||
const a = A();
|
|
||||||
var check = a is int;
|
|
||||||
/* evaluation placeholder */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() => foo();
|
|
||||||
''';
|
|
||||||
|
|
||||||
late TestDriver driver;
|
|
||||||
setUp(() {
|
|
||||||
driver = TestDriver(options, source);
|
|
||||||
});
|
|
||||||
|
|
||||||
tearDown(() {
|
|
||||||
driver.delete();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('evaluation that non-destructively appends to the type container',
|
|
||||||
() async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
|
||||||
expression: 'a is String',
|
|
||||||
expectedResult: '''
|
|
||||||
(function(a, check) {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const core = dart_sdk.core;
|
|
||||||
const dart = dart_sdk.dart;
|
|
||||||
var T = {
|
|
||||||
StringL: () => (T.StringL = dart.constFn(dart.legacy(core.String)))()
|
|
||||||
};
|
|
||||||
return T.StringL().is(a);
|
|
||||||
}(
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('evaluation that reuses the type container', () async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
|
||||||
expression: 'a is int',
|
|
||||||
expectedResult: '''
|
|
||||||
(function(a, check) {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const core = dart_sdk.core;
|
|
||||||
const dart = dart_sdk.dart;
|
|
||||||
var T = {
|
|
||||||
intL: () => (T.intL = dart.constFn(dart.legacy(core.int)))()
|
|
||||||
};
|
|
||||||
return T.intL().is(a);
|
|
||||||
}(
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('evaluation that non-destructively appends to the constant container',
|
|
||||||
() async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
|
||||||
expression: 'const B()',
|
|
||||||
expectedResult: '''
|
|
||||||
(function(a, check) {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const dart = dart_sdk.dart;
|
|
||||||
const foo\$46dart = ${options.loadModule}('foo.dart');
|
|
||||||
const foo = foo\$46dart.foo;
|
|
||||||
const CT = Object.create(null);
|
|
||||||
dart.defineLazy(CT, {
|
|
||||||
get C0() {
|
|
||||||
return C[0] = dart.const(Object.setPrototypeOf({
|
|
||||||
}, foo.B.prototype));
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
var C = [void 0];
|
|
||||||
return C[0] || CT.C0;
|
|
||||||
}(
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
|
||||||
'evaluation that reuses the constant container and canonicalizes properly',
|
|
||||||
() async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
|
||||||
expression: 'a == const A()',
|
|
||||||
expectedResult: '''
|
|
||||||
(function(a, check) {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const dart = dart_sdk.dart;
|
|
||||||
const foo\$46dart = ${options.loadModule}('foo.dart');
|
|
||||||
const foo = foo\$46dart.foo;
|
|
||||||
const CT = Object.create(null);
|
|
||||||
dart.defineLazy(CT, {
|
|
||||||
get C0() {
|
|
||||||
return C[0] = dart.const(Object.setPrototypeOf({
|
|
||||||
}, foo.A.prototype));
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
var C = [void 0];
|
|
||||||
return dart.equals(a, C[0] || CT.C0);
|
|
||||||
}(
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('Expression compiler tests using extension symbols', () {
|
|
||||||
var source = '''
|
|
||||||
${options.dartLangComment}
|
|
||||||
void bar() {
|
|
||||||
/* evaluation placeholder */
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() => bar();
|
|
||||||
''';
|
|
||||||
|
|
||||||
late TestDriver driver;
|
|
||||||
setUp(() {
|
|
||||||
driver = TestDriver(options, source);
|
|
||||||
});
|
|
||||||
|
|
||||||
tearDown(() {
|
|
||||||
driver.delete();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('map access', () async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
|
|
||||||
expression:
|
|
||||||
'(Map<String, String> params) { return params["index"]; }({})',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const core = dart_sdk.core;
|
|
||||||
const _js_helper = dart_sdk._js_helper;
|
|
||||||
const dart = dart_sdk.dart;
|
|
||||||
const dartx = dart_sdk.dartx;
|
|
||||||
var T = {
|
|
||||||
StringL: () => (T.StringL = dart.constFn(dart.legacy(core.String)))(),
|
|
||||||
MapOfStringL\$StringL: () => (T.MapOfStringL\$StringL = dart.constFn(core.Map\$(T.StringL(), T.StringL())))(),
|
|
||||||
MapLOfStringL\$StringL: () => (T.MapLOfStringL\$StringL = dart.constFn(dart.legacy(T.MapOfStringL\$StringL())))(),
|
|
||||||
MapLOfStringL\$StringLToStringL: () => (T.MapLOfStringL\$StringLToStringL = dart.constFn(dart.fnType(T.StringL(), [T.MapLOfStringL\$StringL()])))(),
|
|
||||||
IdentityMapOfStringL\$StringL: () => (T.IdentityMapOfStringL\$StringL = dart.constFn(_js_helper.IdentityMap\$(T.StringL(), T.StringL())))()
|
|
||||||
};
|
|
||||||
var S = {\$_get: dartx._get};
|
|
||||||
return dart.fn(params => params[S.\$_get]("index"), T.MapLOfStringL\$StringLToStringL())(new (T.IdentityMapOfStringL\$StringL()).new());
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void runSoundTests(ModuleFormat moduleFormat) {
|
|
||||||
var options = SetupCompilerOptions(
|
|
||||||
soundNullSafety: true,
|
|
||||||
moduleFormat: moduleFormat,
|
|
||||||
);
|
|
||||||
|
|
||||||
group('Expression compilations on the same expression compiler |', () {
|
|
||||||
var source = '''
|
|
||||||
${options.dartLangComment}
|
|
||||||
main() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void foo() {
|
|
||||||
/* evaluation placeholder */
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
|
|
||||||
late TestDriver driver;
|
|
||||||
|
|
||||||
setUp(() {
|
|
||||||
driver = TestDriver(options, source);
|
|
||||||
});
|
|
||||||
|
|
||||||
tearDown(() {
|
|
||||||
driver.delete();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('successful expression compilations', () async {
|
|
||||||
var compiler = await driver.createCompiler();
|
|
||||||
await driver.check(
|
|
||||||
compiler: compiler,
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'true',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
return true;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
await driver.check(
|
|
||||||
compiler: compiler,
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'false',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
return false;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('some successful expression compilations', () async {
|
|
||||||
var compiler = await driver.createCompiler();
|
|
||||||
await driver.check(
|
|
||||||
compiler: compiler,
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'true',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
return true;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
await driver.check(
|
|
||||||
compiler: compiler,
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'blah',
|
|
||||||
expectedError: "Undefined name 'blah'",
|
|
||||||
);
|
|
||||||
await driver.check(
|
|
||||||
compiler: compiler,
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'false',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
return false;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('failing expression compilations', () async {
|
|
||||||
var compiler = await driver.createCompiler();
|
|
||||||
await driver.check(
|
|
||||||
compiler: compiler,
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'blah1',
|
|
||||||
expectedError: "Undefined name 'blah1'",
|
|
||||||
);
|
|
||||||
await driver.check(
|
|
||||||
compiler: compiler,
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'blah2',
|
|
||||||
expectedError: "Undefined name 'blah2'",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('Expression compiler import tests', () {
|
|
||||||
var source = '''
|
|
||||||
${options.dartLangComment}
|
|
||||||
import 'dart:io' show Directory;
|
|
||||||
import 'dart:io' as p;
|
|
||||||
import 'dart:convert' as p;
|
|
||||||
|
|
||||||
main() {
|
|
||||||
print(Directory.systemTemp);
|
|
||||||
print(p.Directory.systemTemp);
|
|
||||||
print(p.utf.decoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void foo() {
|
|
||||||
/* evaluation placeholder */
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
|
|
||||||
late TestDriver driver;
|
|
||||||
|
|
||||||
setUp(() {
|
|
||||||
driver = TestDriver(options, source);
|
|
||||||
});
|
|
||||||
|
|
||||||
tearDown(() {
|
|
||||||
driver.delete();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('expression referencing unnamed import', () async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'Directory.systemTemp',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const io = dart_sdk.io;
|
|
||||||
return io.Directory.systemTemp;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('expression referencing named import', () async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'p.Directory.systemTemp',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const io = dart_sdk.io;
|
|
||||||
return io.Directory.systemTemp;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('expression referencing another library with the same named import',
|
|
||||||
() async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{},
|
|
||||||
expression: 'p.utf8.decoder',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const convert = dart_sdk.convert;
|
|
||||||
return convert.utf8.decoder;
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('Expression compiler expressions that import extension symbols', () {
|
|
||||||
var source = '''
|
|
||||||
${options.dartLangComment}
|
|
||||||
void bar() {
|
|
||||||
/* evaluation placeholder */
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() => bar();
|
|
||||||
''';
|
|
||||||
|
|
||||||
late TestDriver driver;
|
|
||||||
setUp(() {
|
|
||||||
driver = TestDriver(options, source);
|
|
||||||
});
|
|
||||||
|
|
||||||
tearDown(() {
|
|
||||||
driver.delete();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('map access', () async {
|
|
||||||
await driver.check(
|
|
||||||
scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
|
|
||||||
expression:
|
|
||||||
'(Map<String, String> params) { return params["index"]; }({})',
|
|
||||||
expectedResult: '''
|
|
||||||
(function() {
|
|
||||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
|
||||||
const core = dart_sdk.core;
|
|
||||||
const _js_helper = dart_sdk._js_helper;
|
|
||||||
const dart = dart_sdk.dart;
|
|
||||||
const dartx = dart_sdk.dartx;
|
|
||||||
var T = {
|
|
||||||
StringN: () => (T.StringN = dart.constFn(dart.nullable(core.String)))(),
|
|
||||||
MapOfString\$String: () => (T.MapOfString\$String = dart.constFn(core.Map\$(core.String, core.String)))(),
|
|
||||||
MapOfString\$StringToStringN: () => (T.MapOfString\$StringToStringN = dart.constFn(dart.fnType(T.StringN(), [T.MapOfString\$String()])))(),
|
|
||||||
IdentityMapOfString\$String: () => (T.IdentityMapOfString\$String = dart.constFn(_js_helper.IdentityMap\$(core.String, core.String)))()
|
|
||||||
};
|
|
||||||
var S = {\$_get: dartx._get};
|
|
||||||
return dart.fn(params => params[S.\$_get]("index"), T.MapOfString\$StringToStringN())(new (T.IdentityMapOfString\$String()).new());
|
|
||||||
}(
|
|
||||||
|
|
||||||
))
|
|
||||||
''');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
import 'package:dev_compiler/dev_compiler.dart';
|
import 'package:dev_compiler/dev_compiler.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_worker_shared.dart';
|
import 'expression_compiler_worker_shared.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
// Set to true to enable debug output
|
// Set to true to enable debug output
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
import 'package:dev_compiler/dev_compiler.dart';
|
import 'package:dev_compiler/dev_compiler.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_worker_shared.dart';
|
import 'expression_compiler_worker_shared.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
// Set to true to enable debug output
|
// Set to true to enable debug output
|
||||||
|
|
|
@ -22,7 +22,7 @@ import 'package:shelf/shelf.dart';
|
||||||
import 'package:shelf/shelf_io.dart';
|
import 'package:shelf/shelf_io.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
import 'setup_compiler_options.dart';
|
import '../shared_test_options.dart';
|
||||||
|
|
||||||
void runTests(SetupCompilerOptions setup, {bool verbose = false}) {
|
void runTests(SetupCompilerOptions setup, {bool verbose = false}) {
|
||||||
group('expression compiler worker on startup', () {
|
group('expression compiler worker on startup', () {
|
||||||
|
@ -77,37 +77,20 @@ void runTests(SetupCompilerOptions setup, {bool verbose = false}) {
|
||||||
});
|
});
|
||||||
|
|
||||||
group('reading assets using standard file system - ', () {
|
group('reading assets using standard file system - ', () {
|
||||||
runExpressionCompilationTests(StandardFileSystemTestDriver(
|
runExpressionCompilationTests(StandardFileSystemTestDriver(setup, verbose));
|
||||||
setup.soundNullSafety,
|
|
||||||
setup.moduleFormat,
|
|
||||||
setup.canaryFeatures,
|
|
||||||
setup.enableAsserts,
|
|
||||||
verbose,
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
group('reading assets using multiroot file system - ', () {
|
group('reading assets using multiroot file system - ', () {
|
||||||
runExpressionCompilationTests(MultiRootFileSystemTestDriver(
|
runExpressionCompilationTests(
|
||||||
setup.soundNullSafety,
|
MultiRootFileSystemTestDriver(setup, verbose));
|
||||||
setup.moduleFormat,
|
|
||||||
setup.canaryFeatures,
|
|
||||||
setup.enableAsserts,
|
|
||||||
verbose,
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
group('reading assets using asset file system -', () {
|
group('reading assets using asset file system -', () {
|
||||||
runExpressionCompilationTests(AssetFileSystemTestDriver(
|
runExpressionCompilationTests(AssetFileSystemTestDriver(setup, verbose));
|
||||||
setup.soundNullSafety,
|
|
||||||
setup.moduleFormat,
|
|
||||||
setup.canaryFeatures,
|
|
||||||
setup.enableAsserts,
|
|
||||||
verbose,
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void runExpressionCompilationTests(TestDriver driver) {
|
void runExpressionCompilationTests(ExpressionCompilerWorkerTestDriver driver) {
|
||||||
group('expression compiler worker', () {
|
group('expression compiler worker', () {
|
||||||
setUpAll(() async {
|
setUpAll(() async {
|
||||||
await driver.setUpAll();
|
await driver.setUpAll();
|
||||||
|
@ -963,13 +946,9 @@ class E {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class TestDriver {
|
abstract class ExpressionCompilerWorkerTestDriver {
|
||||||
final bool soundNullSafety;
|
SetupCompilerOptions setup;
|
||||||
final ModuleFormat moduleFormat;
|
bool verbose;
|
||||||
final bool canaryFeatures;
|
|
||||||
final bool enableAsserts;
|
|
||||||
final bool verbose;
|
|
||||||
|
|
||||||
late FileSystem assetFileSystem;
|
late FileSystem assetFileSystem;
|
||||||
|
|
||||||
late Directory tempDir;
|
late Directory tempDir;
|
||||||
|
@ -981,13 +960,7 @@ abstract class TestDriver {
|
||||||
ExpressionCompilerWorker? worker;
|
ExpressionCompilerWorker? worker;
|
||||||
Future<void>? workerDone;
|
Future<void>? workerDone;
|
||||||
|
|
||||||
TestDriver(
|
ExpressionCompilerWorkerTestDriver(this.setup, this.verbose);
|
||||||
this.soundNullSafety,
|
|
||||||
this.moduleFormat,
|
|
||||||
this.canaryFeatures,
|
|
||||||
this.enableAsserts,
|
|
||||||
this.verbose,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Initialize file systems, inputs, and start servers if needed.
|
/// Initialize file systems, inputs, and start servers if needed.
|
||||||
Future<void> start();
|
Future<void> start();
|
||||||
|
@ -996,7 +969,8 @@ abstract class TestDriver {
|
||||||
|
|
||||||
Future<void> setUpAll() async {
|
Future<void> setUpAll() async {
|
||||||
tempDir = Directory.systemTemp.createTempSync('foo bar');
|
tempDir = Directory.systemTemp.createTempSync('foo bar');
|
||||||
config = TestProjectConfiguration(tempDir, soundNullSafety, moduleFormat)
|
config = TestProjectConfiguration(
|
||||||
|
tempDir, setup.soundNullSafety, setup.moduleFormat)
|
||||||
..initialize();
|
..initialize();
|
||||||
|
|
||||||
await start();
|
await start();
|
||||||
|
@ -1026,10 +1000,10 @@ abstract class TestDriver {
|
||||||
fileSystem: assetFileSystem,
|
fileSystem: assetFileSystem,
|
||||||
requestStream: requestController.stream,
|
requestStream: requestController.stream,
|
||||||
sendResponse: responseController.add,
|
sendResponse: responseController.add,
|
||||||
soundNullSafety: soundNullSafety,
|
soundNullSafety: setup.soundNullSafety,
|
||||||
moduleFormat: moduleFormat,
|
moduleFormat: setup.moduleFormat,
|
||||||
canaryFeatures: canaryFeatures,
|
canaryFeatures: setup.canaryFeatures,
|
||||||
enableAsserts: enableAsserts,
|
enableAsserts: setup.enableAsserts,
|
||||||
verbose: verbose,
|
verbose: verbose,
|
||||||
);
|
);
|
||||||
workerDone = worker?.run();
|
workerDone = worker?.run();
|
||||||
|
@ -1043,15 +1017,9 @@ abstract class TestDriver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StandardFileSystemTestDriver extends TestDriver {
|
class StandardFileSystemTestDriver extends ExpressionCompilerWorkerTestDriver {
|
||||||
StandardFileSystemTestDriver(
|
StandardFileSystemTestDriver(SetupCompilerOptions setup, bool verbose)
|
||||||
bool soundNullSafety,
|
: super(setup, verbose);
|
||||||
ModuleFormat moduleFormat,
|
|
||||||
bool canaryFeatures,
|
|
||||||
bool enableAsserts,
|
|
||||||
bool verbose,
|
|
||||||
) : super(soundNullSafety, moduleFormat, canaryFeatures, enableAsserts,
|
|
||||||
verbose);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> start() async {
|
Future<void> start() async {
|
||||||
|
@ -1060,15 +1028,9 @@ class StandardFileSystemTestDriver extends TestDriver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiRootFileSystemTestDriver extends TestDriver {
|
class MultiRootFileSystemTestDriver extends ExpressionCompilerWorkerTestDriver {
|
||||||
MultiRootFileSystemTestDriver(
|
MultiRootFileSystemTestDriver(SetupCompilerOptions setup, bool verbose)
|
||||||
bool soundNullSafety,
|
: super(setup, verbose);
|
||||||
ModuleFormat moduleFormat,
|
|
||||||
bool canaryFeatures,
|
|
||||||
bool enableAsserts,
|
|
||||||
bool verbose,
|
|
||||||
) : super(soundNullSafety, moduleFormat, canaryFeatures, enableAsserts,
|
|
||||||
verbose);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> start() async {
|
Future<void> start() async {
|
||||||
|
@ -1079,18 +1041,12 @@ class MultiRootFileSystemTestDriver extends TestDriver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetFileSystemTestDriver extends TestDriver {
|
class AssetFileSystemTestDriver extends ExpressionCompilerWorkerTestDriver {
|
||||||
late TestAssetServer server;
|
late TestAssetServer server;
|
||||||
late int port;
|
late int port;
|
||||||
|
|
||||||
AssetFileSystemTestDriver(
|
AssetFileSystemTestDriver(SetupCompilerOptions setup, bool verbose)
|
||||||
bool soundNullSafety,
|
: super(setup, verbose);
|
||||||
ModuleFormat moduleFormat,
|
|
||||||
bool canaryFeatures,
|
|
||||||
bool enableAsserts,
|
|
||||||
bool verbose,
|
|
||||||
) : super(soundNullSafety, moduleFormat, canaryFeatures, enableAsserts,
|
|
||||||
verbose);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> start() async {
|
Future<void> start() async {
|
||||||
|
|
|
@ -6,11 +6,11 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
import 'expression_compiler_e2e_suite.dart';
|
import 'expression_compiler_e2e_suite.dart';
|
||||||
import 'setup_compiler_options.dart';
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
var driver = await TestDriver.init();
|
var driver = await ExpressionEvaluationTestDriver.init();
|
||||||
|
|
||||||
tearDownAll(() async {
|
tearDownAll(() async {
|
||||||
await driver.finish();
|
await driver.finish();
|
||||||
|
@ -116,7 +116,8 @@ main() {
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
|
|
||||||
void runSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
void runSharedTests(
|
||||||
|
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||||
group('Runtime debugging API |', () {
|
group('Runtime debugging API |', () {
|
||||||
var source = simpleClassSource;
|
var source = simpleClassSource;
|
||||||
|
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
// Copyright (c) 2023, 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 'package:dev_compiler/src/compiler/module_builder.dart';
|
|
||||||
import 'package:dev_compiler/src/kernel/command.dart';
|
|
||||||
import 'package:dev_compiler/src/kernel/target.dart' show DevCompilerTarget;
|
|
||||||
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
|
||||||
import 'package:front_end/src/compute_platform_binaries_location.dart' as fe;
|
|
||||||
import 'package:kernel/target/targets.dart';
|
|
||||||
import 'package:path/path.dart' as p;
|
|
||||||
|
|
||||||
class SetupCompilerOptions {
|
|
||||||
static final sdkRoot = fe.computePlatformBinariesLocation();
|
|
||||||
static final buildRoot =
|
|
||||||
fe.computePlatformBinariesLocation(forceBuildDir: true);
|
|
||||||
static final sdkUnsoundSummaryPath =
|
|
||||||
buildRoot.resolve('ddc_outline_unsound.dill').toFilePath();
|
|
||||||
static final sdkSoundSummaryPath =
|
|
||||||
buildRoot.resolve('ddc_outline.dill').toFilePath();
|
|
||||||
static final librariesSpecificationUri =
|
|
||||||
buildRoot.resolve('lib/libraries.json').toFilePath();
|
|
||||||
|
|
||||||
final bool legacyCode;
|
|
||||||
final List<String> errors = [];
|
|
||||||
final List<String> diagnosticMessages = [];
|
|
||||||
final ModuleFormat moduleFormat;
|
|
||||||
final fe.CompilerOptions options;
|
|
||||||
final bool soundNullSafety;
|
|
||||||
final bool canaryFeatures;
|
|
||||||
final bool enableAsserts;
|
|
||||||
|
|
||||||
static fe.CompilerOptions _getOptions(
|
|
||||||
{required bool enableAsserts, required bool soundNullSafety}) {
|
|
||||||
var options = fe.CompilerOptions()
|
|
||||||
..verbose = false // set to true for debugging
|
|
||||||
..sdkRoot = sdkRoot
|
|
||||||
..target =
|
|
||||||
DevCompilerTarget(TargetFlags(soundNullSafety: soundNullSafety))
|
|
||||||
..librariesSpecificationUri = p.toUri('sdk/lib/libraries.json')
|
|
||||||
..omitPlatform = true
|
|
||||||
..sdkSummary =
|
|
||||||
p.toUri(soundNullSafety ? sdkSoundSummaryPath : sdkUnsoundSummaryPath)
|
|
||||||
..environmentDefines =
|
|
||||||
addGeneratedVariables({}, enableAsserts: enableAsserts)
|
|
||||||
..nnbdMode = soundNullSafety ? fe.NnbdMode.Strong : fe.NnbdMode.Weak;
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetupCompilerOptions._({
|
|
||||||
this.enableAsserts = true,
|
|
||||||
this.soundNullSafety = true,
|
|
||||||
this.legacyCode = false,
|
|
||||||
this.moduleFormat = ModuleFormat.amd,
|
|
||||||
this.canaryFeatures = false,
|
|
||||||
}) : options = _getOptions(
|
|
||||||
soundNullSafety: soundNullSafety, enableAsserts: enableAsserts) {
|
|
||||||
options.onDiagnostic = (fe.DiagnosticMessage m) {
|
|
||||||
diagnosticMessages.addAll(m.plainTextFormatted);
|
|
||||||
if (m.severity == fe.Severity.error ||
|
|
||||||
m.severity == fe.Severity.internalProblem) {
|
|
||||||
errors.addAll(m.plainTextFormatted);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates current compiler setup options.
|
|
||||||
///
|
|
||||||
/// Reads options determined by the test configuration from the configuration
|
|
||||||
/// environment variable set by the test runner.
|
|
||||||
///
|
|
||||||
/// To run tests locally using test.py, pass a vm option defining required
|
|
||||||
/// configuration, for example:
|
|
||||||
///
|
|
||||||
/// `./tools/test.py -n web-dev-canary-unittest-asserts-mac`
|
|
||||||
///
|
|
||||||
/// To run a single test locally, pass the --canary or --enable-asserts flags
|
|
||||||
/// to the command line to enable corresponding features, for example:
|
|
||||||
///
|
|
||||||
/// `dart test/expression_compiler/assertions_enabled_test.dart --canary --enable-asserts`
|
|
||||||
factory SetupCompilerOptions({
|
|
||||||
bool soundNullSafety = true,
|
|
||||||
bool legacyCode = false,
|
|
||||||
ModuleFormat moduleFormat = ModuleFormat.amd,
|
|
||||||
List<String> args = const <String>[],
|
|
||||||
}) {
|
|
||||||
// Find if the test is run with arguments overriding the configuration
|
|
||||||
late bool enableAsserts;
|
|
||||||
late bool canaryFeatures;
|
|
||||||
|
|
||||||
// Read configuration settings from matrix.json
|
|
||||||
var configuration = String.fromEnvironment('test_runner.configuration');
|
|
||||||
if (configuration.isEmpty) {
|
|
||||||
// If not running from test runner, read options from the args
|
|
||||||
enableAsserts = args.contains('--enable-asserts');
|
|
||||||
canaryFeatures = args.contains('--canary');
|
|
||||||
} else {
|
|
||||||
// If running from the test runner, read options from the environment
|
|
||||||
// (set to configuration settings from matrix.json).
|
|
||||||
enableAsserts = configuration.contains('-asserts-');
|
|
||||||
canaryFeatures = configuration.contains('-canary-');
|
|
||||||
}
|
|
||||||
return SetupCompilerOptions._(
|
|
||||||
enableAsserts: enableAsserts,
|
|
||||||
soundNullSafety: soundNullSafety,
|
|
||||||
legacyCode: legacyCode,
|
|
||||||
moduleFormat: moduleFormat,
|
|
||||||
canaryFeatures: canaryFeatures,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
154
pkg/dev_compiler/test/expression_compiler/test_compiler.dart
Normal file
154
pkg/dev_compiler/test/expression_compiler/test_compiler.dart
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
// Copyright (c) 2023, 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:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io' show File;
|
||||||
|
|
||||||
|
import 'package:dev_compiler/src/compiler/shared_command.dart'
|
||||||
|
show SharedCompilerOptions;
|
||||||
|
import 'package:dev_compiler/src/kernel/command.dart';
|
||||||
|
import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler;
|
||||||
|
import 'package:dev_compiler/src/kernel/expression_compiler.dart'
|
||||||
|
show ExpressionCompiler;
|
||||||
|
import 'package:dev_compiler/src/kernel/module_metadata.dart';
|
||||||
|
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
||||||
|
import 'package:kernel/ast.dart' show Component, Library;
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:source_maps/source_maps.dart' as source_maps;
|
||||||
|
|
||||||
|
import '../shared_test_options.dart';
|
||||||
|
|
||||||
|
class TestCompilationResult {
|
||||||
|
final String? result;
|
||||||
|
final bool isSuccess;
|
||||||
|
|
||||||
|
TestCompilationResult(this.result, this.isSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestExpressionCompiler {
|
||||||
|
final SetupCompilerOptions setup;
|
||||||
|
final Component component;
|
||||||
|
final ExpressionCompiler compiler;
|
||||||
|
final ModuleMetadata? metadata;
|
||||||
|
final source_maps.SingleMapping sourceMap;
|
||||||
|
|
||||||
|
TestExpressionCompiler._(
|
||||||
|
this.setup, this.component, this.compiler, this.metadata, this.sourceMap);
|
||||||
|
|
||||||
|
static Future<TestExpressionCompiler> init(SetupCompilerOptions setup,
|
||||||
|
{required Uri input,
|
||||||
|
required Uri output,
|
||||||
|
Uri? packages,
|
||||||
|
Map<String, bool> experiments = const {}}) async {
|
||||||
|
setup.diagnosticMessages.clear();
|
||||||
|
setup.errors.clear();
|
||||||
|
// Initialize the incremental compiler and module component.
|
||||||
|
// TODO: extend this for multi-module compilations by storing separate
|
||||||
|
// compilers/components/names per module.
|
||||||
|
setup.options.packagesFileUri = packages;
|
||||||
|
setup.options.explicitExperimentalFlags.addAll(fe.parseExperimentalFlags(
|
||||||
|
experiments,
|
||||||
|
onError: (message) => throw Exception(message)));
|
||||||
|
var frontend = DevelopmentIncrementalCompiler(setup.options, input);
|
||||||
|
var compilerResult = await frontend.computeDelta();
|
||||||
|
var component = compilerResult.component;
|
||||||
|
component.computeCanonicalNames();
|
||||||
|
// Initialize DDC.
|
||||||
|
var moduleName = p.basenameWithoutExtension(output.toFilePath());
|
||||||
|
|
||||||
|
var classHierarchy = compilerResult.classHierarchy!;
|
||||||
|
var compilerOptions = SharedCompilerOptions(
|
||||||
|
replCompile: true,
|
||||||
|
moduleName: moduleName,
|
||||||
|
experiments: experiments,
|
||||||
|
soundNullSafety: setup.soundNullSafety,
|
||||||
|
emitDebugMetadata: true,
|
||||||
|
canaryFeatures: setup.canaryFeatures,
|
||||||
|
enableAsserts: setup.enableAsserts,
|
||||||
|
);
|
||||||
|
var coreTypes = compilerResult.coreTypes;
|
||||||
|
|
||||||
|
final importToSummary = Map<Library, Component>.identity();
|
||||||
|
final summaryToModule = Map<Component, String>.identity();
|
||||||
|
for (var lib in component.libraries) {
|
||||||
|
importToSummary[lib] = component;
|
||||||
|
}
|
||||||
|
summaryToModule[component] = moduleName;
|
||||||
|
|
||||||
|
var kernel2jsCompiler = ProgramCompiler(component, classHierarchy,
|
||||||
|
compilerOptions, importToSummary, summaryToModule,
|
||||||
|
coreTypes: coreTypes);
|
||||||
|
var module = kernel2jsCompiler.emitModule(component);
|
||||||
|
|
||||||
|
// Perform a full compile, writing the compiled JS + sourcemap.
|
||||||
|
var code = jsProgramToCode(
|
||||||
|
module,
|
||||||
|
setup.moduleFormat,
|
||||||
|
inlineSourceMap: compilerOptions.inlineSourceMap,
|
||||||
|
buildSourceMap: compilerOptions.sourceMap,
|
||||||
|
emitDebugMetadata: compilerOptions.emitDebugMetadata,
|
||||||
|
emitDebugSymbols: compilerOptions.emitDebugSymbols,
|
||||||
|
jsUrl: '$output',
|
||||||
|
mapUrl: '$output.map',
|
||||||
|
compiler: kernel2jsCompiler,
|
||||||
|
component: component,
|
||||||
|
);
|
||||||
|
var codeBytes = utf8.encode(code.code);
|
||||||
|
var sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
|
||||||
|
|
||||||
|
File(output.toFilePath()).writeAsBytesSync(codeBytes);
|
||||||
|
File('${output.toFilePath()}.map').writeAsBytesSync(sourceMapBytes);
|
||||||
|
|
||||||
|
// Save the expression compiler for future compilation.
|
||||||
|
var compiler = ExpressionCompiler(
|
||||||
|
setup.options,
|
||||||
|
setup.moduleFormat,
|
||||||
|
setup.errors,
|
||||||
|
frontend,
|
||||||
|
kernel2jsCompiler,
|
||||||
|
component,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (setup.errors.isNotEmpty) {
|
||||||
|
throw Exception('Compilation failed with: ${setup.errors}');
|
||||||
|
}
|
||||||
|
setup.diagnosticMessages.clear();
|
||||||
|
setup.errors.clear();
|
||||||
|
|
||||||
|
var sourceMap = source_maps.SingleMapping.fromJson(
|
||||||
|
code.sourceMap!.cast<String, dynamic>());
|
||||||
|
return TestExpressionCompiler._(
|
||||||
|
setup, component, compiler, code.metadata, sourceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TestCompilationResult> compileExpression(
|
||||||
|
{required Uri input,
|
||||||
|
required int line,
|
||||||
|
required int column,
|
||||||
|
required Map<String, String> scope,
|
||||||
|
required String expression}) async {
|
||||||
|
// clear previous errors
|
||||||
|
setup.errors.clear();
|
||||||
|
|
||||||
|
var libraryUri = metadataForLibraryUri(input);
|
||||||
|
var jsExpression = await compiler.compileExpressionToJs(
|
||||||
|
libraryUri.importUri, line, column, scope, expression);
|
||||||
|
if (setup.errors.isNotEmpty) {
|
||||||
|
jsExpression = setup.errors.toString().replaceAll(
|
||||||
|
RegExp(
|
||||||
|
r'org-dartlang-debug:synthetic_debug_expression:[0-9]*:[0-9]*:'),
|
||||||
|
'');
|
||||||
|
|
||||||
|
return TestCompilationResult(jsExpression, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TestCompilationResult(jsExpression, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
LibraryMetadata metadataForLibraryUri(Uri libraryUri) =>
|
||||||
|
metadata!.libraries.entries
|
||||||
|
.firstWhere((entry) => entry.value.fileUri == '$libraryUri')
|
||||||
|
.value;
|
||||||
|
}
|
|
@ -5,97 +5,139 @@
|
||||||
import 'package:dev_compiler/src/compiler/module_builder.dart'
|
import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||||
show ModuleFormat;
|
show ModuleFormat;
|
||||||
import 'package:dev_compiler/src/kernel/command.dart'
|
import 'package:dev_compiler/src/kernel/command.dart'
|
||||||
show addGeneratedVariables, getSdkPath;
|
show addGeneratedVariables;
|
||||||
import 'package:dev_compiler/src/kernel/target.dart' show DevCompilerTarget;
|
import 'package:dev_compiler/src/kernel/target.dart' show DevCompilerTarget;
|
||||||
import 'package:front_end/src/api_unstable/ddc.dart';
|
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
||||||
import 'package:front_end/src/compute_platform_binaries_location.dart';
|
import 'package:front_end/src/compute_platform_binaries_location.dart' as fe;
|
||||||
import 'package:front_end/src/fasta/incremental_serializer.dart';
|
import 'package:front_end/src/fasta/incremental_serializer.dart' as fe;
|
||||||
import 'package:kernel/ast.dart' show Component;
|
import 'package:kernel/ast.dart' show Component;
|
||||||
import 'package:kernel/target/targets.dart';
|
import 'package:kernel/target/targets.dart' show TargetFlags;
|
||||||
import 'package:path/path.dart' as p;
|
|
||||||
|
|
||||||
class DevelopmentIncrementalCompiler extends IncrementalCompiler {
|
class DevelopmentIncrementalCompiler extends fe.IncrementalCompiler {
|
||||||
Uri entryPoint;
|
Uri entryPoint;
|
||||||
|
|
||||||
DevelopmentIncrementalCompiler(CompilerOptions options, this.entryPoint,
|
DevelopmentIncrementalCompiler(fe.CompilerOptions options, this.entryPoint,
|
||||||
[Uri? initializeFrom,
|
[Uri? initializeFrom,
|
||||||
bool? outlineOnly,
|
bool? outlineOnly,
|
||||||
IncrementalSerializer? incrementalSerializer])
|
fe.IncrementalSerializer? incrementalSerializer])
|
||||||
: super(
|
: super(
|
||||||
CompilerContext(
|
fe.CompilerContext(
|
||||||
ProcessedOptions(options: options, inputs: [entryPoint])),
|
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||||
initializeFrom,
|
initializeFrom,
|
||||||
outlineOnly,
|
outlineOnly,
|
||||||
incrementalSerializer);
|
incrementalSerializer);
|
||||||
|
|
||||||
DevelopmentIncrementalCompiler.fromComponent(CompilerOptions options,
|
DevelopmentIncrementalCompiler.fromComponent(fe.CompilerOptions options,
|
||||||
this.entryPoint, Component componentToInitializeFrom,
|
this.entryPoint, Component componentToInitializeFrom,
|
||||||
[bool? outlineOnly, IncrementalSerializer? incrementalSerializer])
|
[bool? outlineOnly, fe.IncrementalSerializer? incrementalSerializer])
|
||||||
: super.fromComponent(
|
: super.fromComponent(
|
||||||
CompilerContext(
|
fe.CompilerContext(
|
||||||
ProcessedOptions(options: options, inputs: [entryPoint])),
|
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||||
componentToInitializeFrom,
|
componentToInitializeFrom,
|
||||||
outlineOnly,
|
outlineOnly,
|
||||||
incrementalSerializer);
|
incrementalSerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetupCompilerOptions {
|
class SetupCompilerOptions {
|
||||||
static final sdkRoot = computePlatformBinariesLocation();
|
static final sdkRoot = fe.computePlatformBinariesLocation();
|
||||||
// Unsound .dill files are not longer in the released SDK so this file must be
|
static final buildRoot =
|
||||||
// read from the build output directory.
|
fe.computePlatformBinariesLocation(forceBuildDir: true);
|
||||||
static final sdkUnsoundSummaryPath =
|
static final _sdkUnsoundSummaryPath =
|
||||||
computePlatformBinariesLocation(forceBuildDir: true)
|
buildRoot.resolve('ddc_outline_unsound.dill');
|
||||||
.resolve('ddc_outline_unsound.dill');
|
static final _sdkSoundSummaryPath = buildRoot.resolve('ddc_outline.dill');
|
||||||
// Use the outline copied to the released SDK.
|
|
||||||
static final sdkSoundSummaryPath = sdkRoot.resolve('ddc_outline.dill');
|
|
||||||
static final librariesSpecificationUri =
|
|
||||||
p.join(p.dirname(p.dirname(getSdkPath())), 'libraries.json');
|
|
||||||
|
|
||||||
static CompilerOptions getOptions(bool soundNullSafety) {
|
static final _dartUnsoundComment = '// @dart = 2.9';
|
||||||
var options = CompilerOptions()
|
static final _dartSoundComment = '//';
|
||||||
|
String get dartLangComment =>
|
||||||
|
soundNullSafety ? _dartSoundComment : _dartUnsoundComment;
|
||||||
|
|
||||||
|
final bool legacyCode;
|
||||||
|
final List<String> errors = [];
|
||||||
|
final List<String> diagnosticMessages = [];
|
||||||
|
final ModuleFormat moduleFormat;
|
||||||
|
final fe.CompilerOptions options;
|
||||||
|
final bool soundNullSafety;
|
||||||
|
final bool canaryFeatures;
|
||||||
|
final bool enableAsserts;
|
||||||
|
|
||||||
|
static fe.CompilerOptions _getOptions(
|
||||||
|
{required bool enableAsserts, required bool soundNullSafety}) {
|
||||||
|
var options = fe.CompilerOptions()
|
||||||
..verbose = false // set to true for debugging
|
..verbose = false // set to true for debugging
|
||||||
..sdkRoot = sdkRoot
|
..sdkRoot = sdkRoot
|
||||||
..target =
|
..target =
|
||||||
DevCompilerTarget(TargetFlags(soundNullSafety: soundNullSafety))
|
DevCompilerTarget(TargetFlags(soundNullSafety: soundNullSafety))
|
||||||
..librariesSpecificationUri = Uri.base.resolve('sdk/lib/libraries.json')
|
|
||||||
..omitPlatform = true
|
..omitPlatform = true
|
||||||
..sdkSummary =
|
..sdkSummary =
|
||||||
soundNullSafety ? sdkSoundSummaryPath : sdkUnsoundSummaryPath
|
soundNullSafety ? _sdkSoundSummaryPath : _sdkUnsoundSummaryPath
|
||||||
..environmentDefines = addGeneratedVariables({}, enableAsserts: true)
|
..environmentDefines =
|
||||||
..nnbdMode = soundNullSafety ? NnbdMode.Strong : NnbdMode.Weak;
|
addGeneratedVariables({}, enableAsserts: enableAsserts)
|
||||||
|
..nnbdMode = soundNullSafety ? fe.NnbdMode.Strong : fe.NnbdMode.Weak;
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String dartUnsoundComment = '// @dart = 2.9';
|
SetupCompilerOptions._({
|
||||||
static final String dartSoundComment = '//';
|
this.enableAsserts = true,
|
||||||
|
|
||||||
final List<String> errors = [];
|
|
||||||
final CompilerOptions options;
|
|
||||||
final String dartLangComment;
|
|
||||||
final ModuleFormat moduleFormat;
|
|
||||||
final bool soundNullSafety;
|
|
||||||
final bool canaryFeatures;
|
|
||||||
|
|
||||||
SetupCompilerOptions({
|
|
||||||
this.soundNullSafety = true,
|
this.soundNullSafety = true,
|
||||||
|
this.legacyCode = false,
|
||||||
this.moduleFormat = ModuleFormat.amd,
|
this.moduleFormat = ModuleFormat.amd,
|
||||||
this.canaryFeatures = false,
|
this.canaryFeatures = false,
|
||||||
}) : options = getOptions(soundNullSafety),
|
}) : options = _getOptions(
|
||||||
dartLangComment =
|
soundNullSafety: soundNullSafety, enableAsserts: enableAsserts) {
|
||||||
soundNullSafety ? dartSoundComment : dartUnsoundComment {
|
options.onDiagnostic = (fe.DiagnosticMessage m) {
|
||||||
options.onDiagnostic = (DiagnosticMessage m) {
|
diagnosticMessages.addAll(m.plainTextFormatted);
|
||||||
errors.addAll(m.plainTextFormatted);
|
if (m.severity == fe.Severity.error ||
|
||||||
|
m.severity == fe.Severity.internalProblem) {
|
||||||
|
errors.addAll(m.plainTextFormatted);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
String get loadModule {
|
/// Creates current compiler setup options.
|
||||||
switch (moduleFormat) {
|
///
|
||||||
case ModuleFormat.amd:
|
/// Reads options determined by the test configuration from the configuration
|
||||||
return 'require';
|
/// environment variable set by the test runner.
|
||||||
case ModuleFormat.ddc:
|
///
|
||||||
return 'dart_library.import';
|
/// To run tests locally using test.py, pass a vm option defining required
|
||||||
default:
|
/// configuration, for example:
|
||||||
throw UnsupportedError('Module format: $moduleFormat');
|
///
|
||||||
|
/// `./tools/test.py -n web-dev-canary-unittest-asserts-mac`
|
||||||
|
///
|
||||||
|
/// To run a single test locally, pass the --canary or --enable-asserts flags
|
||||||
|
/// to the command line to enable corresponding features, for example:
|
||||||
|
///
|
||||||
|
/// `dart test/expression_compiler/assertions_enabled_test.dart --canary --enable-asserts`
|
||||||
|
factory SetupCompilerOptions({
|
||||||
|
bool soundNullSafety = true,
|
||||||
|
bool legacyCode = false,
|
||||||
|
ModuleFormat moduleFormat = ModuleFormat.amd,
|
||||||
|
List<String> args = const <String>[],
|
||||||
|
}) {
|
||||||
|
// Find if the test is run with arguments overriding the configuration
|
||||||
|
late bool enableAsserts;
|
||||||
|
late bool canaryFeatures;
|
||||||
|
|
||||||
|
// Read configuration settings from matrix.json
|
||||||
|
var configuration = String.fromEnvironment('test_runner.configuration');
|
||||||
|
if (configuration.isEmpty) {
|
||||||
|
// If not running from test runner, read options from the args
|
||||||
|
enableAsserts = args.contains('--enable-asserts');
|
||||||
|
canaryFeatures = args.contains('--canary');
|
||||||
|
} else {
|
||||||
|
// If running from the test runner, read options from the environment
|
||||||
|
// (set to configuration settings from matrix.json).
|
||||||
|
enableAsserts = configuration.contains('-asserts-');
|
||||||
|
canaryFeatures = configuration.contains('-canary-');
|
||||||
}
|
}
|
||||||
|
return SetupCompilerOptions._(
|
||||||
|
enableAsserts: enableAsserts,
|
||||||
|
soundNullSafety: soundNullSafety,
|
||||||
|
legacyCode: legacyCode,
|
||||||
|
moduleFormat: moduleFormat,
|
||||||
|
canaryFeatures: canaryFeatures,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get loadModule =>
|
||||||
|
moduleFormat == ModuleFormat.amd ? 'require' : 'dart_library.import';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue