blob: be4c561340b1a3a892a1d8469be48c384864f94b [file] [log] [blame]
// 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');
/// 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;