Repository: flutter
Issue: Dart SDK libraries and Flutter for web
Labels: framework,dependency: dart,customer: crowd,platform-web,P2,team: skip-test,team-web,triaged-web

### Background

An *unsupported library* is either missing an implementation in the platform's libraries.json file, or has an implementation where all members throw when called.

The only mechanism for conditionally including code is config-specific imports and exports. The mechanism for using these is the presence/absence of an *unsupported library

### Specific Issues

- `dart:io` provides a reasonable set of functionality that we currently rely on in the framework. Specifically, we use the `HttpClient` to make network requests, `Platform` to detect the initial non-overridden platform, and `File` to transfer bytes across certain compute boundaries, like `Isolates` and through `PlatformChannels`. See also https://github.com/flutter/flutter/issues/32220, https://github.com/flutter/flutter/issues/36281, https://github.com/dart-lang/sdk/issues/35969

- The existing dart4web tooling refuses to compile applications to the web that have an *unsupported library* in the transitive closure, including `dart:isolate` and `dart:io`. Under this restriction, almost no current flutter applications will compile to the web unless all dependencies are rewritten to use config specific imports. See also https://github.com/dart-lang/build/pull/2420.

 - The analyzer does not support having multiple analysis summaries. Thus either dart libraries that exist are displayed as missing, or dart libraries that are missing are displayed as existing. See also https://github.com/flutter/flutter/issues/35588

- The analyzer is not capable of analyzing code that uses config specific imports beyond the default import case. Because it does not analyze other paths, the user is responsible for verifying that the interfaces are used in a compatible way. For example, an API incompatibility that will not be detected until compile time:

a.dart
```
import 'b.dart'
  if (dart.library.io) 'c.dart'

void main() {
  bar(1); // No error
}
```

b.dart
```
void bar(int x) { }
```

c.dart
```
import 'dart:io';

void bar(String x) { }
```

- The analyzer is not capable of analyzing code that uses config specific exports beyond the default export case. Config specific exports are required if a type from an *unsupported library* is a part of a public API. For example, to include `File` in an interface conditionally:

a.dart
```
export 'b.dart'
  if (dart.library.io) 'c.dart'
```
b.dart
```
void foo(Object file) {}
```

c.dart
```
import 'dart:io';

void foo(File file) {}
```

This relies on the fact that it is always safe to substitute the two APIs, but the caller will not get any information about which implementation is used, or when to use it.

- Pub is not capable of distinguishing between a library that conditionally supports Web/Flutter/Flutter for Web/VM. Specifically see https://github.com/flutter/flutter/issues/35588#issuecomment-524373451

### Library Delta

Due to the additional inclusion of web specific libraries that we can't currently remove, the delta between a Flutter for Mobile/Desktop and Flutter for Web is currently quite large. The complexity is entirely placed on our users to deal with:

Library | Web | Mobile/Desktop
-- | -- | --
ui | ✔ | ✔
async | ✔ | ✔
core | ✔ | ✔
collection | ✔ | ✔
typed_data | ✔ | ✔
developer | ✔ | ✔
convert | ✔ | ✔
math | ✔ | ✔
wasm | x | ✔
ffi | x | ✔
io | x | ✔
isolate | x| ✔
js | ✔| x
js_util | ✔ | x
html | ✔ | x
web_audio | ✔ | x
web_gl | ✔ | x
indexed_db | ✔ | x
web_sql | ✔ | x
svg | ✔ | x
mirrors | x | x

The only way to write an app, plugin, or package that works across all platforms without heavy use of config specific imports/exports is to _only_ touch libraries supported on all platforms. However this represents a lowest common denominator strategy, which is against the core principals of flutter.

### Comparison to method/message channels

Flutter already deals with platform specific features using platform channels. An asynchronous message is sent to the platform side, where platform code *may* respond (for example, a camera), or it might go into the void. The application author can choose to ignore the error or make a requirement, but Flutter itself does not make that choice.

The introduction of the web and web libraries has put us in a situation where we are deciding for the application author.

### Problems with `dart:html`

Due to the highly dynamic nature of the browser DOM, any usage of `dart:html` will transitively pull in almost all of the dart core libraries. These libraries are also somewhat intertwined with the implementation of dart2js, the production JavaScript compiler. This adds additional code size to all flutter applications, even though the only use case may be within the web implementation of dart:ui. The only alternative would be to use JavaScript interop, but this again pulls in `dart:html` transitively.

`dart:html` is also generated from a chrome IDL and may not be accurate for a given browser/version. It is somewhat equivalent to a code generated `dart:android` or `dart:ios` library.

### Rock and a Hard Place

It seems as if we either need dramatically better support for the config specific import or other conditional compilation feature, or we need to standardize the set of dart SDK libraries (even if some methods are unimplemented).

cc @Hixie @tvolkert @goderbauer @ferhatb