| // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:expect/expect.dart'; | |
| import 'package:js/js.dart'; | |
| const dart2js = const bool.fromEnvironment('dart.library._dart2js_only'); | |
| const ddc = const bool.fromEnvironment('dart.library._ddc_only'); | |
| dynamic obj; | |
| @JS() | |
| external dynamic eval(String code); | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external String returnsNull(); | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external String returnsNullInlined(); | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external String returnsUndefined(); | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external String returnsUndefinedInlined(); | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external int get getsNull; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external int get getsNullInlined; | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external int get undefinedGetter; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external int get undefinedGetterInlined; | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external double Function() get getterFunctionReturnsNull; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external double Function() get getterFunctionReturnsNullInlined; | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external double Function() get getterFunctionReturnsUndefined; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external double Function() get getterFunctionReturnsUndefinedInlined; | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external bool nullField; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external bool nullFieldInlined; | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external bool undefinedField; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external bool undefinedFieldInlined; | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external int? nullableFunction(); | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external int? nullableFunctionInlined(); | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external int? get nullableGetter; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external int? get nullableGetterInlined; | |
| @JS() | |
| @pragma('dart2js:never-inline') | |
| external int? nullableField; | |
| @JS() | |
| @pragma('dart2js:prefer-inline') | |
| external int? nullableFieldInlined; | |
| @JS() | |
| @anonymous | |
| class SomeClass { | |
| @pragma('dart2js:never-inline') | |
| external String returnsNull(); | |
| @pragma('dart2js:prefer-inline') | |
| external String returnsNullInlined(); | |
| @pragma('dart2js:never-inline') | |
| external String returnsUndefined(); | |
| @pragma('dart2js:prefer-inline') | |
| external String returnsUndefinedInlined(); | |
| @pragma('dart2js:never-inline') | |
| external int get getsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external int get getsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external int get undefinedGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external int get undefinedGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external double Function() get getterFunctionReturnsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external double Function() get getterFunctionReturnsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external double Function() get getterFunctionReturnsUndefined; | |
| @pragma('dart2js:prefer-inline') | |
| external double Function() get getterFunctionReturnsUndefinedInlined; | |
| @pragma('dart2js:never-inline') | |
| external bool nullField; | |
| @pragma('dart2js:prefer-inline') | |
| external bool nullFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external bool undefinedField; | |
| @pragma('dart2js:prefer-inline') | |
| external bool undefinedFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external int? nullableFunction(); | |
| @pragma('dart2js:prefer-inline') | |
| external int? nullableFunctionInlined(); | |
| @pragma('dart2js:never-inline') | |
| external int? get nullableGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external int? get nullableGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external int? nullableField; | |
| @pragma('dart2js:prefer-inline') | |
| external int? nullableFieldInlined; | |
| } | |
| @JS() | |
| @anonymous | |
| class AnotherClass { | |
| @pragma('dart2js:never-inline') | |
| external static String staticReturnsNull(); | |
| @pragma('dart2js:prefer-inline') | |
| external static String staticReturnsNullInlined(); | |
| @pragma('dart2js:never-inline') | |
| external static String staticReturnsUndefined(); | |
| @pragma('dart2js:prefer-inline') | |
| external static String staticReturnsUndefinedInlined(); | |
| @pragma('dart2js:never-inline') | |
| external static int get staticGetsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external static int get staticGetsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external static int get staticUndefinedGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external static int get staticUndefinedGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external static double Function() get staticGetterFunctionReturnsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external static double Function() get staticGetterFunctionReturnsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external static double Function() get staticGetterFunctionReturnsUndefined; | |
| @pragma('dart2js:prefer-inline') | |
| external static double Function() | |
| get staticGetterFunctionReturnsUndefinedInlined; | |
| @pragma('dart2js:never-inline') | |
| external static bool staticNullField; | |
| @pragma('dart2js:prefer-inline') | |
| external static bool staticNullFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external static bool staticUndefinedField; | |
| @pragma('dart2js:prefer-inline') | |
| external static bool staticUndefinedFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external static int? staticNullableFunction(); | |
| @pragma('dart2js:prefer-inline') | |
| external static int? staticNullableFunctionInlined(); | |
| @pragma('dart2js:never-inline') | |
| external static int? get staticNullableGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external static int? get staticNullableGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external static int? staticNullableField; | |
| @pragma('dart2js:prefer-inline') | |
| external static int? staticNullableFieldInlined; | |
| } | |
| @JS() | |
| class NamedClass { | |
| @pragma('dart2js:never-inline') | |
| external String returnsNull(); | |
| @pragma('dart2js:prefer-inline') | |
| external String returnsNullInlined(); | |
| @pragma('dart2js:never-inline') | |
| external String returnsUndefined(); | |
| @pragma('dart2js:prefer-inline') | |
| external String returnsUndefinedInlined(); | |
| @pragma('dart2js:never-inline') | |
| external static String staticReturnsNull(); | |
| @pragma('dart2js:prefer-inline') | |
| external static String staticReturnsNullInlined(); | |
| @pragma('dart2js:never-inline') | |
| external static String staticReturnsUndefined(); | |
| @pragma('dart2js:prefer-inline') | |
| external static String staticReturnsUndefinedInlined(); | |
| @pragma('dart2js:never-inline') | |
| external int get getsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external int get getsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external int get undefinedGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external int get undefinedGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external static int get staticGetsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external static int get staticGetsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external static int get staticUndefinedGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external static int get staticUndefinedGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external double Function() get getterFunctionReturnsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external double Function() get getterFunctionReturnsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external double Function() get getterFunctionReturnsUndefined; | |
| @pragma('dart2js:prefer-inline') | |
| external double Function() get getterFunctionReturnsUndefinedInlined; | |
| @pragma('dart2js:never-inline') | |
| external static double Function() get staticGetterFunctionReturnsNull; | |
| @pragma('dart2js:prefer-inline') | |
| external static double Function() get staticGetterFunctionReturnsNullInlined; | |
| @pragma('dart2js:never-inline') | |
| external static double Function() get staticGetterFunctionReturnsUndefined; | |
| @pragma('dart2js:prefer-inline') | |
| external static double Function() | |
| get staticGetterFunctionReturnsUndefinedInlined; | |
| @pragma('dart2js:never-inline') | |
| external bool nullField; | |
| @pragma('dart2js:prefer-inline') | |
| external bool nullFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external bool undefinedField; | |
| @pragma('dart2js:prefer-inline') | |
| external bool undefinedFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external int? nullableFunction(); | |
| @pragma('dart2js:prefer-inline') | |
| external int? nullableFunctionInlined(); | |
| @pragma('dart2js:never-inline') | |
| external int? get nullableGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external int? get nullableGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external int? nullableField; | |
| @pragma('dart2js:prefer-inline') | |
| external int? nullableFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external static bool staticNullField; | |
| @pragma('dart2js:prefer-inline') | |
| external static bool staticNullFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external static bool staticUndefinedField; | |
| @pragma('dart2js:prefer-inline') | |
| external static bool staticUndefinedFieldInlined; | |
| @pragma('dart2js:never-inline') | |
| external static int? staticNullableFunction(); | |
| @pragma('dart2js:prefer-inline') | |
| external static int? staticNullableFunctionInlined(); | |
| @pragma('dart2js:never-inline') | |
| external static int? get staticNullableGetter; | |
| @pragma('dart2js:prefer-inline') | |
| external static int? get staticNullableGetterInlined; | |
| @pragma('dart2js:never-inline') | |
| external static int? staticNullableField; | |
| @pragma('dart2js:prefer-inline') | |
| external static int? staticNullableFieldInlined; | |
| external factory NamedClass.createNamedClass(); | |
| } | |
| @JS() | |
| external SomeClass createSomeClass(); | |
| void topLevelMemberTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| eval(r'self.returnsNull = function() { return null; }'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => returnsNull()); | |
| eval(r'self.returnsUndefined = function() { return void 0; }'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => returnsUndefined()); | |
| var functionTearoff = returnsNull; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| functionTearoff = returnsUndefined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| eval(r'self.getsNull = null;'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => getsNull); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => undefinedGetter); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| eval(r'self.getterFunctionReturnsNull = function() { return null; };'); | |
| Expect.isNull(getterFunctionReturnsNull()); | |
| var getterFunction = getterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| eval( | |
| r'self.getterFunctionReturnsUndefined = function() { ' | |
| 'return void 0; };', | |
| ); | |
| Expect.isNull(getterFunctionReturnsUndefined()); | |
| getterFunction = getterFunctionReturnsUndefined; | |
| Expect.isNull(getterFunction()); | |
| eval(r'self.nullField = null;'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => nullField); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => undefinedField); | |
| eval(r'self.nullableFunction = function() { return null; };'); | |
| Expect.isNull(nullableFunction()); | |
| eval(r'self.nullableGetter = null;'); | |
| Expect.isNull(nullableGetter); | |
| eval(r'self.nullableField = null;'); | |
| Expect.isNull(nullableField); | |
| } | |
| void inlinedTopLevelMemberTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| eval(r'self.returnsNullInlined = function() { return null; }'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => returnsNullInlined()); | |
| eval(r'self.returnsUndefinedInlined = function() { return void 0; }'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => returnsUndefinedInlined()); | |
| var functionTearoff = returnsNullInlined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| functionTearoff = returnsUndefinedInlined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| eval(r'self.getsNullInlined = null;'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => getsNullInlined); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => undefinedGetterInlined); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| eval(r'self.getterFunctionReturnsNullInlined = function() { return null; };'); | |
| Expect.isNull(getterFunctionReturnsNullInlined()); | |
| var getterFunction = getterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| eval( | |
| r'self.getterFunctionReturnsUndefinedInlined = function() { ' | |
| 'return void 0; };', | |
| ); | |
| Expect.isNull(getterFunctionReturnsUndefinedInlined()); | |
| getterFunction = getterFunctionReturnsUndefinedInlined; | |
| Expect.isNull(getterFunction()); | |
| eval(r'self.nullFieldInlined = null;'); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => nullFieldInlined); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => undefinedFieldInlined); | |
| eval(r'self.nullableFunctionInlined = function() { return null; };'); | |
| Expect.isNull(nullableFunctionInlined()); | |
| eval(r'self.nullableGetterInlined = null;'); | |
| Expect.isNull(nullableGetterInlined); | |
| eval(r'self.nullableFieldInlined = null;'); | |
| Expect.isNull(nullableFieldInlined); | |
| } | |
| void anonymousClassSetup() { | |
| eval(r'''self.createSomeClass = function() { | |
| return { | |
| "returnsNull": function() { return null; }, | |
| "returnsNullInlined": function() { return null; }, | |
| "returnsUndefined": function() { return void 0; }, | |
| "returnsUndefinedInlined": function() { return void 0; }, | |
| "getsNull" : null, | |
| "getsNullInlined" : null, | |
| "jsGetsNull": { get: function() { return null; } }, | |
| "jsGetsNullInlined": { get: function() { return null; } }, | |
| "jsGetsUndefined": { get: function() { return void 0; } }, | |
| "jsGetsUndefinedInlined": { get: function() { return void 0; } }, | |
| "getterFunctionReturnsNull": function() { return null; }, | |
| "getterFunctionReturnsNullInlined": function() { return null; }, | |
| "getterFunctionReturnsUndefined": function() { return void 0; }, | |
| "getterFunctionReturnsUndefinedInlined": function() { return void 0; }, | |
| "nullField" : null, | |
| "nullFieldInlined" : null, | |
| "nullableFunction": function() { return null; }, | |
| "nullableFunctionInlined": function() { return null; }, | |
| "nullableGetter": null, | |
| "nullableGetterInlined": null, | |
| "nullableField": null, | |
| "nullableFieldInlined": null, | |
| }; | |
| }; | |
| '''); | |
| eval(r'''self.AnotherClass = class AnotherClass { | |
| static staticReturnsNull() { return null; } | |
| static staticReturnsNullInlined() { return null; } | |
| static staticReturnsUndefined() { return void 0; } | |
| static staticReturnsUndefinedInlined() { return void 0; } | |
| static get staticGetsNull() { return null; } | |
| static get staticGetsNullInlined() { return null; } | |
| static get staticGetterFunctionReturnsNull() { | |
| return function() { return null; }; | |
| } | |
| static get staticGetterFunctionReturnsNullInlined() { | |
| return function() { return null; }; | |
| } | |
| static get staticGetterFunctionReturnsUndefined() { | |
| return function() { return void 0; }; | |
| } | |
| static get staticGetterFunctionReturnsUndefinedInlined() { | |
| return function() { return void 0; }; | |
| } | |
| static staticNullableFunction() { return null; } | |
| static staticNullableFunctionInlined() { return null; } | |
| static get staticNullableGetter() { return null; } | |
| static get staticNullableGetterInlined() { return null; } | |
| static staticNullableField = null; | |
| static staticNullableFieldInlined = null; | |
| };'''); | |
| } | |
| void anonymousClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| var x = createSomeClass(); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.returnsNull()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.returnsUndefined()); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = x.returnsNull; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| functionTearoff = x.returnsUndefined; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.getsNull); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.undefinedGetter); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => x.getterFunctionReturnsNull(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => x.getterFunctionReturnsUndefined(), | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = x.getterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = x.getterFunctionReturnsUndefined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.nullField); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.undefinedField); | |
| Expect.isNull(x.nullableFunction()); | |
| Expect.isNull(x.nullableGetter); | |
| Expect.isNull(x.nullableField); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticReturnsNull(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticReturnsUndefined(), | |
| ); | |
| functionTearoff = AnotherClass.staticReturnsNull; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| functionTearoff = AnotherClass.staticReturnsUndefined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => AnotherClass.staticGetsNull); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticUndefinedGetter, | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| Expect.isNull(AnotherClass.staticGetterFunctionReturnsNull()); | |
| Expect.isNull(AnotherClass.staticGetterFunctionReturnsUndefined()); | |
| getterFunction = AnotherClass.staticGetterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = AnotherClass.staticGetterFunctionReturnsUndefined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => AnotherClass.staticNullField); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticUndefinedField, | |
| ); | |
| Expect.isNull(AnotherClass.staticNullableFunction()); | |
| Expect.isNull(AnotherClass.staticNullableGetter); | |
| Expect.isNull(AnotherClass.staticNullableField); | |
| } | |
| void inlinedAnonymousClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| var x = createSomeClass(); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.returnsNullInlined()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.returnsUndefinedInlined()); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = x.returnsNullInlined; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| functionTearoff = x.returnsUndefinedInlined; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.getsNullInlined); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.undefinedGetterInlined); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => x.getterFunctionReturnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => x.getterFunctionReturnsUndefinedInlined(), | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = x.getterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = x.getterFunctionReturnsUndefinedInlined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.nullFieldInlined); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => x.undefinedFieldInlined); | |
| Expect.isNull(x.nullableFunctionInlined()); | |
| Expect.isNull(x.nullableGetterInlined); | |
| Expect.isNull(x.nullableFieldInlined); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticReturnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticReturnsUndefinedInlined(), | |
| ); | |
| functionTearoff = AnotherClass.staticReturnsNullInlined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| functionTearoff = AnotherClass.staticReturnsUndefinedInlined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticGetsNullInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticUndefinedGetterInlined, | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| Expect.isNull(AnotherClass.staticGetterFunctionReturnsNullInlined()); | |
| Expect.isNull(AnotherClass.staticGetterFunctionReturnsUndefinedInlined()); | |
| getterFunction = AnotherClass.staticGetterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = AnotherClass.staticGetterFunctionReturnsUndefinedInlined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticNullFieldInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => AnotherClass.staticUndefinedFieldInlined, | |
| ); | |
| Expect.isNull(AnotherClass.staticNullableFunctionInlined()); | |
| Expect.isNull(AnotherClass.staticNullableGetterInlined); | |
| Expect.isNull(AnotherClass.staticNullableFieldInlined); | |
| } | |
| // DDC does not perform checks for dynamic invocations. | |
| void dynamicAnonymousClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| obj = createSomeClass(); | |
| Expect.throwsTypeErrorWhen(dart2js && checksEnabled, () => obj.returnsNull()); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.returnsUndefined(), | |
| ); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = obj.returnsNull; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| functionTearoff = obj.returnsUndefined; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen(dart2js && checksEnabled, () => obj.getsNull); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedGetter, | |
| ); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsNull(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsUndefined(), | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = obj.getterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = obj.getterFunctionReturnsUndefined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen(dart2js && checksEnabled, () => obj.nullField); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedField, | |
| ); | |
| Expect.isNull(obj.nullableFunction()); | |
| Expect.isNull(obj.nullableGetter); | |
| Expect.isNull(obj.nullableField); | |
| } | |
| // DDC does not perform checks for dynamic invocations. | |
| void dynamicInlinedAnonymousClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| obj = createSomeClass(); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.returnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.returnsUndefinedInlined(), | |
| ); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = obj.returnsNullInlined; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| functionTearoff = obj.returnsUndefinedInlined; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getsNullInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedGetterInlined, | |
| ); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsUndefinedInlined(), | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = obj.getterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = obj.getterFunctionReturnsUndefinedInlined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.nullFieldInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedFieldInlined, | |
| ); | |
| Expect.isNull(obj.nullableFunctionInlined()); | |
| Expect.isNull(obj.nullableGetterInlined); | |
| Expect.isNull(obj.nullableFieldInlined); | |
| } | |
| void namedClassSetup() { | |
| eval(r'''self.NamedClass = class NamedClass { | |
| returnsNull() { return null; } | |
| returnsNullInlined() { return null; } | |
| returnsUndefined() { return void 0; } | |
| returnsUndefinedInlined() { return void 0; } | |
| static staticReturnsNull() { return null; } | |
| static staticReturnsNullInlined() { return null; } | |
| static staticReturnsUndefined() { return void 0; } | |
| static staticReturnsUndefinedInlined() { return void 0; } | |
| get getsNull() { return null; } | |
| get getsNullInlined() { return null; } | |
| static get staticGetsNull() { return null; } | |
| static get staticGetsNullInlined() { return null; } | |
| get getterFunctionReturnsNull() { | |
| return function() { return null; }; | |
| } | |
| get getterFunctionReturnsNullInlined() { | |
| return function() { return null; }; | |
| } | |
| get getterFunctionReturnsUndefined() { | |
| return function() { return void 0; }; | |
| } | |
| get getterFunctionReturnsUndefinedInlined() { | |
| return function() { return void 0; }; | |
| } | |
| static get staticGetterFunctionReturnsNull() { | |
| return function() { return null; }; | |
| } | |
| static get staticGetterFunctionReturnsNullInlined() { | |
| return function() { return null; }; | |
| } | |
| static get staticGetterFunctionReturnsUndefined() { | |
| return function() { return void 0; }; | |
| } | |
| static get staticGetterFunctionReturnsUndefinedInlined() { | |
| return function() { return void 0; }; | |
| } | |
| nullableFunction() { return null; } | |
| nullableFunctionInlined() { return null; } | |
| get nullableGetter() { return null; } | |
| get nullableGetterInlined() { return null; } | |
| nullableField = null; | |
| nullableFieldInlined = null; | |
| static staticNullableFunction() { return null; } | |
| static staticNullableFunctionInlined() { return null; } | |
| static get staticNullableGetter() { return null; } | |
| static get staticNullableGetterInlined() { return null; } | |
| static staticNullableField = null; | |
| static staticNullableFieldInlined = null; | |
| static createNamedClass() { return new NamedClass(); } | |
| };'''); | |
| } | |
| void namedClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| var y = NamedClass.createNamedClass(); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.returnsNull()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.returnsUndefined()); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = y.returnsNull; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| functionTearoff = y.returnsUndefined; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticReturnsNull(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticReturnsUndefined(), | |
| ); | |
| functionTearoff = NamedClass.staticReturnsNull; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| functionTearoff = NamedClass.staticReturnsUndefined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.getsNull); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.undefinedGetter); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => y.getterFunctionReturnsNull(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => y.getterFunctionReturnsUndefined(), | |
| ); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => NamedClass.staticGetsNull); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticUndefinedGetter, | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = y.getterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = y.getterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| Expect.isNull(NamedClass.staticGetterFunctionReturnsNull()); | |
| Expect.isNull(NamedClass.staticGetterFunctionReturnsUndefined()); | |
| getterFunction = NamedClass.staticGetterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = NamedClass.staticGetterFunctionReturnsUndefined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.nullField); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.undefinedField); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => NamedClass.staticNullField); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticUndefinedField, | |
| ); | |
| Expect.isNull(y.nullableFunction()); | |
| Expect.isNull(y.nullableGetter); | |
| Expect.isNull(y.nullableField); | |
| Expect.isNull(NamedClass.staticNullableFunction()); | |
| Expect.isNull(NamedClass.staticNullableGetter); | |
| Expect.isNull(NamedClass.staticNullableField); | |
| } | |
| void inlinedNamedClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| var y = NamedClass.createNamedClass(); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.returnsNullInlined()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.returnsUndefinedInlined()); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = y.returnsNullInlined; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| functionTearoff = y.returnsUndefinedInlined; | |
| Expect.throwsTypeErrorWhen(ddc && checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticReturnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticReturnsUndefinedInlined(), | |
| ); | |
| functionTearoff = NamedClass.staticReturnsNullInlined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| functionTearoff = NamedClass.staticReturnsUndefinedInlined; | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.getsNullInlined); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.undefinedGetterInlined); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => y.getterFunctionReturnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => y.getterFunctionReturnsUndefinedInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticGetsNullInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticUndefinedGetterInlined, | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = y.getterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = y.getterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| Expect.isNull(NamedClass.staticGetterFunctionReturnsNullInlined()); | |
| Expect.isNull(NamedClass.staticGetterFunctionReturnsUndefinedInlined()); | |
| getterFunction = NamedClass.staticGetterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = NamedClass.staticGetterFunctionReturnsUndefinedInlined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.nullFieldInlined); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => y.undefinedFieldInlined); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticNullFieldInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| checksEnabled, | |
| () => NamedClass.staticUndefinedFieldInlined, | |
| ); | |
| Expect.isNull(y.nullableFunctionInlined()); | |
| Expect.isNull(y.nullableGetterInlined); | |
| Expect.isNull(y.nullableFieldInlined); | |
| Expect.isNull(NamedClass.staticNullableFunctionInlined()); | |
| Expect.isNull(NamedClass.staticNullableGetterInlined); | |
| Expect.isNull(NamedClass.staticNullableFieldInlined); | |
| } | |
| // DDC does not perform checks for dynamic invocations. | |
| void dynamicNamedClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| obj = NamedClass.createNamedClass(); | |
| Expect.throwsTypeErrorWhen(dart2js && checksEnabled, () => obj.returnsNull()); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.returnsUndefined(), | |
| ); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = obj.returnsNull; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| functionTearoff = obj.returnsUndefined; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen(dart2js && checksEnabled, () => obj.getsNull); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedGetter, | |
| ); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsNull(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsUndefined(), | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = obj.getterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = obj.getterFunctionReturnsNull; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen(dart2js && checksEnabled, () => obj.nullField); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedField, | |
| ); | |
| Expect.isNull(obj.nullableFunction()); | |
| Expect.isNull(obj.nullableGetter); | |
| Expect.isNull(obj.nullableField); | |
| } | |
| // DDC does not perform checks for dynamic invocations. | |
| void dynamicInlinedNamedClassTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| obj = NamedClass.createNamedClass(); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.returnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.returnsUndefinedInlined(), | |
| ); | |
| // In dart2js, a tearoff of an interop method is indistinguishable from a | |
| // getter returning the underlying function. | |
| var functionTearoff = obj.returnsNullInlined; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| functionTearoff = obj.returnsUndefinedInlined; | |
| Expect.throwsTypeErrorWhen(false, () => functionTearoff()); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getsNullInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedGetterInlined, | |
| ); | |
| // Immediate invocations of instance getters are seen as function calls so | |
| // the results get checked. | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsNullInlined(), | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.getterFunctionReturnsUndefinedInlined(), | |
| ); | |
| // At the time this test was written, getters that return function types don't | |
| // get the same wrappers as function tearoffs so there isn't an opportunity to | |
| // check the return values so they can still leak null or undefined through | |
| // from the JavaScript side. | |
| var getterFunction = obj.getterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| getterFunction = obj.getterFunctionReturnsNullInlined; | |
| Expect.isNull(getterFunction()); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.nullFieldInlined, | |
| ); | |
| Expect.throwsTypeErrorWhen( | |
| dart2js && checksEnabled, | |
| () => obj.undefinedFieldInlined, | |
| ); | |
| Expect.isNull(obj.nullableFunctionInlined()); | |
| Expect.isNull(obj.nullableGetterInlined); | |
| Expect.isNull(obj.nullableFieldInlined); | |
| } | |
| @JS() | |
| class CollisionA { | |
| @pragma('dart2js:prefer-inline') | |
| external String foo([int? x]); | |
| @pragma('dart2js:never-inline') | |
| external String bar([int? x]); | |
| external factory CollisionA.create(); | |
| } | |
| @JS() | |
| class CollisionB { | |
| @pragma('dart2js:prefer-inline') | |
| external String? foo(); | |
| @pragma('dart2js:never-inline') | |
| external String? bar(); | |
| external factory CollisionB.create(); | |
| } | |
| void collisionClassSetup() { | |
| eval(r''' | |
| self.CollisionA = class CollisionA { | |
| foo(x) { return null; } | |
| bar(x) { return null; } | |
| static create() { return new CollisionA(); } | |
| }; | |
| self.CollisionB = class CollisionB { | |
| foo() { return null; } | |
| bar() { return null; } | |
| static create() { return new CollisionB(); } | |
| };'''); | |
| } | |
| void collisionTests({required bool checksEnabled}) { | |
| // Provide at least one nullable value to [Expect.isNull] so that dart2js | |
| // doesn't discard the branch. | |
| Expect.isNull(null); | |
| var a = CollisionA.create(); | |
| var b = CollisionB.create(); | |
| // In dart2js, the receiver type is erased to `LegacyJavaScriptObject`, so we | |
| // cannot identify which class's method is being invoked and cannot emit a | |
| // null check. DDC is able to identify the member being invoked. | |
| Expect.throwsTypeErrorWhen(checksEnabled && ddc, () => a.foo()); | |
| Expect.throwsTypeErrorWhen(checksEnabled && ddc, () => a.bar()); | |
| Expect.isNull(b.foo()); | |
| Expect.isNull(b.bar()); | |
| // Because `foo$1` and `bar$1` only exist for [CollisionA] and not | |
| // [CollisionB], dart2js still emits these checks in the callee. | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => a.foo(42)); | |
| Expect.throwsTypeErrorWhen(checksEnabled, () => a.bar(42)); | |
| } | |
| void runTests({required bool checksEnabled}) { | |
| topLevelMemberTests(checksEnabled: checksEnabled); | |
| inlinedTopLevelMemberTests(checksEnabled: checksEnabled); | |
| anonymousClassSetup(); | |
| anonymousClassTests(checksEnabled: checksEnabled); | |
| inlinedAnonymousClassTests(checksEnabled: checksEnabled); | |
| dynamicAnonymousClassTests(checksEnabled: checksEnabled); | |
| dynamicInlinedAnonymousClassTests(checksEnabled: checksEnabled); | |
| namedClassSetup(); | |
| namedClassTests(checksEnabled: checksEnabled); | |
| inlinedNamedClassTests(checksEnabled: checksEnabled); | |
| dynamicNamedClassTests(checksEnabled: checksEnabled); | |
| dynamicInlinedNamedClassTests(checksEnabled: checksEnabled); | |
| collisionClassSetup(); | |
| collisionTests(checksEnabled: checksEnabled); | |
| } |