[dart2js] Add Dart web speciailized expectation helpers.

There are many failing Dart2JS language/library tests due to differences in backend implementations.

We want to adopt a strategy that allows us to make explicit the different expectations we have of each backend.

This adds logic for the 2 most common causes of these backend related failures (numbers and implicit checks) but we can add more of these as we discover more use cases.

This is an iteration on https://dart-review.googlesource.com/c/sdk/+/293463 attempting to integrate feedback from that change.

Change-Id: Ie3a1954066199695d92881497e940385467c9a12
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311780
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
This commit is contained in:
Nate Biggs 2023-08-11 20:59:30 +00:00 committed by Commit Queue
parent adb68f4bb0
commit 779fe017ba
6 changed files with 97 additions and 14 deletions

View file

@ -1231,6 +1231,14 @@ class CompilerOptions implements DiagnosticOptions {
}
environment['dart.web.assertions_enabled'] = '$enableUserAssertions';
environment['dart.tool.dart2js'] = '${true}';
// Eventually pragmas and commandline flags should be aligned so that users
// setting these flag is equivalent to setting the relevant pragmas
// globally.
// See: https://github.com/dart-lang/sdk/issues/49475
// https://github.com/dart-lang/sdk/blob/main/pkg/compiler/doc/pragmas.md
environment['dart.tool.dart2js.primitives:trust'] = '$trustPrimitives';
environment['dart.tool.dart2js.types:trust'] = '$omitImplicitChecks';
}
/// Returns `true` if warnings and hints are shown for all packages.

View file

@ -12,6 +12,31 @@ bool get hasUnsoundNullSafety => const <Null>[] is List<Object>;
/// Whether the program is running with sound null safety.
bool get hasSoundNullSafety => !hasUnsoundNullSafety;
/// Whether the test was compiled by Dart2JS as production web code.
///
/// Production code unsafely omits some type checks that are required by the
/// language, under the assumption that production code will have no type
/// errors.
///
/// For example an invalid implicit down-cast like
/// `dynamic d = 3; String s = d;` might not be caught in production code.
final dart2jsProductionMode = const bool.fromEnvironment(
'dart.tool.dart2js.types:trust',
defaultValue: false);
/// Whether the test is running in a web environment, using JavaScript numbers.
///
/// In web compiled code, Dart integers are compiled to JavaScript numbers,
/// and have different ranges and behaviors of some operations, compared to
/// native compiled code (see [int] for more details about the difference
/// between native numbers and numbers on the web).
///
/// For example, using JavaScript numbers, an `int` value like `1` also
/// implements `double` and is the same object as `1.0`. In native numbers,
/// those values are two different objects, and integers do not implement
/// `double`.
final bool webNumbers = identical(1, 1.0);
/// Expect is used for tests that do not want to make use of the
/// Dart unit test library - for example, the core language tests.
/// Third parties are discouraged from using this, and should use

View file

@ -72,6 +72,11 @@ main() {
// Test that apply works on callable objects when it is passed to a method
// that expects Function (and not dynamic).
Expect.throws(() => testList(42, new Callable(), [13, 29])); //# 01: ok
testListTyped(42, new Callable(), [13, 29]); //# 02: ok
if (dart2jsProductionMode) {
testList(42, new Callable(), [13, 29]);
} else {
Expect.throws(() => testList(42, new Callable(), [13, 29]));
}
testListTyped(42, new Callable(), [13, 29]);
}

View file

@ -65,7 +65,9 @@ testSet(Set newSet(), Set newSetFrom(Iterable from)) {
{
// Check concurrent modification
Set set = newSet()..add(0)..add(1);
Set set = newSet()
..add(0)
..add(1);
{
// Test adding before a moveNext.
@ -301,15 +303,33 @@ void testIdentitySet(Set create()) {
// All compile time constants are identical to themselves.
var constants = [
double.infinity,
double.nan, -0.0, //# 01: ok
0.0, 42, "", null, false, true, #bif, testIdentitySet
double.nan,
-0.0,
0.0,
42,
"",
null,
false,
true,
#bif,
testIdentitySet
];
set.addAll(constants);
Expect.equals(constants.length, set.length);
if (webNumbers) {
// 0.0 and -0.0 are identical in JS.
Expect.equals(constants.length - 1, set.length);
Expect.isTrue(
set.containsAll(constants.where((e) => !(e is double && e.isNaN))),
"constants: $set");
} else {
Expect.equals(constants.length, set.length);
Expect.isTrue(set.containsAll(constants), "constants: $set");
}
for (var c in constants) {
// identical(double.nan, double.nan) == false in JS.
if (webNumbers && c is double && c.isNaN) continue;
Expect.isTrue(set.contains(c), "constant: $c");
}
Expect.isTrue(set.containsAll(constants), "constants: $set");
set.clear();
var m1 = new Mutable(1);

View file

@ -75,6 +75,11 @@ main() {
// Test that apply works on callable objects when it is passed to a method
// that expects Function (and not dynamic).
Expect.throws(() => testList(42, new Callable(), [13, 29])); //# 01: ok
testListTyped(42, new Callable(), [13, 29]); //# 02: ok
if (dart2jsProductionMode) {
testList(42, new Callable(), [13, 29]);
} else {
Expect.throws(() => testList(42, new Callable(), [13, 29]));
}
testListTyped(42, new Callable(), [13, 29]);
}

View file

@ -67,7 +67,9 @@ testSet(Set newSet(), Set newSetFrom(Iterable from)) {
{
// Check concurrent modification
Set set = newSet()..add(0)..add(1);
Set set = newSet()
..add(0)
..add(1);
{
// Test adding before a moveNext.
@ -303,15 +305,33 @@ void testIdentitySet(Set create()) {
// All compile time constants are identical to themselves.
var constants = [
double.infinity,
double.nan, -0.0, //# 01: ok
0.0, 42, "", null, false, true, #bif, testIdentitySet
double.nan,
-0.0,
0.0,
42,
"",
null,
false,
true,
#bif,
testIdentitySet
];
set.addAll(constants);
Expect.equals(constants.length, set.length);
if (webNumbers) {
// 0.0 and -0.0 are identical in JS.
Expect.equals(constants.length - 1, set.length);
Expect.isTrue(
set.containsAll(constants.where((e) => !(e is double && e.isNaN))),
"constants: $set");
} else {
Expect.equals(constants.length, set.length);
Expect.isTrue(set.containsAll(constants), "constants: $set");
}
for (var c in constants) {
// identical(double.nan, double.nan) == false in JS.
if (webNumbers && c is double && c.isNaN) continue;
Expect.isTrue(set.contains(c), "constant: $c");
}
Expect.isTrue(set.containsAll(constants), "constants: $set");
set.clear();
var m1 = new Mutable(1);