226a667ef9
We add the `dart.tool.dart2wasm.minify` environment define (analogous to how dart2js exposes `dart.tool.dart2js.minify`). We make `package:expect/variations.dart` then expose to tests what guarantees they can assume, namely * `readableTypeStrings` * `preciseErrorsWithDetails` Change-Id: I43da09ed924ca9137721f4d70b7a494e01bf36e4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430680 Reviewed-by: Ömer Ağacan <omersa@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
148 lines
6.0 KiB
Dart
148 lines
6.0 KiB
Dart
// 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.
|
|
|
|
/// Behavior variations of the current Dart execution.
|
|
///
|
|
/// Dart compilers vary the behavior of the compiled code in certain predictable
|
|
/// ways depending on the target platform or optimization flags, for example.
|
|
///
|
|
/// When writing SDK or language tests, the tests should be aware of, and
|
|
/// account for, those variations.
|
|
///
|
|
/// The properties in this library are used to narrow expectations in SDK tests.
|
|
/// That helps preserve test coverage in the presence of behavior variations in
|
|
/// Dart implementations and testing configurations.
|
|
///
|
|
/// Some variations in behavior are language compliant:
|
|
///
|
|
/// * [number semantics][1] change when targeting JavaScript
|
|
/// * some features have modalities (whether assertions are enabled, weak vs
|
|
/// sound null safety),
|
|
/// * some compilers support a subset of SDK libraries (for example, `dart:io`
|
|
/// on native platforms), and
|
|
/// * some behaviors are purposely unspecified (such as string representation
|
|
/// of types, which can change in the presence of minification
|
|
/// optimizations).
|
|
///
|
|
/// Some variations can result from unsafe optimizations. These are deviations
|
|
/// from the language or library contracts. Typically, this is done by backends
|
|
/// like dart2js or dart2wasm that run on a sandboxed environment which limits
|
|
/// the consequences of an erroneous optimization. Examples include:
|
|
///
|
|
/// * omitting covariant and dynamic parameter checks
|
|
/// * omitting implicit or explicit downcasts
|
|
/// * bypassing checks in library code, like range checks when accessing
|
|
/// native arrays in JavaScript.
|
|
///
|
|
/// Regardless of the reason, variations are deliberate and should be accounted
|
|
/// for in testing. Each behavior in this library is based on an underlying
|
|
/// variation in an existing Dart implementation.
|
|
///
|
|
/// Note: A coarse-grain alternative for each of these is also available in the
|
|
/// `test_runner` infrastructure for narrowing expectations on entire test
|
|
/// files.
|
|
///
|
|
/// [1]: https://dart.dev/guides/language/numbers "Numbers in Dart"
|
|
// TODO(54798): include conditions for VM/AOT/Wasm backends (current
|
|
// definitions only reflect variations under dart2js and DDC compilers).
|
|
// TODO(54798): update this dartdoc to also have a link to the standard
|
|
// reference of variations when it becomes available in the SDK wiki.
|
|
library;
|
|
|
|
/// Whether `assert`s are enabled.
|
|
// TODO: If information can be made available as a constant, use that.
|
|
// (For example if we introduce a compilation-environment entry for it.)
|
|
final bool enabledAsserts = (() {
|
|
bool result = false;
|
|
assert(result = true);
|
|
return result;
|
|
})();
|
|
|
|
/// Whether the program is running without sound null safety.
|
|
const bool unsoundNullSafety = <Null>[] is List<Object>;
|
|
|
|
/// Whether the program is running with JavaScript [number semantics][1].
|
|
///
|
|
/// In code compiled to JavaScript, Dart integers are represented by JavaScript
|
|
/// numbers, which have different ranges and behavior than native integers.
|
|
///
|
|
/// 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`.
|
|
///
|
|
/// _Note: We do not use the term web-numbers because the Dart Wasm backend is
|
|
/// considered a web backend, but uses native number semantics._
|
|
///
|
|
/// [1]: https://dart.dev/guides/language/numbers "Numbers in Dart"
|
|
const bool jsNumbers = identical(1, 1.0);
|
|
|
|
/// Whether [Type.toString] exposes the source names of types.
|
|
///
|
|
/// If so, the strings are readable and can be used to match certain
|
|
/// expectations. Typically this is not the case in production configurations
|
|
/// that enable minification, like `dart compile js -O2` and `dart compile exe`.
|
|
bool get readableTypeStrings =>
|
|
!const bool.fromEnvironment('dart.tool.dart2js.minify') &&
|
|
!const bool.fromEnvironment('dart.tool.dart2wasm.minify');
|
|
|
|
/// Whether specific subtypes of [Error] with details are thrown or generic
|
|
/// [Error]s.
|
|
bool get preciseErrorsWithDetails =>
|
|
!const bool.fromEnvironment('dart.tool.dart2wasm.minify');
|
|
|
|
/// Whether runtime parameter type checks are enforced.
|
|
///
|
|
/// Runtime parameter type checks include both covariant parameter checks,
|
|
/// either from generics or declared as `covariant`, and parameter checks of
|
|
/// dynamic function invocations through `dynamic` or `Function`.
|
|
///
|
|
/// For example, this code should fail a covariant parameter check:
|
|
///
|
|
/// ```dart
|
|
/// List<Object> list = <String>[];
|
|
/// list.add(1);
|
|
/// ```
|
|
///
|
|
/// And this code should fail a dynamic invocation parameter type check:
|
|
///
|
|
/// ```dart
|
|
/// class A {
|
|
/// m(int x) {}
|
|
/// }
|
|
/// (A() as dynamic).m("value");
|
|
/// ```
|
|
bool get checkedParameters =>
|
|
!const bool.fromEnvironment('dart.tool.dart2js.types:trust');
|
|
|
|
/// Whether implicit downcasts from `dynamic` are typed checked at runtime.
|
|
///
|
|
/// The language allows an expression of type `dynamic` to be used
|
|
/// where any other type is required, by doing a runtime check that
|
|
/// the value has the required type.
|
|
/// This value is `false` when that runtime check is omitted.
|
|
///
|
|
/// For example, this code should fail with an invalid implicit cast:
|
|
/// ```dart
|
|
/// dynamic d = 3; String s = d;
|
|
/// ```
|
|
bool get checkedImplicitDowncasts =>
|
|
!const bool.fromEnvironment('dart.tool.dart2js.types:trust');
|
|
|
|
/// Whether explicit casts are type checked at runtime.
|
|
///
|
|
/// An expression like `e as String` should perform a runtime check that the
|
|
/// value of `e` implements `String`.
|
|
/// This value is `false` when that runtime check is omitted, and the runtime
|
|
/// code will just use the value of `e` assuming it to be a string.
|
|
///
|
|
/// For example, this code should fail the explicit cast when the integer `3` is
|
|
/// checked for being a `String`:
|
|
///
|
|
/// ```dart
|
|
/// Object o = 3;
|
|
/// o as String;
|
|
/// ```
|
|
bool get checkedExplicitCasts => true;
|