Add tests for expression compilation with sound null safety
Change-Id: I895b769ce203c2aed0cfcce9f1fca70f42dbb97c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/172689
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Anna Gringauze <annagrin@google.com>
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
index 48eb3ed..0580af9 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
@@ -50,27 +50,36 @@
class SetupCompilerOptions {
static final sdkRoot = computePlatformBinariesLocation();
- static final sdkSummaryPath = p.join(sdkRoot.path, 'ddc_sdk.dill');
+ static final sdkUnsoundSummaryPath = p.join(sdkRoot.path, 'ddc_sdk.dill');
+ static final sdkSoundSummaryPath =
+ p.join(sdkRoot.path, 'ddc_outline_sound.dill');
static final librariesSpecificationUri =
p.join(p.dirname(p.dirname(getSdkPath())), 'libraries.json');
- static CompilerOptions getOptions() {
+ static CompilerOptions getOptions(bool soundNullSafety) {
var options = CompilerOptions()
..verbose = false // set to true for debugging
..sdkRoot = sdkRoot
..target = DevCompilerTarget(TargetFlags())
..librariesSpecificationUri = Uri.base.resolve('sdk/lib/libraries.json')
..omitPlatform = true
- ..sdkSummary = sdkRoot.resolve(sdkSummaryPath)
+ ..sdkSummary = sdkRoot.resolve(
+ soundNullSafety ? sdkSoundSummaryPath : sdkUnsoundSummaryPath)
..environmentDefines = const {};
return options;
}
- List<String> errors;
- final CompilerOptions options;
+ static final String dartUnsoundComment = '// @dart = 2.9';
+ static final String dartSoundComment = '//';
- SetupCompilerOptions() : options = getOptions() {
- errors = <String>[];
+ final List<String> errors = [];
+ final CompilerOptions options;
+ final String dartLangComment;
+
+ SetupCompilerOptions(bool soundNullSafety)
+ : options = getOptions(soundNullSafety),
+ dartLangComment =
+ soundNullSafety ? dartSoundComment : dartUnsoundComment {
options.onDiagnostic = (DiagnosticMessage m) {
errors.addAll(m.plainTextFormatted);
};
@@ -281,1563 +290,1564 @@
}
void main() {
- var options = SetupCompilerOptions();
+ group('Unsound null safety', () {
+ var options = SetupCompilerOptions(false);
- group('Expression compiler tests in extension method:', () {
- const source = '''
- // @dart = 2.9
- extension NumberParsing on String {
- int parseInt() {
- var ret = int.parse(this);
- /* evaluation placeholder */
- return ret;
- }
- }
- main() => 0;
- ''';
-
- TestDriver driver;
-
- setUp(() {
- driver = TestDriver(options, source);
- });
-
- tearDown(() {
- driver.delete();
- });
-
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'ret': '1234'},
- expression: 'typo',
- expectedError: "Error: Getter not found: 'typo'");
- });
-
- test('local (trimmed scope)', () async {
- // Test that current expression evaluation works in extension methods.
- //
- // Note: the actual scope is {#this, ret}, but #this is effectively
- // removed in the expression compilator because it does not exist
- // in JavaScript code.
- // See (full scope) tests for what will the evaluation will look like
- // when the mapping from dart symbols to JavaScipt symbols is added.
- await driver.check(
- scope: <String, String>{'ret': '1234'},
- expression: 'ret',
- expectedResult: '''
- (function(ret) {
+ group('Expression compiler tests in extension method:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ var ret = int.parse(this);
+ /* evaluation placeholder */
return ret;
- }(
- 1234
- ))
- ''');
- });
-
- test('local (full scope)', () async {
- // Test evalution in extension methods in the future when the mapping
- // from kernel symbols to dartdevc symbols is added.
- //
- // Note: this currently fails due to
- // - incremental compiler not allowing #this as a parameter name
- await driver.check(
- scope: <String, String>{'ret': '1234', '#this': 'this'},
- expression: 'ret',
- expectedError:
- "Illegal parameter name '#this' found during expression compilation.");
- });
-
- test('this (full scope)', () async {
- // Test evalution in extension methods in the future when the mapping
- // from kernel symbols to dartdevc symbols is added.
- //
- // Note: this currently fails due to
- // - incremental compiler not allowing #this as a parameter name
- // - incremental compiler not mapping 'this' from user input to '#this'
- await driver.check(
- scope: <String, String>{'ret': '1234', '#this': 'this'},
- expression: 'this',
- expectedError:
- "Illegal parameter name '#this' found during expression compilation.");
- });
- });
-
- group('Expression compiler tests in static function:', () {
- const source = '''
- // @dart = 2.9
- int foo(int x, {int y}) {
- int z = 0;
- /* evaluation placeholder */
- return x + y + z;
- }
-
- main() => 0;
+ }
+ }
+ main() => 0;
''';
- TestDriver driver;
+ TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'ret': '1234'},
+ expression: 'typo',
+ expectedError: "Error: Getter not found: 'typo'");
+ });
+
+ test('local (trimmed scope)', () async {
+ // Test that current expression evaluation works in extension methods.
+ //
+ // Note: the actual scope is {#this, ret}, but #this is effectively
+ // removed in the expression compilator because it does not exist
+ // in JavaScript code.
+ // See (full scope) tests for what will the evaluation will look like
+ // when the mapping from dart symbols to JavaScipt symbols is added.
+ await driver.check(
+ scope: <String, String>{'ret': '1234'},
+ expression: 'ret',
+ expectedResult: '''
+ (function(ret) {
+ return ret;
+ }(
+ 1234
+ ))
+ ''');
+ });
+
+ test('local (full scope)', () async {
+ // Test evalution in extension methods in the future when the mapping
+ // from kernel symbols to dartdevc symbols is added.
+ //
+ // Note: this currently fails due to
+ // - incremental compiler not allowing #this as a parameter name
+ await driver.check(
+ scope: <String, String>{'ret': '1234', '#this': 'this'},
+ expression: 'ret',
+ expectedError:
+ "Illegal parameter name '#this' found during expression compilation.");
+ });
+
+ test('this (full scope)', () async {
+ // Test evalution in extension methods in the future when the mapping
+ // from kernel symbols to dartdevc symbols is added.
+ //
+ // Note: this currently fails due to
+ // - incremental compiler not allowing #this as a parameter name
+ // - incremental compiler not mapping 'this' from user input to '#this'
+ await driver.check(
+ scope: <String, String>{'ret': '1234', '#this': 'this'},
+ expression: 'this',
+ expectedError:
+ "Illegal parameter name '#this' found during expression compilation.");
+ });
});
- tearDown(() {
- driver.delete();
- });
-
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
- expression: 'typo',
- expectedError: "Getter not found: \'typo\'");
- });
-
- test('local', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
- expression: 'x',
- expectedResult: '''
- (function(x, y, z) {
- return x;
- }(
- 1,
- 2,
- 3
- ))
- ''');
- });
-
- test('formal', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
- expression: 'y',
- expectedResult: '''
- (function(x, y, z) {
- return y;
- }(
- 1,
- 2,
- 3
- ))
- ''');
- });
-
- test('named formal', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
- expression: 'z',
- expectedResult: '''
- (function(x, y, z) {
- return z;
- }(
- 1,
- 2,
- 3
- ))
- ''');
- });
-
- test('function', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
- expression: 'main',
- expectedResult: '''
- (function(x, y, z) {
- var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
- dart.defineLazy(CT, {
- get C0() {
- return C0 = dart.fn(foo.main, VoidTodynamic());
- }
- }, false);
- var C0;
- return C0 || CT.C0;
- }(
- 1,
- 2,
- 3
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in method:', () {
- const source = '''
- // @dart = 2.9
- extension NumberParsing on String {
- int parseInt() {
- return int.parse(this);
- }
- }
-
- int global = 42;
-
- class C {
- C(int this.field, int this._field);
-
- static int staticField = 0;
- static int _staticField = 1;
-
- int _field;
- int field;
-
- int methodFieldAccess(int x) {
+ group('Expression compiler tests in static function:', () {
+ var source = '''
+ ${options.dartLangComment}
+ int foo(int x, {int y}) {
+ int z = 0;
/* evaluation placeholder */
- return x + _field + _staticField;
+ return x + y + z;
}
- Future<int> asyncMethod(int x) async {
- return x;
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'typo',
+ expectedError: "Getter not found: \'typo\'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x, y, z) {
+ return x;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ });
+
+ test('formal', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'y',
+ expectedResult: '''
+ (function(x, y, z) {
+ return y;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ });
+
+ test('named formal', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'z',
+ expectedResult: '''
+ (function(x, y, z) {
+ return z;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ });
+
+ test('function', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'main',
+ expectedResult: '''
+ (function(x, y, z) {
+ var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
+ dart.defineLazy(CT, {
+ get C0() {
+ return C0 = dart.fn(foo.main, VoidTodynamic());
+ }
+ }, false);
+ var C0;
+ return C0 || CT.C0;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in method:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
}
- }
- main() => 0;
- ''';
+ int global = 42;
- TestDriver driver;
+ class C {
+ C(int this.field, int this._field);
- setUp(() {
- driver = TestDriver(options, source);
- });
+ static int staticField = 0;
+ static int _staticField = 1;
- tearDown(() {
- driver.delete();
- });
+ int _field;
+ int field;
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'typo',
- expectedError: "The getter 'typo' isn't defined for the class 'C'");
- });
+ int methodFieldAccess(int x) {
+ /* evaluation placeholder */
+ return x + _field + _staticField;
+ }
- test('local', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x',
- expectedResult: '''
- (function(x) {
+ Future<int> asyncMethod(int x) async {
return x;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('this', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'this',
- expectedResult: '''
- (function(x) {
- return this;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using locals', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + 1',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + 1;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using static fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + staticField',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.C.staticField);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using private static fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + _staticField',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.C._staticField);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + field',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(this.field);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using private fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + _field',
- expectedResult: '''
- (function(x) {
- let _field = dart.privateName(foo, "_field");
- return dart.notNull(x) + dart.notNull(this[_field]);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using globals', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + global',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.global);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'methodFieldAccess(2)',
- expectedResult: '''
- (function(x) {
- return this.methodFieldAccess(2);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('async method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'asyncMethod(2)',
- expectedResult: '''
- (function(x) {
- return this.asyncMethod(2);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('extension method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '"1234".parseInt()',
- expectedResult: '''
- (function(x) {
- return foo['NumberParsing|parseInt']("1234");
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('private field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '_field = 2',
- expectedResult: '''
- (function(x) {
- let _field = dart.privateName(foo, "_field");
- return this[_field] = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'field = 2',
- expectedResult: '''
- (function(x) {
- return this.field = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('private static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '_staticField = 2',
- expectedResult: '''
- (function(x) {
- return foo.C._staticField = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'staticField = 2',
- expectedResult: '''
- (function(x) {
- return foo.C.staticField = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in method with no field access:', () {
- const source = '''
- // @dart = 2.9
- extension NumberParsing on String {
- int parseInt() {
- return int.parse(this);
+ }
}
- }
- int global = 42;
+ main() => 0;
+ ''';
- class C {
- C(int this.field, int this._field);
+ TestDriver driver;
- static int staticField = 0;
- static int _staticField = 1;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
- int _field;
- int field;
+ tearDown(() {
+ driver.delete();
+ });
- int methodNoFieldAccess(int x) {
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x) {
+ return x;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('this', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'this',
+ expectedResult: '''
+ (function(x) {
+ return this;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using locals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + 1',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + 1;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C.staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C._staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + field',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(this.field);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using private fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _field',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return dart.notNull(x) + dart.notNull(this[_field]);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using globals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + global',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.global);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'methodFieldAccess(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.methodFieldAccess(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('async method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'asyncMethod(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.asyncMethod(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('extension method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '"1234".parseInt()',
+ expectedResult: '''
+ (function(x) {
+ return foo['NumberParsing|parseInt']("1234");
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_field = 2',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return this[_field] = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'field = 2',
+ expectedResult: '''
+ (function(x) {
+ return this.field = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C._staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C.staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in method with no field access:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
+ }
+
+ int global = 42;
+
+ class C {
+ C(int this.field, int this._field);
+
+ static int staticField = 0;
+ static int _staticField = 1;
+
+ int _field;
+ int field;
+
+ int methodNoFieldAccess(int x) {
+ /* evaluation placeholder */
+ return x;
+ }
+
+ Future<int> asyncMethod(int x) async {
+ return x;
+ }
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('expression using static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C.staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C._staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + field',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(this.field);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using private fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _field',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return dart.notNull(x) + dart.notNull(this[_field]);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_field = 2',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return this[_field] = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'field = 2',
+ expectedResult: '''
+ (function(x) {
+ return this.field = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C._staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C.staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in async method:', () {
+ var source = '''
+ ${options.dartLangComment}
+ class C {
+ C(int this.field, int this._field);
+
+ int _field;
+ int field;
+
+ Future<int> asyncMethod(int x) async {
+ /* evaluation placeholder */
+ return x;
+ }
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x) {
+ return x;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('this', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'this',
+ expectedResult: '''
+ (function(x) {
+ return this;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in global function:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
+ }
+
+ int global = 42;
+
+ class C {
+ C(int this.field, int this._field);
+
+ static int staticField = 0;
+ static int _staticField = 1;
+
+ int _field;
+ int field;
+
+ int methodFieldAccess(int x) {
+ return (x + _field + _staticField);
+ }
+ int methodFieldAccess(int x) {
+ return (x)
+ }
+
+ Future<int> asyncMethod(int x) async {
+ return x;
+ }
+ }
+
+ int main() {
+ int x = 15;
+ var c = C(1, 2);
/* evaluation placeholder */
- return x;
+ return 0;
}
+ ''';
- Future<int> asyncMethod(int x) async {
- return x;
- }
- }
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
- main() => 0;
- ''';
+ tearDown(() {
+ driver.delete();
+ });
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
- });
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'typo',
+ expectedError: "Getter not found: 'typo'.");
+ });
- tearDown(() {
- driver.delete();
- });
-
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'typo',
- expectedError: "The getter 'typo' isn't defined for the class 'C'");
- });
-
- test('expression using static fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + staticField',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.C.staticField);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using private static fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + _staticField',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.C._staticField);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + field',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(this.field);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using private fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + _field',
- expectedResult: '''
- (function(x) {
- let _field = dart.privateName(foo, "_field");
- return dart.notNull(x) + dart.notNull(this[_field]);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('private field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '_field = 2',
- expectedResult: '''
- (function(x) {
- let _field = dart.privateName(foo, "_field");
- return this[_field] = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'field = 2',
- expectedResult: '''
- (function(x) {
- return this.field = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('private static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '_staticField = 2',
- expectedResult: '''
- (function(x) {
- return foo.C._staticField = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'staticField = 2',
- expectedResult: '''
- (function(x) {
- return foo.C.staticField = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in async method:', () {
- const source = '''
- // @dart = 2.9
- class C {
- C(int this.field, int this._field);
-
- int _field;
- int field;
-
- Future<int> asyncMethod(int x) async {
- /* evaluation placeholder */
- return x;
- }
- }
-
- main() => 0;
- ''';
-
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
- });
-
- tearDown(() {
- driver.delete();
- });
-
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'typo',
- expectedError: "The getter 'typo' isn't defined for the class 'C'");
- });
-
- test('local', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x',
- expectedResult: '''
- (function(x) {
- return x;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('this', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'this',
- expectedResult: '''
- (function(x) {
- return this;
- }.bind(this)(
- 1
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in global function:', () {
- const source = '''
- // @dart = 2.9
- extension NumberParsing on String {
- int parseInt() {
- return int.parse(this);
- }
- }
-
- int global = 42;
-
- class C {
- C(int this.field, int this._field);
-
- static int staticField = 0;
- static int _staticField = 1;
-
- int _field;
- int field;
-
- int methodFieldAccess(int x) {
- return (x + _field + _staticField);
- }
- int methodFieldAccess(int x) {
- return (x)
- }
-
- Future<int> asyncMethod(int x) async {
- return x;
- }
- }
-
- int main() {
- int x = 15;
- var c = C(1, 2);
- /* evaluation placeholder */
- return 0;
- }
- ''';
-
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
- });
-
- tearDown(() {
- driver.delete();
- });
-
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'typo',
- expectedError: "Getter not found: 'typo'.");
- });
-
- test('local with primitive type', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'x',
- expectedResult: '''
- (function(x, c) {
- return x;
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('local object', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'c',
- expectedResult: '''
- (function(x, c) {
- return c;
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('create new object', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'C(1,3)',
- expectedResult: '''
+ test('local with primitive type', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'x',
+ expectedResult: '''
(function(x, c) {
- return new foo.C.new(1, 3);
+ return x;
}(
1,
null
))
''');
- });
+ });
- test('access field of new object', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'C(1,3)._field',
- expectedResult: '''
- (function(x, c) {
- let _field = dart.privateName(foo, "_field");
- return new foo.C.new(1, 3)[_field];
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('access static field', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'C.staticField',
- expectedResult: '''
- (function(x, c) {
- return foo.C.staticField;
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('expression using private static fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'C._staticField',
- expectedError: "Error: Getter not found: '_staticField'.");
- });
-
- test('access field', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'c.field',
- expectedResult: '''
- (function(x, c) {
- return c.field;
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('access private field', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'c._field',
- expectedResult: '''
- (function(x, c) {
- let _field = dart.privateName(foo, "_field");
- return c[_field];
- }(
+ test('local object', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c',
+ expectedResult: '''
+ (function(x, c) {
+ return c;
+ }(
1,
null
- ))
- ''');
+ ))
+ ''');
+ });
+
+ test('create new object', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C(1,3)',
+ expectedResult: '''
+ (function(x, c) {
+ return new foo.C.new(1, 3);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('access field of new object', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C(1,3)._field',
+ expectedResult: '''
+ (function(x, c) {
+ let _field = dart.privateName(foo, "_field");
+ return new foo.C.new(1, 3)[_field];
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('access static field', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C.staticField',
+ expectedResult: '''
+ (function(x, c) {
+ return foo.C.staticField;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C._staticField',
+ expectedError: "Error: Getter not found: '_staticField'.");
+ });
+
+ test('access field', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.field',
+ expectedResult: '''
+ (function(x, c) {
+ return c.field;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('access private field', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c._field',
+ expectedResult: '''
+ (function(x, c) {
+ let _field = dart.privateName(foo, "_field");
+ return c[_field];
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.methodFieldAccess(2)',
+ expectedResult: '''
+ (function(x, c) {
+ return c.methodFieldAccess(2);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('async method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.asyncMethod(2)',
+ expectedResult: '''
+ (function(x, c) {
+ return c.asyncMethod(2);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('extension method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: '"1234".parseInt()',
+ expectedResult: '''
+ (function(x, c) {
+ return foo['NumberParsing|parseInt']("1234");
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c._field = 2',
+ expectedResult: '''
+ (function(x, c) {
+ let _field = dart.privateName(foo, "_field");
+ return c[_field] = 2;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.field = 2',
+ expectedResult: '''
+ (function(x, c) {
+ return c.field = 2;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C._staticField = 2',
+ expectedError: "Setter not found: '_staticField'.");
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C.staticField = 2',
+ expectedResult: '''
+ (function(x, c) {
+ return foo.C.staticField = 2;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('call global function from core library', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'print(x)',
+ expectedResult: '''
+ (function(x, c) {
+ return core.print(x);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
});
- test('method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'c.methodFieldAccess(2)',
- expectedResult: '''
- (function(x, c) {
- return c.methodFieldAccess(2);
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('async method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'c.asyncMethod(2)',
- expectedResult: '''
- (function(x, c) {
- return c.asyncMethod(2);
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('extension method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: '"1234".parseInt()',
- expectedResult: '''
- (function(x, c) {
- return foo['NumberParsing|parseInt']("1234");
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('private field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'c._field = 2',
- expectedResult: '''
- (function(x, c) {
- let _field = dart.privateName(foo, "_field");
- return c[_field] = 2;
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'c.field = 2',
- expectedResult: '''
- (function(x, c) {
- return c.field = 2;
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('private static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'C._staticField = 2',
- expectedError: "Setter not found: '_staticField'.");
- });
-
- test('static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'C.staticField = 2',
- expectedResult: '''
- (function(x, c) {
- return foo.C.staticField = 2;
- }(
- 1,
- null
- ))
- ''');
- });
-
- test('call global function from core library', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'print(x)',
- expectedResult: '''
- (function(x, c) {
- return core.print(x);
- }(
- 1,
- null
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in closures:', () {
- const source = r'''
- // @dart = 2.9
- int globalFunction() {
- int x = 15;
- var c = C(1, 2);
-
- var outerClosure = (int y) {
- var closureCaptureInner = (int z) {
- /* evaluation placeholder */
- print('$y+$z');
- };
- closureCaptureInner(0);
- };
-
- outerClosure(3);
- return 0;
- }
-
- main() => 0;
- ''';
-
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
- });
-
- tearDown(() {
- driver.delete();
- });
-
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
- expression: 'typo',
- expectedError: "Getter not found: 'typo'.");
- });
-
- test('expression using uncaptured variables', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
- expression: r"'$x+$y+$z'",
- expectedResult: '''
- (function(x, c, y, z) {
- return dart.str(x) + "+" + dart.str(y) + "+" + dart.str(z);
- }(
- 1,
- null,
- 3,
- 0
- ))
- ''');
- });
-
- test('expression using captured variables', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
- expression: r"'$y+$z'",
- expectedResult: '''
- (function(x, c, y, z) {
- return dart.str(y) + "+" + dart.str(z);
- }(
- 1,
- null,
- 3,
- 0
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in method with no type use', () {
- const source = '''
- // @dart = 2.9
- abstract class Key {
- const factory Key(String value) = ValueKey;
- const Key.empty();
- }
-
- abstract class LocalKey extends Key {
- const LocalKey() : super.empty();
- }
-
- class ValueKey implements LocalKey {
- const ValueKey(this.value);
- final String value;
- }
-
- class MyClass {
- const MyClass(this._t);
- final int _t;
- }
-
- int bar(int p){
- return p;
- }
- int baz(String t){
- return t;
- }
- void main() {
- var k = Key('t');
- MyClass c = MyClass(0);
- int p = 1;
- const t = 1;
-
- /* evaluation placeholder */
- print('\$c, \$k, \$t');
- }
- ''';
-
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
- });
-
- tearDown(() {
- driver.delete();
- });
-
- test('call function using type', () async {
- await driver.check(
- scope: <String, String>{'p': '1'},
- expression: 'bar(p)',
- expectedResult: '''
- (function(p) {
- return foo.bar(p);
- }(
- 1
- ))
- ''');
- });
-
- test('call function using type', () async {
- await driver.check(
- scope: <String, String>{'p': '0'},
- expression: 'baz(p as String)',
- expectedResult: '''
- (function(p) {
- var StringL = () => (StringL = dart.constFn(dart.legacy(core.String)))();
- return foo.baz(StringL().as(p));
- }(
- 0
- ))
- ''');
- });
-
- test('evaluate new const expression', () async {
- await driver.check(
- scope: <String, String>{'p': '1'},
- expression: 'const MyClass(1)',
- expectedResult: '''
- (function(p) {
- dart.defineLazy(CT, {
- get C0() {
- return C0 = dart.const({
- __proto__: foo.MyClass.prototype,
- [_t]: 1
- });
- }
- }, false);
- var C0;
- return C0 || CT.C0;
- }(
- 1
- ))
- ''');
- });
-
- test('evaluate optimized const expression', () async {
- await driver.check(
- scope: <String, String>{},
- expression: 't',
- expectedResult: '''
- (function() {
- return 1;
- }(
- ))
- ''');
- },
- skip: 'Cannot compile constants optimized away by the frontend. '
- 'Issue: https://github.com/dart-lang/sdk/issues/41999');
-
- test('evaluate factory constructor call', () async {
- await driver.check(
- scope: <String, String>{'p': '1'},
- expression: "Key('t')",
- expectedResult: '''
- (function(p) {
- return new foo.ValueKey.new("t");
- }(
- 1
- ))
- ''');
- });
-
- test('evaluate const factory constructor call', () async {
- await driver.check(
- scope: <String, String>{'p': '1'},
- expression: "const Key('t')",
- expectedResult: '''
- (function(p) {
- dart.defineLazy(CT, {
- get C0() {
- return C0 = dart.const({
- __proto__: foo.ValueKey.prototype,
- [value]: "t"
- });
- }
- }, false);
- var C0;
- return C0 || CT.C0;
- }(
- 1
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in constructor:', () {
- const source = '''
- // @dart = 2.9
- extension NumberParsing on String {
- int parseInt() {
- return int.parse(this);
- }
- }
-
- int global = 42;
-
- class C {
- C(int this.field, int this._field) {
- int x = 1;
- /* evaluation placeholder */
- print(this.field);
- }
-
- static int staticField = 0;
- static int _staticField = 1;
-
- int _field;
- int field;
-
- int methodFieldAccess(int t) {
- return t + _field + _staticField;
- }
-
- Future<int> asyncMethod(int t) async {
- return t;
- }
- }
-
- main() => 0;
- ''';
-
- TestDriver driver;
-
- setUp(() {
- driver = TestDriver(options, source);
- });
-
- tearDown(() {
- driver.delete();
- });
-
- test('compilation error', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'typo',
- expectedError: "The getter 'typo' isn't defined for the class 'C'");
- });
-
- test('local', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x',
- expectedResult: '''
- (function(x) {
- return x;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('this', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'this',
- expectedResult: '''
- (function(x) {
- return this;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using locals', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + 1',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + 1;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using static fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + staticField',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.C.staticField);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using private static fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + _staticField',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.C._staticField);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + field',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(this.field);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using private fields', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + _field',
- expectedResult: '''
- (function(x) {
- let _field = dart.privateName(foo, "_field");
- return dart.notNull(x) + dart.notNull(this[_field]);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('expression using globals', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'x + global',
- expectedResult: '''
- (function(x) {
- return dart.notNull(x) + dart.notNull(foo.global);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'methodFieldAccess(2)',
- expectedResult: '''
- (function(x) {
- return this.methodFieldAccess(2);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('async method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'asyncMethod(2)',
- expectedResult: '''
- (function(x) {
- return this.asyncMethod(2);
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('extension method call', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '"1234".parseInt()',
- expectedResult: '''
- (function(x) {
- return foo['NumberParsing|parseInt']("1234");
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('private field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '_field = 2',
- expectedResult: '''
- (function(x) {
- let _field = dart.privateName(foo, "_field");
- return this[_field] = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'field = 2',
- expectedResult: '''
- (function(x) {
- return this.field = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('private static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: '_staticField = 2',
- expectedResult: '''
- (function(x) {
- return foo.C._staticField = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
-
- test('static field modification', () async {
- await driver.check(
- scope: <String, String>{'x': '1'},
- expression: 'staticField = 2',
- expectedResult: '''
- (function(x) {
- return foo.C.staticField = 2;
- }.bind(this)(
- 1
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in loops:', () {
- const source = r'''
- // @dart = 2.9
- int globalFunction() {
+ group('Expression compiler tests in closures:', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
int x = 15;
var c = C(1, 2);
- for(int i = 0; i < 10; i++) {
- /* evaluation placeholder */
- print('$i+$x');
+ var outerClosure = (int y) {
+ var closureCaptureInner = (int z) {
+ /* evaluation placeholder */
+ print('\$y+\$z');
+ };
+ closureCaptureInner(0);
};
+
+ outerClosure(3);
return 0;
}
main() => 0;
''';
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
+ expression: 'typo',
+ expectedError: "Getter not found: 'typo'.");
+ });
+
+ test('expression using uncaptured variables', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
+ expression: r"'$x+$y+$z'",
+ expectedResult: '''
+ (function(x, c, y, z) {
+ return dart.str(x) + "+" + dart.str(y) + "+" + dart.str(z);
+ }(
+ 1,
+ null,
+ 3,
+ 0
+ ))
+ ''');
+ });
+
+ test('expression using captured variables', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
+ expression: r"'$y+$z'",
+ expectedResult: '''
+ (function(x, c, y, z) {
+ return dart.str(y) + "+" + dart.str(z);
+ }(
+ 1,
+ null,
+ 3,
+ 0
+ ))
+ ''');
+ });
});
- tearDown(() {
- driver.delete();
- });
-
- test('expression using local', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'i': '0'},
- expression: 'x',
- expectedResult: '''
- (function(x, c, i) {
- return x;
- }(
- 1,
- null,
- 0
- ))
- ''');
- });
-
- test('expression using loop variable', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'i': '0'},
- expression: 'i',
- expectedResult: '''
- (function(x, c, i) {
- return i;
- }(
- 1,
- null,
- 0
- ))
- ''');
- });
- });
-
- group('Expression compiler tests in conditional (then):', () {
- const source = r'''
- // @dart = 2.9
- int globalFunction() {
- int x = 1;
- var c = C(1, 2);
-
- if (x == 14) {
- int y = 3;
- /* evaluation placeholder */
- print('$y+$x');
- } else {
- int z = 3;
- print('$z+$x');
+ group('Expression compiler tests in method with no type use', () {
+ var source = '''
+ ${options.dartLangComment}
+ abstract class Key {
+ const factory Key(String value) = ValueKey;
+ const Key.empty();
}
- return 0;
- }
- main() => 0;
- ''';
-
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
- });
-
- tearDown(() {
- driver.delete();
- });
-
- test('expression using local', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'y': '3'},
- expression: 'y',
- expectedResult: '''
- (function(x, c, y) {
- return y;
- }(
- 1,
- null,
- 3
- ))
- ''');
- });
-
- test('expression using local out of scope', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'y': '3'},
- expression: 'z',
- expectedError: "Error: Getter not found: 'z'");
- });
- });
-
- group('Expression compiler tests in conditional (else):', () {
- const source = r'''
- // @dart = 2.9
- int globalFunction() {
- int x = 1;
- var c = C(1, 2);
-
- if (x == 14) {
- int y = 3;
- print('$y+$x');
- } else {
- int z = 3;
- /* evaluation placeholder */
- print('$z+$x');
+ abstract class LocalKey extends Key {
+ const LocalKey() : super.empty();
}
- return 0;
- }
- main() => 0;
- ''';
+ class ValueKey implements LocalKey {
+ const ValueKey(this.value);
+ final String value;
+ }
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
+ class MyClass {
+ const MyClass(this._t);
+ final int _t;
+ }
+
+ int bar(int p){
+ return p;
+ }
+ int baz(String t){
+ return t;
+ }
+ void main() {
+ var k = Key('t');
+ MyClass c = MyClass(0);
+ int p = 1;
+ const t = 1;
+
+ /* evaluation placeholder */
+ print('\$c, \$k, \$t');
+ }
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('call function using type', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: 'bar(p)',
+ expectedResult: '''
+ (function(p) {
+ return foo.bar(p);
+ }(
+ 1
+ ))
+ ''');
+ });
+
+ test('call function using type', () async {
+ await driver.check(
+ scope: <String, String>{'p': '0'},
+ expression: 'baz(p as String)',
+ expectedResult: '''
+ (function(p) {
+ var StringL = () => (StringL = dart.constFn(dart.legacy(core.String)))();
+ return foo.baz(StringL().as(p));
+ }(
+ 0
+ ))
+ ''');
+ });
+
+ test('evaluate new const expression', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: 'const MyClass(1)',
+ expectedResult: '''
+ (function(p) {
+ dart.defineLazy(CT, {
+ get C0() {
+ return C0 = dart.const({
+ __proto__: foo.MyClass.prototype,
+ [_t]: 1
+ });
+ }
+ }, false);
+ var C0;
+ return C0 || CT.C0;
+ }(
+ 1
+ ))
+ ''');
+ });
+
+ test('evaluate optimized const expression', () async {
+ await driver.check(
+ scope: <String, String>{},
+ expression: 't',
+ expectedResult: '''
+ (function() {
+ return 1;
+ }(
+ ))
+ ''');
+ },
+ skip: 'Cannot compile constants optimized away by the frontend. '
+ 'Issue: https://github.com/dart-lang/sdk/issues/41999');
+
+ test('evaluate factory constructor call', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: "Key('t')",
+ expectedResult: '''
+ (function(p) {
+ return new foo.ValueKey.new("t");
+ }(
+ 1
+ ))
+ ''');
+ });
+
+ test('evaluate const factory constructor call', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: "const Key('t')",
+ expectedResult: '''
+ (function(p) {
+ dart.defineLazy(CT, {
+ get C0() {
+ return C0 = dart.const({
+ __proto__: foo.ValueKey.prototype,
+ [value]: "t"
+ });
+ }
+ }, false);
+ var C0;
+ return C0 || CT.C0;
+ }(
+ 1
+ ))
+ ''');
+ });
});
- tearDown(() {
- driver.delete();
- });
+ group('Expression compiler tests in constructor:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
+ }
- test('expression using local', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'z': '3'},
- expression: 'z',
- expectedResult: '''
- (function(x, c, z) {
- return z;
- }(
- 1,
- null,
- 3
+ int global = 42;
+
+ class C {
+ C(int this.field, int this._field) {
+ int x = 1;
+ /* evaluation placeholder */
+ print(this.field);
+ }
+
+ static int staticField = 0;
+ static int _staticField = 1;
+
+ int _field;
+ int field;
+
+ int methodFieldAccess(int t) {
+ return t + _field + _staticField;
+ }
+
+ Future<int> asyncMethod(int t) async {
+ return t;
+ }
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x) {
+ return x;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('this', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'this',
+ expectedResult: '''
+ (function(x) {
+ return this;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using locals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + 1',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + 1;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C.staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C._staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + field',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(this.field);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using private fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _field',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return dart.notNull(x) + dart.notNull(this[_field]);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using globals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + global',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.global);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'methodFieldAccess(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.methodFieldAccess(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('async method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'asyncMethod(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.asyncMethod(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('extension method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '"1234".parseInt()',
+ expectedResult: '''
+ (function(x) {
+ return foo['NumberParsing|parseInt']("1234");
+ }.bind(this)(
+ 1
))
''');
+ });
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_field = 2',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return this[_field] = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'field = 2',
+ expectedResult: '''
+ (function(x) {
+ return this.field = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C._staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C.staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
});
- test('expression using local out of scope', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null', 'z': '3'},
- expression: 'y',
- expectedError: "Error: Getter not found: 'y'");
- });
- });
+ group('Expression compiler tests in loops:', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 15;
+ var c = C(1, 2);
- group('Expression compiler tests after conditionals:', () {
- const source = r'''
- // @dart = 2.9
+ for(int i = 0; i < 10; i++) {
+ /* evaluation placeholder */
+ print('\$i+\$x');
+ };
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'i': '0'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x, c, i) {
+ return x;
+ }(
+ 1,
+ null,
+ 0
+ ))
+ ''');
+ });
+
+ test('expression using loop variable', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'i': '0'},
+ expression: 'i',
+ expectedResult: '''
+ (function(x, c, i) {
+ return i;
+ }(
+ 1,
+ null,
+ 0
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in conditional (then):', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 1;
+ var c = C(1, 2);
+
+ if (x == 14) {
+ int y = 3;
+ /* evaluation placeholder */
+ print('\$y+\$x');
+ } else {
+ int z = 3;
+ print('\$z+\$x');
+ }
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3'},
+ expression: 'y',
+ expectedResult: '''
+ (function(x, c, y) {
+ return y;
+ }(
+ 1,
+ null,
+ 3
+ ))
+ ''');
+ });
+
+ test('expression using local out of scope', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3'},
+ expression: 'z',
+ expectedError: "Error: Getter not found: 'z'");
+ });
+ });
+
+ group('Expression compiler tests in conditional (else):', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 1;
+ var c = C(1, 2);
+
+ if (x == 14) {
+ int y = 3;
+ print('\$y+\$x');
+ } else {
+ int z = 3;
+ /* evaluation placeholder */
+ print('\$z+\$x');
+ }
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'z': '3'},
+ expression: 'z',
+ expectedResult: '''
+ (function(x, c, z) {
+ return z;
+ }(
+ 1,
+ null,
+ 3
+ ))
+ ''');
+ });
+
+ test('expression using local out of scope', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'z': '3'},
+ expression: 'y',
+ expectedError: "Error: Getter not found: 'y'");
+ });
+ });
+
+ group('Expression compiler tests after conditionals:', () {
+ var source = '''
+ ${options.dartLangComment}
int globalFunction() {
int x = 1;
var c = C(1, 2);
if (x == 14) {
int y = 3;
- print('$y+$x');
+ print('\$y+\$x');
} else {
int z = 3;
- print('$z+$x');
+ print('\$z+\$x');
}
/* evaluation placeholder */
return 0;
@@ -1846,20 +1856,20 @@
main() => 0;
''';
- TestDriver driver;
- setUp(() {
- driver = TestDriver(options, source);
- });
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
- tearDown(() {
- driver.delete();
- });
+ tearDown(() {
+ driver.delete();
+ });
- test('expression using local', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'x',
- expectedResult: '''
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'x',
+ expectedResult: '''
(function(x, c) {
return x;
}(
@@ -1867,13 +1877,1612 @@
null
))
''');
+ });
+
+ test('expression using local out of scope', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'z',
+ expectedError: "Error: Getter not found: 'z'");
+ });
+ });
+ });
+
+ group('Sound null safety', () {
+ var options = SetupCompilerOptions(true);
+
+ group('Expression compiler tests in extension method:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ var ret = int.parse(this);
+ /* evaluation placeholder */
+ return ret;
+ }
+ }
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'ret': '1234'},
+ expression: 'typo',
+ expectedError: "Error: Getter not found: 'typo'");
+ });
+
+ test('local (trimmed scope)', () async {
+ // Test that current expression evaluation works in extension methods.
+ //
+ // Note: the actual scope is {#this, ret}, but #this is effectively
+ // removed in the expression compilator because it does not exist
+ // in JavaScript code.
+ // See (full scope) tests for what will the evaluation will look like
+ // when the mapping from dart symbols to JavaScipt symbols is added.
+ await driver.check(
+ scope: <String, String>{'ret': '1234'},
+ expression: 'ret',
+ expectedResult: '''
+ (function(ret) {
+ return ret;
+ }(
+ 1234
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('local (full scope)', () async {
+ // Test evalution in extension methods in the future when the mapping
+ // from kernel symbols to dartdevc symbols is added.
+ //
+ // Note: this currently fails due to
+ // - incremental compiler not allowing #this as a parameter name
+ await driver.check(
+ scope: <String, String>{'ret': '1234', '#this': 'this'},
+ expression: 'ret',
+ expectedError:
+ "Illegal parameter name '#this' found during expression compilation.");
+ });
+
+ test('this (full scope)', () async {
+ // Test evalution in extension methods in the future when the mapping
+ // from kernel symbols to dartdevc symbols is added.
+ //
+ // Note: this currently fails due to
+ // - incremental compiler not allowing #this as a parameter name
+ // - incremental compiler not mapping 'this' from user input to '#this'
+ await driver.check(
+ scope: <String, String>{'ret': '1234', '#this': 'this'},
+ expression: 'this',
+ expectedError:
+ "Illegal parameter name '#this' found during expression compilation.");
+ });
});
- test('expression using local out of scope', () async {
- await driver.check(
- scope: <String, String>{'x': '1', 'c': 'null'},
- expression: 'z',
- expectedError: "Error: Getter not found: 'z'");
+ group('Expression compiler tests in static function:', () {
+ var source = '''
+ ${options.dartLangComment}
+ int foo(int x, {int y}) {
+ int z = 0;
+ /* evaluation placeholder */
+ return x + y + z;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'typo',
+ expectedError: "Getter not found: \'typo\'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x, y, z) {
+ return x;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('formal', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'y',
+ expectedResult: '''
+ (function(x, y, z) {
+ return y;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('named formal', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'z',
+ expectedResult: '''
+ (function(x, y, z) {
+ return z;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('function', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
+ expression: 'main',
+ expectedResult: '''
+ (function(x, y, z) {
+ var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
+ dart.defineLazy(CT, {
+ get C0() {
+ return C0 = dart.fn(foo.main, VoidTodynamic());
+ }
+ }, false);
+ var C0;
+ return C0 || CT.C0;
+ }(
+ 1,
+ 2,
+ 3
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in method:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
+ }
+
+ int global = 42;
+
+ class C {
+ C(int this.field, int this._field);
+
+ static int staticField = 0;
+ static int _staticField = 1;
+
+ int _field;
+ int field;
+
+ int methodFieldAccess(int x) {
+ /* evaluation placeholder */
+ return x + _field + _staticField;
+ }
+
+ Future<int> asyncMethod(int x) async {
+ return x;
+ }
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x) {
+ return x;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('this', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'this',
+ expectedResult: '''
+ (function(x) {
+ return this;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using locals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + 1',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + 1;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C.staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C._staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + field',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(this.field);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using private fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _field',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return dart.notNull(x) + dart.notNull(this[_field]);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using globals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + global',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.global);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'methodFieldAccess(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.methodFieldAccess(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('async method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'asyncMethod(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.asyncMethod(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('extension method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '"1234".parseInt()',
+ expectedResult: '''
+ (function(x) {
+ return foo['NumberParsing|parseInt']("1234");
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_field = 2',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return this[_field] = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'field = 2',
+ expectedResult: '''
+ (function(x) {
+ return this.field = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C._staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C.staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in method with no field access:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
+ }
+
+ int global = 42;
+
+ class C {
+ C(int this.field, int this._field);
+
+ static int staticField = 0;
+ static int _staticField = 1;
+
+ int _field;
+ int field;
+
+ int methodNoFieldAccess(int x) {
+ /* evaluation placeholder */
+ return x;
+ }
+
+ Future<int> asyncMethod(int x) async {
+ return x;
+ }
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('expression using static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C.staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C._staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + field',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(this.field);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using private fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _field',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return dart.notNull(x) + dart.notNull(this[_field]);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_field = 2',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return this[_field] = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'field = 2',
+ expectedResult: '''
+ (function(x) {
+ return this.field = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C._staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C.staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in async method:', () {
+ var source = '''
+ ${options.dartLangComment}
+ class C {
+ C(int this.field, int this._field);
+
+ int _field;
+ int field;
+
+ Future<int> asyncMethod(int x) async {
+ /* evaluation placeholder */
+ return x;
+ }
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x) {
+ return x;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('this', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'this',
+ expectedResult: '''
+ (function(x) {
+ return this;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in global function:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
+ }
+
+ int global = 42;
+
+ class C {
+ C(int this.field, int this._field);
+
+ static int staticField = 0;
+ static int _staticField = 1;
+
+ int _field;
+ int field;
+
+ int methodFieldAccess(int x) {
+ return (x + _field + _staticField);
+ }
+ int methodFieldAccess(int x) {
+ return (x)
+ }
+
+ Future<int> asyncMethod(int x) async {
+ return x;
+ }
+ }
+
+ int main() {
+ int x = 15;
+ var c = C(1, 2);
+ /* evaluation placeholder */
+ return 0;
+ }
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'typo',
+ expectedError: "Getter not found: 'typo'.");
+ });
+
+ test('local with primitive type', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x, c) {
+ return x;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('local object', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c',
+ expectedResult: '''
+ (function(x, c) {
+ return c;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('create new object', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C(1,3)',
+ expectedResult: '''
+ (function(x, c) {
+ return new foo.C.new(1, 3);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('access field of new object', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C(1,3)._field',
+ expectedResult: '''
+ (function(x, c) {
+ let _field = dart.privateName(foo, "_field");
+ return new foo.C.new(1, 3)[_field];
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('access static field', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C.staticField',
+ expectedResult: '''
+ (function(x, c) {
+ return foo.C.staticField;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C._staticField',
+ expectedError: "Error: Getter not found: '_staticField'.");
+ });
+
+ test('access field', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.field',
+ expectedResult: '''
+ (function(x, c) {
+ return c.field;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('access private field', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c._field',
+ expectedResult: '''
+ (function(x, c) {
+ let _field = dart.privateName(foo, "_field");
+ return c[_field];
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.methodFieldAccess(2)',
+ expectedResult: '''
+ (function(x, c) {
+ return c.methodFieldAccess(2);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('async method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.asyncMethod(2)',
+ expectedResult: '''
+ (function(x, c) {
+ return c.asyncMethod(2);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('extension method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: '"1234".parseInt()',
+ expectedResult: '''
+ (function(x, c) {
+ return foo['NumberParsing|parseInt']("1234");
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c._field = 2',
+ expectedResult: '''
+ (function(x, c) {
+ let _field = dart.privateName(foo, "_field");
+ return c[_field] = 2;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'c.field = 2',
+ expectedResult: '''
+ (function(x, c) {
+ return c.field = 2;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C._staticField = 2',
+ expectedError: "Setter not found: '_staticField'.");
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'C.staticField = 2',
+ expectedResult: '''
+ (function(x, c) {
+ return foo.C.staticField = 2;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ });
+
+ test('call global function from core library', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'print(x)',
+ expectedResult: '''
+ (function(x, c) {
+ return core.print(x);
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+ });
+
+ group('Expression compiler tests in closures:', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 15;
+ var c = C(1, 2);
+
+ var outerClosure = (int y) {
+ var closureCaptureInner = (int z) {
+ /* evaluation placeholder */
+ print('\$y+\$z');
+ };
+ closureCaptureInner(0);
+ };
+
+ outerClosure(3);
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
+ expression: 'typo',
+ expectedError: "Getter not found: 'typo'.");
+ });
+
+ test('expression using uncaptured variables', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
+ expression: r"'$x+$y+$z'",
+ expectedResult: '''
+ (function(x, c, y, z) {
+ return dart.str(x) + "+" + dart.str(y) + "+" + dart.str(z);
+ }(
+ 1,
+ null,
+ 3,
+ 0
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using captured variables', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3', 'z': '0'},
+ expression: r"'$y+$z'",
+ expectedResult: '''
+ (function(x, c, y, z) {
+ return dart.str(y) + "+" + dart.str(z);
+ }(
+ 1,
+ null,
+ 3,
+ 0
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+ });
+
+ group('Expression compiler tests in method with no type use', () {
+ var source = '''
+ ${options.dartLangComment}
+ abstract class Key {
+ const factory Key(String value) = ValueKey;
+ const Key.empty();
+ }
+
+ abstract class LocalKey extends Key {
+ const LocalKey() : super.empty();
+ }
+
+ class ValueKey implements LocalKey {
+ const ValueKey(this.value);
+ final String value;
+ }
+
+ class MyClass {
+ const MyClass(this._t);
+ final int _t;
+ }
+
+ int bar(int p){
+ return p;
+ }
+ int baz(String t){
+ return t;
+ }
+ void main() {
+ var k = Key('t');
+ MyClass c = MyClass(0);
+ int p = 1;
+ const t = 1;
+
+ /* evaluation placeholder */
+ print('\$c, \$k, \$t');
+ }
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('call function not using type', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: 'bar(p)',
+ expectedResult: '''
+ (function(p) {
+ return foo.bar(p);
+ }(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('call function using type', () async {
+ await driver.check(
+ scope: <String, String>{'p': '0'},
+ expression: 'baz(p as String)',
+ expectedResult: '''
+ (function(p) {
+ var StringL = () => (StringL = dart.constFn(dart.legacy(core.String)))();
+ return foo.baz(StringL().as(p));
+ }(
+ 0
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('evaluate new const expression', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: 'const MyClass(1)',
+ expectedResult: '''
+ (function(p) {
+ dart.defineLazy(CT, {
+ get C0() {
+ return C0 = dart.const({
+ __proto__: foo.MyClass.prototype,
+ [_t]: 1
+ });
+ }
+ }, false);
+ var C0;
+ return C0 || CT.C0;
+ }(
+ 1
+ ))
+ ''');
+ });
+
+ test('evaluate optimized const expression', () async {
+ await driver.check(
+ scope: <String, String>{},
+ expression: 't',
+ expectedResult: '''
+ (function() {
+ return 1;
+ }(
+ ))
+ ''');
+ },
+ skip: 'Cannot compile constants optimized away by the frontend. '
+ 'Issue: https://github.com/dart-lang/sdk/issues/41999');
+
+ test('evaluate factory constructor call', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: "Key('t')",
+ expectedResult: '''
+ (function(p) {
+ return new foo.ValueKey.new("t");
+ }(
+ 1
+ ))
+ ''');
+ });
+
+ test('evaluate const factory constructor call', () async {
+ await driver.check(
+ scope: <String, String>{'p': '1'},
+ expression: "const Key('t')",
+ expectedResult: '''
+ (function(p) {
+ dart.defineLazy(CT, {
+ get C0() {
+ return C0 = dart.const({
+ __proto__: foo.ValueKey.prototype,
+ [value]: "t"
+ });
+ }
+ }, false);
+ var C0;
+ return C0 || CT.C0;
+ }(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in constructor:', () {
+ var source = '''
+ ${options.dartLangComment}
+ extension NumberParsing on String {
+ int parseInt() {
+ return int.parse(this);
+ }
+ }
+
+ int global = 42;
+
+ class C {
+ C(int this.field, int this._field) {
+ int x = 1;
+ /* evaluation placeholder */
+ print(this.field);
+ }
+
+ static int staticField = 0;
+ static int _staticField = 1;
+
+ int _field;
+ int field;
+
+ int methodFieldAccess(int t) {
+ return t + _field + _staticField;
+ }
+
+ Future<int> asyncMethod(int t) async {
+ return t;
+ }
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('compilation error', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'typo',
+ expectedError: "The getter 'typo' isn't defined for the class 'C'");
+ });
+
+ test('local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x) {
+ return x;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('this', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'this',
+ expectedResult: '''
+ (function(x) {
+ return this;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('expression using locals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + 1',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + 1;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C.staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using private static fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _staticField',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.C._staticField);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + field',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(this.field);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using private fields', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + _field',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return dart.notNull(x) + dart.notNull(this[_field]);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using globals', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'x + global',
+ expectedResult: '''
+ (function(x) {
+ return dart.notNull(x) + dart.notNull(foo.global);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'methodFieldAccess(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.methodFieldAccess(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('async method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'asyncMethod(2)',
+ expectedResult: '''
+ (function(x) {
+ return this.asyncMethod(2);
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('extension method call', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '"1234".parseInt()',
+ expectedResult: '''
+ (function(x) {
+ return foo['NumberParsing|parseInt']("1234");
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_field = 2',
+ expectedResult: '''
+ (function(x) {
+ let _field = dart.privateName(foo, "_field");
+ return this[_field] = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'field = 2',
+ expectedResult: '''
+ (function(x) {
+ return this.field = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('private static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: '_staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C._staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+
+ test('static field modification', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1'},
+ expression: 'staticField = 2',
+ expectedResult: '''
+ (function(x) {
+ return foo.C.staticField = 2;
+ }.bind(this)(
+ 1
+ ))
+ ''');
+ });
+ });
+
+ group('Expression compiler tests in loops:', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 15;
+ var c = C(1, 2);
+
+ for(int i = 0; i < 10; i++) {
+ /* evaluation placeholder */
+ print('\$i+\$x');
+ };
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'i': '0'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x, c, i) {
+ return x;
+ }(
+ 1,
+ null,
+ 0
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using loop variable', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'i': '0'},
+ expression: 'i',
+ expectedResult: '''
+ (function(x, c, i) {
+ return i;
+ }(
+ 1,
+ null,
+ 0
+ ))
+ ''');
+ });
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ group('Expression compiler tests in conditional (then):', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 1;
+ var c = C(1, 2);
+
+ if (x == 14) {
+ int y = 3;
+ /* evaluation placeholder */
+ print('\$y+\$x');
+ } else {
+ int z = 3;
+ print('\$z+\$x');
+ }
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3'},
+ expression: 'y',
+ expectedResult: '''
+ (function(x, c, y) {
+ return y;
+ }(
+ 1,
+ null,
+ 3
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using local out of scope', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'y': '3'},
+ expression: 'z',
+ expectedError: "Error: Getter not found: 'z'");
+ });
+ });
+
+ group('Expression compiler tests in conditional (else):', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 1;
+ var c = C(1, 2);
+
+ if (x == 14) {
+ int y = 3;
+ print('\$y+\$x');
+ } else {
+ int z = 3;
+ /* evaluation placeholder */
+ print('\$z+\$x');
+ }
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'z': '3'},
+ expression: 'z',
+ expectedResult: '''
+ (function(x, c, z) {
+ return z;
+ }(
+ 1,
+ null,
+ 3
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using local out of scope', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null', 'z': '3'},
+ expression: 'y',
+ expectedError: "Error: Getter not found: 'y'");
+ });
+ });
+
+ group('Expression compiler tests after conditionals:', () {
+ var source = '''
+ ${options.dartLangComment}
+ int globalFunction() {
+ int x = 1;
+ var c = C(1, 2);
+
+ if (x == 14) {
+ int y = 3;
+ print('\$y+\$x');
+ } else {
+ int z = 3;
+ print('\$z+\$x');
+ }
+ /* evaluation placeholder */
+ return 0;
+ }
+
+ main() => 0;
+ ''';
+
+ TestDriver driver;
+ setUp(() {
+ driver = TestDriver(options, source);
+ });
+
+ tearDown(() {
+ driver.delete();
+ });
+
+ test('expression using local', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'x',
+ expectedResult: '''
+ (function(x, c) {
+ return x;
+ }(
+ 1,
+ null
+ ))
+ ''');
+ }, skip: 'https://github.com/dart-lang/sdk/issues/44235');
+
+ test('expression using local out of scope', () async {
+ await driver.check(
+ scope: <String, String>{'x': '1', 'c': 'null'},
+ expression: 'z',
+ expectedError: "Error: Getter not found: 'z'");
+ });
});
});
}