Manage the dart.
namespace of the compilation environment.
#54785
Labels
area-meta
Cross-cutting, high-level issues (for tracking many other implementation issues, ...).
Dart SDK compilation environment namespace
The Dart language allows an implementation provided compilation environment (or compilation configuration environment if one wants to be verbose), which maps a finite set of string keys to string values, to be accessible during compilation.
It is used to make choices for configurable imports, allowing only some keys to be used, and the mapping can be directly accessed using
String.fromEnvironment
and indirectly through similar constructors onint
andbool
, which interpret the string value even at compile-time.The only thing we require from the compilation environment is consistency: When compiling a Dart program, the compilation result and runtime behavior must reflect a consistent compilation environment, such that every check against a key reflects the same underlying string value, or lack of a value.
We have reserved the
dart.
prefix for keys as a namespace for ourselves and our tools. We have not made a plan for how to use that namespace. And we are not preventing others from declaring names in that namespace. We should do both of these.Current use
We currently have some well-established uses of the environment, some tool-specific uses which do not follow a consistent naming scheme, and likely some uses that I've been unable to find.
See section "The
dart.
namespace, current use" at the end for the known current uses.Proposal
This is a proposal to introduce a strategy for managing existing names and introducing new names into the compilation environment, and concrete suggestions for adapting existing uses to that strategy. It is meant to ensure that tools behave consistently, and that nobody accidentally uses a naming strategy that will inhibit later extension.
Strategy
The
dart.
namespace (any key starting with"dart."
) is reserved, in its entirety, for use by the Dart SDK tools and as a public channel for configuration options.Users attempting to set values in this namespace using
-Ddart.myname=foo
will not succeed. Each tool may decide if it ignores the declaration or reports it as a warning or error, but it will not have any effect on compilation or runtime behavior otherwise.We can allow opening some name-spaces to users for adding properties, like
-Ddart.tool.vm.config.heapSize="4M"
could be allowed if the VM tool makes thedart.tool.vm.config
scope available to users.The general strategy is to have separate kinds of scopes:
The private scopes are always nested inside shared scopes. The top-level scope, and likely the next level too, are shared. There won't be a shared scope inside a private scope.
For individual scopes, there are two primary kinds of scopes:
Designed — Scopes, maybe with sub-scopes which are deliberately separated, and maybe individual entries which make sense at the current level. Used for grouping, organizing, and providing access to sub-scopes.
These are hand-crafted scopes, designed like an API for whoever needs to access them.
The root
dart.*
scope is the primary example. Adding to entries to these is a design decision.Enumerated — Scopes that provide sub-scopes based on some criterion, generally (potentially) open-ended.
The names are existing names or identifiers of something else. Nothing else should go directly into such a scope, since it can block a later addition.
dart.tool
will contain (up to) an entry per SDK tool, likedart.tool.dart2js
. We don't know which tools we'll have in the future, so we shouldn't add anything else to that scope. An SDK tool need only exist to have right to adart.tool.mytool
category.Concrete naming proposal
SDK Libraries -
dart.library.*
We keep having an enumerated namespace for libraries,
dart.library.io
, etc., with valuetrue
for each supporteddart:*
library in the current compilation. There is no entry for libraries which do not exist (const bool.hasEnvironment("dart.library.not"))
is false).Tool-private namespaces
Introduce
dart.tool
as an enumerated namespace, based on Dart SDK tools that is processing the program.We allows setting
dart.tool.x
totrue
while processing the source with tool x, at least for source processing tools which can possibly access the compilation environment at all.We also allow the
dart.tool.x.
prefix to be used freely by the x tool, for any data it wants to expose while processing with that tool.(Can one tool include another? That is, could we have the analyzer run DartDoc, and therefore have
dart.tool.dartdoc.something
set while analyzing in the analyzer?)Concrete tool names, hypothetical tool-specific entries (the namespace belongs to the tool, so they decide).
dart.tool.dart2js
— true if compiling with dart2jsdart.tool.dart2js.minified
(maybe)dart.tool.dart2js.unsafeCasts
(maybe)dart.tool.vm
— true if compiling/running with VMdart.tool.vm.production
(move fromdart.vm.production
, slowly or with a fix).dart.tool.vm.jit
(non-AoT mode VM running, if they want to expose that.)And maybe a compiler can provide even more precise data about the target, which can be set if it's known at compile time, and absent if unknown:
dart.tool.vm.host.cpu
= "x64"dart.tool.vm.host.cpuBits
= "64"dart.tool.vm.host.cpu.endian
= "little"dart.tool.vm.host.osName
= "windows"dart.tool.vm.host.abi
= "win-x64"Again, the tool decides, these are not even suggestions, just possibilities.
dart.tool.dart2wasm
— true if compiling with dart2wasmdart.tool.dart2wasm.webStrings
(if there is a mode for using web strings instead of Wasm-internal strings)dart.tool.analyzer
— true while analyzing, which includes constant evaluation in the analyzer. (Or the analyzer can choose to not have an entry, it's not required. If the analyzer wants to be general, it may not want anyone doing something specific for it.)dart.tool.macros
- when compiling and running a macro implementation, with access topackage:macros
.dart.mode.macros
set while compiling macro code.dart.tool.macros.something
- if macros want to provide its own constants to macro implementation code.Modes of compilation, semantic differences
Add
dart.mode.x
as a designed namespace, to expose the current, if non-default, behavior of things that differ in a few known ways. Preferably as booleans.dart.mode.asserts
— asserts enabled, set to true if compiled with--enable-asserts
.dart.mode.jsNumbers
— true when compiling with web number semantics (integers are doubles, and all the conseques).Maybe
dart.mode.target.*
for an open-ended set of possible compilation target kinds, which are not necessarily a single tool.dart.mode.target.native
dart.mode.target.web
dart.mode.target.wasm
dart.mode.aot
(but if this is true for everything but VM-JIT, then just usedart.tool.vm.jit
.)Experimental features
dart.mode.enabledExperiment.*
true` if experiment enabled by experiment flag. (Not true after launch or flag-flip, this is for experiments only.)dart.mode.enabledExperiment.inlineClass
would be true on main branch of SDK 3.2 before the flag-switch if the enable-experiment flag is provided, unset after release.Fixed SDK information
A tool can provide information about the SDK, which doesn't change until an SDK update, using the
dart.sdk.*
namespace. Likely all tools should provide the same SDK information, for consistency. These are all hypothetical:dart.sdk.version
="3.3" -- current version.dart.sdk.version.major
= "3"dart.sdk.version.minor
= "3"dart.sdk.language.min
= "2.12" -- minimal language version supported by SDKdart.sdk.language.min.major
= "2"dart.sdk.language.min.minor
= "12"dart.sdk.language.2.12
- true if language version 2.12 supported, currently true.…
dart.sdk.language.x.y
- true for all SDK x.y(major/minor) versions between min-supported and current.dart.sdk.language.3.3
— true if language version supported.dart.sdk.feature.*
— true if a specific language feature is supported. This includes enabled experiments, as an exception to the data here being stable for a particular SDK.dart.sdk.feature.nullSafety
— true when feature supported by SDK (always true now)dart.sdk.feature.extensionTypes
— true when feature supported by SDK as non-experiment (currently true on tip-of-tree after flag flip).Renamed to the feature name, not the experiment flag name.
dart.sdk.feature.macros
— true when feature supported by SDK (currently only true when experiment enabled).These flags includes features enabled by experiments, to enable code that uses these flags to be tested before the feature is launched. If an experiment is enabled, the SDK acts as if the feature was enabled in every way, including this one.
Name format
The names are generally dot-separated identifiers, but nothing requires that. Any string can work. We will use dotted identifiers + numerals for everything that is standardized, and let tools manage their own namespaces.
The identifiers themselves are camelCased,
jsNumbers
, here. The alternative would be snake-cased,js_numbers
. The camelCased names feel more "Dart-ish" to me personally, and it's what I keep writing automatically.Using something which is not a valid identifier precludes that constant ever being used in a conditional import (see below). That is an argument against
dart.sdk.language.3.3
which may precisely be the kind of constant you'd want to use in conditional imports. (On the other hand, using feature detection is better than version detection, so being conditional ondart.sdk.feature.extensionTypes
is better than usingdart.sdk.language.3.3
. In that way, not being usable for conditional imports may be a feature.)I expect most users won't be using the environment directly, they'll access it through a helper library, either one we produce or someone else will. Then naming their constants is that library's problem.
Almost everything here is something users can provide themselves as
-D
flags when compiling, if they know the values, just not in thedart.
namespace. We will not provide any extra expressive power, just convenience. Not unless we allow the environment values to be used in conditional imports.Conditional imports
This is where we can add more power, by making some of these declarations available to conditional imports. Or we can choose not to.
Currently we only allow
dart.library.x
checks. The reason for the limit is to reduce the number of distinct compilation artifacts for modular compilation, inside Google and outside.We don't have to restrict at all, any single program is well-defined based on any given compilation-environment.
The reason to restrict is to prevent user-configurations from being able to affect the number of distinct target configurations that modular, reusable compilation artifacts need to be generated for.
We can retain this, and still allow declarations that are strongly defining for a compilation mode already. The following are likely candidates:
anything in
dart.mode
, or at least asserts/js-numbersanything in
dart.sdk.
dart.tool.macros
, ordart.mode.macros
, if we consider it a separate mode.Summary
These are all suggestions. Can be iterated.
dart
- toplevel namespace.library
enum scope.libraryName
- one for each supported library.tool
- enum scope for tools..toolName
-"true"
when usingtool
to process the code..whatever
- whatever the tool wants to use the namespace for, while using that tool..mode
- compilation mode flags that affect semantics..jsNumbers
, fx. (Or.numbers.javacript
/.numbers.native
. But native really is the default.).target
maybe, a sub-namespace for know OS/runtime/etc information..enabledExperiment
enum namespace for enabled experiments..inlineClass
="true"
when experiment enabled, not released..sdk
- Information about the current Dart version. Mostly static.version
="3.3"
.major
="3"
and.minor
="3"
maybe maybe.3
="true"
maybe.3.3
="true"
maybe..language
- supported language versions.2.12
,.2.13
, … ,.3.3
. All currently supported language versions..feature
- supported language feature enumeration.nullSafety
="true"
forever..extensionTypes
="true"
when enabled. (Can depend on experiment flags).The
dart.
namespace, current useCross-platform fixed values or compiler flags
dart.library.<libraryName>
— is mapped to"true"
ifdart:<libraryName>
is available as a platform library during for current compilation.dart:io
is "available", as in "can be imported", on the web, but the compilation environment say it isn't, because it doesn't actually work.dart.library._something_private
istrue
when compiling for the web, even if no user can actually import that library. That's entirely for our own tools to use.const
access toString.fromEnvironment
, to ensure that the same environment is reflected at runtime.Suggested/experimental:
dart.mode.js_numbers
- whether compiling with JS number semantics (Dart2JS, DDC, not VM/Native or Wasm).Compiler/tool specific constants
Available to
String.fromEnvironment
, but not to configurable imports. A kind of "global constant" which only exists on specific platforms, and which don not require a library being imported. Also means it's not documented, not visible in the platform library documentation, and generally not discoverable. But it can be constant and used for tree-shaking.VM
dart.vm.product
- set to"true"
to make a "production build" (VM service not running. Assertions disabled?),"false"
otherwise. (Should probably be unset otherwise.)dart:_http
, to omit connections using the service protocol. Shoulddart:developer
be unavailable in production builds?-Ddart.vm.product=true
as a flag to thedart
executable, to tell it how to compiler. Should probably be real flag todart
, a--vm-product
flag which would setdart.vm.product
in the compilation environment if necessary. The current use of the compilation environment as a side-channel for undefined flags to thedart
command is … not pretty.(Possibly done this way because it reaches parts of the code which doesn't have access to the command line flags, but that can still be handled by adding the environment entry internally, rather than doing it explicitly on the command line.)
dart.vm.profile
? Not sure, only set in one test file,https://api.flutter.dev/flutter/foundation/kProfileMode-constant.html
. Maybe it's Flutter only?dart.isVM
? Whether running on VM?dart.developer.timeline
? Enable timeline?Dart2js
One older, three recent additions which were put into the
dart.tool.
namespace.dart.web.assertions_enabled
- whether assertions are enabled, but available as a constant. Used in tests?The text was updated successfully, but these errors were encountered: