1
0
mirror of https://github.com/dart-lang/sdk synced 2024-06-28 22:05:22 +00:00
Change-Id: I28db796fadcc111d97d3589bf3988ea0bbb8e18a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366682
Reviewed-by: Alexander Thomas <athom@google.com>
Commit-Queue: Devon Carew <devoncarew@google.com>
This commit is contained in:
Devon Carew 2024-05-16 18:19:40 +00:00 committed by Commit Queue
parent 3bdc1f9c59
commit 2837647bea
66 changed files with 5895 additions and 25 deletions

View File

@ -26,7 +26,7 @@ body:
id: changelist
attributes:
label: Prepared changelist for beta/stable
description: Gerrit changelist(s) against beta and/or stable per https://github.com/dart-lang/sdk/wiki/Cherry-picks-to-a-release-channel
description: Gerrit changelist(s) against beta and/or stable per https://github.com/dart-lang/sdk/tree/main/docs/Cherry-picks-to-a-release-channel.md
validations:
required: true
- type: textarea

View File

@ -35,7 +35,7 @@ In order to submit a patch from a local workspace, you need to install the Chrom
## Getting the code
To work with the Dart code, you need to download and build the development branch. Active development of Dart takes place on the `main` branch, from which we push "green" versions that have passed all tests to `dev` branch. Complete instructions are found at [Getting The Source](https://github.com/dart-lang/sdk/wiki/Building#getting-the-source). **You must use the `gclient` tool (`fetch`), using `git clone` will not get you a functional environment!**
To work with the Dart code, you need to download and build the development branch. Active development of Dart takes place on the `main` branch, from which we push "green" versions that have passed all tests to `dev` branch. Complete instructions are found at [Getting The Source](docs/Building.md#getting-the-source). **You must use the `gclient` tool (`fetch`), using `git clone` will not get you a functional environment!**
## Starting a patch with git

2
DEPS
View File

@ -4,7 +4,7 @@
# IMPORTANT:
# Before adding or updating dependencies, please review the documentation here:
# https://github.com/dart-lang/sdk/wiki/Adding-and-Updating-Dependencies
# https://github.com/dart-lang/sdk/tree/main/docs/Adding-and-Updating-Dependencies.md
#
# Packages can be rolled to the latest version with `tools/manage_deps.dart`.
#

View File

@ -51,10 +51,9 @@ as well as from the [primary development branch](https://api.dart.dev/be)).
## Building Dart
If you want to build Dart yourself, here is a guide to
[getting the source, preparing your machine to build the SDK, and
building](https://github.com/dart-lang/sdk/wiki/Building).
[getting the source, preparing your machine to build the SDK, and building][building].
There are more documents on our [wiki](https://github.com/dart-lang/sdk/wiki).
There are more documents in our repo at [docs](https://github.com/dart-lang/sdk/tree/main/docs).
## Contributing to Dart
@ -67,14 +66,15 @@ You can also contribute patches, as described in [Contributing][contrib].
Future plans for Dart are included in the combined Dart and Flutter
[roadmap][roadmap] on the Flutter wiki.
[website]: https://dart.dev
[license]: https://github.com/dart-lang/sdk/blob/main/LICENSE
[repo]: https://github.com/dart-lang/sdk
[lang]: https://dart.dev/guides/language/language-tour
[tools]: https://dart.dev/tools
[building]: https://github.com/dart-lang/sdk/blob/main/docs/Building.md
[codelabs]: https://dart.dev/codelabs
[dartbug]: http://dartbug.com
[contrib]: https://github.com/dart-lang/sdk/blob/main/CONTRIBUTING.md
[pubsite]: https://pub.dev
[dartbug]: http://dartbug.com
[lang]: https://dart.dev/guides/language/language-tour
[license]: https://github.com/dart-lang/sdk/blob/main/LICENSE
[patent_grant]: https://github.com/dart-lang/sdk/blob/main/PATENT_GRANT
[pubsite]: https://pub.dev
[repo]: https://github.com/dart-lang/sdk
[roadmap]: https://github.com/flutter/flutter/wiki/Roadmap
[tools]: https://dart.dev/tools
[website]: https://dart.dev

View File

@ -0,0 +1,90 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
Since Dart is an open-source project we rely on a number of other open-source projects, as tools
for building and testing, and as libraries compiled into the Dart SDK. Please follow these guidelines when working with third-party dependencies in both source and binary form.
# Third-party source dependencies
> [!IMPORTANT]
> New dependencies need explicit approval from Dart leadership before being added to the Dart SDK `DEPS` file unless they are [Dart core packages](https://pub.dev/publishers/dart.dev/packages) (Googlers see go/dart-sdk-deps-block for background information). To get approval, file an issue in the Dart SDK repo.
When adding new third party source dependencies please be very careful. Make sure that the license for the software is compatible with our license - a large set of licenses are more restrictive when you actually link in the source instead of just using the tools.
For example, a compiler's license might allow using it to compile our binary, but could be too restrictive to allow using its source code as part of the source code for a Dart SDK tool.
You must add a README.google if you check in third-party code, and note any local changes that have been applied to the code (see below for a template). Please cc dart-engprod@google.com on any third-party additions.
If you need to discuss license issues to make sure that a license is compatible please reach out to the legal team at google or talk with dart-engprod@google.com who can guide you to the right
person. Please refrain from speculating about licenses or make assumptions about what you may and may not do. If in doubt you should ask. If you are not a Google employee, contact a Dart team member who is.
We have a few rules to make sure that we can continue to build older versions of the SDK even if people delete or rewrite the history of repositories containing our third-party dependencies. There are two options for using repositories not hosted under https://github.com/dart-lang/ or https://github.com/google/:
1. Move it to the dart-lang org, or fork it there. Moving is better than forking since it avoids fragmented versions. If you do fork, please state in the README that this is used for pulling in as a DEPS, don't make local changes, and be sure to not publish to pub from the dart-lang fork.
2. Get the github repo mirrored on the dart.googlesource.com git server, and pull the dependency from there. This is the same way we do normal dependencies from dart-lang (see below), with one important exception:
**For security reasons, all code pulled in to build the Dart SDK must be reviewed by Google employees, no matter where it comes from.** This means that you, or a Google employee, need to do an initial review of all code up to and including the commit you put in the DEPS file for all external packages.
All external packages must be pinned to a fixed commit (revision) in the DEPS file. If you update the DEPS to pin a newer version, you need to do another review of the changes between the two revisions. You can upload the review (of the changes in the dependency, not just the change in the DEPS file) to https://dart-review.googlesource.com for easy reviewing, and upstream any fixes in this dependency, before pinning the new version of the dependency.
For all dependencies on GitHub, we need a mirror. File a GitHub issue labeled `area-infrastructure` (https://dartbug.com) requesting a mirror. The mirrors go to `https://dart.googlesource.com/external/github.com/<org>/<repo>.git`. Once the mirror is set up, you can commit your changes to the DEPS file pointing at the github mirror.
While you wait for the mirror to get set up, you can add the dependency to the DEPS file pointing directly to `http://github.com/<org>/<repo>.git`. This will let you develop against the dependency locally, but don't commit this.
# Rolling dependencies
Generally, in order to roll a dependency, you edit the SDK's [DEPS](https://github.com/dart-lang/sdk/blob/main/DEPS) file to reference the new commit for the particular package. You then run `gclient sync -D` to bring that commit into your local checkout, and follow the normal contribution process to contribute that change to the SDK (ala `git checkout -b roll_dep_foo; git add DEPS; git commit -m "[deps] update foo dep"; git cl upload`).
We also have two tools in the SDK that can help you roll deps:
## Rolling a specific dependency
To roll a specific dependency, you can use the `tools/manage_deps.dart` script. From the SDK top level directory, run:
```
dart tools/manage_deps.dart bump third_party/pkg/package_config
```
That will update the DEPS file to the latest commit for the `package_config` dep and optionally create a CL for that change.
## Rolling all package dependencies
In order to roll all Dart packages referenced in the DEPS file to their latest versions, run:
```
dart tools/rev_sdk_deps.dart
```
That will modify the DEPS file in-place, updating all the Dart packages deps to their latest versions. You can then create a CL of the changes via the normal contribution process.
# Third-party binaries and binary data in general
We occasionally need add binary versions of tools to make our testing/build/distribution infrastructure easier to maintain. These can be tools derived from our own source code (like fixed stable versions of the Dart standalone binary), or can be open source tools (like the standalone Firefox binary). Please be absolutely sure that the binary is compatible with our license. If your binary is not needed for building/distributing the core dart tool-chain you should consider other options (e.g., lazily fetching the files from the source or from Google Cloud Storage). In any case, always be vigilant about the license and please cc dart-engprod@google.com on any third party additions.
# Where do they go
We put third party binaries on Google Cloud Storage and fetch them using a DEPS hook. We pin the DEPS entries to the hashes of specific versions, and we never delete old entries from the bucket where they are located, since that would destroy our ability to do old builds. This allows us to only have a single location holding the binaries for bleeding edge, dev branch, and stable releases.
Binary data is preferably added as a go/cipd package. Please note that only a select set of people have access to uploading CIPD package. If you feel that you need access or help please contact dart-engprod@google.com
# README.google templates
When adding third party dependencies you must always add a README.google file describing what you put in, which license, which revision if applicable, the repository/page where you obtained the source/binary and any local modifications. You should also always make sure that there is a LICENSE file with the actual license. The following is a verbatim copy of the README.google for the firefox javascript shell, you can use that as a template.
```
Name: Firefox command line javascript shell.
Short Name: js-shell
URL: http://ftp.mozilla.org/pub/mozilla.org/firefox/candidates/15.0.1-candidates/build1/
Version: 15.0.1
Date: September 5th 2012
License: MPL, http://www.mozilla.org/MPL
Description:
This directory contains the firefox js-shell binaries for Windows, Mac and
Linux. The files was fetched from:
http://ftp.mozilla.org/pub/mozilla.org/firefox/candidates/15.0.1-candidates/
on September 28th 2012.
The binaries are used for testing dart code compiled to javascript.
```

View File

@ -0,0 +1,38 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
## Branches and work flows
We have a rather simple branch setup for the dart project. Normally, everything is developed on the master branch. Features that are not yet ready for prime time are hidden under a flag, and enabled when sufficient stability has been proven. We occasionally create feature branches for landing big and disruptive changes. In addition to that, we have our dev, beta, and stable branches used for releasing the sdk.
In summary, we have in four main branches:
* **[master](https://github.com/dart-lang/sdk/blob/master/tools/VERSION)**:
Used for "everyday" development; land your CLs here.
* **[dev](https://github.com/dart-lang/sdk/blob/dev/tools/VERSION)**:
Populated from the master branch via full pushes, usually twice a week. Only in emergencies are [cherry picks](Cherry-picks-to-a-release-channel.md) landed on the dev channel. Don't land CLs here. Released via [dev channel builds](https://dart.dev/tools/sdk/archive#dev-channel).
* **[beta](https://github.com/dart-lang/sdk/blob/beta/tools/VERSION)**:
Populated from the dev branch via full pushes, usually once a month, or via [cherry picks](Cherry-picks-to-a-release-channel.md). Don't land CLs here. Released via [beta channel builds](https://dart.dev/tools/sdk/archive#beta-channel).
* **[stable](https://github.com/dart-lang/sdk/blob/stable/tools/VERSION)**:
Our main release branch, populated from the beta branch via full pushes when a release is ready, or via [cherry picks](Cherry-picks-to-a-release-channel.md). Don't land CLs here. Released via [stable channel builds](https://dart.dev/tools/sdk/archive#stable-channel).
## Release cycle
Our normal release cycle is roughly 2 months long, but we don't make any guarantees, i.e., we may ship early if we feel that the stability is good or we may ship late if it is not. We don't normally follow a feature driven release cycle, but in some cases for larger changes to the language we may postpone a release to get all tools in sync.
During the entire cycle we do full merges of master to dev, basically releasing a green build from master on dev roughly twice a week. In case of bugs found quickly we do another full push.
We spend the last ~2 weeks of the cycle stabilizing the beta channel, starting with a full push of the latest dev release to beta. We only cherry picking critical fixes to the beta channel. People continue working on the master branch and dev releases will continue to be released. In this 2 week period we do multiple batches of cherry picks a week, and release those on the beta channel. We call this cherry-pick season.
Once we have something that looks good we merge it to stable and release it there. During the 2 months we do patch security, crash and critical bug releases on stable based on the latest stable version.
### Getting your changes to beta channel during cherry pick season
See the [cherry pick to beta](Cherry-picks-to-a-release-channel.md) page for all the details on how to get a change cherry picked.

View File

@ -0,0 +1,72 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Introduction
The Dart VM runs on a variety of ARM processors on Linux and Android. This document explains how to build the Dart VM and SDK to target these platforms.
# Cross-compiling
If you are building natively on the device you will be running on, you can skip this step. The build scripts download a cross-compilation toolchain using clang that supports ia32, x64, arm and arm64, so you do not need to install a cross-compiler yourself unless you want to target riscv.
## Linux
If you are running Debian/Ubuntu, you can obtain a cross-compiler by doing the following:
```
$ sudo apt-get install g++-arm-linux-gnueabihf # For 32-bit ARM (ARMv7)
$ sudo apt-get install g++-aarch64-linux-gnu # For 64-bit ARM (ARMv8)
$ sudo apt-get install g++-riscv64-linux-gnu # For 64-bit RISC-V (RV64GC)
```
## Android
Follow instructions under ["One-time Setup" under Android](Building-the-Dart-VM-for-Android)
# Building
## Linux
With the default Debian/Ubuntu toolchains, simply do:
```
$ ./tools/build.py --no-rbe --no-clang --mode release --arch arm create_sdk
$ ./tools/build.py --no-rbe --no-clang --mode release --arch arm64 create_sdk
$ ./tools/build.py --no-rbe --no-clang --mode release --arch riscv64 create_sdk
```
You can also produce only a Dart VM runtime, no SDK, by replacing `create_sdk` with `runtime`. This process involves also building a VM that targets ia32/x64, which is used to generate a few parts of the SDK.
You can use a different toolchain using the -t switch. For example, if the path to your gcc is /path/to/toolchain/prefix-gcc, then you'd invoke the build script with:
```
$ ./tools/build.py --no-rbe --no-clang -m release -a arm -t arm=/path/to/toolchain/prefix create_sdk
$ ./tools/build.py --no-rbe --no-clang -m release -a arm64 -t arm64=/path/to/toolchain/prefix create_sdk
$ ./tools/build.py --no-rbe --no-clang -m release -a riscv32 -t riscv32=/path/to/toolchain/prefix create_sdk
$ ./tools/build.py --no-rbe --no-clang -m release -a riscv64 -t riscv64=/path/to/toolchain/prefix create_sdk
```
## Android
The standalone Dart VM can also target Android.
```
$ ./tools/build.py --mode=release --arch=arm --os=android create_sdk
$ ./tools/build.py --mode=release --arch=arm64 --os=android create_sdk
$ ./tools/build.py --mode=release --arch=riscv64 --os=android create_sdk
```
For all of these configurations, the runtime only can be built using the runtime target as above.
## Debian Packages
You can create Debian packages targeting ARM or RISC-V as follows:
```
$ ./tools/linux_dist_support/create_tarball.py
$ ./tools/linux_dist_support/create_debian_packages.py -a {ia32, x64, arm, arm64, riscv64}
```

View File

@ -0,0 +1,113 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Introduction
It is possible to build and run the standalone Dart VM for Android devices. This setup is not yet thoroughly tested, but is available for experimentation.
## Limitations
* The host (build) machine must be an x86 Linux machine.
* The target (Android) device must be a device or emulator that supports the Android NDK.
* The resulting Android Dart VM can only be run from the Android command line.
* The resulting Android Dart VM only has access to dart:core APIs. It does not have access to the Android C or Java APIs.
* The Android-related tools and emulator image files will take about 2GB of disk space on the host machine.
# One-time Setup
Download and install the Dart source tree using the standard instructions for building Dart.
Use a text editor to add the following line to the very bottom of your Dart .gclient file (which is located in the directory that contains the main 'dart' directory):
`download_android_deps = True`
Run gclient sync to install the Android NDK and SDK. This may take 10 minutes or more depending upon the speed of your Internet connection
`$ gclient sync`
# Building for Android
Once youve set up your build tree, you can build the Dart VM for Android by using the standard Dart build script with the addition of the --os android build flag:
`$ tools/build.py --no-goma --arch=arm,arm64,ia32,x64 --os=android runtime`
# Testing the result
Adding “adb” to your path
For convenience, add the path to the adb tool to your shell PATH:
`$ export PATH=$PATH:path-to-dart/third_party/android_tools/sdk/platform-tools`
Starting an Android emulator
You can start an emulator running, by using the android_finder.py script:
`$ runtime/tools/android_finder.py -a {armeabi-v7a, x86} -b`
The -a flag says to find an Android device for the specified architecture. The -b flag says to start (or bootstrap) a new emulator if no existing emulator or device with a given ABI can be found. This script could take up to 20 seconds to run if a new emulator needs to be started.
## Running the Dart VM on an Android emulator
Once you have finished building the Android Dart VM and have a running Android emulator, you can run Dart scripts on the emulator as follows:
Create a directory on the Android emulator.
`$ adb shell mkdir /data/local/tmp/dart`
Copy the Dart VM executable to the Android emulator:
`$ adb push out/android/ReleaseAndroid{ARM,ARM64,IA32,X64}/dart /data/local/tmp/dart/dart`
Create a simple Dart test script:
`$ echo "main(){ print(\"Hello, world\!\");}" >hello.dart`
Copy the Dart test script to the Android emulator:
`$ adb push hello.dart /data/local/tmp/dart`
Run the Dart VM with the test script:
`$ adb shell /data/local/tmp/dart/dart /data/local/tmp/dart/hello.dart`
Hello, world!
## Stopping an Android Emulator
You can list all currently attached Android devices, including emulators, using the adb command:
`$ adb devices`
You can stop a running emulator using the adb emu kill command:
`$ adb emu kill ← if there is just one emulator running`
or
`$ adb -s emulator-name emu kill ← if there is more than one emulator running`
## Running the Dart VM on an Android device ##
First, make sure that the "USB Debugging" mode is enabled by navigating to Settings > Developer options > USB debugging. The box should be checked. You may need to have root on the device.
Now, plug in your device. Then, run:
`$ adb devices`
There should be an entry for your device, such as:
```
List of devices attached
TA23701VKR device
```
Now, you can copy dart and hello.dart to the device as above. If an emulator is also running, be sure to give adb the -d switch to tell it to use the attached device instead of the emulator. Use the -s switch to give the device ID explicitly.
# Notes
The only effect of the “target_os” line in the Dart .gclient configuration file is to install the Android tools. Despite what the name “target_os” implies, the target_os line does not affect which OS is targeted. Therefore, once youve installed the Android tools you can (and should) leave the target_os = [“android”] line in place even when switching back and forth between building for Android and building for Linux.

261
docs/Building.md Normal file
View File

@ -0,0 +1,261 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
[Dependencies](#dependencies)
[Getting the source](#source)
[Building](#building)
[Testing](#testing)
[Building the standalone VM only](#standalone)
<a name="dependencies"/>
# Dependencies
## Python
Dart SDK requires Python 3 to build.
On Windows you should ensure that `python.bat` wrapper from `depot_tools` comes ahead of any other python binaries in your `PATH` as per [these](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_get_depot_tools) instructions. There are still some steps that require python2 on Windows for now, but Python 3 also has to be available in the path.
## Linux
Install build tools:
```bash
sudo apt-get install git python3 curl xz-utils
```
Install Chromium's [depot tools](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up):
```bash
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:$PWD/depot_tools"
```
## Mac OS X
Install XCode.
> If you encounter the error: `xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance`, run the command:
> ```
> sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
> ```
> See https://stackoverflow.com/questions/17980759.
Install Chromium's [depot tools](http://dev.chromium.org/developers/how-tos/install-depot-tools):
```bash
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:$PWD/depot_tools"
```
## Windows
[Install Visual Studio](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#visual-studio) (2017 or newer). Make sure to install "Desktop development with C++" component.
You must have Windows 10 SDK installed. This can be installed separately or by checking the appropriate box in the Visual Studio Installer.
The SDK Debugging Tools must also be installed. If the Windows 10 SDK was installed via the Visual Studio installer, then they can be installed by going to: Control Panel → Programs → Programs and Features → Select the “Windows Software Development Kit” → Change → Change → Check “Debugging Tools For Windows” → Change. Or, you can download the standalone SDK installer and use it to install the Debugging Tools.
Install Chromium's depot tools following [this](http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up) or [this](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#install) instructions.
**Important:** If you are not a Googler make sure to set `DEPOT_TOOLS_WIN_TOOLCHAIN` system variable to `0` otherwise depot tools will attempt to pull down a Google-internal toolchain instead of using a local installation of Visual Studio.
<a name="source"/>
# Getting the source
> [!NOTE]
> Googlers only: add this to your ~/.gitconfig file _before_ running `fetch dart`:
> ```
> # Googlers need this in ~/.gitconfig or the checkout won't work correctly.
> [url "sso://dart/"]
> insteadOf = https://dart.googlesource.com/
> insteadOf = https://dart-review.googlesource.com/
> insteadOf = http://dart.googlesource.com/
> insteadOf = http://dart-review.googlesource.com/
> ```
You can choose whatever name you want for the directory to check dart out in, here it is called `dart-sdk`.
```bash
mkdir dart-sdk
cd dart-sdk
# On Windows, this needs to be run in a shell with Administrator rights.
fetch dart
```
Dart SDK uses `gclient` to manage dependencies which are described in the `DEPS` file. If you switch branches or update `sdk` checkout you need to run `gclient sync` to bring dependencies in sync with the SDK version.
Note: If you do not have emscripten, you can update your `.gclient` file to pull emscripten:
```
"custom_vars": {
"download_emscripten": True,
},
```
<a name="building"/>
# Building
**IMPORTANT: You must follow instructions for [Getting the source](#source) before attempting to build. Just cloning a GitHub repo or downloading and unpacking a ZIP of the SDK repository would not work.**
Build the 64-bit SDK:
```bash
# From within the "dart-sdk" directory.
cd sdk
./tools/build.py --mode release --arch x64 create_sdk
```
The output will be in `out/ReleaseX64/dart-sdk` on Linux and Windows, and `xcodebuild/ReleaseX64/dart-sdk` on MacOS.
Build the 32-bit SDK:
```bash
# From within the "dart-sdk" directory.
cd sdk
./tools/build.py --mode release --arch ia32 create_sdk
```
The output will be in `out/ReleaseIA32/dart-sdk` on Linux and Windows, or `xcodebuild/ReleaseIA32/dart-sdk` on MacOS.
See also [Building Dart SDK for ARM or RISC-V](Building-Dart-SDK-for-ARM-or-RISC-V.md).
## Tips
By default the build and test scripts select the debug binaries. You can build and test the release version of the VM by specifying `--mode=release` or both debug and release by specifying `--mode=all` on the respective `build.py` and `test.py` command lines. This can be shortened to `-mrelease` or `-m release`, and the architecture can be specified with `--arch=x64` or `-a x64`, the default. Other architectures, like `ia32`, `arm`, and `arm64` are also supported.
We recommend that you use a local file system at least for the output of the builds. The output directory is `out` on linux, `xcodebuild` on Mac OS, and `build` on Windows. If your code is in some NFS partition, you can link the `out` directory to a local directory:
```bash
$ cd sdk/
$ mkdir -p /usr/local/dart-out/
$ ln -s -f /usr/local/dart-out/ out
```
### Notification when build is done
The environment variable `DART_BUILD_NOTIFICATION_DELAY` controls if `build.py` displays a notification when the build is done. If a build takes longer than `DART_BUILD_NOTIFICATION_DELAY` a notification will be displayed.
A notification is a small transient non-modal window, for now, only supported on Mac and Linux.
## Special note for Windows users using Visual Studio Community Edition:
Your Visual Studio executable command may have a different name from the standard Visual Studio installations. You can specify the name for that executable by passing the additional flag "--executable=$VS\_EXECUTABLE\_NAME" to build.py. The executable name will probably be something like "VSExpress.exe".
## Building on Windows with Visual Studio 2015
Gyp should autodetect the version of Visual Studio you have, and produce solution files in the correct format.
If this is not happening, then set environment variable gyp\_msvs\_version to 2015.
For example, this will produce Visual Studio 2015-compliant solution files:
```bash
set gyp_msvs_version=2015
gclient runhooks
```
# Testing
All tests are executed using the `test.py` script under `tools/`. You need to use `build.py` to build the `most` and `run_ffi_unit_tests` targets before testing, e.g.
```bash
$ ./tools/build.py --mode release --arch ia32 most run_ffi_unit_tests
```
Now you can run all tests as follows (Safari, Firefox, Chrome, and IE must be installed, if you want to run the tests on them):
```bash
$ ./tools/test.py -mrelease --arch=ia32 --compiler=dartk,dart2js --runtime=vm,d8,chrome,firefox,[safari,ie10]
```
Specify the compiler used (optional -- only necessary if you are compiling to JavaScript (required for most browsers), the default is "none") and a runtime (where the code will be run).
You can run a specific test by specifying its full name or a prefix. For instance, the following runs only tests from the core libraries:
```bash
$ ./tools/test.py -mrelease --arch=ia32 --runtime=vm corelib
```
The following runs a single test:
```bash
$ ./tools/test.py -mrelease --arch=ia32 --runtime=vm corelib/ListTest
```
Make sure to run tests using the release VM if you have built the release VM, and for the same architecture as you have built.
See also [Testing Dart2js](Testing-Dart2js.md) for dart2js specific examples.
## Complex examples
Adjust the flags to your needs: appropriate values for `--arch` and `--tasks` will depend on your system. The below examples are taken from a 12 core x86\_64 system.
Dart analyzer tests example:
```bash
./tools/test.py \
--compiler dart2analyzer \
--runtime none \
--progress color \
--arch x64 \
--mode release \
--report \
--time \
--tasks 6 \
language
```
VM tests example:
```bash
./tools/test.py \
--compiler none \
--runtime vm \
--progress color \
--arch x64 \
--mode release \
--checked \
--report \
--time \
--tasks 6 \
language
```
Dart2JS example:
```bash
./tools/test.py \
--compiler dart2js \
--runtime chrome \
--progress color \
--arch x64 \
--mode release \
--checked \
--report \
--time \
--tasks 6 \
language
```
## Troubleshooting and tips for browser tests
To debug a browser test failure, you must start a local http server to serve the test. This is made easy with a helper script in dart/tools/testing. The error report from test.py gives the command line to start the server in a message that reads:
```bash
To retest, run: /usr/local/[...]/dart/tools/testing/bin/linux/dart /usr/local/[...]/dart/tools/testing/dart/http_server.dart ...
```
After starting the server, you can run the browser using the command line starting with `Command[[browser name]]`. The debugging tools in the browser can be used to set Javascript or Dart breakpoints, and the reload button should rerun the test.
* **Tip:** In the Sources tab of Chrome's developer tools, a "stop sign" button in the upper right tells the browser to break when an exception is thrown.
Some common problems you might get when running tests for the first time:
* Some fonts are missing. Chromium tests use `DumpRenderTree`, which needs some sets of fonts. See [LayoutTestsLinux](http://code.google.com/p/chromium/wiki/LayoutTestsLinux) for instructions in how to fix it.
* No display is set (e.g. running tests from an ssh terminal). `DumpRenderTree` is a nearly headless browser. Even though it doesn't open any GUI, it still must have an X session available. There are several ways to work around this:
* Use `xvfb`:
```bash
xvfb-run ./tools/test.py --arch=ia32 --compiler=dart2js --runtime=drt ...
```
* Other options include using ssh X tunneling (`ssh -Y`), NX, VNC, setting up `xhost` and exporting the DISPLAY environment variable, or simply running tests locally.
<a name="standalone"/>
# Building the standalone VM only
You can tell the build script to build the runtime targets only with the command:
```bash
$ ./tools/build.py runtime
```

View File

@ -0,0 +1,199 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
Cherry-picking is the process of selecting and merging an existing bug fix from our main development branch into a release branch (e.g. from `main` to `beta` or `stable`) for inclusion into the next hotfix release.
With the Dart and Flutter joint release process, we're using a combined [Dart & Flutter Cherrypick Review and Approval Process](https://github.com/flutter/flutter/wiki/Flutter-Cherrypick-Process). This document is a supplement to the main process and describes the process and flow within the Dart team.
**Note**: This process applies to bugs and regressions. Feature work is not considered for cherry picking and will need to wait for the next release.
## Notice a cherry-pick is required
Resolve the issue and land the fix on the main branch along with tests to
confirm whether the issue was in fact fixed. Identity whether the latest beta
and stable releases contain the issue and judge whether the fix should be
backported. Two changelists may be required if both channels are affected.
## How to cherry-pick a changelist
Cherry-pick your changelist's commit onto a new branch targeting beta or stable:
```console
$ git fetch
$ git new-branch --upstream origin/stable cherry # or origin/beta
$ git cherry-pick --edit $commit
$ $EDITOR CHANGELOG.md # stable only, see below
```
Update the commit message accordingly:
1. Add a `[beta]` or `[stable]` gerrit hashtag at the start of the first line.
2. Rename the `Reviewed-on` field to `Cherry-pick` to link to the original
changelist being cherry-picked.\
3. Add a temporary `Cherry-pick-request` field to be filled in later.
4. Remove the conflicting fields `Change-id`, `Commit-queue`, `Reviewed-by` that
are not true of the new changelist.
E.g.:
```
[stable] Fix foo crash.
Avoid foo doing bar instead.
Add reproducing test case.
Bug: https://github.com/dart-lang/sdk/issues/12345678
Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/12345678
Cherry-pick-request: TBA
```
## Changelog
Stable cherry-picks [must have CHANGELOG.md entries](Gerrit-Submit-Requirements#changelog) explaining the changes. The release engineers don't have your full context and rely on this information.
Beta releases don't have changelog entries.
If the `CHANGELOG.md` does not already have a section for the next stable hotfix, add such a section and increase the patch number (e.g. `3.0.4` -> `3.0.5`) without a date. If a section has a release date, it has already been released and should not be modified. The date will be added when the stable release is authored and it is decided when the release will be published.
```markdown
## 3.0.5
This is a patch release that:
- Fixes all bugs in the Dart SDK (issue [#123456])
[#123456]: https://github.com/dart-lang/sdk/issues/123456
## 3.0.4 - 2023-06-07
This is a patch release that:
...
```
Link to your cherry-pick request as subsequently filed below. You can upload the changelist again with the final link once the github issue has been filed. The cherry-pick request on github is often more useful for users than the original bug, since it explains the rationale concisely and links to the underlying bug for more information.
If the cherry-pick is infrastructure only and is invisible to users, the `Changelog-Exempt: ...` footer exempts the change from the changelog requirement.
## Uploading the cherry-pick changelist
Upload the changelist to gerrit for approval:
```console
git cl upload
```
Trigger a commit queue dry run and add any appropriate try builders to confirm
the fix is correct.
## Request cherry-pick approval
Request approval for releasing the fix to beta/stable using
this [cherry-pick to beta/stable request template][cherry-pick-template]:
* Brief description of the problem.
* The reason for cherry pick, user impact, and a brief risk assessment
(low/medium/high).
* Link to the changelist.
* The `cherry-pick-review` label.
Edit the changelist's commit message with a link to the cherry-pick request:
```
Cherry-pick-request: https://github.com/dart/sdk/issues/56781234
```
Send the changelist for review. Await the appropriate consensus and approval via the
`cherry-pick-request` for them or any OWNER to review the changelist.
## Submitting the cherry-pick
Once the cherry-pick issue is approved and the changelist is reviewed, the
cherry-pick author will submit it to the commit queue. The tryjobs will compare
the test results with the previous commit on the beta/stable branch and fail if
any regressions are introduced. If any regressions must be introduced, or the
try builders don't work on the older beta/stable code, then bypass the commit queue
by force submitting.
The release engineers will apply the `cherry-pick-merged` label and the cherry-pick
will be automatically bundled into the next hotfix release of beta/stable and no
further actions are required.
Once the cherry-pick has landed in a hotfix release, the release engineering team
will close the cherry-pick issue.
[cherry-pick-template]: https://github.com/dart-lang/sdk/issues/new?assignees=mit-mit%2Cwhesse%2Cathomas%2Cvsmenon%2Citsjustkevin&labels=cherry-pick-review&template=2_cherry_pick.yml&title=%5BCP%5D+%3Ctitle%3E
## Cherry-picking a commit in a dependency
If you need to cherry pick a single commit (here `$commit-to-cherry-pick`) in a dependency (here `third-party/pkg/pub`) to a release-channel (here `beta`).
First in the SDK checkout, find the current revision at the release branch:
```
dart-sdk/sdk/ > git checkout beta && git pull
dart-sdk/sdk/ > gclient getdep -r sdk/third_party/pkg/pub
a3f8b2fd36ec432450caf907474a02023ef3e44e
```
Now in a clone of the dependency, create a cherry-pick on a new branch, and push it to the origin repo:
```
pub/ > git checkout -b cherry-pick a3f8b2fd36ec432450caf907474a02023ef3e44e
pub/ > git cherry-pick $commit-to-cherry-pick
pub/ > git push -u origin cherry_pick:cherry_pick
pub/ > git rev-parse HEAD
6d1857c84cfb8a014aefedaf2d453214bf5ddb96 # <-- this is the revision we want to move to.
```
Wait a little while for the change to be mirrored to [dart.googlesource.com](https://dart.googlesource.com/).
We need to ensure that the cherry-picked commit on the dependency gets merged into the protected branch (here `main`). Otherwise there is a risk it will be GC'ed.
The following script creates such a merge:
```
#!/bin/bash
BRANCH="<name of branch to merge>"
REPO="<name of repository>"
# Defaults that may need to be changed.
TARGET_BRANCH="main" # sometimes repositories use a different default branch.
ORG="dart-lang" # most dependencies are in dart-lang, but not all.
REMOTE=origin # use upstream if that is the target repo's remote.
# Clone the repo if you don't already have a clone.
gh repo clone "$ORG/$REPO"
# Switch to the repo's directory.
cd "$REPO"
# Fetch and create a branch tracking the target branch.
git fetch "$REMOTE"
git switch -c "merge-$BRANCH" "$REMOTE/$TARGET_BRANCH"
# Create a merge commit.
git merge -sours "$REMOTE/$BRANCH"
gh pr create
```
Now create a PR for this merge, and make sure to "merge" instead of "squash" it (you might have to temporarily change repo settings to do this).
Now, go back to the SDK checkout, create a bump-commit and a CL that moves the release-channel to the new cherry-pick commit (not the merge) using the manage-deps tool:
```
dart-sdk/sdk/ > tools/manage_deps.dart bump third_party/pkg/pub --target=6d1857c84cfb8a014aefedaf2d453214bf5ddb96
```
Update the CL to be relative to the release-channel:
```
dart-sdk/sdk/ > git branch --set-upstream-to=origin/beta
dart-sdk/sdk/ > git cl upload
```
This CL can be used in the cherry-pick flow above.

View File

@ -0,0 +1,185 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
The Dart Web Libraries have not been updated since Chrome 50. With this release these libraries have been revd to the Chrome 63 APIs (WebIDLs). Below are the known differences between the Chrome 50 and Chrome 63 Dart Web libraries. These are the changes that have affected Dart users code:
* Touch and TouchEvent change
- _initTouchEvent removed see [Chrome Change](https://www.chromestatus.com/features/4923255479599104)
- Example of [Migrating initTouchEvent to Map](https://developers.google.com/web/updates/2016/09/chrome-54-deprecations#use_of_inittouchevent_is_removed)
* TouchEvent constructor takes a map argument, strong mode catches these failures in our tests.
* Web_audio
- AudioBufferSourceNode extends AudioScheduledSourceNode there are two start methods
- AudioScheduledSourceNode.start can't be overloaded and will become operation void start2([num when]);
- AudioBufferSourceNode.start([num when, num grainOffset, num grainDuration]) is void start([num when, num grainOffset, num grainDuration])
* Attributes of type double changed num see section "**Attributes Type Change double to num**" at the end of this document.
* onWheel event exposed
* Created for union of two kinds of canvas HTMLCanvasElement and OffscreenCanvas interface WebGLCanvas
* all other RenderingContext
- readonly attribute WebGLCanvas canvas;
* interface WebGLRenderingContext
- readonly attribute HTMLCanvasElement canvas;
* KeygenElement was removed in Chrome 57
* IDBFactory.webkitGetDatabaseNames() constructor removed in Chrome
* Depreciated FileError and DomError have been removed use DomException
- error.code replaced with error.name (e.g., see fileapi_directory_test.dart)
- Additional because FileError is gone there is no easy way to determine which errors are File only errors. However, these are:
- NOT_FOUND_ERR
- SECURITY_ERR
- ABORT_ERR
- NO_MODIFICATION_ALLOWED_ERR
- INVALID_STATE_ERR
- SYNTAX_ERR
- INVALID_MODIFICATION_ERR
- QUOTA_EXCEEDED_ERR
- TYPE_MISMATCH_ERR
* registerElement and register maps to old style (Chrome 50)
* registerElement2 2nd parameter is a map {'prototype': xxx, 'extends': xxxx} not 2 separate arguments.
* List<Rectangle> getClientRects() is now DomRectList getClientRects()
* Rectangle getBoundingClientRect() is now DomRect getBoundingClientRect()
* postMessage(/*any*/ message, String targetOrigin, [List<MessagePort> transfer]) changed to void postMessage(/*any*/ message, String targetOrigin, [List<Object> transfer]) transfer can now be ArrayBuffer, MessagePort and ImageBitmap
* RTCPeerConnection.setLocalDescription and setRemoteDescription
- takes a Map setLocalDescription(Map description) description is a map e.g., {'type': localSessionDescription, 'sdp': fakeLensSdp}
* nounce removed from HtmlScriptElement added to HtmlElement
- https://codereview.chromium.org/2801243002
- https://github.com/whatwg/html/issues/2369
* Event.deepPath() was removed Chrome 54
- https://developer.mozilla.org/en-US/docs/Web/API/Event/deepPath
* Event.scoped replaced by Event.composed
- https://developer.mozilla.org/en-US/docs/Web/API/Event/composed
***
Summary of API changes from Chrome 51 thru Chrome 63:
<br><br>
[https://developers.google.com/web/updates/tags/chrome51](https://developers.google.com/web/updates/tags/chrome51)
<br>
[https://developers.google.com/web/updates/tags/chrome52](https://developers.google.com/web/updates/tags/chrome52)
<br>
[https://developers.google.com/web/updates/tags/chrome53](https://developers.google.com/web/updates/tags/chrome53)
<br>
[https://developers.google.com/web/updates/tags/chrome54](https://developers.google.com/web/updates/tags/chrome54)
<br>
[https://developers.google.com/web/updates/tags/chrome55](https://developers.google.com/web/updates/tags/chrome55)
<br>
[https://developers.google.com/web/updates/tags/chrome56](https://developers.google.com/web/updates/tags/chrome56)
<br>
[https://developers.google.com/web/updates/tags/chrome57](https://developers.google.com/web/updates/tags/chrome57)
<br>
[https://developers.google.com/web/updates/tags/chrome58](https://developers.google.com/web/updates/tags/chrome58)
<br>
[https://developers.google.com/web/updates/tags/chrome59](https://developers.google.com/web/updates/tags/chrome59)
<br>
[https://developers.google.com/web/updates/tags/chrome60](https://developers.google.com/web/updates/tags/chrome60)
<br>
[https://developers.google.com/web/updates/tags/chrome61](https://developers.google.com/web/updates/tags/chrome61)
<br>
[https://developers.google.com/web/updates/tags/chrome62](https://developers.google.com/web/updates/tags/chrome62)
<br>
[https://developers.google.com/web/updates/tags/chrome63](https://developers.google.com/web/updates/tags/chrome63)
<br>
***
### Attributes Type Change double to num
* Accelerometer
- x, y, z
* AmbientLightSensor
- illuminance
* AnimationEffectTimingReadOnly
- delay, endDelay, iterationStart, iterations
* AnimationEvent
- elapsedTime
* AnimationPlaybackEvent
- currentTime, timelineTime
* AnimationTimeline
- currentTime
* BatteryManager
- chargingTime, dischargingTime, level
* BlobEvent
- timecode
* BudgetState
- budgetAt
* Coordinates
- accuracy, altitude, altitudeAccuracy, heading, latitude, longitude, speed
* CSSImageValue
- intrinsicHeight,intrinsicRatio, intrinsicWidth
* DeviceAcceleration
- x, y, z
* DeviceOrientationEvent
- alpha, beta, gamma
* DeviceRotationRate
- alpha, beta, gamma
* Event
- timeStamp
* GamepadButton
- value
* Gyroscope
- x, y, z
* IntersectionObserverEntry
- intersectionRatio, time
* Magnetometer
- x, y, z
* HTMLMediaElement
- duration
* MediaKeySession
- expiration
* MediaSettingsRange
- max. min, step
* MouseEvent
- clientX, clientY, pageX, pageY, screenX, screenY
* Navigator
- deviceMemory
* NetworkInformation
- downlink, downlinkMax
* PaintSize
- height, width
* PaintWorkletGlobalScope
- devicePixelRatio
* Performance
- timeOrigin
* PerformanceEntry
- duration, startTime
* PerformanceNavigationTiming
- domComplete, domContentLoadedEventEnd, domContentLoadedEventStart, domInteractive, loadEventEnd, loadEventStart, redirectCount, unloadEventEnd, unloadEventStart
* PerformanceResourceTiming
- connectEnd, connectStart, domainLookupEnd, domainLookupStart, encodedBodySize, fetchStart, redirectStart, requestStart, responseEnd, responseStart, secureConnectionStart, workerStart
* PointerEvent
- height, pressure, tangentialPressure, width
* HTMLProgressElement
- position
* RTCRtpContributingSource
- timestamp
* ScrollState
- deltaGranularity, deltaX, deltaY, velocityX, velocityY
* Sensor
- timestamp
* SpeechRecognitionAlternative
- confidence
* SpeechSynthesisEvent
- elapsedTime
* TextMetrics
- actualBoundingBoxAscent, actualBoundingBoxDescent, actualBoundingBoxLeft, actualBoundingBoxRight, alphabeticBaseline, emHeightAscent, emHeightDescent, fontBoundingBoxAscent, fontBoundingBoxDescent, hangingBaseline, ideographicBaseline, width
* Touch
- clientX, clientY, force, pageX, pageY, radiusX, radiusY, rotationAngle, screenX, screenY
* TransitionEvent
- elapsedTime
* VRFrameOfReference
- emulatedHeight
* VRStageBoundsPoint
- x, z
* VRStageParameters
- sizeX, sizeZ
* VideoPlaybackQuality
- creationTime
* VisualViewport
- height, offsetLeft, offsetTop, pageLeft, pageTop, sca, width
* WheelEvent
- deltaX, deltaY, deltaZ
* Window
- devicePixelRatio, pageXOffset, pageYOffset
* WorkerPerformance
- timeOrigin
* XPathResult
- numberValue

View File

@ -0,0 +1,91 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
There are several ways to contribute code in GitHub, for example
1. forking and creating pull request from a forked repo (https://help.github.com/articles/fork-a-repo)
1. branching within the main repo, and doing pull requests from one branch to another.
1. working on a local branch, creating a code review using Gerrit, push directly into master (this article).
## Step 1: get the source
[Checkout the source](Building.md#source)
Tip: if you want to get automatic backups of an NFS directory, but take advantage of fast git performance on a local directory, you can use the instructions above in an NFS directory and use a mirror in a local directory with git-new-workdir.
Then work from the local directory. Files uncommitted are not backed up, but every commit you make is automatically backed up. The script 'git-new-workdir' is described in more detail here: http://nuclearsquid.com/writings/git-new-workdir/.
## Step 2: verify that git-cl is configured correctly.
There is a `codereview.settings` file in the repo to configure things automatically, but it never hurts to check:
> cat codereview.settings
# This file is used by gcl to get repository specific information.
GERRIT_HOST: True
CODE_REVIEW_SERVER: https://dart-review.googlesource.com
VIEW_VC: https://dart.googlesource.com/sdk/+
CC_LIST: reviews@dartlang.org
## Step 3: Create a branch for your new changes
Pick a branch name not existing locally nor in the remote repo, we recommend that you use your user name as a prefix to make things simpler.
> cd sdk # the repo created above
> git checkout -b uname_example # new branch
## Step 4: Do your changes and commit them locally in git
> echo "file contents" > awesome_example.txt
> git add awesome_example.txt
> git commit -a -m "An awesome commit, for an awesome example."
## Step 5: Upload CL using 'git cl' (installed with gcl)
> git cl upload origin/main
> git cl web
Then click on the `Start Review` button to send email to the reviewers from the Gerrit website.
## Step 6: Make code review changes and publish new versions of your code
> echo "better file contents" > awesome_example.txt
> git commit -a -m "An awesomer commit"
> git cl upload origin/main
## Step 7: Sync up to latest changes
If new changes have been made to the repo, you need sync up to the new changes before submitting your code. You can do this in two ways:
There are two ways to sync up:
* merging
> git pull origin main
> git cl upload origin/main
* rebasing
> git pull --rebase origin main
(which is similar to first pull and merge in main, and then rebase:
> git checkout main
> git pull
> git rebase main uname_example)
> git cl upload origin/main
## Step 8: Submit your changes
> git cl land origin/main
This command will close the issue in Gerrit and submit your code directly on main.
## Step 9: Clean up the mess
After submitting, you can delete your local branch so that the repo is clean and tidy :)
> git checkout main
> git branch -D uname_example # delete local branch
## Step 10: Goto step 3

View File

@ -0,0 +1,55 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
1. First line is a capitalized, short (50 chars or less) summary,
* Please include the component for which the change is being made in the first line
* **[Analyzer]** short (50 chars or less) summary
* **[dart2js]** short (50 chars or less) summary
* **[CFE]** short (50 chars or less) summary
* **[CoreLib]** short (50 chars or less) summary
* **[ddc]** short (50 chars or less) summary
* **[VM - Runtime]** short (50 chars or less) summary
1. **Always** add a blank line before more information. Many git tools assume this layout.
1. More detailed explanatory text, if necessary. Wrap it to about 72 characters or so.
1. When linking to an associated GitHub Issue
* **DO NOT** put `Issue 234` in the title
* **DO** Use the full GitHub URL to the issue - this ensures that the issue is clickable in Gerrit
* **DO** Use GitHub notation to auto-close bugs on commit
* This: `Closes https://github.com/dart-lang/sdk/issues/25595`
* Not this: `BUG=https://github.com/dart-lang/sdk/issues/25595`
* If you don't want to delete the `BUG=` boiler plate, at least add a space after the `=`. This ensures that the issue link is clickable in Gerrit.
5. Write your commit message in the present tense: "Fix bug" and not "Fixed bug." This convention matches up with commit messages generated by commands like git merge and git revert.
## Example
```
[VM - GC] Summarize changes in 50 chars or less
More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some
contexts, the first line is treated as the subject of an email and the rest of the text as the
body. The blank line separating the summary from the body is critical (unless you omit the
body entirely); tools like rebase can get confused if you run the two together.
Closes https://github.com/dart-lang/sdk/issues/1
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Use a hyphen or asterisk, followed by a single space.
- Use a hanging indent for
longer lines
```
## See also:
* [Closing issues via commit message (GitHub)](https://help.github.com/articles/closing-issues-via-commit-messages/)
* [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)

View File

@ -0,0 +1,260 @@
> [!warning]
> **Google Summer of Code 2020 is no longer accepting applications**.
The list of accepted projects have been announced on [summerofcode.withgoogle.com](https://summerofcode.withgoogle.com/organizations/6544944065413120/).
------------------
A list of Google Summer of Code project ideas for Dart. Students are welcome
to invent additional proposals.
For GSoC related discussions please use the [dart-gsoc group](https://groups.google.com/forum/#!forum/dart-gsoc).
**Potential mentors**
* `alan.knight@gmail.com`
* `bkonyi@google.com`
* `dacoharkes@google.com`
* `jonasfj@google.com`
* `redbrogdon@google.com`
* `brettmorgan@google.com`
## Project Application Process
All projects assume familiarity with Dart (and sometimes Flutter). Aspiring applicants are encouraged to [learn Dart](https://dart.dev/guides/language/language-tour) and try to write some code.
Applicants are welcome to find and fix bugs in [Dart](https://github.com/dart-lang/sdk) or some of the [packages written by the Dart team](https://pub.dev/publishers/dart.dev/packages). However, getting reviews can take a long time as code owners may be busy working on new features. So instead of requiring applicants to fix a _good first bug_, we
suggest that applicants write a working code sample relevant for the proposed project.
The code sample can be attached to the application as a secret [gist](https://gist.github.com/).
Suggested ideas for code samples include:
* A minimal Dart console program that uses `dart:ffi` to bind a simple C API.
(Perhaps compress a string with brotli, or make an HTTP request with libcurl)
* A small Flutter demo application..
* A minimal Dart library that can parse something simple.
(Perhaps a miniscule subset of YAML).
* A minimal Dart console program that can print the size and filename of the
first file in a USTAR tar archieve (ignoring other tar extensions).
* Check out the _getting started_ section for each idea, invent your own small demo,
or ask the potential mentor.
**Do not spend too much energy on this piece of sample code**, we just want to see
that you can code something relevant. Be aware that we have a limited number of
mentors available, and will only be able to accept a few applicants.
Applications can be submitted through the [summerofcode.withgoogle.com](https://summerofcode.withgoogle.com/) website. Students are encouraged to submit draft proposals, ideally linking to a Google Docs with permission for mentors to comment. See also the [student guide](https://google.github.io/gsocguides/student/writing-a-proposal) on writing a proposal.
**IMPORTANT**: Remember to submit _final proposals_ before [the March 31st deadline](https://summerofcode.withgoogle.com/how-it-works/#timeline).
## **Idea:** Additional File Formats for intl_translation
- **Possible Mentor(s)**: `alan.knight@gmail.com`
- **Difficulty**: Medium to advanced
- **Skills**: Dart; some parsing; some knowledge of internationalization helpful
**Description**:
The Dart [intl_translation](https://github.com/dart-lang/intl_translation) package supports the [ARB](https://github.com/google/app-resource-bundle/wiki/ApplicationResourceBundleSpecification) format for reading and writing text and translations. ARB is a simple format, as it is mostly a wrapper around the ICU [MessageFormat](http://userguide.icu-project.org/formatparse/messages#TOC-MessageFormat) syntax, but it is not widely used. It would be good to support one or more additional formats. It would also be good to allow users to add formats in their own packages, without modifying intl_translation. XLIFF is one obvious choice, both because it is widely used, and because it is quite a different format. XLIFF has a lot of flexibility, so we would want to look at it in the context of a particular usage, for example, iOS. But other formats are widely used as well.
**Getting Started**
Use intl and intl_translation to produce a small program that runs with translated messages, so you understand the workflow. The parsing is done using a grammar written in [petitparser](https://github.com/petitparser/dart-petitparser), take a look at that and try writing a simple grammar. Take a brief look at the ARB, MessageFormat and XLIFF (much larger) documentation.
For the proposal, it would be valuable to include:
- References to the documentation for the format(s) to be supported.
- An example of a complex message (e.g. a plural with several clauses) in both the existing format and in the other format(s)
- Discussion of any changes that would need to be made in intl_translation to support writing these in a separate package.
- Discussion of how to test the translation workflow.
----
## **Idea:** FFI Bindings generation from header files
- **Possible Mentor(s)**: `dacoharkes@google.com`
- **Difficulty**: Medium
- **Skills**: Dart programming skills; C programming skills.
**Description**:
Write a (Dart) program that generates `dart:ffi` bindings from a .h-file.
A possible approach could be to use the FFI to bind to clang.
This would greatly reduce the amount of effort developers using `dart:ffi`
would have to do. For more info [dart-lang/sdk#35843](https://github.com/dart-lang/sdk/issues/35843).
**Getting Started**
Write a Dart package that binds to a native library of your choosing to familiarize yourself with Dart and using `dart:ffi`. On top of that you could write a small Dart app to showcase using that library.
----
## **Idea:** Flutter testing sample app
- **Possible Mentor(s)**: `redbrogdon@google.com`, `brettmorgan@google.com`
- **Difficulty**: Medium
- **Skills**: Dart, Flutter coding skills.
**Description**:
One area in which the [Flutter samples repo](https://github.com/flutter/samples)
is lacking is automated testing. We've always wanted a sample app set up to
demonstrate the proper techniques for testing Flutter apps -- not so much the
testing philosophy involved, but the tech that powers Dart and Flutter's testing
architecture.
This project would involve creating a simple sample application for the repo,
and include unit, widget, and integration tests as the real prize.
**Getting Started** Try creating a small sample using [DartPad](https://dartpad.dev/), the online editor for Flutter and Dart:
* Think of something you found challenging when learning Dart or Flutter.
* Think of a small sample (the smaller the better!) that could have been useful to you when you were learning.
* Maybe a demo of Rows and Columns could have helped you learn how flex layouts work?
* Maybe a Dart sample showing a StreamController would have helped you learn how Streams work?
* Next, code your sample in DartPad and create a gist for it (see [this guide](https://github.com/dart-lang/dart-pad/wiki/Sharing-Guide)).
* Finally, submit your gist ID to [Awesome DartPad](https://github.com/divyanshub024/awesome-dart-pad) so the whole world can learn from it.
----
## **Idea:** Platform channel sample app
- **Possible Mentor(s)**: `redbrogdon@google.com`, `brettmorgan@google.com`
- **Difficulty**: Advanced
- **Skills**: Dart programming skills; C programming skills.
**Description**:
The [Flutter samples repo](https://github.com/flutter/samples) has a few apps
that touch on platform channels, but nothing dedicated to the topic.
A sample app that showed event channels, method channels, moving structured
data, and other related topics would be a welcome addition to the codebase.
**Getting Started** Try creating a small sample using [DartPad](https://dartpad.dev/), the online editor for Flutter and Dart:
* Think of something you found challenging when learning Dart or Flutter.
* Think of a small sample (the smaller the better!) that could have been useful to you when you were learning.
* Maybe a demo of Rows and Columns could have helped you learn how flex layouts work?
* Maybe a Dart sample showing a StreamController would have helped you learn how Streams work?
* Next, code your sample in DartPad and create a gist for it (see [this guide](https://github.com/dart-lang/dart-pad/wiki/Sharing-Guide)).
* Finally, submit your gist ID to [Awesome DartPad](https://github.com/divyanshub024/awesome-dart-pad) so the whole world can learn from it.
----
## **Idea:** Programmatic YAML modification package
- **Possible Mentor(s)**: `jonasfj@google.com`
- **Difficulty**: Easy to medium
- **Skills**: Parsing; abstract-syntax-trees; programming skills in Dart or similar language.
**Description**:
Write a Dart package for programmatically modifying a YAML file while
preserving comments. Figuring out the exact data structure and API for
modification is part of this project, though inspiration may be drawn from
[package:yaml](https://github.com/dart-lang/yaml). The goal is to use this
for implementing a `pub add <package>` command, which modifies the
`pubspec.yaml` without throwing away comments.
Stretch goal might be to preserve as much whitespace and YAML style as possible.
**Getting Started**
Try writing a small sample program that can parse a tiny subset of YAML, or
maybe parse a formula like `a + b / (c - d)`, or find and fix a bug in [package:yaml](https://github.com/dart-lang/yaml) (maybe search internet for [YAML test vectors](https://github.com/yaml/yaml-test-suite), and use that to find bugs in `package:yaml`).
For the proposal, it would be valuable to include:
* What are the challenges with mutating YAML?
* What is the API for this going to look like? What kind of mutations will be
possible?
* How do we plan to test this? What test cases can we find? How can we become
reasonably confident the implementation handles all corner cases?
* How is the mutation logic made robust? Will we need fallback strategies? How
will that work?
----
## **Idea:** TAR-stream reader package
- **Possible Mentor(s)**: `jonasfj@google.com`
- **Difficulty**: Advanced
- **Skills**: Dart programming skills; reading binary data; man files.
**Description**:
Write a Dart package for reading tar archives as a stream of objects, similar
to the [golang API](https://golang.org/pkg/archive/tar/), and ideally being
able to read the same test cases. A critical aspect of a streaming tar-reader is the ability to read a tar-stream `Stream<List<int>>` as a stream of file-entries with sub-streams for reading the file contents, such that a reader can read each file as a stream (never loading an entire file into memory at once).
This involves reading [man-files](https://www.freebsd.org/cgi/man.cgi?query=tar&apropos=0&sektion=5&manpath=FreeBSD+7.0-RELEASE&arch=default&format=html),
and figuring out how to represent all objects (or throw them away).
A stretch goal would be to replace the use of native `tar`
in `pub` for reading and writing tar-files. This would naturally include being
able to read all packages on [pub.dev](https://pub.dev).
**Getting Started**
Try writing a small sample program that can print the file name and size of the
first file in a USTAR tar archieve. Link to the sample in a secret gist attached
to the project proposal. For the proposal, it would be valuable to include:
* References to relevant documentation of the various TAR formats.
* An API outline for the streaming TAR reader package.
(Explain how an program using the package would read a tar file).
* List of TAR features you'd suggest supporting: what are the strech goals,
what features do we ignore, how do we expose these features.
(From the perspective of `pub` we mostly care about ordinary files and folders).
* How do we plan to test this? What test cases can we find? How can we become
reasonably confident the implementation handles all corner cases?
----
## **Idea:** SPDX license detection package
- **Possible Mentor(s)**: `jonasfj@google.com`
- **Difficulty**: Medium
- **Skills**: Dart programming skills; text parsing.
**Description**:
Write a Dart package for detecting SPDX license from a `LICENSE` file following
the [SPDX License List Matching Guidelines](https://spdx.org/spdx-license-list/matching-guidelines).
A goal would be properly represent the license of a package on pub.dev with an
SPDX identifier.
Stretch goal might be to handle `LICENSE` files with multiple licenses and
display an SPDX license expression on pub.dev.
**Getting Started**
Try writing a small sample program that can fetch one of the [SPDX master files](https://github.com/spdx/license-list-XML/tree/master/src) and print it to terminal as
markdown. Don't make it too perfect, just figure out how to parse the XML.
For the proposal, it would be valuable to include:
* References to relevant documentation.
* A discussion of strategies for handling complicated cases with multiple
licenses in the same file.
* An API outline for the package, what does the function signatures look like?
* List of features you would consider adding? what are the stretch goals? What
should be omitted to keep it simple/robust?
* How do we plan to test this? What test cases can we find? How can we become
reasonably confident the implementation handles all corner cases?
----
## **Idea:** Flutter Background Execution - Media Player Example
- **Possible Mentor(s)**: `bkonyi@google.com`
- **Difficulty**: Medium
- **Skills**: Dart, Java / Kotlin, Objective-C / Swift, Flutter programming skills; Android / iOS native development experience
- **Additional Requirements**: Access to a Mac for iOS development
**Description**:
The Flutter repository is lacking any example applications which perform tasks that
require background execution. There have been multiple requests for a [sample media player
application](https://github.com/flutter/flutter/issues/23794), which would involve building
an audio player plugin for both Android and iOS in addition to a UI in Flutter.
**Getting Started**:
Create a simple Flutter application which utilizes method channels to invoke functionality written in native code via Dart (Java or Kotlin for Android, Objective-C or Swift for iOS). This doesn't have to be anything complicated, just enough to experiment with writing code that crosses language boundaries. See Flutter documentation on [developing packages and plugins](https://flutter.dev/docs/development/packages-and-plugins/developing-packages) for information needed to get started.
It's also recommended that you read through the article on [background execution in Flutter](https://medium.com/flutter/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124). While this is slightly out of date, the general concepts are still correct and will be important for this project.
----
## Template for additional ideas
```md
## **Idea:** {{title}}
- **Possible Mentor(s)**: `{{email}}`
- **Difficulty**: {{easy | medium | advanced}}
- **Skills**: {{keyword}}; ...
**Description**:
{{description}}
**Getting Started**
{{how to get started; good first bugs; ideas for code samples; warm-up exercises}}
----
```

View File

@ -0,0 +1,161 @@
> [!warning]
> **Google Summer of Code 2021 is no longer accepting applications**.
---
A list of Google Summer of Code project ideas for Dart.
For GSoC related discussions please use the [dart-gsoc group](https://groups.google.com/forum/#!forum/dart-gsoc).
**Potential mentors**
* `jonasfj@google.com`
* `dacoharkes@google.com`
* `jwren@google.com`
## Project Application Process
All projects assume familiarity with Dart (and sometimes Flutter). Aspiring applicants are encouraged to [learn Dart](https://dart.dev/guides/language/language-tour) and try to write some code.
Applicants are welcome to find and fix bugs in [Dart](https://github.com/dart-lang/sdk) or some of the [packages written by the Dart team](https://pub.dev/publishers/dart.dev/packages). However, getting reviews can take a long time as code owners may be busy working on new features. So instead of requiring applicants to fix a _good first bug_, we
suggest that applicants write a working code sample relevant for the proposed project.
The code sample can be attached to the application as a [gist](https://gist.github.com/), or simply github repository. Suggested ideas below includes proposed "Good Sample Projects".
**Do not spend too much energy on this piece of sample code**, we just want to see
that you can code something relevant -- and that this sample code can run and do something non-trivial. Be aware that we have a limited number of
mentors available, and will only be able to accept a few applicants.
Applications can be submitted through the [summerofcode.withgoogle.com](https://summerofcode.withgoogle.com/) website. Students are encouraged to submit draft proposals, ideally linking to a Google Docs with permission for mentors to comment. See also the [student guide](https://google.github.io/gsocguides/student/writing-a-proposal) on writing a proposal.
**IMPORTANT**: Remember to submit _final proposals_ before [the April 13th deadline](https://summerofcode.withgoogle.com/how-it-works/#timeline).
----
## **Idea:** IntelliJ Live Templates
- **Possible Mentor(s)**: `jwren@google.com`
- **Difficulty**: medium
- **Skills**: Dart, Flutter, Java
**Description**:
Curate and implement live templates in the Flutter and Dart IntelliJ plugins. After this, the candidate may work in other feature areas of the Dart and Flutter IntelliJ plugin stack.
**Good Sample Project**
To start follow the directions here, https://github.com/flutter/flutter-intellij/blob/master/CONTRIBUTING.md, to get the Flutter plugin for IntelliJ compiling and running locally from source. Review the current set of provided templates here in these files in GitHub, then review the feature in other languages and frameworks with an eye on having our live templates feel consistent with IntelliJ.
----
## **Idea:** Standalone pub-server
- **Possible Mentor(s)**: `jonasfj@google.com`
- **Difficulty**: medium
- **Skills**: dart, http, html, css, jwt,
**Description**:
Write a standalone pub server following the [hosted pub repository specification](https://github.com/dart-lang/pub/blob/master/doc/repository-spec-v2.md). Goal could be to allow vendors to host private pub repositories for commercial packages, and/or facilitate internally mirroring of pub.dev for organizations with outgoing network restrictions. In addition to implementing a server, certain tweaks to the `pub` tool might be required for authentication with 3rd party servers.
**Good Sample Project**
Figure out how to make a webserver in Dart using [shelf](https://pub.dev/packages/shelf),
workout how to render HTML templates, convert Dart to JS for use client-side,
handle REST requests and generally familiarize yourself with the Dart server stack.
A hello world server than can serve files from disk, show some HTML and handle a simple REST request in JSON would be a good sample project.
----
## **Idea:** Extends git source in `pubspec.yaml` to understand tags
- **Possible Mentor(s)**: `jonasfj@google.com`
- **Difficulty**: advanced
- **Skills**: dart, git-wizardry,
**Description**:
Currently, `pubspec.yaml` can contain
[git dependencies](https://dart.dev/tools/pub/dependencies#git-packages).
However, `pub` does not support walking through the list of tags in a git repository
and finding all versions of the `pubspec.yaml` in the repository. Hence, a git
dependency always has exactly one version. What if `pub` could find all versions
of a package from a git repository, and use those versions in the solver.
**Good Sample Project**
Explore existing support for `git` dependencies in Dart, figure out how to work
with `--references` in git repositories, as well as commands for listing a
specific file `pubspec.yaml` from various tags in a repository. Explore to what
extend tags and files can be listed remotely without downloading
the entire repository.
A good sample project, might be able to output `pubspec.yaml` for all tags in `git` given a specific git repository and path to `pubspec.yaml`.
----
## **Idea:** SPDX license detection package
- **Possible Mentor(s)**: `jonasfj@google.com`
- **Difficulty**: easy
- **Skills**: Dart programming skills; text parsing.
**Description**:
Write a Dart package for detecting SPDX license from a `LICENSE` file following
the [SPDX License List Matching Guidelines](https://spdx.org/spdx-license-list/matching-guidelines)
or text similarity like [licensee](https://github.com/licensee/licensee) does.
A goal would be properly represent the license of a package on pub.dev with an
SPDX identifier.
Stretch goal might be to handle `LICENSE` files with multiple licenses and
display an SPDX license expression on pub.dev.
**Getting Started**
Try writing a small sample program that can fetch one of the [SPDX master files](https://github.com/spdx/license-list-XML/tree/master/src) and print it to terminal as
markdown. Don't make it too perfect, just figure out how to parse the XML.
For the proposal, it would be valuable to include:
* Comparison of text similarity approach to SPDX matching guidelines,
* References to relevant documentation.
* A discussion of strategies for handling complicated cases with multiple
licenses in the same file.
* An API outline for the package, what does the function signatures look like?
* List of features you would consider adding? what are the stretch goals? What
should be omitted to keep it simple/robust?
* How do we plan to test this? What test cases can we find? How can we become
reasonably confident the implementation handles all corner cases?
----
## **Idea:** Build a Cronet-based HTTP package with `dart:ffi` and `package:ffigen`
- **Possible Mentor(s)**: `dacoharkes@google.com`, `mannprerak2@gmail.com`
- **Difficulty**: advanced
- **Skills**: Dart, `dart:ffi`, API design, HTTP
**Description**:
With `dart:ffi` binding to native libraries we have an opportunity to build more performant and more feature rich IO libraries than `dart:io`.
Building such libraries has become one step easier by [`package:ffigen`](https://pub.dev/packages/ffigen) which can generate the bindings for the native libraries.
In this project we would like to target HTTP by binding to Cronet's [native API](https://chromium.googlesource.com/chromium/src/+/master/components/cronet/native/test_instructions.md).
This project will be challenging.
It requires the whole `dart:ffi` toolbox. For example: native resource management with finalizers and asynchronous callbacks with native ports.
Moreover, we might run into the limitations of Dart and `dart:ffi`, such as not being able to choose which thread the Dart executor thread runs on.
This knowledge will be valuable in shaping future work on `dart:ffi`.
**Good Sample Project**
Try writing a small web server in Dart with `dart:io` [tutorial](https://dart.dev/tutorials/server/httpserver), and replace the `dart:io` HTTP use with your own HTTP class which uses Cronet underneath with `dart:ffi` and `package:ffigen`.
You can go one step further by comparing the performance compared to `dart:io`, or using an HTTP feature that's not enabled in `dart:io`.
----
## Template for additional ideas
```md
## **Idea:** {{title}}
- **Possible Mentor(s)**: `{{email}}`
- **Difficulty**: {{easy | medium | advanced}}
- **Skills**: {{keyword}}; ...
**Description**:
{{description}}
**Good Sample Project**
{{how to get started; good first bugs; ideas for code samples; warm-up exercises}}
----
```

View File

@ -0,0 +1,154 @@
> [!warning]
> **Google Summer of Code 2022 is no longer accepting applications**.
---
A list of Google Summer of Code project ideas for Dart.
For GSoC related discussions please use the [dart-gsoc group](https://groups.google.com/forum/#!forum/dart-gsoc).
**Potential mentors**
* Jonas Jensen ([jonasfj](https://github.com/jonasfj)) `jonasfj@google.com`
* Daco Harkes ([dcharkes](https://github.com/dcharkes)) `dacoharkes@google.com`
* Sighurd Meldgaard ([sigurdm](https://github.com/sigurdm)) `sigurdm@google.com`
* Liam Appelbe ([liamappelbe](https://github.com/liamappelbe)) `liama@google.com`
* Majid Hajian ([mhadaily](https://github.com/mhadaily))
* Simon Lightfoot ([slightfoot](https://github.com/slightfoot))
* Miguel Beltran ([miquelbeltran](https://github.com/miquelbeltran))
## Project Application Process
All projects assume familiarity with Dart (and sometimes Flutter). Aspiring applicants are encouraged to [learn Dart](https://dart.dev/guides/language/language-tour) and try to write some code.
Applicants are welcome to find and fix bugs in [Dart](https://github.com/dart-lang/sdk) or some of the [packages written by the Dart team](https://pub.dev/publishers/dart.dev/packages). However, getting reviews can take a long time as code owners may be busy working on new features. So instead of requiring applicants to fix a _good first bug_, we
suggest that applicants write a working code sample relevant for the proposed project.
The code sample can be attached to the application as a [**secret** gist](https://gist.github.com/) (please use _secret gists_, and do not share these with other applicants). Suggested ideas below includes proposed "Good Sample Projects".
**Do not spend too much energy on this piece of sample code**, we just want to see
that you can code something relevant -- and that this sample code can run and do something non-trivial. Be aware that we have a limited number of
mentors available, and will only be able to accept a few applicants.
Applications can be submitted through the [summerofcode.withgoogle.com](https://summerofcode.withgoogle.com/) website. Students are encouraged to submit draft proposals, ideally linking to a Google Docs with permission for mentors to comment. See also the [student guide](https://google.github.io/gsocguides/student/writing-a-proposal) on writing a proposal.
**IMPORTANT**: Remember to submit _final proposals_ before [the April 19th deadline](https://developers.google.com/open-source/gsoc/timeline).
----
## **Idea:** JNI interop for Dart
- **Possible Mentor(s)**: `dacoharkes@google.com`, `liama@google.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, Java, C
**Description**:
Use `dart:ffi` to bind Java library in Flutter through [JNI](https://developer.android.com/training/articles/perf-jni). This would ideally encompass ergonomic Dart bindings for [JNI C interface](https://github.com/openjdk/jdk/blob/master/src/java.base/share/native/include/jni.h) and a bindings generator that can scan Java code or JARs and generate Dart bindings which uses JNI.
1. This project requires a way to scan Java code or JARs. For inspiration: package:ffigen scans C header files with libclang.
2. Design data structures to hold the information. And generate the C JNI code + Dart bindings.
3. This project needs an architecture design as well. Does it fit in package:ffigen? Or should we make a new package?
4. Make the package work for a killer use case. What Java library would you want to use from Dart?
**Good Sample Project**
Create a Flutter app that (1) calls a Java method from Dart with JNI, and (2) calls a Dart method from Java with JNI.
## **Idea:** Detecting Semantic Version Violations
- **Possible Mentor(s)**: `jonasfj@google.com`, `sigurdm@google.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, Static Analysis
**Description**:
Dart packages on pub.dev use [semantic versioning](https://semver.org/). We should be able to detect obvious compatibility violations. For each version of a package we can generate a JSON file with a summary of public methods/types/properties and their signatures. By comparing the summary of two package versions (which are supposed to be compatible), we should be able to detect obvious cases where semantic versioning was violated because class, member, property or type was removed or changed in a backwards incompatible manner.
Naturally, not all semantic version violations can be detected. But a subset would be detectable. This could be used for scoring on pub.dev, or offered as a utility package authors can run in CI before publishing their package.
A project proposal for this idea is encouraged to outline what the JSON format might look like. It would also be great to have some examples of semantic version violations that can be detected along with a brief description of how. Doing this it's probably also useful to think about a few examples of cases where we cannot detect semantic version violations, included a few such examples also helps demonstrate what limits exist. The project proposal doesn't have to outline the complete JSON format, or a completely list of heuristics, but a few examples showing the possibilities and limitations would be interesting.
**Good Sample Project**
Create a command-line Dart application that given a Dart file will use `package:analyzer` to print a list of all exported top-level symbols.
For example, given [`retry.dart`](https://github.com/google/dart-neats/blob/master/retry/lib/retry.dart) this application should print two lines containing `RetryOptions` and `retry`. Feel free to expand it print additional information about exported symbols, such as type, methods, etc.
## **Idea:** Changelog Parser for pub.dev
- **Possible Mentor(s)**: `jonasfj@google.com`, `sigurdm@google.com`
- **Difficulty**: Medium
- **Project size**: Small (175 hours)
- **Skills**: Dart, Parsing
**Description**:
Most packages on pub.dev contain a `CHANGELOG.md` file. When rendering this
file we would like to parse it and link versions to sections. There is already
some rudimentary code for parsing changelogs, but this doesn't handle
complex cases and does not link to versions. This project would be to write
a Dart package for parsing changelogs. Ideally, we should be able to parse
a large percentage of the existing changelogs on pub.dev correctly. This is
difficult because changelogs are written by hand, and different packages
have slightly different formats.
Goal is to integrate this with pub.dev, document a simple format for writing
changelogs and successfully parse the vast majority of changelogs on pub.dev.
## **Idea:** Flutter Community Admin Dashboard
- **Possible Mentor(s)**: Majid Hajian ([mhadaily](https://github.com/mhadaily)), Simon Lightfoot ([slightfoot](https://github.com/slightfoot))
- **Difficulty**: medium
- **Project size**: large
- **Skills**: Dart, Flutter
**Description**:
The Flutter Community (FC) is providing several packages to the community and pub. dev that is all maintained differently. Its hard for Flutter Community admins to engage with all of the changes, releases, changelogs, and activities on all packages.
One of the main challenges is keeping track of releases, especially allowing maintainers to trigger package releases on pub dev without giving them super admin access.
The FC dashboard would be an intelligent platform where it would gather information including issues, latest activity on repositories, maintainers, level of access, trigger to build and deploy to pub.dev, and more for all Admins as well as maintainers with different levels of permission.
Naturally, This dashboard is going to be an assistant to admins to figure out inactivities on different repositories and try to ping maintainers or admins in order to engage with PRs or users.
The publishing to pub.dev would also be maintained and managed on the dashboard instead of pub.dev, therefore, we would have a history of releases with full logs on who has done what.
Last but not least, it would be great to make the dashboard even smarter by adding some AI tooling that can potentially recognize issues that are not active or need to be closed or help maintainer to organize their way of working on their packages. We potentially like to see the UI done in Flutter so that we can deploy the app on all platforms if we need to!
Tasks:
* [ ] Simple login with Github only
* [ ] Gather information and show them as graphs, numbers and etc. to give a better understanding of the overall performance of the organization
* [ ] Details of each repo under the orgs, such as number of issues, in active issues, closing and maintainers
Ideally the dashboard can be hosted using Firebase. A project proposal for this idea is encouraged to include an outline of what metrics/information/graphs that would be surfaced in the dashboard.
**Good Sample Project** Authentication with Github and access level (authorization) and keep track of all issues grouped by packages/repositories.
Org: https://github.com/fluttercommunity
## **Idea:** Write integration Test for Plus Plugins
- **Possible Mentor(s)**: Majid Hajian ([mhadaily](https://github.com/mhadaily)), Miguel Beltran ([miquelbeltran](https://github.com/miquelbeltran))
- **Difficulty**: medium to hard
- **Project size**: small
- **Skills**: Dart, Flutter
**Description**:
The [plus plugins](https://plus.fluttercommunity.dev/) as provided by fluttercommunity are important as they expose many platform specific APIs. These plus plugins were forked from packages maintained by Flutter a few years ago, after which additional platform support and features have been introduced.
Thousands of users use the plugins! The plus team spends a lot of time handling issues, addressing issues and reviewing pull-requests to fix bugs, add new features and support additional platforms. This work is time consuming because minor bugs can negatively impact developers who rely on these packages for creating apps. Thus, great care is required when reviewing code and additional new features or platforms.
Adding integration tests for all plus plugin packages could help reduce the risk of introducing bugs when fixing bugs and adding new features or platforms.
This project idea is to write integration tests for all plus packages using the `integration_test` package. At a minimum it is desirable to have some tests for each plugin. But depending on much time is available, it would be attractive to expand the project to include:
* Testing most of the functionality using integration tests.
* Integration tests that work on multiple platforms.
* Running integration in continuous integration (Github Actions, when possible)
* Collecting code coverage from integration tests.
* Submitting code coverage statistics to coveralls.io
Links:
* [Example](https://github.com/fluttercommunity/plus_plugins/blob/main/packages/android_alarm_manager_plus/example/integration_test/android_alarm_manager_plus.dart)
* [Repository](https://github.com/fluttercommunity/plus_plugins/)
**Good Sample Project** contribute to the [plus_plugins repository](https://github.com/fluttercommunity/plus_plugins/) by fixing small issues.

View File

@ -0,0 +1,164 @@
> [!warning]
> **Google Summer of Code 2023 is no longer accepting applications**.
---
A list of Google Summer of Code project ideas for Dart.
For GSoC related discussions please use the [dart-gsoc group](https://groups.google.com/forum/#!forum/dart-gsoc).
**Potential mentors**
* Jonas Jensen ([jonasfj](https://github.com/jonasfj)) `jonasfj@google.com`
* Daco Harkes ([dcharkes](https://github.com/dcharkes)) `dacoharkes@google.com`
* Sigurd Meldgaard ([sigurdm](https://github.com/sigurdm)) `sigurdm@google.com`
* Liam Appelbe ([liamappelbe](https://github.com/liamappelbe)) `liama@google.com`
* Hossein Yousefi ([HosseinYousefi](https://github.com/HosseinYousefi)) `yousefi@google.com`
* Majid Hajian ([mhadaily](https://github.com/mhadaily)) `mhadaily@gmail.com`
* Brian Quinlan ([bquinlan](https://github.com/brianquinlan)) `bquinlan@google.com`
## Project Application Process
All projects assume familiarity with Dart (and sometimes Flutter). Aspiring applicants are encouraged to [learn Dart](https://dart.dev/guides/language/language-tour) and try to write some code.
Applicants are welcome to find and fix bugs in [Dart](https://github.com/dart-lang/sdk) or some of the [packages written by the Dart team](https://pub.dev/publishers/dart.dev/packages). However, getting reviews can take a long time as code owners may be busy working on new features. So instead of requiring applicants to fix a _good first bug_, we
suggest that applicants write a working code sample relevant for the proposed project.
The code sample can be attached to the application as a [**secret** gist](https://gist.github.com/) (please use _secret gists_, and do not share these with other applicants). Suggested ideas below includes proposed "Good Sample Projects".
**Do not spend too much energy on this piece of sample code**, we just want to see
that you can code something relevant -- and that this sample code can run and do something non-trivial. Be aware that we have a limited number of
mentors available, and will only be able to accept a few applicants.
Applications can be submitted through the [summerofcode.withgoogle.com](https://summerofcode.withgoogle.com/) website. Applicants are encouraged to submit draft proposals, linking to Google Docs with permission for mentors to comment. See also the [contributor guide](https://google.github.io/gsocguides/student/writing-a-proposal) on writing a proposal.
**IMPORTANT**: Remember to submit _final proposals_ before [the April 4th deadline](https://developers.google.com/open-source/gsoc/timeline).
## **Idea:** GOgen (or Rustgen, or ...)
- **Possible Mentor(s)**: dacoharkes@google.com, liama@google.com
- **Difficulty**: Hard
- **Project size**: / Large (350 hours)
- **Skills**: Dart, Go
**Description**: Package [FFIgen](https://github.com/dart-lang/ffigen) makes interop with C and Objective-C seamless, and the (experimental) package [JNIgen](https://github.com/dart-lang/jnigen) does the same for Java and Kotlin. However, what about [Go](https://go.dev/)?
In this project we would parse Go files and generate C wrappers and Dart bindings to those C wrappers so that developers can easily interop with Go from Dart.
1. Design a way to interop with Go. We can explore [cgo](https://pkg.go.dev/cmd/cgo), is this at the right abstraction level for interop? Or would we want a more high level interaction? For example, since Go is garbage collected, can we have handles to Go data structures from Dart that prevent them from being Garbage collected?
2. Design an approach to get the right information from a Go API. This will likely involve a Go parser and static analysis tool. That data structure then needs to be made accessible in Dart (either serialization such as in JNIgen or with direct FFI as in FFIgen).
3. Generate the code that does 1 and 2.
4. Profit!
(Alternatively, we could also do this project for another language. IDL, C++, Rust, …)
**Good Sample Project**: (1) Build a small sample project where you interop with a Go library. (2) Build a prototype for generating the bindings for that library, and (3) use a Go parser to generate those bindings.
## **Idea:** Testing documentation comments
- **Possible Mentor(s)**: `jonasfj@google.com`, `sigurdm@google.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, static analysis
**Description**: When writing Dart code it is useful to write
[documentation comments](https://dart.dev/guides/language/effective-dart/documentation#doc-comments),
such comments will be included in automatically generated documentation created by `dartdoc`.
Documentation comments for `dartdoc` are written in markdown, which allows authors to
embed [code samples](https://dart.dev/guides/language/effective-dart/documentation#consider-including-code-samples-in-doc-comments).
This project aims to create tools for testing _code samples_ embedded in documentation comments.
This will likely involve:
* Using `package:analyzer` to extract documentation comments.
* Using `package:markdown` to extract code samples.
* Testing these code samples by:
* Running `dart analyze` on the code sample,
* Passing the code sample through `dart format`, and/or,
* Running the code sample in an isolate and compare stdout to comments from the sample.
For this project, we'll finish the [`dartdoc_test`](https://pub.dev/packages/dartdoc_test) package, such that it can be used by
package authors who wish to test code samples in their documentation comments.
As part of this project, we'll likely have to define conventions for what is expected of a
code sample in documentation comments:
* What libraries (if any) are implicitly imported?
* Can you make code samples that are excluded from testing?
* Can comments inside the code sample be used to indicate expected output in stdout?
* How should code be written?
* Do all code samples need a `main` function?
* Do we wrap top-level code in an implicit `main` to keep it simple?
* Do we run the top-level function if it has a name other than `main`?
* Do we allow dead-code in samples (without an `// ignore: unreachable` comment)?
* What lints do we apply to sample code (same as the top-level project).
Some of these questions might be debated in the project proposal.
A project proposal should also discuss how package authors would run the code sample tests.
Finally, a project proposal is encouraged to outline implementation stages, including strech goals.
**Good Sample Project**: Create a function that given some Dart code will use `package:analyzer` to do static analysis of the code and count static errors. Additional step would be to try and use `package:analyzer` to extract documentation comments from source code and use `package:markdown` to extract code-snippets from source code comments, and then run analysis on the extracted source code snippets. Ideally, all of this could be done, in-memory without writing files to disk.
## **Idea:** Build a Dart HTTP client using Java APIs
- **Possible Mentor(s)**: `bquinlan@google.com`, `yousefi@google.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, Java, Android
**Description**: Write a HTTP client that conforms to the [`package:http` `Client` interface](https://pub.dev/documentation/http/latest/http/Client-class.html) and uses [native Java APIs](https://docs.oracle.com/en/java/javase/12/docs/api/java.net.http/java/net/http/package-summary.html) through [`package:jnigen`](https://pub.dev/packages/jnigen). This will allow us to provide several features requested by our users such as:
* Support for `KeyStore` `PrivateKey`s ([#50669](https://github.com/dart-lang/sdk/issues/50669))
* Support for the system proxy ([#50434](https://github.com/dart-lang/sdk/issues/50434))
* Support for user-installed certificates ([#50435](https://github.com/dart-lang/sdk/issues/50435))
Successfully completely this project will likely involve:
* Determining exactly what APIs should be make available in Dart.
* Creating a JNI bindings for those APIs using [`package:jnigen`](https://pub.dev/packages/jnigen).
* Creating a higher-level interface over the JNI bindings e.g. so the Dart developer can work with [Dart URIs](https://api.dart.dev/stable/dart-core/Uri-class.html) rather than [java.net.URI](https://developer.android.com/reference/java/net/URI).
* Creating a [`package:http` `Client`](https://pub.dev/documentation/http/latest/http/Client-class.html) implementation using the interface above.
* Verifying that the `Client` implementation passes the [conformance tests](https://github.com/dart-lang/http/tree/master/pkgs/http_client_conformance_tests).
You'll like working on this project because:
* It will be easy to implement incrementally. After the basic functionality is present, more advanced APIs can be added as time permits.
* There are existing [conformance tests](https://github.com/dart-lang/http/tree/master/pkgs/http_client_conformance_tests) to validate the correctness of the work.
* Dart users want it!
A good project proposal will describe what Java APIs are necessary to implement the [`package:http` `Client` interface](https://pub.dev/documentation/http/latest/http/Client-class.html) and an *excellent* project proposal will discuss what features [`package:jnigen`](https://pub.dev/packages/jnigen) needs to to use those APIs from Dart.
**Good Sample Project**: Try writing a small [Flutter](https://flutter.dev/) application that makes HTTP requests using Java API bindings created with [`package:jnigen`](https://pub.dev/packages/jnigen).
## **Idea:** Refactor Plus packages to utilize new Dart 3 language features
- **Possible Mentor(s)**: Majid Hajian <mhadaily@gmail.com>
- **Difficulty**: Hard
- **Project size**: / Medium (175 hours)
- **Skills**: Dart
**Description**: Dart 3 introduces a few new language features. There are several features such as Records, pattern matching and new direct platform library interop which potentially helps to improve code readability and better API design for packages.
We would like to explore the possibilities of the new language features that could help to improve packages and create a new API (potentially) or refactor internal coding that make the package to take full advantage of Dart 3. We would like to also prepare a guideline after this refactoring for other maintainers to figure out what could be improved or changed.
We are using [Federated plugins](https://docs.flutter.dev/development/packages-and-plugins/developing-packages#federated-plugins) therefore this is likely to involve:
* refactoring `platform_interface` class for each package,
* refactoring app-faceing and platform-specific-implementation packages,
* potentially removing native code and replacing it with direct dart API calls,
* rewriting the entire package unit and e-2-e tests,
* replacing CI/CD existing workflow making it compatible with upcoming language feature, and
* potentially breaking the API and releasing a new major version.
Some of these questions might be debated in the project proposal. A project proposal is encouraged to outline implementation stages, including stretch goals.
**Good Sample Project**: Create new packages for both [Device_Info](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus) or [Connectivity_Plus](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus) and redesign part of the APIs including in platform interface and use Dart 3 language features, then create a Flutter project from Master branch and then use these packages with latest Flutter and Dart 3 version that uses all APIs.

View File

@ -0,0 +1,259 @@
A list of Google Summer of Code project ideas for Dart.
For GSoC related discussions please use the [dart-gsoc group](https://groups.google.com/forum/#!forum/dart-gsoc).
**Potential mentors**
* Jonas Jensen ([jonasfj](https://github.com/jonasfj)) `jonasfj@google.com`
* Daco Harkes ([dcharkes](https://github.com/dcharkes)) `dacoharkes@google.com`
* Hossein Yousefi ([HosseinYousefi](https://github.com/HosseinYousefi)) `yousefi@google.com`
* Chinmoy Chakraborty ([chinmoy12c](https://github.com/chinmoy12c)) `chinmoy12c@gmail.com`
* Liam Appelbe ([liamappelbe](https://github.com/liamappelbe)) `liama@google.com`
* Prerak Mann ([mannprerak2](https://github.com/mannprerak2)) `mannprerak2@gmail.com`
* Jackson Gardner ([eyebrowsoffire](https://github.com/eyebrowsoffire)) `jacksongardner@google.com`
* Camille Simon ([camsim99](https://github.com/camsim99)) `camillesimon@google.com`
* Brian Quinlan ([bquinlan](https://github.com/brianquinlan)) `bquinlan@google.com`
## Project Application Process
All projects assume familiarity with Dart (and sometimes Flutter). Aspiring applicants are encouraged to [learn Dart](https://dart.dev/guides/language/language-tour) and try to write some code.
Applicants are welcome to find and fix bugs in [Dart](https://github.com/dart-lang/sdk) or some of the [packages written by the Dart team](https://pub.dev/publishers/dart.dev/packages). However, getting reviews can take a long time as code owners may be busy working on new features. So instead of requiring applicants to fix a _good first bug_, we
suggest that applicants write a working code sample relevant for the proposed project.
The code sample can be attached to the application as a [**secret** gist](https://gist.github.com/) (please use _secret gists_, and do not share these with other applicants). Suggested ideas below includes proposed "Good Sample Projects".
**Do not spend too much energy on this piece of sample code**, we just want to see
that you can code something relevant -- and that this sample code can run and do something non-trivial. Be aware that we have a limited number of
mentors available, and will only be able to accept a few applicants.
Applications can be submitted through the [summerofcode.withgoogle.com](https://summerofcode.withgoogle.com/) website. Applicants are encouraged to submit draft proposals, linking to Google Docs with permission for mentors to comment. See also the [contributor guide](https://google.github.io/gsocguides/student/writing-a-proposal) on writing a proposal.
**IMPORTANT**: Remember to submit _final proposals_ before [the April 2nd deadline](https://developers.google.com/open-source/gsoc/timeline).
## **Idea:** FFIgenpad
- **Possible Mentor(s)**: @dcharkes @mannprerak2 @eyebrowsoffire
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: C, WASM, Web development, Dart
**Description**:
Original idea: A web interface in which you paste a C header in a textbox on the left, and it outputs `dart:ffi` bindings generated by `package:ffigen` in a textbox on the right. (Inspiration is https://godbolt.org/ which does this for a C file on the left and assembly on the right.)
In order to avoid needing a server to do the backend, we'd like to compile the Dart code in `package:ffigen` and `libclang` to WASM. That way everything can run in the browser.
**Good Sample Project**:
* Compile some C code to WASM and call it from Dart (non-Flutter) web app compiled to WASM.
* Explore compiling libclang from the llvm repository to WASM.
For the purposes of this project, we decided that direct linking is going to make more sense for interfacing with libclang. It should be noted that direct linking will not actually work with a Flutter app, since wasm-compiled flutter apps already link against a separate wasm module for rendering and you cannot link more than one linear memory to the dart2wasm compiled module.
The recommended approach is going to be something like the following:
* Compile a small wasm module via emscripten with a single C function that will be called from dart code
* The Dart code can use the `dart:ffi` and `@Native` annotations to import the C function and call it.
* The Dart code can also use `package:web` to interact with the DOM, in order to input and output information to the user.
* Compile the Dart code to WebAssembly using `dart compile wasm`. The compiler outputs a `main.dart.mjs` file that is produced alongside the `main.dart.wasm` file. This is used to instantiate and invoke the webassembly-compiled dart program. Usage in JavaScript should look something like this:
```
import 'main.dart.mjs' as dartProgram;
const imports = ...; // Do something here to instantiate the external C module so its exports can be passed in as imports
const module = await dartProgram.instantiate(WebAssembly.compileStreaming(fetch('main.dart.wasm')), imports);
dartProgram.invoke(module);
```
Getting all this working and communicating would be a good first step. After that we'd probably want to look into doing some simple virtual filesystem access in the C module, as `libclang` will need access to the source files.
**Expected outcome**: A web app (possibly hosted on github.io).
## **Idea:** Swift/ObjC compatibility tool
- **Possible Mentor(s)**: @liamappelbe
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Swift
**Description**:
`package:ffigen` allows Dart to interact with ObjC. Swift modules can be invoked from ObjC (and Dart through ffi),
but only if the classes and methods have been annotated with `@objc`. So if a user wants to interact with a Swift
module they don't own from Dart, they need to write a wrapper module that mirrors the API, but has `@objc`
annotations.
It should be possible to write a tool that can automatically generate this ObjC compatibility wrapper. The official
[Swift parsing library](https://github.com/apple/swift-syntax) is written in Swift, so the tool should probably
also be written in Swift. In fact, the candidate doesn't even really need any Dart experience, just Swift and ObjC.
**Good Sample Project**: Use the Swift parsing library to load a module and print some of its metadata (e.g.
print a list of the classes in the module).
A great project proposal will also talk about which Swift language features can be feasibly supported by this tool.
For example, is it possible to write an `@objc` wrapper method for an `async` Swift method? What would that look
like? Swift is a modern language, and ObjC is not, so there are probably a lot of features that will be problematic
to wrap in a compatibility class.
**Expected outcome**: A dart package available on [pub.dev](https://pub.dev/).
## **Idea:** JNIgen transformations
- **Possible Mentor(s)**: `yousefi@google.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, Java
**Description**: With JNIgen, we bridge between Dart and Java by generating Dart bindings for Java classes. Sometimes however, the semantic differences between the languages means that we want to make some changes to these bindings. For example, accessing the `i`th element of an `List` in Java is done by `list.get(i)` but in Dart we can do `list[i]`. To facilitate these changes, we want to introduce a transformation mechanism.
Specifically we want to add the ability to rename, exclude, convert to operators, add members, and generally transform the classes and methods using visitor pattern. Something like this:
```dart
Config(
visitors: [Foo2BarRenamer()], // User passes the visitor to config
);
class Foo2BarRenamer extends JnigenVisitor {
void visitClass(Class c) {
if (c.name == 'foo') c.name = 'bar';
c.visitMethods(this);
// ...
}
// ...
}
```
**Good Sample Project**: Create a simple renamer/excluder visitor, so JNIgen users can pass that in, and rename/exclude classes, methods, and fields. You will have to create a user-facing AST that wraps the original AST. For the sample project, the wrapper AST could only expose `name` or `included` properties.
Feel free to email me and ask further questions about the project!
**Expected outcome**: A new set of features for [`package:jnigen`](https://pub.dev/packages/jnigen).
## **Idea:** Integrate OkHttp with Dart
- **Possible Mentor(s)**: `camillesimon@google.com`, `bquinlan@google.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, Java, Android
**Description**: Write a flutter plugin that wraps the [OkHttp](https://square.github.io/okhttp/) package using [`package:jnigen`](https://pub.dev/packages/jnigen) and implements the [`package:http` `Client` interface](https://pub.dev/documentation/http/latest/http/Client-class.html). Time permitting, the plugin will also implement the [`package:web_socket_channel` `WebSocketChannel` interface](https://pub.dev/documentation/web_socket_channel/latest/web_socket_channel/WebSocketChannel-class.html). This will allow us to provide several features requested by our users such as:
* Support for `KeyStore` `PrivateKey`s ([#50669](https://github.com/dart-lang/sdk/issues/50669))
* Support for the system proxy ([#50434](https://github.com/dart-lang/sdk/issues/50434))
* Support for user-installed certificates ([#50435](https://github.com/dart-lang/sdk/issues/50435))
Successfully completely this project will likely involve:
* Determining exactly what APIs should be make available in Dart.
* Creating a JNI bindings for those APIs using [`package:jnigen`](https://pub.dev/packages/jnigen).
* Creating a [`package:http` `Client`](https://pub.dev/documentation/http/latest/http/Client-class.html) implementation using those bindings.
* Verifying that the `Client` implementation passes the [conformance tests](https://github.com/dart-lang/http/tree/master/pkgs/http_client_conformance_tests).
You'll like working on this project because:
* It will be easy to implement incrementally. After the basic functionality is present, more advanced APIs can be added as time permits.
* There are existing [conformance tests](https://github.com/dart-lang/http/tree/master/pkgs/http_client_conformance_tests) to validate the correctness of the work.
* Dart users want it!
A good project proposal will describe what Java APIs are necessary to implement the [`package:http` `Client` interface](https://pub.dev/documentation/http/latest/http/Client-class.html) e.g. [`OkHttpClient.newCall()`](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-ok-http-client/new-call.html). An *excellent* proposal will use asynchronous APIs.
**Good Sample Project**: Try writing a small [Flutter](https://flutter.dev/) application that makes HTTP requests using OkHttp bindings created with [`package:jnigen`](https://pub.dev/packages/jnigen). You can use [`package:cronet_http`](https://github.com/dart-lang/http/tree/master/pkgs/cronet_http) and [`package:java_http`](https://github.com/dart-lang/http/tree/master/pkgs/java_http) as starting points.
> [!TIP]
> Look at the [`package:cronet_http`](https://github.com/dart-lang/http/tree/master/pkgs/cronet_http)
> [jnigen.yaml](https://github.com/dart-lang/http/blob/master/pkgs/cronet_http/jnigen.yaml) and
> [build.gradle](https://github.com/dart-lang/http/blob/master/pkgs/cronet_http/example/android/app/build.gradle#L76) files.
**Expected outcome**: A dart package available on [pub.dev](https://pub.dev/).
## **Idea:** Exception testing for `package:webcrypto`
- **Possible Mentor(s)**: `jonasfj@google.com`, `chinmoy12c@gmail.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, FFI, JS
**Description**: `package:webcrypto` ([github.com/google/webcrypto.dart](https://github.com/google/webcrypto.dart)) is a cross-platform implementation of the [Web Cryptography API](https://www.w3.org/TR/WebCryptoAPI/).
It is important that it behaves the same way whether it's running on Windows, Linux, Mac, Android, iOS, Chrome, Firefox, or Safari. Towards that end, it has a lot of test cases. We could and should probably make more test cases.
But we should also test that it throws the types of exceptions when given incorrect parameters. This probably needs a small test framework to ensure good test coverage.
We expect a proposal for this project to include:
* A sample showing how to test exceptions for `RsaPssPrivateKey.generateKey`.
Ideally, the sample project includes parts of a generalized framework for testing exceptions.
* An outline of what kind of exceptions should be tested?
* A design for extending `TestRunner`, or creating a new framework, to test exceptions thrown by all methods.
* Illustrative code for how test cases would be configured
* Pros and cons of the design (especially when multiple choices are available)
* Timeline for the project
**Good Sample Project**:
Write a test cases that tests the different kinds of errors and exceptions that can be thrown by `RsaPssPrivateKey.generateKey`, run the tests across desktop, Chrome and Firefox. Consider extending the tests to cover all members of `RsaPssPrivateKey`.
Try to generalize these test cases to avoid repetitive code, see the existing [TestRunner](https://github.com/google/webcrypto.dart/blob/5e6d20f820531d2b7b05935c1d78f38a036035e8/lib/src/testing/utils/testrunner.dart#L227) for inspiration.
**Expected outcome**: PRs that land in `package:webcrypto` and increases our confidence in correctness cross-platforms.
## **Idea:** Testing documentation comments
- **Possible Mentor(s)**: `jonasfj@google.com`, `chinmoy12c@gmail.com`
- **Difficulty**: Hard
- **Project size**: Large (350 hours)
- **Skills**: Dart, static analysis
**Description**: When writing Dart code it is useful to write
[documentation comments](https://dart.dev/guides/language/effective-dart/documentation#doc-comments),
such comments will be included in automatically generated documentation created by `dartdoc`.
Documentation comments for `dartdoc` are written in markdown, which allows authors to
embed [code samples](https://dart.dev/guides/language/effective-dart/documentation#consider-including-code-samples-in-doc-comments).
This project aims to create tools for testing _code samples_ embedded in documentation comments.
This will likely involve:
* Using `package:analyzer` to extract documentation comments.
* Using `package:markdown` to extract code samples.
* Testing these code samples by:
* Running `dart analyze` on the code sample,
* Passing the code sample through `dart format`, and/or,
* Running the code sample in an isolate and compare stdout to comments from the sample.
For this project, we'll finish the [`dartdoc_test`](https://pub.dev/packages/dartdoc_test) package, such that it can be used by
package authors who wish to test code samples in their documentation comments.
As part of this project, we'll likely have to define conventions for what is expected of a
code sample in documentation comments:
* What libraries (if any) are implicitly imported?
* Can you make code samples that are excluded from testing?
* Can comments inside the code sample be used to indicate expected output in stdout?
* How should code be written?
* Do all code samples need a `main` function?
* Do we wrap top-level code in an implicit `main` to keep it simple?
* Do we run the top-level function if it has a name other than `main`?
* Do we allow dead-code in samples (without an `// ignore: unreachable` comment)?
* What lints do we apply to sample code (same as the top-level project).
Some of these questions might be debated in the project proposal.
A project proposal should also discuss how package authors would run the code sample tests.
Finally, a project proposal is encouraged to outline implementation stages, including strech goals.
**Good Sample Project**: Create a function that given some Dart code will use `package:analyzer` to do static analysis of the code and count static errors. Additional step would be to try and use `package:analyzer` to extract documentation comments from source code and use `package:markdown` to extract code-snippets from source code comments, and then run analysis on the extracted source code snippets. Ideally, all of this could be done, in-memory without writing files to disk.
Useful hints: [analyzer tutorial](https://github.com/dart-lang/sdk/tree/main/pkg/analyzer/doc/tutorial) | [analyzer API docs](https://pub.dev/documentation/analyzer/latest/) | [analyzer file_system abstraction](https://pub.dev/documentation/analyzer/latest/file_system_file_system/file_system_file_system-library.html).
# Template:
Copy this template.
## **Idea:** ...
- **Possible Mentor(s)**:
- **Difficulty**: Easy / Hard
- **Project size**: Small (90) / Medium (175 hours) / Large (350 hours)
- **Skills**: ...
**Description**: ...
**Good Sample Project**: ...
**Expected outcome**: ...

View File

@ -0,0 +1,63 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Building and Testing
## AddressSanitizer
```
export ASAN_OPTIONS="handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1"
export ASAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
./tools/build.py --mode release --arch x64 --sanitizer asan runtime runtime_precompiled create_sdk
./tools/sdks/dart-sdk/bin/dart ./tools/test.dart -n dartk-asan-linux-release-x64 -N dartk-asan-linux-release-x64
```
## MemorySanitizer
```
export MSAN_OPTIONS="handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1"
export MSAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
./tools/build.py --mode release --arch x64 --sanitizer msan runtime runtime_precompiled create_sdk
./tools/sdks/dart-sdk/bin/dart ./tools/test.dart -n dartk-asan-linux-release-x64 -N dartk-msan-linux-release-x64
```
## LeakSanitizer
```
export ASAN_OPTIONS="handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1"
export ASAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
./tools/build.py --mode release --arch x64 --sanitizer lsan runtime runtime_precompiled create_sdk
./tools/sdks/dart-sdk/bin/dart ./tools/test.dart -n dartk-asan-linux-release-x64 -N dartk-lsan-linux-release-x64
```
## ThreadSanitizer
```
export TSAN_OPTIONS="handle_segv=0:disable_coredump=0:abort_on_error=1"
export TSAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
./tools/build.py --mode release --arch x64 --sanitizer tsan dart runtime runtime_precompiled create_sdk
./tools/sdks/dart-sdk/bin/dart ./tools/test.dart -n dartk-asan-linux-release-x64 -N dartk-tsan-linux-release-x64
```
## UndefinedBehaviorSanitizer
```
export UBSAN_OPTIONS="handle_segv=0:disable_coredump=0:abort_on_error=1"
export UBSAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
./tools/build.py --mode release --arch x64 --sanitizer ubsan runtime runtime_precompiled create_sdk
./tools/sdks/dart-sdk/bin/dart ./tools/test.dart -n dartk-linux-release-x64 -N dartk-ubsan-linux-release-x64
```
The handle_segv=0 is only crucial when running through the test suite, wherein several tests are expected to segfault, and will fail if ASan installs its own segfault handler.
# Development #
AddressSanitizer works at the C++ language level, hence does not automatically know about code that Dart VM's JIT compiler generates, nor about low-level direct manipulation of the stack from C++ code.
Use the macro `ASAN_UNPOISON(ptr, len)` to explicitly inform ASan about a region of the stack that has been manipulated outside normal portable C++ code.
## Stack pointer ##
When running with detect_stack_use_after_return=1, ASan will return a fake stack pointer when taking the address of a local variable. Use `Isolate::GetCurrentStackPointer()` to get the real stack pointer (calls a tiny pregenerated stub).

View File

@ -0,0 +1,42 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
## Experimental Flags
_**NOTE**: This page is intended for developers working on the Dart SDK. If you are a developer and want to **use** experiment flags, see the [experiment flags documentation](https://dart.dev/tools/experiment-flags)._
When working on new features, it is common to control the availability of the feature through a flag. These features are turned off by default during the development cycle and enabled by default after there is sufficient signal that the feature is ready.
Experiment flags are defined in this SDK file:
https://github.com/dart-lang/sdk/blob/main/tools/experimental_features.yaml
Once there is a decision to enable the flag by default in a release, we need to retire the flag.
### When do we retire flags?
Flags should be retired once they have been in stable for a full release cycle (~3 months) and have not caused a significant amount of issues.
1. Feature is developed and hidden behind a flag, which is usually made public in beta 1 of version n-1.
2. Feature flag is enabled by default in beta 1 of version n.
3. Feature flag is retired in beta 1 of version n+1.
Typically, a feature will be experimentally available in the SDK prior to the feature being officially released, but there can be exceptions.
Development of a feature can span several versions, either because it's a big feature like null safety, or because the feature got deprioritized like triple-shift. Feature development can also be very short and happen entirely within a single release cycle, with the experiment only available through dev-releases of version n.
Example:
> The Dart community has been working on implementing telepathic code generation to be released in Dart 6.2. Users of the Dart 6.1 beta can try this experimental feature using the `--enable-experiment=telepathy` flag. The feature seems to be stable and successful. In dart 6.2 the feature is no longer behind an experimental flag and is enabled by default. The team now cleans up the experimental flag tests and removes the flag before launching Dart 6.3.
### Flag retirement work
1. Clean up tests that use experimental flags.
2. Ensure non-test code does not rely on experimental flags.
3. Verify that tests in `/pkg/*` directory do not rely on experimental flags.
4. Set `expired: true` in `tools/experimental_features.yaml` under the experimental flag entry.
5. Run the update scripts to update generated flag-handling code.
6. Alert the EngProd team of work completion.
7. EngProd team increments the SDK version.

View File

@ -0,0 +1,130 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Versioning Packages
## Bumping versions
Dart packages have two varieties of versioning schemes. We use
[semver](semver.org) with a variation that the numbers are shifted to the right
if the package is not stable enough to reach a `1.0.0` release. Note that the
Dart team culture was previously to keep packages at `0.x` for a long time,
whereas now we prefer to publish `1.0.0` as soon as feasible to avoid confusion
over these patterns.
- For packages that are not yet stable: `0.major.minor+patch`.
- For most packages: `major.minor.patch`.
Never include a `+1` on a version if the first number is not `0`. For breaking
changes, bump the _major_ version. For new features, including all non-breaking
API changes like introducing a new class, bump the _minor_ version. For bug
fixes, documentation changes, or any other change which doesn't impact calling
code, bump the _patch_ version.
## Making a change
Any time the code in the repo does not match exactly the code of a version
published on `pub`, both the `pubspec.yaml` and `CHANGELOG.md` should include a
`-wip` version. We bump the version on the _first_ change after a publish, even
if we don't plan on publishing the code in that state or if the change doesn't
impact consumers.
When opening a PR, check if the `pubspec` and `CHANGELOG` already have a `-wip`
version listed. If there is already a version, check what variety of version
bump it is from the previous published version and compare to the type for the
change you are making. If necessary you can "upgrade" the version change, for
instance if the current `-wip` version is a _patch_ number higher than what is
published, and you are adding a feature, rewrite the version into a _minor_
version change from what is published.
If the version is not currently a `-wip`, perform the appropriate version bump
and add a `-wip`. Add a section in the `CHANGELOG` to match. Include the `-wip`
suffix in both places to avoid potential confusion about what versions are
published. If the change has no external impact (for instance a safe refactoring
or lint cleanup) it is OK to leave the `CHANGELOG` section empty. If the change
has external impact add an entry to the section for that version.
## Making breaking version bumps
Whenever you have the occasion to make a breaking version change, check if there
are other minor breaking changes that should come with it.
- Search the issue tracker for potential breaking changes. Hopefully these are
tagged with `next-breaking-release`.
- Search the code for `@deprecated` members and remove them.
In most packages a breaking version bump should be rare. Before making a breaking
change you should weight many factors against the value provided by the change.
Some of these factors include:
### How many packages depend on this package?
All of these packages will have to release a new version, and possibly make
changes if they were actually broken by the changes.
### Will this change cause downstream breaking changes in other packages?
Be very careful about changes like this - as they can have much larger cascading
effects.
**Example**: Changing a sync API to be async. This could cause other packages to
change their APIs to also be async, so they also have to do a breaking change.
### Does this change break any internal projects?
Anything which could break internal projects is potentially much more difficult
to roll out. The entire internal codebase typically has to be migrated at once at
the same time as the roll.
This can cause cascading issues in rolling all the packages that depend on your
package internally, so it is important to take this consideration seriously.
For this reason it is recommended that any potentially breaking change be ran
through an internal presubmit before publishing externally.
This can also be mitigated by rolling out the breaking change in an incremental
way, where both the new behavior can be opted into and the old is the default
for some period of time. This allows internal code to be migrated one project
at a time and then the old behavior can be removed once everything is migrated.
## Publishing a package
- Always sync the package into google3 before publishing so that it can be
validated against a larger corpus of code. If the package rolls with SDK
it should be updated in DEPS and published only after the next successful
SDK roll.
- Open a PR which removes the trailing `-wip` from the version in both the
pubspec and the changelog. It is OK to do this in the same PR as another
change if that change should be published immediately.
- `pub publish`. Don't ignore any warnings or errors reported by pub unless
you are _completely_ confident they are safe to ignore.
- Add a git tag with the version that was published (e.g., `git tag v1.2.3`). Check
other tags in the repo to decide whether to include a leading `v` in the tag
(`git tag` or `git tag -l`). New repositories should prefer to include the `v`. In a
[mono repo](https://en.wikipedia.org/wiki/Monorepo), start the tag with the
name of the package. For example
[`build_runner-v1.7.0`](https://github.com/dart-lang/build/tree/build_runner-v1.7.0).
Be sure to `git push --tags` after adding a tag. Note that you can tag a specific commit -
instead of just tagging head - with `git tag v1.2.3 <commit-hash>`.
# Handling pull requests
- Pull requests should usually have a 1:1 correspondence with final commits.
Use "Squash and merge" after a review.
- Once a pull request is sent for review, commits on that branch should be
considered shared history. Never force push to a branch with an open pull
request. Prefer to merge into that branch to resolve conflicts, prefer not
to rebase.
- Comments are tied to commits, so force pushing also destroys comment
history in github prs.
- Pushing a new commit with code review updates makes it easy to review
changes since your last review, by looking at the new commits only.
- Add comments from the "Files changed" view, even as the PR author, so that
they can sent in a batch rather than replying to each one by one on the
"Conversation" view.
- The [gh cli tool](https://cli.github.com/) makes it easy to checkout a PR
in cases where a change may be easer to understand in an IDE.

View File

@ -0,0 +1,19 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
Please file issues found in Dart using github issue tracking. However, please note that Dart is being developed in several github repos, so please make sure to file the issue in the correct repo. Consult the table below for details.
Component | Issue tracker
--------- | -------------
SDK core (language, VM, dart2js, Analyzer, Debugger/Observatory) | [dart-lang/sdk](https://github.com/dart-lang/sdk/issues)
DartPad editor | [dart-lang/dart-pad](https://github.com/dart-lang/dart-pad/issues)
Pub tool | [dart-lang/pub](https://github.com/dart-lang/pub/issues)
dartfmt tool | [dart-lang/dart_style](https://github.com/dart-lang/dart_style/issues)
Dartdoc tool | [dart-lang/dartdoc](https://github.com/dart-lang/dartdoc/issues)
test library | [dart-lang/test](https://github.com/dart-lang/test/issues)
AngularDart | [dart-lang/angular](https://github.com/dart-lang/angular/issues)
www.dartlang.org website | [dart-lang/site-www](https://github.com/dart-lang/site-www/issues)

View File

@ -0,0 +1,49 @@
## What are Flutter pinned packages?
Flutter pinned packages are a set of packages that are pinned by the Flutter SDK to specific versions. Some examples are `package:characters` (pinned by `package:flutter`), `package:collection` (also pinned by `package:flutter`), and `package:path` (pinned by `package:flutter_test`).
To see the current list of pinned packages of the Flutter SDK at head, see the dependencies section of the following pubspecs:
- https://github.com/flutter/flutter/blob/master/packages/flutter/pubspec.yaml
- https://github.com/flutter/flutter/blob/master/packages/flutter_test/pubspec.yaml
- https://github.com/flutter/flutter/blob/master/packages/flutter_localizations/pubspec.yaml
If youre not using one of the above packages (e.g. `package:flutter_localizations`) then you wont be affected by its package pinning.
## Why does Flutter pin package versions?
By pinning its dependencies it is ensured the future release of a new package-version will not break apps made with an old Flutter SDK.
## How does the pinning affect me?
If youre developing a Flutter app, your app can only use the specific version of a package that Flutter has pinned. If you have a direct dependency on a pinned package, your pubspec constraint must support the version pinned by Flutter. E.g. if Flutter has pinned `package:path` to `1.8.3`, your pubspec constraint must support that version:
```yaml
dependencies:
path: ^1.8.0
```
Similarly, if youre using a package which itself has a dependency on a pinned package, that package needs to support the pinned version (i.e. your transitive dependencies also need to support the pinned version).
Generally people experience issues with pinning if their pubspec constraints dont support the pinned Flutter version, or - transitively - if one of their package dependencies dont support the pinned version.
## What are some workarounds?
### An immediate dependency doesnt resolve
Widen your constraint on the package in question (e.g. change a `>=1.7.0 < 1.8.0` constraint on package:path to `^1.8.0`).
### I see issues through one of my dependencies
The package youre using needs to widen its constraint on the pinned package. Either you need to update your dependency to bring in a new version of the package, or, that package needs to publish a new version that supports the pinned package version. If a version of the package isnt available which supports the pinned version, try visiting the issue tracker of the dependency to let them know about the issue.
### I see issues through one of my dependencies but they cant immediately release a new version
As a fallback solution, you can specify a [dependency override](https://dart.dev/tools/pub/dependencies#dependency-overrides) in your own pubspec. This will tell pub to use a specific version of a package whether or not its compatible with the other packages youre using.
```yaml
dependency_overrides:
foo: 1.8.3
```
Note that youre now consuming a version of foo that not all of your other dependencies have been tested with; you may see analysis or runtime issues as a result (this should be considered a short-term solution).

View File

@ -0,0 +1,29 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Frequently asked questions about the Dart VM
## Inlining of Dart methods by the JIT/AOT compilers
1. What are the conditions and requirements for a method to be inlined ?
First, compiler needs to figure out that a particular call in the caller leads to a particular callee. For static methods and constructors this is always the case. For instance methods it depends on the class hierarchy, whether the method is overridden and whether compiler can determine (or speculate on) the actual type of the receiver. Method is less likely to be inlined if call site is polymorphic (can call multiple different methods).
After figuring out the target of the call, compiler uses a very complex heuristic to decide whether to inline a method or not. The heuristic is based on the size of the caller and the callee, number of call sites in the callee, loop nesting in the caller etc. @pragma("vm:prefer-inline") on the callee bypasses those heuristics and tells compiler to inline annotated method if it is possible.
Currently compiler cannot inline certain methods, even if they are annotated with @pragma("vm:prefer-inline"). Those include methods with a try block, methods declared async, async*, sync* and certain core library methods.
2. Could this pragma be useful for public methods which called from other classes and using private fields like in this example
`@pragma(vm:prefer-inline)`
`void removeClient(int fd) => _serversByClients.remove(fd);`?
Absolutely. However, unless the method is critical for performance and you can measure that inlining of this method improves performance, consider relying on the compiler heuristic. Excessive inlining causes larger code size, and in certain cases inlining may regress performance instead of improving it.
3. Inlining is possible in JIT and AOT modes or only JIT?
Both JIT and AOT compilers do the method inlining. However, the heuristic for choosing whether to inline is slightly different and based on different information. JIT can inline speculatively, based on the collected feedback from executing program. AOT compiler uses whole-program analysis to determine possible call targets which can be inlined. Both JIT and AOT respect @pragma("vm:prefer-inline") annotation.

View File

@ -0,0 +1,55 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
In addition to requiring reviews from OWNERS our Gerrit instance applies a number of additional requirements to specific CLs.
# Commit-Message-Has-TEST
All CLs touching one of the Dart VM source directories require a line `TEST=...` or a footer `Tested:...` describing how the change was tested.
```
# New test was added to cover the issue and prevent regressions.
TEST=vm/cc/IL_Canonicalize_RepresentationChange
# There is a reason to believe CI tests already cover newly added code.
TEST=ci
# Some debug code was added which is not worth testing on CI.
TEST=manually by running a test with debug flags
Tested: Used a footer to describe testing. No blank lines allowed before other footers.
Change-Id: abcdef
```
Rationale for this requirement is to encourage both the author and reviewers to consider if the change comes with adequate test coverage.
# Core-Library-Review
All CLs changing core libraries sources (i.e. Dart files residing in `sdk/lib` directory with the exception of `_http` and `_internal` sub-directories) require either:
* `CR+1` from representatives of all backend teams (g2/dart-core-library-change-approvers-vm, g2/dart-core-library-change-approvers-wasm, g2/dart-core-library-change-approvers-web) and Core Library API owners (g2/dart-core-library-change-approvers-api);
* or `CoreLibraryReviewExempt: ...` footer which explains why this change is exempt from the requirement.
Rationale for this requirement is to avoid API or implementation changes which have negative impact on one of the platforms.
# Changelog
All CLs to the stable branch must modify the `CHANGELOG.md` file to explain the changes. The beta branch does not have `CHANGELOG.md` entries.
If changes are important enough to cherry-pick to stable, they are important enough to tell our users about. Infrastructure changes that are invisible to users can be exempted using the `Changelog-Exempt: ...` footer explaining why a CHANGELOG entry isn't needed.
See the [instructions for writing stable changelogs](Cherry-picks-to-a-release-channel#changelog) for more information.
# Cherry-Pick
All CLs to the stable and beta branches go through the [cherry-pick approval process](Cherry-picks-to-a-release-channel) and have metadata reflecting the process.
The commit message must contain the `[stable]` or `[beta]` hashtags to ensure reviewers notice the change is a cherry-pick to a release branch.
The `Cherry-pick` footer must link to the original review on the main branch. Use the footer multiple times if multiple changes are bundled into the cherry-pick. If the change is original and isn't cherry-picked from main, then describe why the change is original. The purpose of the footer is to help reviewers understand the original change and know it is safe on the release branch.
The `Cherry-pick-request` footer must link to the github issue where the cherry-pick's rationale is being approved. The purpose of the footer is to help reviewers understand why the cherry-pick is needed and to ensure the approvals are obtained before submission.
The commit message must not contain the old `Reviewed-on`, `Reviewed-by`, and `Commit-Queue` footers from the old commit message as they are not true of the new change. The appropriate new footers will be automatically generated on submission.

103
docs/Heap-snapshots.md Normal file
View File

@ -0,0 +1,103 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
The [VM service protocol](https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md) provides access to _heap snapshots_, a description of all the objects and references in the heap at some point in time. Tools such as Observatory provide analysis and visualization of these snapshots to help developers understand the memory usage of their applications.
* [Concepts](#concepts)
* [Advice](#concepts)
## Concepts
```dart
class R {
var field1;
var field2;
}
class A {
var field1;
var field2;
}
class B {
var field1;
var field2;
}
class C {
var field1;
var field2;
}
class D {
var field1;
var field2;
var field3;
}
class E {
var field1;
var field2;
}
class F {
var field1;
var field2;
}
class G {
var field1;
var field2;
}
var root;
main() {
var r = new R();
var a = new A();
var b = new B();
var c = new C();
var d = new D();
var e = new E();
var f = new F();
var g = new G();
r.field1 = a;
r.field2 = b;
a.field1 = c;
b.field1 = c;
b.field2 = d;
c.field1 = d;
d.field1 = b;
d.field2 = e;
d.field3 = f;
e.field1 = g;
f.field1 = g;
root = r;
}
```
### Successors
The successors of an object are the objects it directly references, such as through an instance variable or an array element.
![Graph theory successors](images/successors.svg)
![Observatory successors](images/observatory-successors.png)
### Predecessors
The predecessors of an object are the objects that directly reference it.
![Graph theory predecessors](images/predecessors.svg)
![Observatory predecessors](images/observatory-predecessors.png)
### Dominators
In a heap [dominator](https://en.wikipedia.org/wiki/Dominator_(graph_theory)) tree, an object X is a parent of object Y if every path from the root to Y goes through X. This allows you to find "choke points" that are holding onto a lot of memory. If an object becomes garbage, all its children in the dominator tree become garbage as well.
![Graph theory dominators](images/dominators.svg)
![Observatory dominators](images/observatory-dominators.png)
### Owners
An object X is said to "own" object Y if X is the only object that references Y, or X owns the only object that references Y. In particular, objects "own" the space of any unshared lists or maps they reference.
![Graph theory owners](images/owners.svg)
## Advice

336
docs/Hot-reload.md Normal file
View File

@ -0,0 +1,336 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Live program changes in the Dart VM ("Hot reload")
The Dart VM can apply changes to a running (live) program, which it calls _hot reload_. The semantics are very close to those of Smalltalk, which doesn't have a name for this feature since in most Smalltalk implementations program changes can only be made in a live programming environment.
The main principles of reload's behavior are
* [The program behaves as if method lookup happens at every call.](#pervasive-late-binding)
* [The "atoms" of reload are methods. Methods are never changed, but method dictionaries are updated with new methods.](#immutable-methods)
* [Fields retain their values.](#state-is-retained)
It's also important to note that hot reloading only changes the behavior of the program going forward. It does not change the program's state to reflect what would have happened if the new program had been running from the beginning. The behavior of a hot reloaded program can differ from the behavior of both the old and the new program running without a hot reload.
## Pervasive late-binding
The program behaves as if method lookup happens at every call. Any call that runs after a reload, even those call sites that have previously run or are pending on the stack, should reflect the result of a lookup in the new program rather than the old program.
(In the implementation, the VM aggressively attempts to avoid method lookups by using caches and inlining. To preserve the semantics of hot reload, inline caches are cleared and inlining is unfolded at the time of a reload.)
Before:
```dart
class C {
foo() => "before";
}
main() {
var c = new C();
print(c.foo());
reload();
print(c.foo());
}
```
After:
```dart
class C {
foo() => "after";
}
main() {
var c = new C();
print(c.foo());
reload();
print(c.foo());
}
```
Result:
```
before
after
```
## Immutable methods
The "atoms" of reload are methods. Methods are never mutated. Changes to a method declaration create a new method, mutating the class or library's method dictionary. The old method may still exist if has been captured by a closure or stack frame.
Closures capture their function when they are created. A closure always has the same function before and after a change, and all invocations of a given closure run the same function.
Before:
```dart
class C {
deferredPrint() {
return () => print("before");
}
}
main() {
var c = new C();
var closure = c.deferredPrint();
closure();
reload();
closure();
}
```
After:
```dart
class C {
deferredPrint() {
return () => print("after");
}
}
main() {
var c = new C();
var closure = c.deferredPrint();
closure();
reload();
closure();
}
```
Result:
```
before
before
```
Stack frames capture their function. A stack frame will continue to run the same function until it returns.
Before:
```dart
main() {
print("before");
reload();
print("before");
}
```
After:
```dart
main() {
print("after");
reload();
print("after");
}
```
Result:
```
before
before
```
## State is retained
Hot reload does not reset fields, neither the fields of instances nor those of classes or libraries. Resetting all fields would make a hot reload equivalent to a restart.
Before:
```dart
var foo = "before";
main() {
print(foo);
reload();
print(foo);
}
```
After:
```dart
var foo = "after";
main() {
print(foo);
reload();
print(foo);
}
```
Result:
```
before
before
```
Remember that statics fields in Dart are lazily initialized. If a field has not been accessed before a change, the new initializer will run if it is accessed after the change.
Before:
```dart
var foo = "before";
main() {
reload();
print(foo);
}
```
After:
```dart
var foo = "after";
main() {
reload();
print(foo);
}
```
Result:
```
after
```
## Limitations
The Dart VM will reject some types of changes that it cannot handle. Changes are atomic: they are never partially applied. If a change is rejected, the program continues as if no change had been attempted.
The cases where a reload is rejected are
- Changes between regular classes, enums and typedefs (`class C {}` <=> `enum C {}` <=> `typedef void C()`)
- Changes to the number of type arguments in a class. (`class C<T>` <=> `class C<T,S> {}`)
(Schema changes to type arguments are not safe because of the type argument prefix optimization.)
- Changes to a library with deferred imports (`import 'a' deferred as a`).
(This simply hasn't been implemented.)
- Changes to the number of native fields (`class C extends NativeFieldWrapperClass1 {}` <=> `class C extends NativeFieldWrapperClass2 {}`).
(Changing the shape of native wrappers generally requires corresponding changes to the native code.)
The Dart VM also lacks a way to migrate field values during a change. In particular, there is no way to communicate the intention of a renamed field to carry the value over from the old name to the new name. The Dart VM only sees addition and removal of unrelated fields.
## Defects
In the following cases, the VM will accept changes, but it can produce incorrect results. Note all of these cases involve code pending on the call stack. In Flutter, reload usually happens at the top of the message loop where there is an empty call stack, so one is quite unlikely to encounter these cases in Flutter.
- A call without an explicit receiver that changes meaning from an instance call to a static call (or vice versa), that was on the stack at the time of reload.
Before:
```dart
bar() => "before";
class C {
foo() {
print(bar());
reload();
print(bar());
}
}
main() {
new C().foo();
}
```
After:
```dart
class C {
bar() => "after";
foo() {
print(bar());
reload();
print(bar());
}
}
main() {
new C().foo();
}
```
Correct result:
```
before
after
```
Actual result:
```
before
before
```
- A super call that was on the stack at the time of reload has a new target.
Before:
```dart
class A {
bar() => "A-bar";
}
class B extends A {}
class C extends B {
bar() => "C-bar";
foo() {
print(super.bar());
reload();
print(super.bar());
}
}
main() {
new C().foo();
}
```
After:
```dart
class A {}
class B extends A {
bar() => "B-bar";
}
class C extends B {
bar() => "C-bar";
foo() {
print(super.bar());
reload();
print(super.bar());
}
}
main() {
new C().foo();
}
```
Correct result:
```
A-bar
B-bar
```
Actual result:
```
A-bar
A-bar
```
- A static call that was on the stack at the time of reload changes between having a target and having no target.
Before:
```dart
foo() => "before";
main() {
print(foo());
reload();
print(foo());
}
```
After:
```dart
main() {
print(foo());
reload();
print(foo());
}
```
Correct result:
```
before
NoSuchMethod: foo
```
Actual result:
```
before
before
```

View File

@ -0,0 +1,322 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
The Dart SDK repo contains a large number of tools and libraries maintained by a
variety of sub-teams. Having them all in one repo makes it easier to land sweeping
changes across those components, but it comes at the expense of a big, unwieldy
issue tracker. To tame that chaos, we use the labels and policies explained here.
## Assignment
Like many modern software teams, Dart uses a pull model to assign tasks to
people. Most issues are assigned to a team (using the area labels below), but
not proactively assigned to an individual. When a person begins active work on
an issue, they assign the issue to themselves.
If you see an issue with a person assigned to it, it's usually in-progress. This
isn't always the case. Sometimes an issue is assigned to someone because we know
they will be the one to fix it, but they haven't started yet. When work gets
paused (sometimes for a long time) the assignee might not unassign themselves.
## Labels
Labels help us narrow down issues to the subsets each team or person cares
about. They let us count related issues to compare areas or see trends over
time. And they help the larger community understand what we're working on and
the state of their bugs.
For consistency, label names are `kebab-case`: lowercase words separated
by hyphens. Since we have a lot of labels, most of them are categorized. The
first word in the label name usually indicates the category. The labels and
categories are:
### Area ("area-")
These are the main labels that people on the Dart team care about. Each area
label defines a subteam (sometimes just one person) that owns issues and is
responsible for resolving them or passing them to another area.
Every issue must have a single area label. We've found that when labels have no
area, or multiple areas, it's not clear who is responsible for it, and it falls
through the cracks. If a single issue needs work from multiple teams, then it's
split into two or more issues, each one assigned to a single area.
The "[area-meta][]" area is special. A meta-issue groups a set of other issues
together to coordinate work across multiple teams. The issue usually describes
the overall plan at a high level and then links to the specific issues related
to it. Since no one team is responsible for "area-meta", an issue with that
label should also be assigned to a single person that is responsible for
tracking the status of the individual linked issues and closing the meta-issue
when everything is complete.
### Browser
For issues on our web products, this tracks which browser is affected by the
issue. We don't always apply this diligently, so the absence of this could mean
either "all browsers" or "we haven't investigated which browsers are affected".
Likewise, the *presence* of this doesn't necessarily mean other browsers are in
the clear.
### Customer ("customer-")
If an issue seriously affects a key partner, this tracks who they are. This
helps us prioritize the issue and makes sure we keep them in the loop on it.
We also use this to track Dart subteams that are affected by an issue owned
by another area. For example, if someone files a bug that the VM is failing to
display a certain static error, it would likely have "[area-cfe][]" (because the
front end team handles static errors) and "[customer-vm][]" because that's where
the error isn't being surfaced.
### OS ("os-")
Similar to browser, this tracks which operating systems an issue manifests on.
Again, we aren't super diligent about this. The presence of this label indicates
that we know it *does* have a problem on that OS, but may still possibly affect
others.
### Priority
Priority labels indicate the team's urgency around resolving the issue. They
roughly mean:
* **[P0][]**: "World is on fire." Issues like multiple products
unusable, a security issue exposing personal information, or a dramatic
performance regression. As many team members as needed should drop
everything to fix this.
* **[P1][]**: "Something's broken." A single project is unusable or has
many test failures. It should be fixed before resuming normal work.
* **[P2][]**: "Business as usual." These are normal issues and feature
requests that we can work into our schedule without any particular urgency.
* **[P3][]**: "If you get a chance." Cosmetic or minor bugs with no
urgency and low visibility. Polish or nice-to-haves.
Almost every issue should have exactly one of these labels.
### Closed ("closed-")
As the name implies, these labels are applied to closed issues, and indicate why
it was closed. In a perfect world, every issue filed would uniquely identify a
real, important problem and every closed issue would be fixed.
Alas, sometimes issues are duplicates of others, are too confusing, or we simply
don't have the time to do anything about it. We take every issue seriously, but
we also have to maximize the value we provide in the limited time we have, which
requires some trade-offs.
If an issue is closed without a closed label, that implies it is fixed. There
should usually be a link to the commit that fixes the issue or a comment
explaining it. Otherwise, it should have one of the resolution labels applied,
and often a comment explaining why that resolution was chosen.
The reasons are:
* **[closed-as-intended][]**: This is one of the most contentious reasons to
close an issue. This label means the current behavior is what we want, even
though it's clearly not what the person who filed the issue wants.
When possible, the person closing the bug should write a comment explaining
why the current behavior is preferred. Often, there are constraints or
interactions with other systems that prevent us from supporting the
requested behavior. Sometimes it's simply making a trade-off between users
who want different things.
* **[closed-cannot-reproduce][]**: It's hard to verify that a fix is the right
one without being able to see the underlying problem first. Sometimes this
happens because the bug got fixed before anyone looked at the issue. Other
times, the problem is still there but the investigator failed to get it to
manifest. This resolution means they weren't able to make the issue happen
and they believe it's likely to not be a problem any more.
If an issue you filed is closed with this but it is still valid, consider
adding a comment with more detailed reproduction steps so the issue can be
re-opened.
* **[closed-duplicate][]**: There is already another issue that tracks
this change. When an issue is closed with this label, it should also have a
comment that links to the other issue it is a duplicate of.
Determining if two issues are duplicates often relies on
understanding internal architecture and implementation details. Sometimes
two issues look like the same problem but need to get solved in different
ways. Other times, two seemingly-different issues have the same underlying
cause.
Because we use issues to track units of work, we treat issues as duplicates
if they will be solved by a single change. This means that when we close one
issue, we are not discarding the information in the issue or the important
discussion it might have. That's still there and easy to find since the open
issue links to it. It simply means we think there is only one task to
perform that will address both issues, so there is no need to keep both
open.
In general, when deduplicating issues, we tend to keep the older one open
unless the newer one is clearly more useful.
* **[closed-invalid][]**: Sometimes, despite everyone's best intentions, we
can't figure out what an issue description is trying to convey. Users
sometimes file issues on our repo for completely unrelated products.
Mistakes happen. This label means we couldn't make heads or tails of the
issue.
Most of the time, we try to avoid this and instead use "[needs-info][]" to
get clarification from the person who filed the issue.
* **[closed-obsolete][]**: The issue has been around for a long time with no
activity. No one has worked on a solution and people don't seem to be
clamoring for one either. The problem may have been fixed without someone
realizing there was an issue. Sometimes stuff that was important turns out
not to be later when needs change.
In that case, there's little value keeping a zombie issue around and it will
get closed. It's always OK to re-open the issue or file a new one of it
turns out the problem is still relevant. This label is often applied
manually by people when closing bugs, but also by the bot according to our
expiration policy below.
* **[closed-not-planned][]**: Possibly the saddest label. This is for issues
where the request is valid but isn't expected to happen. Sometimes this is
because other higher-priority enhancements would directly conflict with it.
Often, it's simply a matter of not having enough time to get to it.
When an issue is closed as not planned, that doesn't mean it will *never*
happen. Priorities and capacity changes over time and it's entirely possible
that it will come to the fore in the future. But in the meantime, we think
it more clearly communicates the team's current priorities to close the
issue instead of letting it linger even though we have no intent to
allocate time to it.
### Type ("type-")
An issue's type categorizes the kind of problem entailed, or the nature of the
work required to solve it. There are a handful:
* **[type-bug][]**: Issues with this label describe problems where the current
behavior of the system is wrong and is not intended to act this way. It
could be as severe as a crash or a more subtle misbehavior, but it should be
obviously wrong in a way that almost no user wants.
* **[type-code-health][]**: This tracks internal changes to our tools and
workflows to make them cleaner, simpler, or more maintainable in ways that
aren't user visible.
* **[type-documentation][]**: A request to add or improve documentation. Since
most of the high level docs like the pages on [dartlang.org][] are managed
in other repositories, this ends up not being particularly common and is
mostly API-level doc comments.
* **[type-enhancement][]**: Every request for a concrete change to a tool that
isn't a bug is an enhancement. These are new features, refinements to
existing features, or other changes where the current behavior was intended
but may no longer be desired or sufficient. Most issues around changing code
get this label.
* **[type-performance][]**: These are issues where the observed behavior is
correct but the efficiency leaves something to be desired. "Performance"
varies across a number of axes: execution time, memory usage, startup time,
etc.
* **[type-security][]**: The scariest kind of issue. These are problems
related to user privacy or the ability of a malicious actor to take over a
system.
* **[type-task][]**: Tasks track work that needs to be done but where the
result isn't a change to code or documentation. This is things like moving
data around, publishing packages, tweaking servers or other infrastructure,
etc.
Any given issue should have exactly one of these. If not, it's probably still
waiting to be triaged.
### Area-specific labels
Subteams often have their own labels that are only meaningful for a certain
product or system. Those labels start with the name of the team's area. For
example, "analyzer-", "vm-", etc. Area-specific labels are owned by the
respective team and it's up to that team to manage how the labels are used, what
they mean, and when they can be removed.
### Other labels
There are a few other miscellaneous labels you might run into:
* **[blocked][]**: This marks an issue where the team is unable to make
progress on it because of some external constraint or other team. There
should be a comment explaining what it's blocked on. When possible, it will
link directly to another issue that is blocking this one.
* **[cla: yes][]**, **[cla: no][]**: Before we can accept a change from a
non-Google contributor, they must sign our [contributor license
agreement][cla]. We have a bot that requests that they do that and tracks
whether they have using these labels.
* **[contributions-welcome][]**: This marks an issue which has been vetted as
"legitimate," and which the owning subteam would welcome a contribution
from an external developer. Resolving an issue marked with this label
should not be overly difficult, and should not require a great amount of
code. This label is typically applied to bugs and documentation requests,
rather than feature requests, due to the lower cost of review and
maintenance.
* **[merge-to-dev][]**, **[merge-to-stable][]**: These are used to track
requests to cherry-pick a change from master to one of the [release
branches][branches].
* **[needs-info][]**: Like the name says, this means we need more
information. This is often because the initial issue description is unclear.
Other times, it means we have done some work fixing the issue and want
someone else to validate the solution.
When someone applies this label, they should also write a comment explaining
what information or clarification they are looking for. Issues like this
have a tendency to go stale because we can't make progress on it and the
original submitter may have moved on. This means that we are likely to close
an issue with this label if it hasn't had any activity in 60 days. If you
care about keeping the issue alive, please try to provide the information it
needs.
[area-cfe]: https://github.com/dart-lang/sdk/labels/area-cfe
[area-meta]: https://github.com/dart-lang/sdk/labels/area-meta
[blocked]: https://github.com/dart-lang/sdk/labels/blocked
[branches]: Branches-and-releases.md
[cla: no]: https://github.com/dart-lang/sdk/labels/cla%3A%20no
[cla: yes]: https://github.com/dart-lang/sdk/labels/cla%3A%20yes
[cla]: https://cla.developers.google.com/about/google-individual
[closed-as-intended]: https://github.com/dart-lang/sdk/labels/closed-as-intended
[closed-cannot-reproduce]: https://github.com/dart-lang/sdk/labels/closed-cannot-reproduce
[closed-duplicate]: https://github.com/dart-lang/sdk/labels/closed-duplicate
[closed-invalid]: https://github.com/dart-lang/sdk/labels/closed-invalid
[closed-not-planned]: https://github.com/dart-lang/sdk/labels/closed-not-planned
[closed-obsolete]: https://github.com/dart-lang/sdk/labels/closed-obsolete
[contributions-welcome]: https://github.com/dart-lang/sdk/labels/contributions-welcome
[customer-vm]: https://github.com/dart-lang/sdk/labels/customer-vm
[dartlang.org]: https://www.dartlang.org
[merge-to-dev]: https://github.com/dart-lang/sdk/labels/merge-to-dev
[merge-to-stable]: https://github.com/dart-lang/sdk/labels/merge-to-stable
[needs-info]: https://github.com/dart-lang/sdk/labels/needs-info
[P0]: https://github.com/dart-lang/sdk/labels/P0
[P1]: https://github.com/dart-lang/sdk/labels/P1
[P2]: https://github.com/dart-lang/sdk/labels/P2
[P3]: https://github.com/dart-lang/sdk/labels/P3
[type-bug]: https://github.com/dart-lang/sdk/labels/type-bug
[type-code-health]: https://github.com/dart-lang/sdk/labels/type-code-health
[type-documentation]: https://github.com/dart-lang/sdk/labels/type-documentation
[type-enhancement]: https://github.com/dart-lang/sdk/labels/type-enhancement
[type-performance]: https://github.com/dart-lang/sdk/labels/type-performance
[type-security]: https://github.com/dart-lang/sdk/labels/type-security
[type-task]: https://github.com/dart-lang/sdk/labels/type-task
## Queries
* [Issues with no area](https://github.com/dart-lang/sdk/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+-label%3Aarea-analyzer-cfe+-label%3Aarea-analyzer+-label%3Aarea-build+-label%3Aarea-dart2js+-label%3Aarea-dev-compiler+-label%3Aarea-documentation+-label%3Aarea-front-end+-label%3Aarea-html+-label%3Aarea-infrastructure+-label%3Aarea-intellij+-label%3Aarea-js-interop+-label%3Aarea-kernel+-label%3Aarea-language+-label%3Aarea-library+-label%3Aarea-meta+-label%3Aarea-observatory+-label%3Aarea-pkg+-label%3Aarea-samples+-label%3Aarea-sdk+-label%3Aarea-spec-parser+-label%3Aarea-specification+-label%3Aarea-test+-label%3Aarea-vm)
* [Issues with no priority](https://github.com/dart-lang/sdk/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+-label%3Ap0-critical+-label%3Ap1-high+-label%3Ap2-medium+-label%3Ap3-low+)
* [Issues with no type](https://github.com/dart-lang/sdk/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+-label%3Atype-bug+-label%3Atype-code-health+-label%3Atype-documentation+-label%3Atype-enhancement+-label%3Atype-performance+-label%3Atype-security+-label%3Atype-task)
* [Meta-issues with no assignee](https://github.com/dart-lang/sdk/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Aarea-meta+no%3Aassignee)

View File

@ -0,0 +1,114 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
These instructions supplement https://dart.dev/get-dart with additional details for how to install beta and dev releases with brew (on MacOS), choco (on Windows), and apt-get (on Linux). Note that on all platforms you can also download SDK archives from all channels at https://dart.dev/tools/sdk/archive.
# Installing and upgrading on macOS with Homebrew
## Installing
To install a **stable channel** release, use the `dart` formula:
```terminal
$ brew tap dart-lang/dart
$ brew install dart
```
To install a **beta channel** release, use the `dart-beta` formula:
```terminal
$ brew install dart-beta
```
To install a **dev channel** release, use the `dart` formula and `--head`:
```terminal
$ brew install --head dart
```
## Upgrading
To upgrade when a new release of Dart is available run:
```terminal
# On the stable channel
$ brew upgrade dart # replace dart with dart-beta if you are on the beta channel.
# On the dev channel
$ brew reinstall dart
```
## Switching channels
When switching channels (e.g. from stable to beta), first unlink the current release:
```terminal
# stable or dev to beta
$ brew unlink dart # replace dart with dart-beta if you are on the beta channel.
# dev to stable
$ brew install -f dart
```
Then install using the command listed under Installing above.
# Installing and upgrading on Windows with Chocolatey
To use [Chocolatey][] to install a **stable** release of the Dart SDK, run this
command:
```terminal
C:\> choco install dart-sdk
```
To install a **beta** release, run this command (you'll need the exact version
number):
```terminal
C:\> choco install dart-sdk --pre --version 2.8.0.20-c-011-beta
```
To install a **dev** release, run this command:
```terminal
C:\> choco install dart-sdk --pre
```
To **upgrade** the Dart SDK, run this command
(add `--pre` to upgrade the dev release):
```terminal
C:\> choco upgrade dart-sdk
```
# Installing and upgrading on Linux with `apt-get`
To use `apt-get` to install Dart SDK packages, you first need to do this one time setup:
```
$ apt-get -q update && apt-get install --no-install-recommends -y -q gnupg2 curl git ca-certificates apt-transport-https openssh-client && \
curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list && \
curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_testing.list > /etc/apt/sources.list.d/dart_testing.list && \
curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_unstable.list > /etc/apt/sources.list.d/dart_unstable.list && \
apt-get update
```
Then, there are multiple ways to install the different channels from `apt-get`:
```
$ apt-get -t unstable install dart # installs the latest dev dart
$ apt-get -t testing install dart # installs the latest beta dart
$ apt-get -t stable install dart # installs the latest stable dart
$ apt-get install dart # installs the latest version of dart
```
You can also install a specific version of Dart like this:
```
$ apt-get install dart=2.9.0-4.0.dev-1
```
[Chocolatey]: https://chocolatey.org

View File

@ -0,0 +1,12 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
Dart Kernel is an intermediate language for Dart programs, a compact binary object-file format supporting separate compilation and linking, and an infrastructure for program transformation. This page is an index of Kernel documentation.
[Binary format](https://github.com/dart-lang/sdk/blob/main/pkg/kernel/binary.md)
[Operational semantics](Kernel-Operational-Semantics.md)
[Type System](Kernel-Type-System.md)

View File

@ -0,0 +1,70 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
The small-step operational semantics of Dart Kernel is given by an abstract machine in the style of the CEK machine. The machine is defined by a single step transition function where each step of the machine starts in a configuration and deterministically gives a next configuration. There are several different configurations defined below.
_x_ ranges over variables, &rho; ranges over environments, _K_ ranges over expression continuations, _A_ ranges over application continuations, _E_ ranges over expressions, _S_ ranges over statements, _V_ ranges over values.
Environments are finite functions from variables to values. _&rho;_[_x_ &rarr; _V_] denotes the environment that maps _x_ to _V_ and _y_ to _&rho;_(_y_) for all _y_ &ne; _x_.
#### Expression configuration
An expression configuration indicates the evaluation of an expression with respect to an environment and an expression continuation.
Expression configuration | Next configuration
-- | --
<_x_, _&rho;_, _K_><sub>_expr_</sub> | <_K_, _&rho;_(_x_), _&rho;_><sub>_cont_</sub>
<_x = E_, _&rho;_, _K_><sub>_expr_</sub> | <_E_, _&rho;_, **VarSetK**(_x_, _K_)><sub>_expr_</sub>
<_!E_, _&rho;_, _K_><sub>_expr_</sub> | <_E_, _&rho;_, **NotK**(_K_)><sub>_expr_</sub>
<_E<sub>1</sub> **and** E<sub>2</sub>_, _&rho;_, _K_><sub>_expr_</sub> | <_E<sub>1</sub>_, _&rho;_, **AndK**(_E<sub>2</sub>_, _K_)><sub>_expr_</sub>
<_E<sub>1</sub> **or** E<sub>2</sub>_, _&rho;_, _K_><sub>_expr_</sub> | <_E<sub>1</sub>_, _&rho;_, **OrK**(_E<sub>2</sub>_, _K_)><sub>_expr_</sub>
<_E<sub>1</sub>? E<sub>2</sub> : E<sub>3</sub>_, _&rho;_, _K_><sub>_expr_</sub> | <_E<sub>1</sub>_, _&rho;_, **ConditionalK**(_E<sub>2</sub>_, _E<sub>3</sub>_, _K_)><sub>_expr_</sub>
<_StringConcat(exprList)_, _&rho;_, _K_><sub>_expr_</sub> | <_exprList_, _&rho;_, **StringConcatenationA**(_K_)><sub>_exprList_</sub>
<_print(E)_, _&rho;_, _K_><sub>_expr_</sub> | <_E_, _&rho;_, **PrintK**</sub>(_K_)><sub>_expr_</sub>
<_f(exprList)_, _&rho;_, _K_><sub>_expr_</sub> | <_exprList_, _&rho;_, **StaticInvocationA**(_S : f.body_, _K_)><sub>_exprList_</sub>
<_BasicLiteral_, _&rho;_, _K_><sub>_expr_</sub> | <_K_, _BasicLiteral_, _&rho;_><sub>_cont_</sub>
<_**Let** x = E<sub>1</sub> **in** E<sub>2</sub>_, _&rho;_, _K_><sub>_expr_</sub> | <_E<sub>1</sub>_, _&rho;_, **LetK**(_x_, E<sub>2</sub>, _&rho;_, _K_)><sub>_expr_</sub>
#### Expression continuation configuration
An expression continuation configuration indicates the application of an expression continuation __K__ to a value and an environment. The environment is threaded to the continuation because expressions can mutate the environment.
Expression continuation configuration | Next configuration
-- | --
<**VarSetK**(_x_, _K_), _V_, _&rho;_><sub>_cont_</sub> | <_K_, _V_, _&rho;_[_x_ &rarr; _V_]><sub>cont</sub>
<**PrintK**(_K_), _V_, _&rho;_><sub>_cont_</sub> | <_K_, _&empty;_, _&rho;_><sub>cont</sub>
<**ExpressionListK**(_exprList_, _A_), _V_, _&rho;_><sub>_cont_</sub> | <_exprList_, _&rho;_, **ValueApplicationA**(_V_, _A_)><sub>_exprList_</sub>
<**ExpressionK**(_C_), _V_, _&rho;_ ><sub>_cont_</sub> | _C_
#### Expression list configuration
An expression list configuration indicates the evaluation of a list of expressions with respect to an environment and an application continuation.
Expression list configuration | Next configuration
--|--
<_&empty;_, _&rho;_, _A_><sub>_exprList_</sub> | <_A_, _&empty;_><sub>_acont_</sub>
<_E :: tail_, _&rho;_, _A_><sub>_exprList_</sub> | <_E_, _&rho;_, **ExpressionListK**(_tail_, _A_)><sub>_expr_</sub>
#### Application continuation configuration
An application continuation configuration indicates the application of __A__ to a list of values.
Application continuation configuration | Next configuration
--|--
<**StaticInvocationA**(_S_, _K_), _valList_><sub>_acont_</sub> | <_S_, _&rho;_[_formalList_ &rarr; _valList_], _&empty;_, **ExitC**(_K_), _K_><sub>_exec_</sub>
<**ValueApplicationA**(V, _A_), _valList_><sub>_acont_</sub> | <_A_, _V :: valList_><sub>_acont_</sub>
#### Statement configuration
A statement configuration indicates the execution of a statement with respect to an environment.
_S_ ranges over statements, _L_ ranges over labels, _C_ ranges over statement configurations.
Statement configuration | Next configuration
--|--
<**Expression**(_E_), _&rho;_, _L_, _C_, _K_><sub>_exec_</sub> | <_E_, _&rho;_, **ExpressionK**(_C_)><sub>_expr_</sub>

View File

@ -0,0 +1,8 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
Kernel is a typed language with a sound type-system.

View File

@ -0,0 +1,37 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Developer notes for working on kernel
## How to test changes on pkg/kernel:
Run dartanalyzer in strong mode:
```
(cd pkg/kernel && dartanalyzer --strong bin lib test)
```
Run unit tests of kernel, front_end, and dart2js that are directly affected:
```
./tools/test.py pkg/kernel -mrelease --checked
./tools/test.py pkg/front_end -mrelease --checked
./tools/test.py dart2js/kernel -mrelease --checked
```
Run end-to-end tests using dartk + VM:
```
./tools/test.py -m release -c dartk language
```
Optionally (this is slow) run end-to-end tests using AOT:
```
./tools/build.py dart_precompiled_runtime
./tools/test.py -cdartkp -rdart_precompiled language co19
```
Comparing the output of compiling dart2js before and after the change. This [script][1] can make it easier to compare the results.
[1]: https://gist.github.com/asgerf/adde37ed58fe984d53b82d362187c777

View File

@ -0,0 +1,24 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
While creating Gerrit reviews is the preferred approach to contribute to the
Dart SDK, contributors sometimes create PRs, anyway.
**For administrators: GitHub PRs MUST NOT be merged on GitHub for the SDK repo. Merging a
GitHub PR directly breaks mirroring and the repository will be closed until mirroring
is restored.**
Instead, GitHub PRs are automatically synced to Gerrit if their owner has signed
the CLA. They can be submitted like any other patch in Gerrit.
* If the creator of the PR has a Gerrit user account, they will be added as a
reviewer.
* The owner of the review is the "Copybara Service" user (subject to change).
* Find all open or merged synced PRs in Gerrit
[here](https://dart-review.googlesource.com/q/hashtag:%22github-pr%22+\(status:open%20OR%20status:merged\)).
* When the Gerrit CL is submitted the PR will be closed automatically.
* In the future, a link to the Gerrit review will be added to the PR.

View File

@ -0,0 +1,96 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Null safety migration
This page contains stats for the migration of packages on [pub.dev](https://pub.dev)
to Dart's [sound null safety](https://dart.dev/null-safety) feature.
The data below is based on the following criteria:
* Package supports null safety: The Dart SDK lower constraint is `>= 2.12.0-0`
* Package is unblocked for starting migrating to null safety: All direct dep of the package support null safety
* Blocking score: The number of packages (incl. transitive deps) only blocked from null-safety migration by this package. If a package is blocked by N dependencies, then it only contributes with a blocking score of 1/N.
_Note_: Pub.dev also has a list of
[packages with null safety](https://pub.dev/packages?unlisted=1&prerelease-null-safe=1).
This may show a slightly lower count than the "raw" counts below, as some
categories of packages (e.g. those
[marked discontinued](https://dart.dev/tools/pub/publishing#discontinue))
are not shown in the pub.dev search UI.
# Summary:
## Package counts (each package counts only once)
```
packages with null safety: 8208
packages without null safety total: 13066
packages without null safety blocked: 2054
packages without null safety unblocked: 11012
packages in total (w. Dart 2.12 support): 21274
```
# Top blocking packages
Top 50 by blocking score (unblocked for migr.):
```
shared_aws_api 216.5 Yes
angel_framework 30.6 No
angular 29.4 No
galileo_framework 21.2 No
awareframework_core 21.0 Yes
mustache 18.0 Yes
resource 16.7 Yes
mango_ui 15.0 Yes
dart2_constant 14.5 Yes
ocg_app 14.4 Yes
jaguar_serializer 13.3 Yes
flushbar 11.2 Yes
angel_container 10.9 Yes
flutter_facebook_login 10.6 Yes
transformer_page_view 10.5 Yes
toast 10.5 Yes
nui_core 10.3 No
validate 10.1 Yes
intl_translation 10.1 Yes
mustache4dart 9.4 Yes
console_log_handler 9.3 Yes
masamune_flutter 9.0 No
streams_channel 9.0 Yes
latlong 8.9 No
pip_services3_commons 8.2 Yes
database 8.0 Yes
screen 8.0 Yes
pip_services3_components 7.7 No
plugin_scaffold 7.0 Yes
class_extensions_annotations 6.3 Yes
flutter_swiper 6.2 No
time_machine 6.0 Yes
merge_map 5.8 Yes
react 5.8 Yes
progress_dialog 5.6 Yes
code_buffer 5.6 Yes
modal_progress_hud 5.6 Yes
jaguar_query 5.3 Yes
flutter_masked_text 5.3 Yes
utf 5.2 Yes
kiilib_core 5.0 Yes
pub_client 5.0 Yes
flutter_icons 5.0 Yes
flutter_widgets 4.9 Yes
flutter_page_indicator 4.8 Yes
tinycolor 4.7 Yes
pip_services3_rpc 4.7 No
tripledes 4.7 Yes
galileo_orm 4.7 Yes
body_parser 4.5 No
```

View File

@ -1,3 +1,2 @@
file:/tools/OWNERS_ECOSYSTEM
file:/tools/OWNERS_FOUNDATION
file:/tools/OWNERS_PRODUCT
# Allow all committers to review documentation CLs.
file:/tools/OWNERS_ENG

View File

@ -0,0 +1,22 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
## Publishing an alpha version
`package:analyzer` depends on kernel and front_end. We push those last two packages for the benefit of `package:analyzer`, but their APIs don't currently follow semver, so we set analyzer to depend on exact versions.
Publishing a new alpha version of package analyzer involves a few steps:
- rev package:analyzer to a new alpha version (`0.31.0-alpha.0` ==> `0.31.0-alpha.1`)
- rev package:front_end to a new alpha version; update its version of package:kernel (see the next line)
- rev package:kernel to a new alpha version; update its version of package:front_end
- update the kernel and front_end version in `package:analyzer`'s pubspec
- commit a CL with the above changes
- publish `package:analyzer`, `package:kernel`, and `package:front_end`
## Publishing a new stable version
Many packages depend on `package:analyzer`. These packages often have version constraints that have an upper bound on the last major version of the analyzer. Publishing a new major version of `package:analyzer` requires careful orchestration with other major packages in the Dart ecosystem (in particular, `package:test`, and to a lesser extent, `package:angular`).

33
docs/README.md Normal file
View File

@ -0,0 +1,33 @@
Welcome to the developer documentation for the Dart SDK!
[Contributions](../CONTRIBUTING.md) welcome! Please help us keep these docs
up-to-date.
## Important pages
Important pages include:
- [Filing Dart issues](Filing-Dart-issues.md)
- [How the issue tracker works](How-the-issue-tracker-works.md)
- [Building the SDK](Building.md)
- [Testing](Testing.md)
Also, check out the combined
[Dart and Flutter roadmap](https://github.com/flutter/flutter/wiki/Roadmap)
on the Flutter wiki.
## Process pages
Various process pages include:
- [Dart SDK breaking change process](process/breaking-changes.md)
- [Dart SDK process for changes behind experimental flags](process/experimental-flags.md)
- [Language Versioning and Experiments](process/language-versions-and-experiments.md)
## Contributing
Contributions welcome via Gerrit CLs or GitHub PRs. See our
[contributing](../CONTRIBUTING.md) doc for more information.
Contributions could include helping to keep pages up-to-date, adding additional
context to this main page, or re-organizing the documentation.

305
docs/Status-files.md Normal file
View File

@ -0,0 +1,305 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
Stability is important for a programming language used to implement applications
that [manage billions of dollars](http://news.dartlang.org/2016/03/the-new-adwords-ui-uses-dart-we-asked.html). To that end, the Dart repository contains a
comprehensive test suite to cover the various configurations, compilers, tools,
and runtimes we maintain and support.
We have tens of thousands of tests and a single test may be run across a
combinatorial explosion of configurations. Does the static analyzer report any
errors on it? In strong mode? Does it run on the standalone VM? Can dart2js
compile it? Does the resulting code run in Chrome? Firefox? IE? In checked mode?
With minification on? You get the idea.
Many tests are only meaningful for certain combinations of configurations. A
test that uses "dart:io" is, by design, not going to run in a browser which
doesn't have access to the local file system. Some bleeding edge web features
aren't fully supported across all browsers. As we ramp up new tools, parts of
our own stack may not be passing all tests.
So, for all of these tests, we need to track not just the test itself, but it's
*status* -- what the expected outcome of the test is on various configurations.
This status information lives (mostly) outside of the tests in separate "status
files" with a ".status" extension.
This document explains the format of those files and how the test runner
interprets them.
## Outcomes and expectations
The test runner's main job, as you'd imagine, is to run tests. This sometimes
involves invoking a compiler, and then spawning another process to execute the
test itself. That process then may or may not complete successfully.
The test runner monitors this and tracks the various ways it can go wrong.
Each of these outcomes has a canonical name. Things like:
- **Pass** The runtime exited with exit code zero.
- **CompileTimeError** The compiler exited with a non-zero exit code.
- **RuntimeError** The runtime exited with a non-zero exit code.
There are other, more exotic outcomes. For the full list of them, see the code:
[pkg/status_file/lib/expectation.dart](https://github.com/dart-lang/sdk/blob/master/pkg/status_file/lib/expectation.dart)
In a perfect world, every test would pass in every configuration and the test
runner could simplify verify that every test's outcome was "Pass". Alas, life is
complicated. The status files keep track of what the *expected* outcome of each
test is, which is why these outcomes are usually referred to as "expectations".
A test that ends with a runtime error is a successful test if the status file
says we *expect* to get a runtime error. The test fails if no runtime error
occurred.
## Status files
Status files define the expectations for the tests by combining three facets:
* What are the expected outcomes...
* ...for which tests...
* ...under which configurations.
It's a bit like [Clue][]'s "Miss Scarlett, in the library, with the revolver."
The status file says something like "'math/low_test', when compiled using
dart2js, should produce a CompileError".
[clue]: https://en.wikipedia.org/wiki/Cluedo
With miles of tests and piles of configurtions, we need a compact notation for
defining expectations. That's what status files aim to be.
A status file is a line-oriented (newlines are significant) plain text file.
Comments start with `#` and continue to the end of the line. Blank lines are
ignored.
### Sections
Each status file consists of a list of **sections**. Each section starts with a
**header**, followed by one or more **entries**. (Entries at the top of the file
above any header go into an implicit header-less section.)
Sections have no relation to each other and the order does not matter.
### Headers
The header defines which configurations its entries apply to. It lets you
specify the conditions under which a set of expectations come into play. The
header contains an expression made up of accesses to various configuration
variables. It's evaluated against the current configuration's values for those
variables. If the expression evaluates to true, the section is applied and its
entries are used. Otherwise, its entries are ignored.
If there are entries in the implicit first headerless section, the condition is
always considered to be true and the entries are always applied.
Arbitarily large expressions are supported, but the larger they are, the harder
it is for your fellow teammates to understand what outcomes are expected for a
given configuration.
Here's a complex example:
```text
[ $compiler == dart2js && ( $browser || $runtime == d8 ) ]
```
The expression is contained in square brackets. Since we all love EBNF, the
grammar for the expression inside is:
```text
expression := or
or := and ( "||" and )*
and := primary ( "&&" primary )*
primary := "$" identifier ( "==" | "!=" ) identifier |
"!"? "$" identifier |
"(" expression ")"
identifier := regex "\w+"
```
There are a few different expression forms:
* **Variable** This looks up the value of some configuration option like
`$runtime` for which execution environment the test will be run in or
`$strong` for whether the test is run in strong mode. Variables are always
prefixed by `$`.
If the variable is a Boolean, you use it as a bare identifier like `$strong`
or `$checked`. It may be prefixed with `!` to negate its value, so `!
$checked` evaluates to true if the test is run in unchecked mode.
Non-Boolean variables accept one of an enumerated set of values. The set of
values depends on the variable. For example, `$mode` can be `debug`,
`release`, or `product`. To use one of these, it must be followed by `==` or
`!=` and the value being tested. Examples:
```text
$runtime == vm
$mode != debug
```
Note that unlike variables, values are not prefixed with `$`. Note also
that the equality operator and value is part of the variable expression
itself. You can't do something like: `$mode == $runtime`. You always have
to test against a literal value.
The set of variables that are available in status file expressions is baked
into test.dart. You can see the full list of them here:
[tools/testing/dart/environment.dart](https://github.com/dart-lang/sdk/blob/master/tools/testing/dart/environment.dart#L13)
For each variable, test.dart also knows all of the values that are allowed
for it. It uses this to validate these expressions at parse time. If you
misspell a variable, like `$compile` or test it against a value it can't
have like `$runtime == dart2js` (dart2js is a compiler, not a runtime), it
reports an error.
* **Logical operators** - You can join two subexpressions using `||` or `&&`,
with their usual meaning. `&&` has higher precedence than `||`.
* **Parentheses** If you want a `||` expression to be an operand to a `&&`
expression, you can explicitly parenthesize.
Here are some examples:
```text
[ ! $checked ]
```
This section applies only when not running the test in checked mode.
```text
[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te ]
```
This section applies only on various ARM simulator architectures.
```text
[ $checked && ($compiler == dartk || $compiler == dartkp) ]
```
This section applies if the test is running in checked mode and using either of
two Kernel compilers.
```text
[ $compiler != dart2js ]
```
This section applies for any compiler except dart2js.
### Entries
After the header, a section contains a list of entries. Each entry defines a
glob-like path that matches a set of test files. Then it specifies the set of
allowed outcomes for those tests.
For example:
```
typed_data/int64_list_load_store_test: RuntimeError # Issue 10275
```
The syntax is a path, followed by `:`, followed by a comma-separated list of
expectation names. It's a good idea to have a comment explaining why the test(s)
have this expectation. If the expectation is because the test should be passing
but isn't, the comment usually mentions the relevant issue number.
Here, it says the "int64_list_load_store_test" is failing at runtime because of
some bug we should fix.
The path string is relative to the directory containing the status file. Note
that paths do not have ".dart" extensions, even when they only match a single
file (which is the normal case). You can also use `*` like a glob to match part
of a path component as in:
```text
async/*deferred*: Pass,RuntimeError # Issue 17458
```
This matches any test inside the "async" directory whose name contains
"deferred". If you want an entry that matches every single test in the directory
containing the status file, use:
```text
*: Skip # Issue 28649
```
## Applying status files
The trickiest part of status files is that the same test may be matched by
multiple entries in different sections, potentially spread across different
status files. These entries may apply and overlap in some configurations but not
in others. For example, the status file for the corelib tests has five sections
with entries that all match "async/multiple_timer_test" (I removed other
unrelated entries here):
```text
[ $compiler == dart2js && $runtime == jsshell ]
async/multiple_timer_test: RuntimeError,OK # Needs Timer to run.
[ $runtime == vm && $system == fuchsia ]
async/multiple_timer_test: RuntimeError
[ $compiler == none && ($runtime == drt || $runtime == dartium) ]
async/multiple_timer_test: Fail, Pass # Issue 15487
[ $compiler == none && $runtime == drt && $system == windows ]
async/multiple_timer_test: Fail, Pass # See Issue 10982
[ $hot_reload || $hot_reload_rollback ]
async/multiple_timer_test: Pass, Fail # Timing related
```
Many of these sections are disjoint so that if one applies, another won't, but
not all of them are. For example, if you're running on Fuchsia on the VM with
hot reload enabled, the second and last sections both apply. They have different
expectations. So what does test.dart expect this test to do?
When there are multiple sets of expectations for the same file, test.dart unions
all of the sets together. So, in this case, the resulting expectation is
"RuntimeError, Pass, Fail".
A test succeeds if the outcome is *any* of the expectations. Here, that
basically means the test is going to succeed no matter what as long as it
doesn't crash or timeout or something.
If no entries match a given file, the default expectation is "Pass". That means
you only need to mention a file in a status file if it doesn't pass in at least
one configuration.
## Special expectations
Some "expectations" don't line up with actual possible test outcomes. Instead,
they affect how the test runner works or have another purpose. A couple of
important ones are:
* **Skip** and **SkipByDesign** These tell test.dart to not run the test at
all. The latter is OK, it means "this behavior isn't relevant for this
configuration". For example, Dartium doesn't support "dart:io", so the
status file says:
```text
[ $compiler == none && ($runtime == drt || $runtime == dartium) ]
io/*: SkipByDesign # Don't run tests using dart:io in the browser
```
The "Skip" expectation is older and should be avoided, since it doesn't
convey *why* the test is being skipped.
* **OK** isn't a real expectation. It's more like a comment for a reader of
the status file to know the behavior is intentional and desired. For
example:
```text
[ $compiler == dart2js && $runtime == jsshell ]
async/timer_cancel_test: RuntimeError,OK # Needs Timer to run.
```
jsshell doesn't support Times, so we never expect this test to pass.
There are some other special expectations, documented in the source here:
[/pkg/status_file/lib/expectation.dart](https://github.com/dart-lang/sdk/blob/master/pkg/status_file/lib/expectation.dart)

View File

@ -0,0 +1,17 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
| Operating System | JIT | AOT |
| ------------- | ------------- | ----- |
| Android | ia32, x64, armv7, armv8, rv64gc | x64, armv7, armv8, rv64gc |
| Fuchsia | x64, armv8, rv64gc | x64, armv8, rv64gc |
| iOS | armv7, armv8 | armv7, armv8 |
| Linux | ia32, x64, armv7, armv8, rv32gc, rv64gc | x64, armv7, armv8, rv32gc, rv64gc |
| macOS | x64, armv8 | x64, armv8 |
| Windows | ia32, x64, armv8 | x64, armv8 |
Past versions of the Dart VM also supported mipsel, armv6 and armv5te.

38
docs/Test-Requirements.md Normal file
View File

@ -0,0 +1,38 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
We have several tools, compilers, and runtimes that implement Dart in some way. We must test all of them thoroughly. We'd also like to reuse tests across as many of those tools as we can. The primary challenge is that these tools sometimes vary in their behavior deliberately. For example:
```dart
main() {
Expect.notEquals(1.0, 1);
}
```
On the web, we represent all numbers using JavaScript numbers, which don't distinguish between integers and floating point numbers of the same value. So in dart2js and DDC, this test "fails". But that is the behavior we *intend* it to have, so this failure doesn't indicate a bug in the tool.
Other times, behavior varies across different configurations of a single tool. A test of the `assert()` statement will produce a different outcome in debug versus release mode. To manage this, we need a mechanism to define which tests are considered meaningful for which configurations.
Currently, we mostly express this in the status files. There are status file entries that mark tests as being `SkipByDesign` on some configurations. That means "this test specifies the wrong behavior for this configuration, so don't use it". We'd like to move away from status files over time.
There is now a new system called "requirements" which is used for testing NNBD but could be extended for other needs. It works like this:
## Test Requirements
A test can have a comment line starting with `Requirements=` followed by a comma-separated list of identifiers. Each identifier is the name of a "feature" that a Dart tool may support. For example:
```dart
// Requirements=nnbd
main() {
late var i = 3;
Expect.equals(3, i);
}
```
The full set of features is defined [here][features]. For any given configuration, the test runner knows which features that configuration supports. When it is determining which tests to run, if a test requires a feature that the configuration does not support, the test is automatically skipped.
[features]: https://github.com/dart-lang/sdk/blob/master/pkg/test_runner/lib/src/feature.dart

101
docs/Testing-Dart2js.md Normal file
View File

@ -0,0 +1,101 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Testing the dart2js Compiler
Testing dart2js is complicated. There are a lot of configurations that are tested on the build bots. In this document we describe the build bots, and what they test. We also recommend a minimum set of tests that will increase your chances of submitting without a hitch.
## Test Configurations
* **VM Release/Debug:** the release version of the Dart VM is the version you will normally use as a Dart developer. The debug version of the Dart VM is much slower and only intended to be used by VM compiler engineers. It includes debug symbols and a lot of assertions which makes this VM slow.
* **VM Production/Developer mode:** this is the mode that Dart developers use to enable assertions and type checks while developing a Dart program. Since dart2js is a Dart program, the dart2js compiler engineers want to make sure that their assertions and type annotations are checked.
* **dart2js Production/Developer mode:** dart2js is an implementation of the Dart programming language. And just like the VM, dart2js should also support developer mode where assertions an type annotations are checked. So both production mode and developer mode of dart2js should be tested. Ideally, both in production mode and developer mode on the VM.
Ideally, we would want to test all the entries in this matrix:
| | dart2js Production | dart2js Developer |
| :------------ |:-------------------:|:-----------------:|
| VM Production | X | X |
| VM Developer | X | X |
## Build Bot Configurations
[dart2js-linux-release-N-4](http://build.chromium.org/p/client.dart/waterfall?builder=dart2js-linux-release-1-4&builder=dart2js-linux-release-2-4&builder=dart2js-linux-release-3-4&builder=dart2js-linux-release-4-4) (where 0 < N < 5), runs:
```
./tools/build.py -mrelease dart2js_bot
./tools/test.py -mrelease -cnone -rvm --use-sdk -v --shards=4 --shard=N dart2js
./tools/test.py -mrelease -cdart2js -rd8 --use-sdk --shards=4 --shard=N
./tools/test.py -mrelease -cdart2js -rd8 --use-sdk --shards=4 --shard=N dart2js_extra dart2js_native
./tools/test.py -mrelease -cnone -rvm --use-sdk --shards=4 --shard=N --enable-asserts dart2js
./tools/test.py -mrelease -cdart2js -rd8 --use-sdk --shards=4 --shard=N --enable-asserts
./tools/test.py -mrelease -cdart2js -rd8 --use-sdk --shards=4 --shard=N --enable-asserts dart2js_extra dart2js_native
```
Let's break down the name, dart2js-linux-release-N-4:
* **dart2js** means that we're _testing_ dart2js.
* **linux** means the tests are _running_ on Linux.
* **release** means that we use the release version of the Dart VM for _running_ unit tests or dart2js.
* **N-4** means that we have distributed the test across four build bots. N is a number that identifies one of these four build bots.
[dart2js-linux-release-checked-N-4](http://build.chromium.org/p/client.dart/waterfall?builder=dart2js-linux-release-checked-1-4&builder=dart2js-linux-release-checked-2-4&builder=dart2js-linux-release-checked-3-4&builder=dart2js-linux-release-checked-4-4) (where 0 < N < 5), runs:
```
./tools/build.py -mrelease dart2js_bot
./tools/test.py -mrelease -cnone -rvm --use-sdk --shards=4 --shard=N --host-checked dart2js
./tools/test.py -mrelease -cdart2js -rd8 --use-sdk --shards=4 --shard=N --host-checked
./tools/test.py -mrelease -cdart2js -rd8 --use-sdk --shards=4 --shard=N --host-checked dart2js_extra dart2js_native
```
[web-chrome-OS](http://build.chromium.org/p/client.dart/waterfall?builder=web-chrome-linux&builder=web-chrome-mac&builder=web-chrome-win7) (where OS is one of linux, mac, or win7).
[web-ff-OS](http://build.chromium.org/p/client.dart/waterfall?builder=web-ff-linux&builder=web-ff-win7) (where OS is one of linux, or win7).
[web-opera-linux](http://build.chromium.org/p/client.dart/waterfall?builder=web-opera-linux)
[web-safari-mac](http://build.chromium.org/p/client.dart/waterfall?builder=web-safari-mac)
## Basic test recommendation
The full test matrix is so huge that we recommend you use minimal local testing and rely on the build bot for full coverage (but keep an eye on the build bot and be ready to revert).
```
./tools/build.py -m release dart2js_bot
./tools/test.py -mrelease --use-sdk --time -pcolor --report --enable-asserts dart2js utils
./tools/test.py -mrelease -cdart2js -rd8 --time -pcolor --report --host-checked dart2js_extra dart2js_native
./tools/test.py -mrelease -cdart2js -rd8,drt --use-sdk --time -pcolor --report
```
(The version above uses --use-sdk which means it starts from the dart2js snapshot. This means that changes to .dart files in dart2js won't be tested unless you remember to run the build.py command first.)
The bare minimum follows (but you risk breaking the build):
Mac:
```
./tools/build.py -mrelease dart2js
./sdk/bin/dart2js_developer -v --categories=all --package-root=out/ReleaseIA32/packages/ tests/utils/dummy_compiler_test.dart
```
Linux:
```
./tools/build.py -mrelease dart2js
./sdk/bin/dart2js_developer -v --categories=all --package-root=out/ReleaseIA32/packages/ tests/utils/dummy_compiler_test.dart
```
Windows:
```
python ./tools/build.py -mrelease dart2js
sdk\bin\dart2js_developer.bat -v --categories=all --package-root=out/ReleaseIA32/packages/ tests/utils/dummy_compiler_test.dart

58
docs/Testing-the-VM.md Normal file
View File

@ -0,0 +1,58 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
## JIT
```
./tools/build.py -m all runtime
./tools/test.py -m all
./tools/test.py -m all --checked
```
## [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer)
```
./tools/gn.py -m release --asan
./tools/build.py -m release runtime
./tools/test.py -m release --builder-tag=asan -t240
```
## [ThreadSanitizer](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual)
```
./tools/gn.py -m release --tsan
./tools/build.py -m release runtime
./tools/test.py -m release
```
## Noopt
```
./tools/build.py -mdebug,release runtime_and_noopt
./tools/test.py -mdebug,release --noopt
```
## Precompilation
```
./tools/build.py -mrelease runtime_precompiled
./tools/test.py -mrelease -cprecompiler -rdart_precompiled
```
## Precompilation on Android devices
```
./tools/build.py -mrelease -aarm --os=android runtime_precompiled
export PATH=$PATH:$PWD/third_party/android_tools/sdk/platform-tools
./tools/test.py -mrelease -aarm --system=android -cprecompiler -rdart_precompiled --use-blobs
```
## App snapshots
```
./tools/build.py -mall runtime
./tools/test.py -mall -capp_jit
```

759
docs/Testing.md Normal file
View File

@ -0,0 +1,759 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
A programming language and its core libraries sits near the bottom of a
developer's technology stack. Because of that, they expect it to be reliable and
bug free. They expect new releases of the Dart SDK to not break any of their
existing programs, even in rare, strange edge cases. At the scale of Dart today,
even the darkest corner of the language or libraries still has users who care
about its behavior.
We engineer that reliability using automated tests. The tests for the language
and core libraries, which is what this doc is about, live in the SDK repo under
`tests/`. As of this writing, there are 25,329 Dart files in there, containing
over 1.5 million lines of code and over 95,000 individual assertions. Making
this even harder is that Dart includes a variety of tools and
implementations. We have multiple compilers, runtimes, and static analyzers.
Each supports several platforms and options. All told, we currently have 476
supported, tested configurations.
Since our testing needs are both complex and unique, we have several custom test
formats and our own test runner for executing those tests. This doc explains how
to work with tests and use the test runner.
## Concepts
There are several workflows that share the same concepts and terms, so let's get
those out of the way first.
* **"test.py"**, **"test.dart"**, **test_runner** - The tool that runs tests.
For many years, it had no real name, so was simply called "test.py" after
the main entrypoint script used to invoke it. (It was originally written in
Python before we had any functioning Dart implementations.) When we started
migrating away from status files, we created a new entrypoint script,
"test.dart". The pub package that contains all of the real code is named
"test_runner" and lives at `pkg/test_runner`.
* **Test suite** - A collection of test files that can be run. Most suites
correspond to a top level directory under `tests/`: `language_2`, `lib_2`,
and `co19_2` are each test suites. There are a couple of special suites
like `pkg` whose files live elsewhere and have special handling in the test
runner.
Directories with the `_2` suffix contain pre-null-safety tests, while the
corresponding suites without `_2` are the null-safe tests. (The `_2`
suffix is a vestige of the migration from Dart 1.0 to Dart 2.0.)
* **Test** - A test is a Dart file (which may reference other files) that the
test runner will send to a Dart implementation and then validate the
resulting behavior. Most test files are named with an `_test.dart` suffix.
* **Configuration** - A specific combination of tools and options that can be
used to invoke a test. For example, "run on the VM on Linux in debug mode"
is a configuration, "compile to JavaScript with DDC and then run in
Chrome", or "analyze using the analyzer package with its asserts enabled".
Each configuration is a combination of architecture, mode, operating system,
compiler, runtime and many other options. There are thousands of potential
combinations. We officially support hundreds of points in that space by
testing them on our bots.
* **Bots**, **BuildBots**, **builders** - The infrastructure for automatically
running the tests in the cloud across a number of configurations. Whenever a
change lands on master, the bots run all of the tests to determine what
behavior changed.
## Expectations, outcomes, status files, and the results database
This concept is so important it gets its own section. The intent of the test
corpus is to ensure that the behavior we ship is the behavior we intend to ship.
In a perfect world, at every commit, every configuration of every tool would
pass every test. Alas, there are many complications:
* Some tests deliberately test the error-reporting behavior of a tool. Compile
errors are also specified behavior, so we have tests to guarantee things
like "this program reports a compile error". In that case "pass" does *not*
mean "executes the program without error" because the intent of the test is
to report the error.
* Some tests validate behavior that is not supported by some configurations.
We have tests for "dart:io", but that library is not supported on the web.
That means all of the "dart:io" tests "fail" on DDC and dart2js, but we of
course intend and expect that to be true.
* Some tests are for features that aren't implemented yet. We're constantly
evolving and at any point in time, there is often some lag between the
state of various tests and implementations.
* Some tests are failing that shouldn't be, but they have been for some time
and we don't currently intend to fix what's causing the failure. We should
at some point, but we don't want this constant failure to drown out other,
newer, unexpected failures.
All this means that it's not as simple as "run test and if no errors then great,
otherwise blow up." At a high level, what we really want is:
* To encode the behavior we *intend* to ship.
* To know what behavior are *are* shipping.
* To know when that behavior *changes* and what commits cause it.
### Expectation
You can think of each test as having an intent. A human reading the test's code
(and any special comments in it) should be able to predict the behavior the test
produces. For most tests, the intent is to run to completion without error. For
example:
```dart
import 'package:expect/expect.dart';
main() {
Expect.equals(3, 1 + 2);
}
```
The `Expect.equals()` method throws an exception if the two arguments aren't
equal. So this test will complete silently if `1 + 2` is `3`. Otherwise, it will
throw an uncaught exception, which the test runner detects. So the intent is to
"pass" where "pass" means "run to completion".
Other tests exist to validate the error reporting behavior of the system:
```dart
main() {
int i = "not int"; //# 01: compile-time error
}
```
This test (a "multitest", see below), says that a conforming tool should produce
a compile time error when the second line of code is included.
Before running a test, the test runner parses the test file and infers an
**expectation** from it&mdash;what the human author says a tool should do when
it runs the test. By default, the expectation is "pass", but some tests are
expected to produce runtime errors or compile-time errors.
### Outcome
When the test runner runs a test on some tool, the tool does some thing. It can
report a compile error or report a runtime error. Maybe it hangs indefinitely
and the test runner has to shut it down and consider it a time out. If it does
none of those things and exits cleanly, it "passes".
We call this the **outcome**. It's the actual observed behavior of the tool.
### Status
In order to tell if a behavior *changes*, we need to record what the previous
behavior was the last time we ran the test under some configuration. We call
this the test's **status**.
In the past, status was recorded in a separate set of
[**status files**][Status-files.md]. These live in the repo under `tests/`.
In order to change the expected
behavior of a test, you had to manually change the status file and then commit
that change. In practice, we found this doesn't scale to the number of tools and
configurations we have today.
Instead, we now store the results of previous test runs in a **results
database**. This database is updated automatically by the bots when tests
complete. Every time a bot runs a test suite for some configuration it gathers
up the outcome of every test and records that in the database, associated with
the commit that it ran against. That database is queried by tools (including the
test runner itself) to determine the status of any test for any supported
configuration, at any point in the commit stream.
### Skips and slows
However, we have not yet completely eliminated status files. They are still
around because they are still the source of truth for some hand-authored data
about what a test *should* do. In particular, some tests don't make sense for a
certain configuration at all and should be **skipped**. For example, there's no
point in running the "dart:io" tests on dart2js.
Today, the place a human says "skip these 'dart:io' tests if the configuration
uses dart2js" is in the *status* files. Likewise, some tests are particularly
slow on some configurations and we want to give the test runner more time before
it declares them timing out. That data is also stored in the status files.
Eventually, we hope to move this data into the test itself.
### Comparison and confusion
The previous three sections lay things out in a nice clean way, but the reality
is much more muddled. This is largely because we end up overloading words and don't have clear ways to talk about the *combinations* of outcome, expectation, and status.
For example, if a test "passes", it could mean:
* The *outcome* is that it completes without error, even though the
*expectation* is that it should not.
* The *outcome* is that it completes without error and the *expectation* is
that it does that.
* The *expectation* is that it produces a compile error and the outcome is
that it correctly produces that error.
* The *outcome* matches the *status*, regardless of what they are.
If a test "fails", it could be:
* The *outcome* is that it reports an error.
* The *outcome* is that it does *not* and the *expectation* is that it
*should*.
* The *outcome* is that it reports an error, the *expectation* is that it
should *not*, but the *status* is that it *does*.
Ugh, I could go on. All this really means is that the combination of outcome,
expectation, and status makes things confusing and you have to be careful when
talking about tests and trying to understand the output of tools. Now that
you're nice and confused...
## How the test runner works
When you invoke the test runner, it walks all of the files in the specified
test suites. For each test file:
1. **Parse the test file to figure out its expectation.** As you'll see below,
there are a enough of special marker comments you can use in a test to tell
the test runner what the intent of the test is.
2. **Figure out what commands to execute with what arguments.** For a simple VM
test, that may be just "run the VM and give it the path to the test file".
For a web test, it's multiple commands: One to compile the test to
JavaScript, and then a separate command to run the result in a JavaScript
environment. There is custom code in the test runner for each pair of
compiler and runtime to do this.
3. **Run the commands and wait for them to complete.** There's a whole little
dependency graph build system in there that knows which commands depend on
which ones and tries to run stuff in parallel when it can.
4. **Analyze the result of the commands to determine the test's outcome.** For
each command the test runner invokes, it has code to parse the command's
output. This is usually some combination of looking at the exit code,
stdout, and stderr.
5. **Compare the expectation to the outcome.** This produces a new value that
the test runner vaguely calls "actual". It's sort of a higher-order outcome
relative to the expectation. We should figure out a better word for it. Some
examples:
```text
expectation + outcome -> actual
--------------------------------------------------
Pass + Pass Pass
CompileTimeError + CompileTimeError -> Pass
Pass + CompileTimeError -> CompileTimeError
CompileTimeError + Pass -> MissingCompileTimeError
```
In other words, if the outcome and the expectation align, that's a "pass" in
that the tool does what a human says its supposed to. If they disagree,
there is some kind of "failure"&mdash;either an error was supposed to
reported and wasn't, or an unexpected error occurred.
6. **Compare actual to the status and report any difference.** Now we know what
the tool did relative to what a human said it's supposed to do. Next is
figuring out how that result compares to the tool's *previous* behavior.
If the result and status are the same, the test runner reports the test as
passing. Otherwise, it reports a failure and shows you the both the result
and status. To make things profoundly confusing, it refers to the status as
"expectation".
### A confusing example
The fact that we have three levels of "result" which then get mixed together is
what makes this so confusing, but each level does serve a useful function. The
tools could definitely be clearer about how it's presented.
Here's a maximally tricky example. Let's say we decide to change Dart and make
it a static error to add doubles and ints. You create this test:
```
void main() {
1 + 2.3; //# 00: compile-time error
}
```
You run it on analyzer before the analyzer team has had a chance to implement
the new behavior. This test is brand new, so it has no existing status and
defaults to "Pass". You'll get:
* Expectation: CompileTimeError. That's what the multitest marker comment
means.
* Outcome: Pass. In Dart today, this code has no errors, so the analyzer
doesn't report any compile error.
* Actual: MissingCompileTimeError. There was supposed to be an error reported,
but the tool didn't report any, so the result was a failure to report an
expected error.
* Status: Pass. This is the default status since it's a new test.
Then the test runner prints out something like:
```
FAILED: dart2analyzer-none release_x64 language_2/int_double_plus_test/00
Expected: Pass
Actual: MissingCompileTimeError
```
If you change the status to `MissingCompileTimeError` then it will "pass" and
not print a failure. If, instead, the analyzer team implements the new error,
then the outcome will become CompileTimeError. Since that aligns with the
expectation, the actual becomes Pass. That in turn matches the status, so the
whole test will report as successful.
In short: **When the test runner reports a test as succeeding it means the
difference between the tool's actual behavior and intended behavior has not
changed since the last time a human looked at it.**
## Running tests locally
There are two ways to run tests (cue surprisingly accurate "the old deprecated
way and the way that doesn't work yet" joke).
### Using test.py
The old entrypoint is "test.py":
```sh
./tools/test.py -n analyzer-mac language_2/spread_collections
```
The `-n analyzer-mac` means "run the tests using the 'analyzer-mac' named
configurations". Configurations are defined in the "test matrix", which is a
giant JSON file at `tools/bots/test_matrix.json`. The
`language_2/spread_collections` argument is a "selector". The selector syntax is
a little strange but it's basically a test suite name followed by an optional
somewhat glob-like path for the subset of tests you want to run.
When running the test runner through the `test.py` entrypoint, it does not look
up the current test status from the results database. Instead it just uses the
old status files. This is dubious because those status files are no longer being
maintained, so you will likely get spurious failures simply because the status
is out of date even the tool is doing what it should.
Eventually, this way of running tests should be removed, along with the status
files.
### Using test.dart
The new entrypoint is "test.dart":
```sh
$ ./tools/sdks/dart-sdk/bin/dart tools/test.dart -n analyzer-asserts-mac
```
This ultimately uses the same test runner and works similar to "test.py",
except reads test status from the **results database**.
### Finding a configuration
Reading a several thousand line JSON file to find the name of the configuration
that matches the way you want to run a batch of tests is not fun. Usually, you
know what compiler and runtime you want to test, and you want something that
can run on your local machine. To help you find a configuration that matches
that, the test runner has a `--find-configurations` option.
Pass that, and the test runner prints out the list of configuration names that
match an optional set of filters you provide, which can be any combination of:
```
-m, --mode
Mode in which to run the tests.
-c, --compiler
How the Dart code should be compiled or statically processed.
-r, --runtime
Where the tests should be run.
--nnbd
Which set of non-nullable type features to use.
-a, --arch
The architecture to run tests for.
-s, --system
The operating system to run tests on.
```
If you don't provide them, then `mode` defaults to `release`, `system` to your
machine's OS, and `arch` to `x64`. If you don't want those default filters, you
can use `all` for any of those options to not filter by that.
Pass `--help` to the test runner to see the allowed values for all of these.
### Local configurations
You typically want to run the tests locally using the same configuration that
the status results are pulled from. It would be strange, for example, to use the
status of some dart2js configuration to define the expected outcome of a batch
of VM tests.
But the bots don't always test every configuration and sometimes there is a
"nearby" configuration to what you want to run that will work for what you're
testing locally. The common case is if you're running tests on a Mac but the bot
only tests a Linux config. Results don't often vary by platform, so you can just
use the Linux results for your local run. To do that, there is an extra flag:
```sh
$ ./tools/sdks/dart-sdk/bin/dart tools/test.dart -n analyzer-asserts-linux \
-N analyzer-asserts-mac
```
The `-n` (lowercase) flag says "use the results for this config". The `-N`
(uppercase) flag says "run this configuration locally". By default, when you
omit `-N`, it runs the same config locally that it gets results from.
## Running tests on the bots and commit queue
Once you have some code working to your satisfaction, the next step is getting
it landed. This is where the bots come into play. Your first interaction with
them will be the **trybots** on the **commit queue**. When you send a change out
for code review, a human must approve it before you can land it. But it must
also survive a gauntlet of robots.
The commit queue is a system that automatically runs your not-yet-landed change
on a subset of all of the bots. This subset is the trybots. They run a selected
set of configurations to balance good coverage against completing in a timely
manner. If all of those tests pass the change can land on master. Here "pass"
means that the test result is *the same as it was before your change.* A
*change* in status is what's considered "failure".
Of course, many times getting something working and changing the outcome of a
test from failing to passing is your exact goal! In that case, you can *approve*
the changes. This is how a human tells the bots that the change in status is
deliberate and desired.
This workflow is still in flux as part of the move away from status files.
**TODO: Rewrite or remove this once the approval workflow is gone or complete.**
Once you please all of the trybots, the change can land on master. After that
*all* of the bots pick up the change and run the tests on all of the supported
configurations against your change. Assuming we've picked a good set of trybots,
these should all pass. But sometimes you encounter a test that behaves as
expected on the subset of trybots but still changes the behavior on some other
configuration. So failures can happen here and the bots "turn red". When this
happens, you'll need to either approve the new outcomes, revert the change, or
land a fix.
## Working on tests
Your job may mostly entail working on a Dart implementation, but there's still
a good chance you'll end up touching the tests themselves. If you are designing
or implementing a new feature, you will likely edit or add new tests. Our tests
have an unfortunate amount of technical debt, including bugs, so you may end up
finding and needing to fix some of that too.
SDK tests are sort of like "integration tests". They are complete Dart programs
that validate some Dart tool's behavior by having the tool run the program and
then verifying the tool's externally visible behavior. (Most tools also have
their own set of white box unit tests, but those are out of scope for this doc.)
The simplest and most typical test is simply a Dart script that the tool should
run without error and then exit with exit code zero. For example:
```dart
import 'package:expect/expect.dart';
main() {
Expect.equals(3, 1 + 2);
}
```
We don't use the ["test"][test pkg] package for writing language and core
library tests. Since the behavior we're testing is so low level and fundamental,
we try to minimize the quantity and complexity of the code under test. The
"test" package is great but it uses tons of language and core library
functionality. If you're trying to fix a bug in that same functionality, it's no
fun if your test framework itself is broken by the same bug.
[test pkg]: https://pub.dev/packages/test
Instead, we have a much simpler package called ["expect"][expect pkg]. It's [a
single Dart file][expect lib] that exposes a rudimentary JUnit-like API for
making assertions about behavior. Fortunately, since the behavior we're testing
is also pretty low-level, that API is usually sufficient.
[expect pkg]: https://github.com/dart-lang/sdk/tree/master/pkg/expect
[expect lib]: https://github.com/dart-lang/sdk/blob/master/pkg/expect/lib/expect.dart
The way it works is that if an assertion fails, it throws an exception. That
exception unwinds the entire callstack and a Dart implementation then exits in
some failed way that the test runner can detect and determine that a runtime
error occurred.
If you are writing asynchronous tests, there is a separate tiny
["async_helper"][async pkg] package that talks to the test runner to ensure all
asynchronous operations performed by the test have a chance to complete.
[async pkg]: https://github.com/dart-lang/sdk/tree/master/pkg/async_helper
With these two packages, it's straightforward to write tests of expected correct
runtime behavior. You can also write tests for validating runtime *failures* by
using the helper functions for checking that certain exceptions are thrown:
```dart
import 'package:expect/expect.dart';
main() {
var list = [0, 1];
Expect.throwsRangeError(() {
list[2];
});
}
```
This test correctly passes if executing `list[2]` throws a RangeError.
We also need to pin down the *static* behavior of Dart programs. The set of
compile errors are specified by the language and tools are expected to report
them correctly. Plain tests aren't enough for that because a test containing a
static error can't be run at all. To handle that, the test runner has built-in
support for other kinds of tests. They are:
### Multitests
A simple multitest looks like this:
```dart
// language_2/abstract_syntax_test.dart
class A {
foo(); //# 00: compile-time error
static bar(); //# 01: compile-time error
}
```
Each line containing `//#` marks that line as being owned by a certain multitest
section. The identifier after that is the name of the section. It's usually just
a number like `00` and `01` here, but can be anything. Then, after the colon,
you have an expected outcome.
The test runner takes this file and splits it into several new test files, one
for each section, with an extra one for the "no sections". Each file contains
all of the unmarked lines as well as the lines marked for a certain section. So
the above test gets split into three files:
```dart
// language_2/abstract_syntax_test/none.dart
class A {
}
```
```dart
// language_2/abstract_syntax_test/00.dart
class A {
foo(); //# 00: compile-time error
}
```
```dart
// language_2/abstract_syntax_test/01.dart
class A {
static bar(); //# 01: compile-time error
}
```
This is literally done textually. Then the test runner runs each of those files
separately. The expectation for the file is whatever was set in its section's
marker. The "none" file is always expected to pass.
So, in this case, it expects `none.dart` to compile and run without error. It
expects `00.dart` and `01.dart` to report some kind of compile-time error
anywhere in the file.
A single file can contain multiple distinct sections which lets you test for
multiple different errors in a single file. It can distinguish between reporting
a compile-time error versus a runtime error. It's the best we had for a long
time, and works pretty well, so there are many many multitests.
But they aren't great. A single test file containing 20 multitest section gets
split into 21 files, each of which has to pass through the entire compilation
and execution pipeline independently. That's pretty slow. You get better
granularity, but still not perfect. As long as *some* error is reported
*somewhere* in the file that contains the section's lines, it considers that
good enough.
We see a lot of multitests that incorrectly pass because they are supposed to
detect some interesting static type error reported by the type checker. But they
actually pass because the author had a typo somewhere, which gets reported as a
syntax error at compile time.
To try to more precisely and easily write tests for static errors, there is a
yet another kind of test...
### Static error tests
This is the newest form of test. These tests are *only* for validating static
errors reported by one of the two front ends: CFE and analyzer. For all other
configurations, they are automatically skipped.
The previous multitest converted to a static error test looks like this:
```dart
class A {
// ^
// [cfe] The non-abstract class 'A' is missing implementations for these members:
foo();
//^^^^^^
// [analyzer] STATIC_WARNING.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER
static bar();
// ^
// [analyzer] SYNTACTIC_ERROR.MISSING_FUNCTION_BODY
// [cfe] Expected a function body or '=>'.
}
```
Each group of adjacent line comments here defines an **error expectation**. The
first comment line defines the error's location. The line is the preceding line,
the column is the column containing the first caret, and the length is the
number of carets. If the preceding line is itself part of some other error
expectation, it will be skipped over, so you can define multiple errors that
are reported on the same line:
```dart
int i = "not int" / 345;
// ^^^^^^^^^
// [analyzer] STATIC_WARNING.SOME_ERROR
// ^^^
// [analyzer] STATIC_WARNING.ANOTHER_ERROR
```
In cases where the location doesn't neatly fit into this syntax&mdash;it either
starts before column 2 or spans multiple lines&mdash;an explicit syntax can be
used instead:
```dart
var obj1 = [...(123)];
// [error line 1, column 17, length 3]
// [analyzer] CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH
// [cfe] Error: Unexpected type 'int' of a spread. Expected 'dynamic' or an Iterable.
```
After the location comment line are line defining how analyzer and CFE
should report the error. First, a line comment starting with `[analyzer]`
followed by an analyzer error code specifies that analyzer should report an
error at this location with this error code. If omitted, analyzer is not
expected to report this error.
Finally, a line comment starting with "[cfe] " followed by an error message
specifies that CFE should report an error with the given text at this location.
If omitted, the CFE is not expected to report an error here. If the CFE error
message is longer than a single line, you can have further line comments after
the initial `// [cfe]` one:
```dart
var obj1 = [...(123)];
// ^^^^^
// [cfe] Error: Unexpected type 'int' of a spread.
// Expected 'dynamic' or an Iterable.
// Another line of error message text.
```
When the test runner runs a test, it looks for and parses all error
expectations. If it finds any, the test is a static error test. It runs the test
once under the given configuration and validates that it produces all of the
expected errors at the expected locations. The test passes if all errors are
reported at the right location. With the analyzer front end, all expected error
codes must match. For the CFE, error messages must match.
Using a single invocation to report all errors requires our tools to do decent
error recovery and detect and report multiple errors. But our users expect that
behavior anyway, and this lets us validate that and get a significant
performance benefit.
#### Web static errors
Most static errors are reported by all Dart tools. The implementation of that
error reporting either comes from analyzer or the CFE and the above two static
error categories `[analyzer]` and `[cfe]` cover almost all static error tests.
However, the web compilers DDC and dart2js also have a few additional static
restrictions they place on Dart. Code that fails to meet those restrictions
produces compile-time errors. We have static error tests for those too, and
they use a separate `[web]` marker comment. Those tests are run on DDC and
dart2js to ensure the error is reported.
#### Divergent errors
Since we don't validate analyzer error messages or CFE error codes, there is
already some flexibility when the two front ends don't report identical errors.
But sometimes one front end may not report an error at all, or at a different
location.
To support that, the error code or message can be omitted. An error expectation
with no error code is ignored on analyzer. Conversely one with no message is
ignored on CFE. Note in the above example that CFE reports the error about
`foo()` on the class declaration while analyzer reports it at the declaration of
`foo()` itself. Those are two separate error expectations.
#### Unspecified errors
A good tool takes into account the processes around it. One challenge for us is
that tests for new errors are often authored before the implementations exist.
In the case of co19, those tests are authored by people outside of the team in a
separate Git repo. At that point in time, we don't know what the precise error
code or message will be.
To make this a little less painful, we allow an error to be "unspecified":
```dart
var obj1 = [...(123)];
// ^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
```
The special word `unspecifed` in place of an error code or message means the
error must be reported on the given line, but that any code or message is
acceptable. Also, the column and length information is ignored. That enables
this workflow:
1. Someone adds a test for an unimplemented feature using `unspecified` lines.
2. The analyzer or CFE team implements the feature and lands support. The tests
start passing.
3. In order to pin down the precise behavior now that it's known, someone goes
back and replaces `unspecified` with the actual error code or message. Now,
any minor change will cause the test to break so we notice if, for example,
a syntax error starts masking a type error.
4. The other front end team does the same.
5. Now the test is fully precise and passing.
The important points are that the tests start passing on step 2 and continue to
pass through the remaining steps. The syntax above is chosen to be easily
greppable so we can keep track of how many tests need to be made more precise.
#### Automatic error generation
Step three in the above workflow is a chore. Run a test on some front end. Copy
the error output. Paste it into the test file in the right place. Turn it into a
comment. This needs to happen both for new tests and any time the error
reporting for a front end changes, which is frequent. The analyzer and CFE folks
are always improving the usability of their tools by tweaking error messages and
locations.
To make this less painful, we have a tool that will automatically take the
current output of either front end and insert the corresponding error
expectation into a test file for you. It can also remove existing error
implementations.
The tool is:
```sh
$ dart pkg/test_runner/tool/update_static_error_tests.dart -u "**/abstract_syntax_test.dart"
```
It takes a couple of flags for what operation to perform (insert, remove,
update) and for what front end (analyzer, CFE, both) followed by a glob for
which files to modify. Then it goes through and updates all of the matching
tests.
This should give us very precise testing of static error behavior without
much manual effort and good execution performance.

View File

@ -0,0 +1,71 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
**Author**: eernst@
**Version**: 0.2
We have created a _Dart specification parser_, built on a grammar specification [Dart.g](https://github.com/dart-lang/sdk/blob/master/tools/spec_parser/Dart.g), which is transformed into a working parser by the tool [ANTLR](https://www.antlr.org/index.html), using a couple of helper files (in particular, [spec_parse.py](https://github.com/dart-lang/sdk/blob/master/tools/spec_parse.py) and [spec_parser](https://github.com/dart-lang/sdk/tree/master/tools/spec_parser)). This document gives a short introduction to what it is, and some motivations for why we have it, along with an outline of the consequences for the testing workflow when we have a specification parser.
## Motivation
One main **motivation** for having this specification parser is that we can use it to parse existing Dart source code. This allows us to verify that `Dart.g` **specifies the syntax** in a manner which is consistent and parseable, and which corresponds precisely to the language as it is **actually implemented** and used.
The other main **motivation** is that `Dart.g` is a mechanized and hence precise specification of the language syntax. This allows us to use `Dart.g` as a source of information about how to maintain the grammar rules in the [language specification](https://github.com/dart-lang/language/blob/master/specification/dartLangSpec.tex). The grammar rules in the language specification will never be a verbatim copy of the ones in `Dart.g`, because that is an ANTLR specification which necessarily contains a number of details that are specific to ANTLR, or otherwise accidental. However, `Dart.g` is still such a detailed source of trustworthy information that we expect it to be very **helpful in the maintenance of** the language **specification** grammar rules.
The grammar rules in the **language specification** should be **more abstract** than the ones in `Dart.g`. It is not even a problem if the grammar rules in the language specification are somewhat ambiguous, especially if this allows them to be significantly simpler and more readable. One justification for this is that grammar rules in a language specification may well be used for mentally constructing expressions, declarations, or other constructs, when the reader is thinking about how the language can be used to express a specific idea as software.
Grammar ambiguities must be resolved in order to enable (non-exotic) parsing, but derivation of snippets of code will work just fine, even when there are some ambiguities. Besides, those who seek **practical** solutions in relation to **Dart parsing** would be able to use `Dart.g` as a source of information about how it can be done.
## Testing: Now includes syntax errors
The Dart testing setup makes it possible to specify **multi-tests**, i.e., test libraries where certain lines are deleted or preserved according to the given labels. For instance, the following library will print "none" and "01" during subtest "01", "none" and "02" during subtest "02", and it will report a compile-time error (in Dart 2 and strong mode) in subtest "03", thus enabling one of the subtests at a time. Moreover, it will just print "none" in a separate run where none of the subtests are enabled, i.e., all the subtest specific lines are deleted. Here is the code:
```dart
main() {
print("none");
print("01"); //# 01: ok
print("02"); //# 02: ok
print("03" + new Map()); //# 03: compile-time error
}
```
Now that the Dart specification parser has been added to the toolset there is a **need** for one more expected **outcome**, namely `syntax error`:
```dart
main() {
print("nothing because this fails to parse!"; //# 01: syntax error
}
```
Every tool other than the specification parser will consider `syntax error` to be an indication that the expected outcome for this subtest is a compile-time error, i.e., we might as well have written `//# 01: compile-time error`, for running tests with all those other tools.
However, the specification parser makes the distinction between syntax errors and other compile-time errors, because it does not perform any static analysis except syntax checking. This also means that any subtest outcome expectation which is a `compile-time error` (or any variant thereof which is _not_ `syntax error`) will be considered to mean "expect no errors" by the specification parser. So we will both detect unexpected syntax errors (when the specification parser detects an error, but the expected outcome is not `syntax error`) and unexpectedly missing syntax errors (when the specification parser parses the test library successfully, but the expected subtest outcome is `syntax error`).
This means that multi-tests should be written and maintained such that **syntax errors** are **indicated as such**, and other compile-time errors are indicated as `compile-time error` (or `checked mode compile-time error`, or whatever other variant that may be available and appropriate).
It will not (yet) produce failing **buildbot** runs to continue to use `compile-time error` everywhere as we have done until now, because the specification parser is not (yet) running on a buildbot.
However, it is likely to be **useful to make the distinction** anyway, because it will typically destroy the ability of a test to test the right thing if it contains a syntax error that the developer did not intend to write. In particular, a `compile-time error` may be reported as expected, but it never tests the type error or similar phenomenon which was intended, because the static analysis fails already in the parser. This may then masquerade as a successful test for months, and everybody thinks that the test works as intended. This does occur, by the way: I fixed several of these issue while doing this work.
At this point (November 2017) I would **recommend using a best effort approach**, and simply marking those subtests as `syntax error` which are intended to be syntax errors. These marks will be adjusted as needed before the specification parser runs on a main waterfall buildbot, which may not happen at all, and in any case will not happen right now.
It should be noted that **every Dart tool** (except the specification parser) **is free to redistribute error detection from the parser to other parts of the static analysis, and vice versa**. This means that that certain things which are syntax errors according to `Dart.g` are detected later on in the static analysis of some tool, or certain things which are not syntax errors according to `Dart.g` will be rejected by the parser in some tool. This does not create any conflicts, because all other tools than the specification parser should continue to report all compile-time errors as compile-time errors, no matter whether they are detected by the parser or by some other part of static analysis, and the testing framework (`test.py`) will consider the test run as successful as long as each tool (except the specification parser) reports a compile-time error in a subtest which has any of the expectations `syntax error`, `compile-time error`, or any of its variants. In other words, each tool which is not the specification parser should not make an attempt to detect and report syntax errors separately (they should be considered as compile-time errors, as they have been until now), and in particular _it should not be considered to be a bug if such tools report a certain expected `syntax error` as a non-syntax compile-time error, or vice versa_.
## Use
If you need to use the specification parser, or you're just curious, there is support for running it, in some situations. In particular, it is not yet possible to build it using `tools/build.py`, and it may not work on all platforms.
On a Linux host where the ANTLR library is available at `/usr/share/java/antlr4-runtime.jar`, the specification parser can be generated with the command `make parser` in `tools/spec_parser`, and it may then be invoked as `tools/spec_parse.py <files-to-parse>...` (or with `some/other/path/tools/spec_parse.py` from some other directory, or via the `PATH`, etc.).
Support for building the specification parser using `tools/build.py` or `tools/ninja.py` and on all platforms will be implemented.
For test runs involving multi-tests it is necessary to use `tools/test.py` (as always, because a multi-test is generally full of syntax errors until it has been processed by `tools/test.py`). Here is an example invocation:
```
> tools/test.py -c spec_parser language_2/variable
[00:05 | 100% | + 137 | - 0]
>
```

View File

@ -0,0 +1,3 @@
## What are the `@dart-github-bot` comments?
We're experimenting with triage automation. You may see comments made by a `@dart-github-bot` - that's related to our automation investigations. We may or may not continue experimentation here; for now, you can safely ignore these comments.

View File

@ -0,0 +1,79 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
## Workflow
* Look through issues that don't have an area assigned.
* Use the [SDK triage query].
* Does the issue relate to code in the SDK?
* Assign to the right area by adding an `area-*` label. **Note: `area-language` is deprecated. New language issues should be [moved][move] to the [language repo](https://github.com/dart-lang/language).**
* Is the issue in `area-library`?
* Assign the right `library-*` label, too.
* Is it obvious if the issue is a bug or enhancement?
* Optional: Add `type-bug` or `type-enhancement` if you can.
* Does the issue relate to code in another `dart-lang` project/package?
* Move the issue to the right repo by using the `Transfer issue` link (between github orgs, use [`/move to ...`][move]).
* Get emails when issues are tagged with labels you care about
* Use the [Dart SDK email tool].
## Issue Labels
### Priority
* Level of **team urgency**
* Should be the opinion of team and/or product management
* Can be affected by the quantity/priority of existing issues - *If everything is P0, nothing is P0*
* May evolve as other issues are resolved and new issues are opened
* Levels
* **[p0-critical][]**: Drop everything and fix it.
* For dev channel: blocks the release. Valid cherry-pick.
* For release channel: worthy of a "dot" release
* **[p1-high][]**: Planned for the in-progress release
* Should be aligned with other work to ensure likely completion in current release
* **[p2-medium][]**: Important work for later release.
* Should be done eventually.
* **[p3-low][]**: Maybe, someday
* First candidates to close as "closed-not-planned"
* When we enter cherry pick season for release X...
* p0 issues: are the only fixes that will be taken for release X
* p1-3 issues:
* Milestone flag should be changed to release X+1 or
* p1 issues can be changed to p2/3 and milestone flag removed
## Using the `needs-info` label
If you need additional information from an issue reporter to triage or otherwise act
on an issue, say so, and consider adding the `needs-info` label to the issue. Issues
with a `needs-info` label are triaged by our [no response] bot; it will auto-close
the issue after 14 days if the issue reporter does not respond.
## Follow up steps for Dart VM and Dart IO Library issues
Issues filed against the Dart VM (issues with label `area-vm` : [VM issues](https://github.com/dart-lang/sdk/issues?q=is%3Aissue+is%3Aopen+label%3Aarea-vm+)) and IO library (issues with labels `area-library` `library-io` : [io library issues](https://github.com/dart-lang/sdk/issues?q=is%3Aissue+is%3Aopen+label%3Aarea-library+label%3Alibrary-io)) are triaged at least weekly by a member of the Dart VM team.
Triaging a bug entails the following steps
* Figure out if it is a bug, enhancement request, performance issue, general question, documentation issue or one of the other types and mark the issue appropriately as `type-bug`,`type-question`,`type-enhancement`,`type-performance` or one of the other types.
* If additional information is needed for addressing the bug please add the label `needs-info` to the issue and a comment back to the person filing the issue asking for information
* Review contents of the issue and assign one of 4 priorities listed below
* P0 - the issue critically impacts many users: somebody is actively working on it and daily updates will be posted on the issue, it is definitely a cherry pick candidate
* P1 - the issue blocks several users: it is desirable to address it in the next beta release, there will be weekly updates on the issue (could be a cherry pick to the previous stable release)
* P2 - the issue is represents an important issue for a small number of users or is of minor importance for many users: it is desirable to address it in the next stable release, there will be quarterly updates on the issue
* P3 - the issue is not critical and is not being actively addressed
If the priority is <= P2 then it is also assigned to a developer.
* Assign a milestone to the issue based on the priority selected so that the expected resolution timeline is clear. At this point add the `triaged` label so that it is clear the issue has been looked at.
Issues may have their priorities adjusted up or down based on user feedback and milestones may also be adjusted based on available bandwidth in the team to address issues.
[SDK triage query]: https://goto.google.com/dart-triage
[move]: https://github.com/apps/move
[Dart SDK email tool]: https://dart-github-label-notifier.web.app
[p0-critical]: https://github.com/dart-lang/sdk/labels/p0-critical
[p1-high]: https://github.com/dart-lang/sdk/labels/p1-high
[p2-medium]: https://github.com/dart-lang/sdk/labels/p2-medium
[p3-low]: https://github.com/dart-lang/sdk/labels/p3-low
[no response]: https://github.com/dart-lang/sdk/blob/main/.github/workflows/no-response.yml

View File

@ -0,0 +1,32 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
When doing a large task that involves multiple people or changes to the codebase, it helps to have a single issue that tracks the overall state of the task. This is called a "meta-issue". It describes the overall goal and links to more specific issues for individual pieces of work.
If a meta-issue involves work across multiple areas, it should have the "[area-meta][]" label. It should also be assigned to a person who is responsible for coordinating the work across teams and keeping the meta-issue updated. If all of the tasks are within a single area, the meta-issue should instead be labeled with that area. In that case, it doesn't need an assignee, though having one doesn't hurt.
Like other specific issues, it should have a type label that describes the type of the overall change: [type-bug], [type-enhancement], etc.
[area-meta]: https://github.com/dart-lang/sdk/labels/area-meta
[type-bug]: https://github.com/dart-lang/sdk/labels/type-bug
[type-enhancement]: https://github.com/dart-lang/sdk/labels/type-enhancement
The meta-issue's body text should give a high-level overview of the change followed by a task list for all the sub-issues. Each entry should have a very brief description and a link to the sub-issue. A task list can be created using the following Markdown:
```markdown
- [ ] item
- [ ] item
- [x] checked item
```
Once a sub-issue is completed, its entry should be checked. If applicable, the first release to contain the fix should be mentioned as well.
Occasionally new sub-issues come up. For example, a bug might be found in the solution to a previously-completed sub-issue. To add these to the meta-issue, a triager should both add a comment linking to the new sub-issue *and* add it to the task list. Adding a comment notifies interested parties of a new blocking issue, and updating the task list ensures that the original post continues to provide an up-to-date view of everything required for the meta-issue.
When all of the sub-issues are closed and the owner of the meta-issue decides the overall task is complete, they should close the meta-issue.
See [this issue](https://github.com/dart-lang/sdk/issues/23454) for a good example of a meta-issue.

View File

@ -0,0 +1,132 @@
> [!IMPORTANT]
> This page was copied from https://github.com/dart-lang/sdk/wiki and needs review.
> Please [contribute](../CONTRIBUTING.md) changes to bring it up-to-date -
> removing this header - or send a CL to delete the file.
---
# Who is this article for?
If you are writing tests of core parts of the Dart SDK, there are special
tools to run these tests on browsers. If you are writing tests for a package
that is not part of the Dart SDK distribution, then
[package:test](http://github.com/dart-lang/test/blob/master/README.md),
previously called "unittest", is the best way for you to write your unit tests
for browsers and the standalone Dart vm. Published Dart packages are
automatically tested using [Drone.io](http://readme.drone.io/pub/overview).
The remainder of this article is about the browser test infrastructure for
core Dart libraries and tools in the Dart repository. These test suites
are run by the tools/test.py tool,
and can be run on web browsers as well as the standalone Dart vm.
In the most common case, Dart scripts are wrapped in an automatically-created
HTML wrapper page, and compiled to JS using dart2js, to run on web browsers.
Usually, this is the best way to test dart:html or other web features,
but a few complex cases require us to write a custom html file, rather
than using the HTML wrapper file.
# Details
A test script testing Dart's web libraries, for example a test in
tests/html, will create the DOM elements it needs to test in the test
script itself. WebPlatformTest tests in the test/co19 test suite will
add HTML or DOM elements to the document, and then operate on them.
This is the best way to create and test a web page. For example, the
test
WebPlatformTest/html/semantics/tabular-data/the-table-element/insertRow-method\_t01.dart
contains the following Dart code:
```dart
const String htmlEL = r'''
<div id="test">
<table>
<tr>
<td>
</table>
</div>
''';
void main() {
document.body.appendHtml(htmlEL);
...
}
```
## Running Tests
When a test is run on a browser, the wrapper HTML file, and the
modified or compiled Dart scripts are put into a directory called
generated\_tests, under the build directory that the Dart executable
and SDK are built in. The test server runs a local HTTP server, that
serves files from the build directory, and also from the Dart
repository root, and starts a browser that runs the tests fetched from
this server. To debug a test, you can start this HTTP server, and
then open the test's web page manually in a browser. The output of
test.py includes the command lines necessary to do this.
## Custom HTML Tests
If a test requires a custom HTML file, and cannot be written by adding
DOM elements to a page after it is loaded, then the test scripts allow
you to write the HTML file separately, and use it instead. There are
two systems for doing this. The first system adds a custom HTML file
to the test called foo\_test.dart by putting an HTML file called
foo\_test.html in the same directory. The second system creates a
test from any file ending in `_htmltest.html` in that directory, like
bar\_htmltest.html.
### `_test.html` custom HTML files
To be filled in
### `_htmltest.html` tests
An HTML file with a name that ends in `_htmltest.html` will be read by
the test infrastructure, and metadata about what scripts are used and
what messages the test should post to the document window is read from
an annotation in that file.
The annotation is a JSON dictionary, embedded between two delimiters,
and it can be put inside an HTML comment so that the unprocessed page
looks like valid HTML:
```html
<!--
START_HTML_DART_TEST
{
"scripts": ["scripts_test_dart.dart", "scripts_test_js.js"],
"expectedMessages": ["crab", "fish", "squid", "sea urchin"]
}
END_HTML_DART_TEST
-->
```
The test will pass if the web page posts all the strings in the
expectedMessages property to its top-level window, for example by
executing lines like
```javascript
window.postMessage('squid', '*');
```
Scripts in the 'scripts' property of the annotation will be
automatically copied from the test directory to the generated-test
directory, and compiled from dart to js if necessary. The script tags
using Dart scripts should be written exactly like
```html
<script src="foo.dart" type="application/dart"></script>
```
in order for the test generation to find and modify them.
In order for the test framework to catch all errors in this HTML test,
the first script that executes on this page must be:
```html
<script>window.parent.dispatchEvent(new Event('detect_errors'));</script>
```
This allows the test framework
to attach an error handler to the window at the first opportunity,
before the scripts being tested have run.

13
docs/images/Makefile Normal file
View File

@ -0,0 +1,13 @@
successors.svg: successors.dot
dot -Tsvg successors.dot -o successors.svg
predecessors.svg: predecessors.dot
dot -Tsvg predecessors.dot -o predecessors.svg
dominators.svg: dominators.dot
dot -Tsvg dominators.dot -o dominators.svg
owners.svg: owners.dot
dot -Tsvg owners.dot -o owners.svg
all: successors.svg predecessors.svg dominators.svg owners.svg

View File

@ -0,0 +1,15 @@
digraph {
label="Dominators";
r -> a;
r -> b;
r -> c;
r -> d;
d -> e;
d -> f;
d -> g;
{ rank=same; r }
{ rank=same; a; b }
{ rank=same; c; d }
{ rank=same; e; f }
{ rank=same; g }
}

104
docs/images/dominators.svg Normal file
View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="350pt" height="211pt"
viewBox="0.00 0.00 350.00 211.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 207)">
<title>%3</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-207 346,-207 346,4 -4,4"/>
<text text-anchor="middle" x="171" y="-7.8" font-family="Times,serif" font-size="14.00">Dominators</text>
<!-- r -->
<g id="node1" class="node">
<title>r</title>
<ellipse fill="none" stroke="black" cx="135" cy="-185" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-181.3" font-family="Times,serif" font-size="14.00">r</text>
</g>
<!-- a -->
<g id="node2" class="node">
<title>a</title>
<ellipse fill="none" stroke="black" cx="27" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-109.3" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- r&#45;&gt;a -->
<g id="edge1" class="edge">
<title>r&#45;&gt;a</title>
<path fill="none" stroke="black" d="M116.19,-171.81C99,-160.67 73.38,-144.06 54.01,-131.5"/>
<polygon fill="black" stroke="black" points="55.89,-128.56 45.6,-126.05 52.08,-134.43 55.89,-128.56"/>
</g>
<!-- b -->
<g id="node3" class="node">
<title>b</title>
<ellipse fill="none" stroke="black" cx="99" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-109.3" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- r&#45;&gt;b -->
<g id="edge2" class="edge">
<title>r&#45;&gt;b</title>
<path fill="none" stroke="black" d="M126.65,-167.76C122.29,-159.28 116.85,-148.71 111.96,-139.2"/>
<polygon fill="black" stroke="black" points="114.99,-137.44 107.3,-130.15 108.77,-140.64 114.99,-137.44"/>
</g>
<!-- c -->
<g id="node4" class="node">
<title>c</title>
<ellipse fill="none" stroke="black" cx="171" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="171" y="-109.3" font-family="Times,serif" font-size="14.00">c</text>
</g>
<!-- r&#45;&gt;c -->
<g id="edge3" class="edge">
<title>r&#45;&gt;c</title>
<path fill="none" stroke="black" d="M143.35,-167.76C147.71,-159.28 153.15,-148.71 158.04,-139.2"/>
<polygon fill="black" stroke="black" points="161.23,-140.64 162.7,-130.15 155.01,-137.44 161.23,-140.64"/>
</g>
<!-- d -->
<g id="node5" class="node">
<title>d</title>
<ellipse fill="none" stroke="black" cx="243" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="243" y="-109.3" font-family="Times,serif" font-size="14.00">d</text>
</g>
<!-- r&#45;&gt;d -->
<g id="edge4" class="edge">
<title>r&#45;&gt;d</title>
<path fill="none" stroke="black" d="M153.81,-171.81C171,-160.67 196.62,-144.06 215.99,-131.5"/>
<polygon fill="black" stroke="black" points="217.92,-134.43 224.4,-126.05 214.11,-128.56 217.92,-134.43"/>
</g>
<!-- e -->
<g id="node6" class="node">
<title>e</title>
<ellipse fill="none" stroke="black" cx="171" cy="-41" rx="27" ry="18"/>
<text text-anchor="middle" x="171" y="-37.3" font-family="Times,serif" font-size="14.00">e</text>
</g>
<!-- d&#45;&gt;e -->
<g id="edge5" class="edge">
<title>d&#45;&gt;e</title>
<path fill="none" stroke="black" d="M228.43,-97.83C218.25,-87.94 204.48,-74.55 192.97,-63.36"/>
<polygon fill="black" stroke="black" points="195.41,-60.85 185.8,-56.38 190.53,-65.87 195.41,-60.85"/>
</g>
<!-- f -->
<g id="node7" class="node">
<title>f</title>
<ellipse fill="none" stroke="black" cx="243" cy="-41" rx="27" ry="18"/>
<text text-anchor="middle" x="243" y="-37.3" font-family="Times,serif" font-size="14.00">f</text>
</g>
<!-- d&#45;&gt;f -->
<g id="edge6" class="edge">
<title>d&#45;&gt;f</title>
<path fill="none" stroke="black" d="M243,-94.7C243,-86.98 243,-77.71 243,-69.11"/>
<polygon fill="black" stroke="black" points="246.5,-69.1 243,-59.1 239.5,-69.1 246.5,-69.1"/>
</g>
<!-- g -->
<g id="node8" class="node">
<title>g</title>
<ellipse fill="none" stroke="black" cx="315" cy="-41" rx="27" ry="18"/>
<text text-anchor="middle" x="315" y="-37.3" font-family="Times,serif" font-size="14.00">g</text>
</g>
<!-- d&#45;&gt;g -->
<g id="edge7" class="edge">
<title>d&#45;&gt;g</title>
<path fill="none" stroke="black" d="M257.57,-97.83C267.75,-87.94 281.52,-74.55 293.03,-63.36"/>
<polygon fill="black" stroke="black" points="295.47,-65.87 300.2,-56.38 290.59,-60.85 295.47,-65.87"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

34
docs/images/owners.dot Normal file
View File

@ -0,0 +1,34 @@
digraph {
label="Owners";
r -> a;
r -> b;
a -> c;
b -> c;
b -> d;
c -> d;
d -> b;
d -> e;
d -> f;
e -> g;
f -> g;
subgraph cluster_0 {
label="";
r; a;
}
subgraph cluster_1 {
label="";
b;
}
subgraph cluster_2 {
label="";
c;
}
subgraph cluster_3 {
label="";
d; e; f;
}
subgraph cluster_4 {
label="";
g
}
}

148
docs/images/owners.svg Normal file
View File

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="244pt" height="387pt"
viewBox="0.00 0.00 244.00 387.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 383)">
<title>%3</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-383 240,-383 240,4 -4,4"/>
<text text-anchor="middle" x="118" y="-7.8" font-family="Times,serif" font-size="14.00">Owners</text>
<g id="clust1" class="cluster">
<title>cluster_0</title>
<polygon fill="none" stroke="black" points="8,-247 8,-371 78,-371 78,-247 8,-247"/>
</g>
<g id="clust2" class="cluster">
<title>cluster_1</title>
<polygon fill="none" stroke="black" points="86,-247 86,-299 156,-299 156,-247 86,-247"/>
</g>
<g id="clust3" class="cluster">
<title>cluster_2</title>
<polygon fill="none" stroke="black" points="8,-175 8,-227 78,-227 78,-175 8,-175"/>
</g>
<g id="clust4" class="cluster">
<title>cluster_3</title>
<polygon fill="none" stroke="black" points="86,-103 86,-227 228,-227 228,-103 86,-103"/>
</g>
<g id="clust5" class="cluster">
<title>cluster_4</title>
<polygon fill="none" stroke="black" points="122,-31 122,-83 192,-83 192,-31 122,-31"/>
</g>
<!-- r -->
<g id="node1" class="node">
<title>r</title>
<ellipse fill="none" stroke="black" cx="43" cy="-345" rx="27" ry="18"/>
<text text-anchor="middle" x="43" y="-341.3" font-family="Times,serif" font-size="14.00">r</text>
</g>
<!-- a -->
<g id="node2" class="node">
<title>a</title>
<ellipse fill="none" stroke="black" cx="43" cy="-273" rx="27" ry="18"/>
<text text-anchor="middle" x="43" y="-269.3" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- r&#45;&gt;a -->
<g id="edge1" class="edge">
<title>r&#45;&gt;a</title>
<path fill="none" stroke="black" d="M43,-326.7C43,-318.98 43,-309.71 43,-301.11"/>
<polygon fill="black" stroke="black" points="46.5,-301.1 43,-291.1 39.5,-301.1 46.5,-301.1"/>
</g>
<!-- b -->
<g id="node3" class="node">
<title>b</title>
<ellipse fill="none" stroke="black" cx="121" cy="-273" rx="27" ry="18"/>
<text text-anchor="middle" x="121" y="-269.3" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- r&#45;&gt;b -->
<g id="edge2" class="edge">
<title>r&#45;&gt;b</title>
<path fill="none" stroke="black" d="M58.41,-330.17C69.73,-320.01 85.31,-306.03 98.09,-294.56"/>
<polygon fill="black" stroke="black" points="100.52,-297.09 105.62,-287.8 95.84,-291.88 100.52,-297.09"/>
</g>
<!-- c -->
<g id="node4" class="node">
<title>c</title>
<ellipse fill="none" stroke="black" cx="43" cy="-201" rx="27" ry="18"/>
<text text-anchor="middle" x="43" y="-197.3" font-family="Times,serif" font-size="14.00">c</text>
</g>
<!-- a&#45;&gt;c -->
<g id="edge3" class="edge">
<title>a&#45;&gt;c</title>
<path fill="none" stroke="black" d="M43,-254.7C43,-246.98 43,-237.71 43,-229.11"/>
<polygon fill="black" stroke="black" points="46.5,-229.1 43,-219.1 39.5,-229.1 46.5,-229.1"/>
</g>
<!-- b&#45;&gt;c -->
<g id="edge4" class="edge">
<title>b&#45;&gt;c</title>
<path fill="none" stroke="black" d="M105.59,-258.17C94.27,-248.01 78.69,-234.03 65.91,-222.56"/>
<polygon fill="black" stroke="black" points="68.16,-219.88 58.38,-215.8 63.48,-225.09 68.16,-219.88"/>
</g>
<!-- d -->
<g id="node5" class="node">
<title>d</title>
<ellipse fill="none" stroke="black" cx="121" cy="-201" rx="27" ry="18"/>
<text text-anchor="middle" x="121" y="-197.3" font-family="Times,serif" font-size="14.00">d</text>
</g>
<!-- b&#45;&gt;d -->
<g id="edge5" class="edge">
<title>b&#45;&gt;d</title>
<path fill="none" stroke="black" d="M126.84,-255.41C127.7,-247.51 127.95,-237.85 127.59,-228.94"/>
<polygon fill="black" stroke="black" points="131.08,-228.68 126.88,-218.96 124.1,-229.18 131.08,-228.68"/>
</g>
<!-- c&#45;&gt;d -->
<g id="edge6" class="edge">
<title>c&#45;&gt;d</title>
<path fill="none" stroke="black" d="M70.12,-201C74.71,-201 79.31,-201 83.91,-201"/>
<polygon fill="black" stroke="black" points="83.97,-204.5 93.97,-201 83.97,-197.5 83.97,-204.5"/>
</g>
<!-- d&#45;&gt;b -->
<g id="edge7" class="edge">
<title>d&#45;&gt;b</title>
<path fill="none" stroke="black" d="M115.12,-218.96C114.29,-226.83 114.05,-236.37 114.42,-245.19"/>
<polygon fill="black" stroke="black" points="110.94,-245.69 115.16,-255.41 117.93,-245.18 110.94,-245.69"/>
</g>
<!-- e -->
<g id="node6" class="node">
<title>e</title>
<ellipse fill="none" stroke="black" cx="121" cy="-129" rx="27" ry="18"/>
<text text-anchor="middle" x="121" y="-125.3" font-family="Times,serif" font-size="14.00">e</text>
</g>
<!-- d&#45;&gt;e -->
<g id="edge8" class="edge">
<title>d&#45;&gt;e</title>
<path fill="none" stroke="black" d="M121,-182.7C121,-174.98 121,-165.71 121,-157.11"/>
<polygon fill="black" stroke="black" points="124.5,-157.1 121,-147.1 117.5,-157.1 124.5,-157.1"/>
</g>
<!-- f -->
<g id="node7" class="node">
<title>f</title>
<ellipse fill="none" stroke="black" cx="193" cy="-129" rx="27" ry="18"/>
<text text-anchor="middle" x="193" y="-125.3" font-family="Times,serif" font-size="14.00">f</text>
</g>
<!-- d&#45;&gt;f -->
<g id="edge9" class="edge">
<title>d&#45;&gt;f</title>
<path fill="none" stroke="black" d="M135.57,-185.83C145.75,-175.94 159.52,-162.55 171.03,-151.36"/>
<polygon fill="black" stroke="black" points="173.47,-153.87 178.2,-144.38 168.59,-148.85 173.47,-153.87"/>
</g>
<!-- g -->
<g id="node8" class="node">
<title>g</title>
<ellipse fill="none" stroke="black" cx="157" cy="-57" rx="27" ry="18"/>
<text text-anchor="middle" x="157" y="-53.3" font-family="Times,serif" font-size="14.00">g</text>
</g>
<!-- e&#45;&gt;g -->
<g id="edge10" class="edge">
<title>e&#45;&gt;g</title>
<path fill="none" stroke="black" d="M129.35,-111.76C133.71,-103.28 139.15,-92.71 144.04,-83.2"/>
<polygon fill="black" stroke="black" points="147.23,-84.64 148.7,-74.15 141.01,-81.44 147.23,-84.64"/>
</g>
<!-- f&#45;&gt;g -->
<g id="edge11" class="edge">
<title>f&#45;&gt;g</title>
<path fill="none" stroke="black" d="M184.65,-111.76C180.29,-103.28 174.85,-92.71 169.96,-83.2"/>
<polygon fill="black" stroke="black" points="172.99,-81.44 165.3,-74.15 166.77,-84.64 172.99,-81.44"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,19 @@
digraph {
label="Predecessors";
r -> a [dir = "back"];
r -> b [dir = "back"];
a -> c [dir = "back"];
b -> c [dir = "back"];
b -> d [dir = "back"];
c -> d [dir = "back"];
d -> b [dir = "back"];
d -> e [dir = "back"];
d -> f [dir = "back"];
e -> g [dir = "back"];
f -> g [dir = "back"];
{ rank=same; r }
{ rank=same; a; b }
{ rank=same; c; d }
{ rank=same; e; f }
{ rank=same; g }
}

View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="170pt" height="355pt"
viewBox="0.00 0.00 170.00 355.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 351)">
<title>%3</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-351 166,-351 166,4 -4,4"/>
<text text-anchor="middle" x="81" y="-7.8" font-family="Times,serif" font-size="14.00">Predecessors</text>
<!-- r -->
<g id="node1" class="node">
<title>r</title>
<ellipse fill="none" stroke="black" cx="63" cy="-329" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-325.3" font-family="Times,serif" font-size="14.00">r</text>
</g>
<!-- a -->
<g id="node2" class="node">
<title>a</title>
<ellipse fill="none" stroke="black" cx="27" cy="-257" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-253.3" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- r&#45;&gt;a -->
<g id="edge1" class="edge">
<title>r&#45;&gt;a</title>
<path fill="none" stroke="black" d="M49.99,-302.7C45.09,-293.18 39.66,-282.61 35.3,-274.15"/>
<polygon fill="black" stroke="black" points="46.96,-304.47 54.65,-311.76 53.19,-301.27 46.96,-304.47"/>
</g>
<!-- b -->
<g id="node3" class="node">
<title>b</title>
<ellipse fill="none" stroke="black" cx="99" cy="-257" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-253.3" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- r&#45;&gt;b -->
<g id="edge2" class="edge">
<title>r&#45;&gt;b</title>
<path fill="none" stroke="black" d="M76.01,-302.7C80.91,-293.18 86.34,-282.61 90.7,-274.15"/>
<polygon fill="black" stroke="black" points="72.81,-301.27 71.35,-311.76 79.04,-304.47 72.81,-301.27"/>
</g>
<!-- c -->
<g id="node4" class="node">
<title>c</title>
<ellipse fill="none" stroke="black" cx="27" cy="-185" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-181.3" font-family="Times,serif" font-size="14.00">c</text>
</g>
<!-- a&#45;&gt;c -->
<g id="edge3" class="edge">
<title>a&#45;&gt;c</title>
<path fill="none" stroke="black" d="M27,-228.67C27,-220.05 27,-210.79 27,-203.1"/>
<polygon fill="black" stroke="black" points="23.5,-228.7 27,-238.7 30.5,-228.7 23.5,-228.7"/>
</g>
<!-- b&#45;&gt;c -->
<g id="edge4" class="edge">
<title>b&#45;&gt;c</title>
<path fill="none" stroke="black" d="M76.96,-234.57C65.55,-223.48 51.93,-210.24 41.8,-200.38"/>
<polygon fill="black" stroke="black" points="74.82,-237.37 84.43,-241.83 79.7,-232.35 74.82,-237.37"/>
</g>
<!-- d -->
<g id="node5" class="node">
<title>d</title>
<ellipse fill="none" stroke="black" cx="99" cy="-185" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-181.3" font-family="Times,serif" font-size="14.00">d</text>
</g>
<!-- b&#45;&gt;d -->
<g id="edge5" class="edge">
<title>b&#45;&gt;d</title>
<path fill="none" stroke="black" d="M92.42,-229.19C92.05,-220.37 92.29,-210.83 93.12,-202.96"/>
<polygon fill="black" stroke="black" points="88.94,-229.69 93.16,-239.41 95.93,-229.18 88.94,-229.69"/>
</g>
<!-- c&#45;&gt;d -->
<g id="edge6" class="edge">
<title>c&#45;&gt;d</title>
<path fill="none" stroke="black" d="M64.09,-185C66.7,-185 69.31,-185 71.93,-185"/>
<polygon fill="black" stroke="black" points="64,-181.5 54,-185 64,-188.5 64,-181.5"/>
</g>
<!-- d&#45;&gt;b -->
<g id="edge7" class="edge">
<title>d&#45;&gt;b</title>
<path fill="none" stroke="black" d="M105.59,-212.94C105.95,-221.85 105.7,-231.51 104.84,-239.41"/>
<polygon fill="black" stroke="black" points="109.08,-212.68 104.88,-202.96 102.1,-213.18 109.08,-212.68"/>
</g>
<!-- e -->
<g id="node6" class="node">
<title>e</title>
<ellipse fill="none" stroke="black" cx="63" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-109.3" font-family="Times,serif" font-size="14.00">e</text>
</g>
<!-- d&#45;&gt;e -->
<g id="edge8" class="edge">
<title>d&#45;&gt;e</title>
<path fill="none" stroke="black" d="M85.99,-158.7C81.09,-149.18 75.66,-138.61 71.3,-130.15"/>
<polygon fill="black" stroke="black" points="82.96,-160.47 90.65,-167.76 89.19,-157.27 82.96,-160.47"/>
</g>
<!-- f -->
<g id="node7" class="node">
<title>f</title>
<ellipse fill="none" stroke="black" cx="135" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-109.3" font-family="Times,serif" font-size="14.00">f</text>
</g>
<!-- d&#45;&gt;f -->
<g id="edge9" class="edge">
<title>d&#45;&gt;f</title>
<path fill="none" stroke="black" d="M112.01,-158.7C116.91,-149.18 122.34,-138.61 126.7,-130.15"/>
<polygon fill="black" stroke="black" points="108.81,-157.27 107.35,-167.76 115.04,-160.47 108.81,-157.27"/>
</g>
<!-- g -->
<g id="node8" class="node">
<title>g</title>
<ellipse fill="none" stroke="black" cx="99" cy="-41" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-37.3" font-family="Times,serif" font-size="14.00">g</text>
</g>
<!-- e&#45;&gt;g -->
<g id="edge10" class="edge">
<title>e&#45;&gt;g</title>
<path fill="none" stroke="black" d="M76.01,-86.7C80.91,-77.18 86.34,-66.61 90.7,-58.15"/>
<polygon fill="black" stroke="black" points="72.81,-85.27 71.35,-95.76 79.04,-88.47 72.81,-85.27"/>
</g>
<!-- f&#45;&gt;g -->
<g id="edge11" class="edge">
<title>f&#45;&gt;g</title>
<path fill="none" stroke="black" d="M121.99,-86.7C117.09,-77.18 111.66,-66.61 107.3,-58.15"/>
<polygon fill="black" stroke="black" points="118.96,-88.47 126.65,-95.76 125.19,-85.27 118.96,-88.47"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,19 @@
digraph {
label="Successors";
r -> a;
r -> b;
a -> c;
b -> c;
b -> d;
c -> d;
d -> b;
d -> e;
d -> f;
e -> g;
f -> g;
{ rank=same; r }
{ rank=same; a; b }
{ rank=same; c; d }
{ rank=same; e; f }
{ rank=same; g }
}

128
docs/images/successors.svg Normal file
View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="170pt" height="355pt"
viewBox="0.00 0.00 170.00 355.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 351)">
<title>%3</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-351 166,-351 166,4 -4,4"/>
<text text-anchor="middle" x="81" y="-7.8" font-family="Times,serif" font-size="14.00">Successors</text>
<!-- r -->
<g id="node1" class="node">
<title>r</title>
<ellipse fill="none" stroke="black" cx="63" cy="-329" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-325.3" font-family="Times,serif" font-size="14.00">r</text>
</g>
<!-- a -->
<g id="node2" class="node">
<title>a</title>
<ellipse fill="none" stroke="black" cx="27" cy="-257" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-253.3" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- r&#45;&gt;a -->
<g id="edge1" class="edge">
<title>r&#45;&gt;a</title>
<path fill="none" stroke="black" d="M54.65,-311.76C50.29,-303.28 44.85,-292.71 39.96,-283.2"/>
<polygon fill="black" stroke="black" points="42.99,-281.44 35.3,-274.15 36.77,-284.64 42.99,-281.44"/>
</g>
<!-- b -->
<g id="node3" class="node">
<title>b</title>
<ellipse fill="none" stroke="black" cx="99" cy="-257" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-253.3" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- r&#45;&gt;b -->
<g id="edge2" class="edge">
<title>r&#45;&gt;b</title>
<path fill="none" stroke="black" d="M71.35,-311.76C75.71,-303.28 81.15,-292.71 86.04,-283.2"/>
<polygon fill="black" stroke="black" points="89.23,-284.64 90.7,-274.15 83.01,-281.44 89.23,-284.64"/>
</g>
<!-- c -->
<g id="node4" class="node">
<title>c</title>
<ellipse fill="none" stroke="black" cx="27" cy="-185" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-181.3" font-family="Times,serif" font-size="14.00">c</text>
</g>
<!-- a&#45;&gt;c -->
<g id="edge3" class="edge">
<title>a&#45;&gt;c</title>
<path fill="none" stroke="black" d="M27,-238.7C27,-230.98 27,-221.71 27,-213.11"/>
<polygon fill="black" stroke="black" points="30.5,-213.1 27,-203.1 23.5,-213.1 30.5,-213.1"/>
</g>
<!-- b&#45;&gt;c -->
<g id="edge4" class="edge">
<title>b&#45;&gt;c</title>
<path fill="none" stroke="black" d="M84.43,-241.83C74.25,-231.94 60.48,-218.55 48.97,-207.36"/>
<polygon fill="black" stroke="black" points="51.41,-204.85 41.8,-200.38 46.53,-209.87 51.41,-204.85"/>
</g>
<!-- d -->
<g id="node5" class="node">
<title>d</title>
<ellipse fill="none" stroke="black" cx="99" cy="-185" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-181.3" font-family="Times,serif" font-size="14.00">d</text>
</g>
<!-- b&#45;&gt;d -->
<g id="edge5" class="edge">
<title>b&#45;&gt;d</title>
<path fill="none" stroke="black" d="M93.16,-239.41C92.3,-231.51 92.05,-221.85 92.41,-212.94"/>
<polygon fill="black" stroke="black" points="95.9,-213.18 93.12,-202.96 88.92,-212.68 95.9,-213.18"/>
</g>
<!-- c&#45;&gt;d -->
<g id="edge6" class="edge">
<title>c&#45;&gt;d</title>
<path fill="none" stroke="black" d="M54,-185C56.61,-185 59.23,-185 61.84,-185"/>
<polygon fill="black" stroke="black" points="61.93,-188.5 71.93,-185 61.93,-181.5 61.93,-188.5"/>
</g>
<!-- d&#45;&gt;b -->
<g id="edge7" class="edge">
<title>d&#45;&gt;b</title>
<path fill="none" stroke="black" d="M104.88,-202.96C105.71,-210.83 105.95,-220.37 105.58,-229.19"/>
<polygon fill="black" stroke="black" points="102.07,-229.18 104.84,-239.41 109.06,-229.69 102.07,-229.18"/>
</g>
<!-- e -->
<g id="node6" class="node">
<title>e</title>
<ellipse fill="none" stroke="black" cx="63" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-109.3" font-family="Times,serif" font-size="14.00">e</text>
</g>
<!-- d&#45;&gt;e -->
<g id="edge8" class="edge">
<title>d&#45;&gt;e</title>
<path fill="none" stroke="black" d="M90.65,-167.76C86.29,-159.28 80.85,-148.71 75.96,-139.2"/>
<polygon fill="black" stroke="black" points="78.99,-137.44 71.3,-130.15 72.77,-140.64 78.99,-137.44"/>
</g>
<!-- f -->
<g id="node7" class="node">
<title>f</title>
<ellipse fill="none" stroke="black" cx="135" cy="-113" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-109.3" font-family="Times,serif" font-size="14.00">f</text>
</g>
<!-- d&#45;&gt;f -->
<g id="edge9" class="edge">
<title>d&#45;&gt;f</title>
<path fill="none" stroke="black" d="M107.35,-167.76C111.71,-159.28 117.15,-148.71 122.04,-139.2"/>
<polygon fill="black" stroke="black" points="125.23,-140.64 126.7,-130.15 119.01,-137.44 125.23,-140.64"/>
</g>
<!-- g -->
<g id="node8" class="node">
<title>g</title>
<ellipse fill="none" stroke="black" cx="99" cy="-41" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-37.3" font-family="Times,serif" font-size="14.00">g</text>
</g>
<!-- e&#45;&gt;g -->
<g id="edge10" class="edge">
<title>e&#45;&gt;g</title>
<path fill="none" stroke="black" d="M71.35,-95.76C75.71,-87.28 81.15,-76.71 86.04,-67.2"/>
<polygon fill="black" stroke="black" points="89.23,-68.64 90.7,-58.15 83.01,-65.44 89.23,-68.64"/>
</g>
<!-- f&#45;&gt;g -->
<g id="edge11" class="edge">
<title>f&#45;&gt;g</title>
<path fill="none" stroke="black" d="M126.65,-95.76C122.29,-87.28 116.85,-76.71 111.96,-67.2"/>
<polygon fill="black" stroke="black" points="114.99,-65.44 107.3,-58.15 108.77,-68.64 114.99,-65.44"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -11,7 +11,7 @@ The Dart SDK ships via a number of channels:
Each of these channels use varying release calendars, and keeping these entirely
aligned is not practical. Further, a number of developers interested in staying
current with Dart changes, consume the Dart SDK via our [dev
channel](https://github.com/dart-lang/sdk/wiki/Branches-and-releases). As a
channel](../Branches-and-releases.md). As a
result, we should anticipate that any dev channel build has the potential to end
up as a shipped SDK though some channel. And as a consequence of that, it is
critical that we keep the quality of our dev channel high AND that we keep it

View File

@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
/// Converts a multi-test to a test using the new static error test framework
/// (see https://github.com/dart-lang/sdk/wiki/Testing#static-error-tests)
/// (see https://github.com/dart-lang/sdk/tree/main/docs/Testing.md#static-error-tests)
/// and a copy of the '/none' test.
library;

View File

@ -251,7 +251,7 @@ On Isolate shutdown, native finalizers are run, but regular finalizers are not.
## Become
Become is an operation that atomically forwards the identity of a set of objects. A heap walk is performed where every pointer to a _before_ object is replaced with a pointer to an _after_ object, and each after object gains the identity hash of the corresponding before object. In the Dart VM, it is only used during [reload](https://github.com/dart-lang/sdk/wiki/Hot-reload) to map the old program and instances with the old sizes onto the new program and instances with the new sizes.
Become is an operation that atomically forwards the identity of a set of objects. A heap walk is performed where every pointer to a _before_ object is replaced with a pointer to an _after_ object, and each after object gains the identity hash of the corresponding before object. In the Dart VM, it is only used during [reload](../../docs/Hot-reload.md) to map the old program and instances with the old sizes onto the new program and instances with the new sizes.
This operation dates back to the early Smalltalk implementations. It was O(1) because pointers were indirect through an object table and was used to resize collections.

View File

@ -122,23 +122,23 @@ A set of isolates that are sharing the same program and the same heap. Isolates
A message that is delivered at any interrupt check, such as at function entry or the back-edge of a loop, rather than only when returning to the message loop.
## [Hot reload](https://github.com/dart-lang/sdk/wiki/Hot-reload)
## [Hot reload](../../docs/Hot-reload.md)
Changing a running program while retaining its current state: globals, frames, and objects transitively reachable from such.
## [AddressSanitizer, ASAN](https://github.com/dart-lang/sdk/wiki/Debugging-Dart-VM-with-AddressSanitizer)
## [AddressSanitizer, ASAN][debugging-asan]
Instrumentation to detect use-after-free and other similar issues.
## [MemorySanitizer, MSAN](https://github.com/dart-lang/sdk/wiki/Debugging-Dart-VM-with-AddressSanitizer)
## [MemorySanitizer, MSAN][debugging-asan]
Instrumentation to detect use of uninitialized memory and other similar issues.
## [ThreadSanitizer, TSAN](https://github.com/dart-lang/sdk/wiki/Debugging-Dart-VM-with-AddressSanitizer)
## [ThreadSanitizer, TSAN][debugging-asan]
Instrumentation to detect use of data races and other similar issues.
## [UndefinedBehaviorSanitizer, UBSAN](https://github.com/dart-lang/sdk/wiki/Debugging-Dart-VM-with-AddressSanitizer)
## [UndefinedBehaviorSanitizer, UBSAN][debugging-asan]
Instrumentation to detect undefined behavior such as signed integer overflow.
@ -177,3 +177,5 @@ The Dart VM has simulators for ARM, ARM64, RV32GC and RV64GC, but not for IA32 o
A commonly used sequence of machine code that has been factored out into a separate procedure to be called when needed instead of being repeated inline.
## [Type arguments, type argument vector](types.md#typearguments)
[debugging-asan]: https://github.com/dart-lang/sdk/tree/main/docs/Debugging-Dart-VM-with-AddressSanitizer.md

View File

@ -1,2 +1,2 @@
This directory contains tests of the language and core library implementations.
For more information, see https://github.com/dart-lang/sdk/wiki/Testing.
For more information, see https://github.com/dart-lang/sdk/tree/main/docs/Testing.md.