Skip to content

[breaking change] Remove dart:cli waitFor experiment #52121

Closed
@mraleph

Description

@mraleph

Change Intent

waitFor contradicts Dart's event-loop model in a way that no other old or new feature does: it allows async and synchronous code to interleave. The feature has been marked experimental since the beginning and effectively has only two users: sass and dcli package. It is not available in Flutter or on the Web because dart:cli library is not exposed there.

See discussion on #39390 for context.

Justification

We would like to reduce VM's technical debt by removing this experimental functionality, which we believe was added hastily and without due thought to the consequences.

We also have some indications (based on some internal code which has been migrated from waitFor) that availability of waitFor encourages ineffecient and convoluted coding patterns.

If you compare waitFor with Finalizer (which was added in 2.17) you will observe that we choose to make Finalizer less powerful by specifying that finalizers are only invoked at the turn of the event loop for the sake of maintaining semantic purity around interleaving of synchronous code.

Impact

Current users (which basically amounts to dcli and sass) will have to migrate off waitFor which will require them to rewrite their code.

Mitigation

Based on our analysis of dcli and sass multiple migration strategies are available:

  • The usage of asynchronous dart:io methods can be replaced with synchronous counterparts, eliminating the need for waitFor;
  • Asynchronous code can be moved to a helper isolate which communicates with the main isolate through synchronous communication channel built on top of low-level dart:ffi primitives;
  • Synchronous code be rewritten to become asynchronous, following Dart's canonical style for writing such code.

Note that it is an explicit non-goal to provide a completely equivalent replacement for waitFor, because we believe the feature itself is incompatible with how Dart's async is designed and should be removed.

Synchronous communication over dart:ffi

This code demonstrates how dart:ffi can be used to establish an entirely synchronous communication channel between the main (dispatcher) isolate and a worker isolate. This type of communication channel should cover sass needs.

To make migration simpler we will provide a portable synchronization package which implements mutexes and conditional variables, though we leave implementation of cross-isolate communication channels to the developers.

Isolate.resolvePackageUri

Some minor users of waitFor use it to synchronously unwrap Future returned from Isolate.resolvePackageUri API. In reality the underlying implementation of Isolate.resolvePackageUri is entirely synchronous.

While there is migration path for this code using dart:ffi and isolates we can simplify things by directly exposing Isolate.resolvePackageUriSync(...) and deprecating async version of this API.

Timeline

The removal will follow this timeline:

  • Dart 2.15: The waitForfeature was marked deprecated
  • Dart 3.0: We announce the upcoming removal, offering ~1 year migration timeline
  • Dart 3.3: waitFor is now disabled by default, but can be temporarily enabled by passing the flag --enable_deprecated_wait_for to the VM / dart command
  • Dart 3.4: We'll fully remove waitFor and there will be no way of enabling it

Metadata

Metadata

Assignees

Labels

area-core-librarySDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries.breaking-change-approvedbreaking-change-requestThis tracks requests for feedback on breaking changes

Type

No type

Projects

Status

Complete

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions