Reland https://github.com/flutter/flutter/pull/33663 (#33828)

diff --git a/packages/flutter/lib/foundation.dart b/packages/flutter/lib/foundation.dart
index f2e6791..725efc2 100644
--- a/packages/flutter/lib/foundation.dart
+++ b/packages/flutter/lib/foundation.dart
@@ -35,6 +35,7 @@
 export 'src/foundation/assertions.dart';
 export 'src/foundation/basic_types.dart';
 export 'src/foundation/binding.dart';
+export 'src/foundation/bitfield.dart';
 export 'src/foundation/change_notifier.dart';
 export 'src/foundation/collections.dart';
 export 'src/foundation/consolidate_response.dart';
diff --git a/packages/flutter/lib/src/animation/animation.dart b/packages/flutter/lib/src/animation/animation.dart
index 8522785..3a6bd0a 100644
--- a/packages/flutter/lib/src/animation/animation.dart
+++ b/packages/flutter/lib/src/animation/animation.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:ui' show VoidCallback;
 
 import 'package:flutter/foundation.dart';
 
diff --git a/packages/flutter/lib/src/animation/animations.dart b/packages/flutter/lib/src/animation/animations.dart
index 80cc60e..4f0dc26 100644
--- a/packages/flutter/lib/src/animation/animations.dart
+++ b/packages/flutter/lib/src/animation/animations.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'dart:math' as math;
-import 'dart:ui' show VoidCallback;
 
 import 'package:flutter/foundation.dart';
 
diff --git a/packages/flutter/lib/src/animation/listener_helpers.dart b/packages/flutter/lib/src/animation/listener_helpers.dart
index 2236ac5..d2f8785 100644
--- a/packages/flutter/lib/src/animation/listener_helpers.dart
+++ b/packages/flutter/lib/src/animation/listener_helpers.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:ui' show VoidCallback;
-
 import 'package:flutter/foundation.dart';
 
 import 'animation.dart';
diff --git a/packages/flutter/lib/src/foundation/_bitfield_io.dart b/packages/flutter/lib/src/foundation/_bitfield_io.dart
new file mode 100644
index 0000000..f1205e5
--- /dev/null
+++ b/packages/flutter/lib/src/foundation/_bitfield_io.dart
@@ -0,0 +1,48 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'bitfield.dart' as bitfield;
+
+/// The dart:io implementation of [bitfield.kMaxUnsignedSMI].
+const int kMaxUnsignedSMI = 0x3FFFFFFFFFFFFFFF;
+
+/// The dart:io implementation of [bitfield.Bitfield].
+class BitField<T extends dynamic> implements bitfield.BitField<T> {
+  /// The dart:io implementation of [bitfield.Bitfield()].
+  BitField(this._length)
+    : assert(_length <= _smiBits),
+      _bits = _allZeros;
+
+  /// The dart:io implementation of [bitfield.Bitfield.filled].
+  BitField.filled(this._length, bool value)
+    : assert(_length <= _smiBits),
+      _bits = value ? _allOnes : _allZeros;
+
+  final int _length;
+  int _bits;
+
+  static const int _smiBits = 62; // see https://www.dartlang.org/articles/numeric-computation/#smis-and-mints
+  static const int _allZeros = 0;
+  static const int _allOnes = kMaxUnsignedSMI; // 2^(_kSMIBits+1)-1
+
+  @override
+  bool operator [](T index) {
+    assert(index.index < _length);
+    return (_bits & 1 << index.index) > 0;
+  }
+
+  @override
+  void operator []=(T index, bool value) {
+    assert(index.index < _length);
+    if (value)
+      _bits = _bits | (1 << index.index);
+    else
+      _bits = _bits & ~(1 << index.index);
+  }
+
+  @override
+  void reset([ bool value = false ]) {
+    _bits = value ? _allOnes : _allZeros;
+  }
+}
diff --git a/packages/flutter/lib/src/foundation/bitfield_unsupported.dart b/packages/flutter/lib/src/foundation/_bitfield_web.dart
similarity index 60%
rename from packages/flutter/lib/src/foundation/bitfield_unsupported.dart
rename to packages/flutter/lib/src/foundation/_bitfield_web.dart
index c7baf47..2fa843a 100644
--- a/packages/flutter/lib/src/foundation/bitfield_unsupported.dart
+++ b/packages/flutter/lib/src/foundation/_bitfield_web.dart
@@ -2,32 +2,34 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/// Unsupported.
+import 'bitfield.dart' as bitfield;
+
+/// The dart:html implementation of [bitfield.kMaxUnsignedSMI].
 const int kMaxUnsignedSMI = 0;
 
-/// Unsupported.
-class BitField<T extends dynamic> {
-  /// Unsupported.
-  // Ignored so that both bitfield implementations have the same API.
+/// The dart:html implementation of [bitfield.Bitfield].
+class BitField<T extends dynamic> implements bitfield.BitField<T> {
+  /// The dart:html implementation of [bitfield.Bitfield].
+  // Can remove when we have metaclasses.
   // ignore: avoid_unused_constructor_parameters
   BitField(int length);
 
-  /// Unsupported.
-  // Ignored so that both bitfield implementations have the same API.
+  /// The dart:html implementation of [bitfield.Bitfield.filled].
+  // Can remove when we have metaclasses.
   // ignore: avoid_unused_constructor_parameters
   BitField.filled(int length, bool value);
 
-  /// Unsupported.
+  @override
   bool operator [](T index) {
     throw UnsupportedError('Not supported when compiling to JavaScript');
   }
 
-  /// Unsupported.
+  @override
   void operator []=(T index, bool value) {
     throw UnsupportedError('Not supported when compiling to JavaScript');
   }
 
-  /// Unsupported.
+  @override
   void reset([ bool value = false ]) {
     throw UnsupportedError('Not supported when compiling to JavaScript');
   }
diff --git a/packages/flutter/lib/src/foundation/_isolates_io.dart b/packages/flutter/lib/src/foundation/_isolates_io.dart
new file mode 100644
index 0000000..be2a418
--- /dev/null
+++ b/packages/flutter/lib/src/foundation/_isolates_io.dart
@@ -0,0 +1,92 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate';
+import 'package:meta/meta.dart';
+
+import 'constants.dart';
+import 'isolates.dart' as isolates;
+
+/// The dart:io implementation of [isolate.compute].
+Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, { String debugLabel }) async {
+  if (!kReleaseMode) {
+    debugLabel ??= callback.toString();
+  }
+  final Flow flow = Flow.begin();
+  Timeline.startSync('$debugLabel: start', flow: flow);
+  final ReceivePort resultPort = ReceivePort();
+  final ReceivePort errorPort = ReceivePort();
+  Timeline.finishSync();
+  final Isolate isolate = await Isolate.spawn<_IsolateConfiguration<Q, FutureOr<R>>>(
+    _spawn,
+    _IsolateConfiguration<Q, FutureOr<R>>(
+      callback,
+      message,
+      resultPort.sendPort,
+      debugLabel,
+      flow.id,
+    ),
+    errorsAreFatal: true,
+    onExit: resultPort.sendPort,
+    onError: errorPort.sendPort,
+  );
+  final Completer<R> result = Completer<R>();
+  errorPort.listen((dynamic errorData) {
+    assert(errorData is List<dynamic>);
+    assert(errorData.length == 2);
+    final Exception exception = Exception(errorData[0]);
+    final StackTrace stack = StackTrace.fromString(errorData[1]);
+    if (result.isCompleted) {
+      Zone.current.handleUncaughtError(exception, stack);
+    } else {
+      result.completeError(exception, stack);
+    }
+  });
+  resultPort.listen((dynamic resultData) {
+    assert(resultData == null || resultData is R);
+    if (!result.isCompleted)
+      result.complete(resultData);
+  });
+  await result.future;
+  Timeline.startSync('$debugLabel: end', flow: Flow.end(flow.id));
+  resultPort.close();
+  errorPort.close();
+  isolate.kill();
+  Timeline.finishSync();
+  return result.future;
+}
+
+@immutable
+class _IsolateConfiguration<Q, R> {
+  const _IsolateConfiguration(
+    this.callback,
+    this.message,
+    this.resultPort,
+    this.debugLabel,
+    this.flowId,
+  );
+  final isolates.ComputeCallback<Q, R> callback;
+  final Q message;
+  final SendPort resultPort;
+  final String debugLabel;
+  final int flowId;
+
+  R apply() => callback(message);
+}
+
+Future<void> _spawn<Q, R>(_IsolateConfiguration<Q, FutureOr<R>> configuration) async {
+  R result;
+  await Timeline.timeSync(
+    '${configuration.debugLabel}',
+    () async { result = await configuration.apply(); },
+    flow: Flow.step(configuration.flowId),
+  );
+  Timeline.timeSync(
+    '${configuration.debugLabel}: returning result',
+    () { configuration.resultPort.send(result); },
+    flow: Flow.step(configuration.flowId),
+  );
+}
diff --git a/packages/flutter/lib/src/foundation/_isolates_web.dart b/packages/flutter/lib/src/foundation/_isolates_web.dart
new file mode 100644
index 0000000..00f249f
--- /dev/null
+++ b/packages/flutter/lib/src/foundation/_isolates_web.dart
@@ -0,0 +1,14 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'isolates.dart' as isolates;
+
+/// The dart:html implementation of [isolate.compute].
+Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, { String debugLabel }) async {
+  // To avoid blocking the UI immediately for an expensive function call, we
+  // pump a single frame to allow the framework to complete the current set
+  // of work.
+  await null;
+  return callback(message);
+}
diff --git a/packages/flutter/lib/src/foundation/_platform_io.dart b/packages/flutter/lib/src/foundation/_platform_io.dart
new file mode 100644
index 0000000..7726331
--- /dev/null
+++ b/packages/flutter/lib/src/foundation/_platform_io.dart
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:io';
+import 'assertions.dart';
+import 'platform.dart' as platform;
+
+/// The dart:io implementation of [platform.defaultTargetPlatform].
+platform.TargetPlatform get defaultTargetPlatform {
+  platform.TargetPlatform result;
+  if (Platform.isIOS) {
+    result = platform.TargetPlatform.iOS;
+  } else if (Platform.isAndroid) {
+    result = platform.TargetPlatform.android;
+  } else if (Platform.isFuchsia) {
+    result = platform.TargetPlatform.fuchsia;
+  }
+  assert(() {
+    if (Platform.environment.containsKey('FLUTTER_TEST'))
+      result = platform.TargetPlatform.android;
+    return true;
+  }());
+  if (platform.debugDefaultTargetPlatformOverride != null)
+    result = platform.debugDefaultTargetPlatformOverride;
+  if (result == null) {
+    throw FlutterError(
+      'Unknown platform.\n'
+      '${Platform.operatingSystem} was not recognized as a target platform. '
+      'Consider updating the list of TargetPlatforms to include this platform.'
+    );
+  }
+  return result;
+}
diff --git a/packages/flutter/lib/src/foundation/_platform_web.dart b/packages/flutter/lib/src/foundation/_platform_web.dart
new file mode 100644
index 0000000..c020d36
--- /dev/null
+++ b/packages/flutter/lib/src/foundation/_platform_web.dart
@@ -0,0 +1,16 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'platform.dart' as platform;
+
+/// The dart:html implementation of [platform.defaultTargetPlatform].
+platform.TargetPlatform get defaultTargetPlatform {
+  // To getter a better guess at the targetPlatform we need to be able to
+  // reference the window, but that won't be availible until we fix the
+  // platforms configuration for Flutter.
+  platform.TargetPlatform result = platform.TargetPlatform.android;
+  if (platform.debugDefaultTargetPlatformOverride != null)
+    result = platform.debugDefaultTargetPlatformOverride;
+  return result;
+}
diff --git a/packages/flutter/lib/src/foundation/basic_types.dart b/packages/flutter/lib/src/foundation/basic_types.dart
index 4713cc4..7760dd1 100644
--- a/packages/flutter/lib/src/foundation/basic_types.dart
+++ b/packages/flutter/lib/src/foundation/basic_types.dart
@@ -8,7 +8,6 @@
 // COMMON SIGNATURES
 
 export 'dart:ui' show VoidCallback;
-export 'bitfield.dart' if (dart.library.html) 'bitfield_unsupported.dart';
 
 /// Signature for callbacks that report that an underlying value has changed.
 ///
diff --git a/packages/flutter/lib/src/foundation/binding.dart b/packages/flutter/lib/src/foundation/binding.dart
index a5e9f6e..5ab2145 100644
--- a/packages/flutter/lib/src/foundation/binding.dart
+++ b/packages/flutter/lib/src/foundation/binding.dart
@@ -6,8 +6,8 @@
 import 'dart:convert' show json;
 import 'dart:developer' as developer;
 import 'dart:io' show exit;
-// Before adding any more dart:ui imports, pleaes read the README.
 import 'dart:ui' as ui show saveCompilationTrace, Window, window;
+// Before adding any more dart:ui imports, please read the README.
 
 import 'package:meta/meta.dart';
 
diff --git a/packages/flutter/lib/src/foundation/bitfield.dart b/packages/flutter/lib/src/foundation/bitfield.dart
index b4b3b11..8ca3829 100644
--- a/packages/flutter/lib/src/foundation/bitfield.dart
+++ b/packages/flutter/lib/src/foundation/bitfield.dart
@@ -2,25 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import '_bitfield_io.dart'
+  if (dart.library.html) '_bitfield_web.dart' as _bitfield;
+
 /// The largest SMI value.
 ///
-/// See <https://dart.dev/articles/numeric-computation/#smis-and-mints>
+/// See <https://www.dartlang.org/articles/numeric-computation/#smis-and-mints>
 ///
 /// When compiling to JavaScript, this value is not supported since it is
 /// larger than the maximum safe 32bit integer.
-const int kMaxUnsignedSMI = 0x3FFFFFFFFFFFFFFF;
+const int kMaxUnsignedSMI = _bitfield.kMaxUnsignedSMI;
 
 /// A BitField over an enum (or other class whose values implement "index").
 /// Only the first 62 values of the enum can be used as indices.
 ///
 /// When compiling to JavaScript, this class is not supported.
-class BitField<T extends dynamic> {
+abstract class BitField<T extends dynamic> {
   /// Creates a bit field of all zeros.
   ///
   /// The given length must be at most 62.
-  BitField(this._length)
-    : assert(_length <= _smiBits),
-      _bits = _allZeros;
+  factory BitField(int length) = _bitfield.BitField<T>;
 
   /// Creates a bit field filled with a particular value.
   ///
@@ -28,40 +29,20 @@
   /// the bits are filled with zeros.
   ///
   /// The given length must be at most 62.
-  BitField.filled(this._length, bool value)
-    : assert(_length <= _smiBits),
-      _bits = value ? _allOnes : _allZeros;
-
-  final int _length;
-  int _bits;
-
-  static const int _smiBits = 62; // see https://dart.dev/articles/numeric-computation/#smis-and-mints
-  static const int _allZeros = 0;
-  static const int _allOnes = kMaxUnsignedSMI; // 2^(_kSMIBits+1)-1
+  factory BitField.filled(int length, bool value) = _bitfield.BitField<T>.filled;
 
   /// Returns whether the bit with the given index is set to one.
-  bool operator [](T index) {
-    assert(index.index < _length);
-    return (_bits & 1 << index.index) > 0;
-  }
+  bool operator [](T index);
 
   /// Sets the bit with the given index to the given value.
   ///
   /// If value is true, the bit with the given index is set to one. Otherwise,
   /// the bit is set to zero.
-  void operator []=(T index, bool value) {
-    assert(index.index < _length);
-    if (value)
-      _bits = _bits | (1 << index.index);
-    else
-      _bits = _bits & ~(1 << index.index);
-  }
+  void operator []=(T index, bool value);
 
   /// Sets all the bits to the given value.
   ///
   /// If the value is true, the bits are all set to one. Otherwise, the bits are
   /// all set to zero. Defaults to setting all the bits to zero.
-  void reset([ bool value = false ]) {
-    _bits = value ? _allOnes : _allZeros;
-  }
+  void reset([ bool value = false ]);
 }
diff --git a/packages/flutter/lib/src/foundation/isolates.dart b/packages/flutter/lib/src/foundation/isolates.dart
index 8afeb86..d0f2d3c 100644
--- a/packages/flutter/lib/src/foundation/isolates.dart
+++ b/packages/flutter/lib/src/foundation/isolates.dart
@@ -3,12 +3,9 @@
 // found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:developer' show Timeline, Flow;
-import 'dart:isolate';
 
-import 'package:meta/meta.dart';
-
-import 'constants.dart';
+import '_isolates_io.dart'
+  if (dart.library.html) '_isolates_web.dart' as _isolates;
 
 /// Signature for the callback passed to [compute].
 ///
@@ -20,6 +17,9 @@
 /// {@macro flutter.foundation.compute.limitations}
 typedef ComputeCallback<Q, R> = FutureOr<R> Function(Q message);
 
+// The signature of [compute].
+typedef _ComputeImpl = Future<R> Function<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debugLabel });
+
 /// Spawn an isolate, run `callback` on that isolate, passing it `message`, and
 /// (eventually) return the value returned by `callback`.
 ///
@@ -44,82 +44,6 @@
 ///
 /// The `debugLabel` argument can be specified to provide a name to add to the
 /// [Timeline]. This is useful when profiling an application.
-Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debugLabel }) async {
-  if (!kReleaseMode) {
-    debugLabel ??= callback.toString();
-  }
-  final Flow flow = Flow.begin();
-  Timeline.startSync('$debugLabel: start', flow: flow);
-  final ReceivePort resultPort = ReceivePort();
-  final ReceivePort errorPort = ReceivePort();
-  Timeline.finishSync();
-  final Isolate isolate = await Isolate.spawn<_IsolateConfiguration<Q, FutureOr<R>>>(
-    _spawn,
-    _IsolateConfiguration<Q, FutureOr<R>>(
-      callback,
-      message,
-      resultPort.sendPort,
-      debugLabel,
-      flow.id,
-    ),
-    errorsAreFatal: true,
-    onExit: resultPort.sendPort,
-    onError: errorPort.sendPort,
-  );
-  final Completer<R> result = Completer<R>();
-  errorPort.listen((dynamic errorData) {
-    assert(errorData is List<dynamic>);
-    assert(errorData.length == 2);
-    final Exception exception = Exception(errorData[0]);
-    final StackTrace stack = StackTrace.fromString(errorData[1]);
-    if (result.isCompleted) {
-      Zone.current.handleUncaughtError(exception, stack);
-    } else {
-      result.completeError(exception, stack);
-    }
-  });
-  resultPort.listen((dynamic resultData) {
-    assert(resultData == null || resultData is R);
-    if (!result.isCompleted)
-      result.complete(resultData);
-  });
-  await result.future;
-  Timeline.startSync('$debugLabel: end', flow: Flow.end(flow.id));
-  resultPort.close();
-  errorPort.close();
-  isolate.kill();
-  Timeline.finishSync();
-  return result.future;
-}
-
-@immutable
-class _IsolateConfiguration<Q, R> {
-  const _IsolateConfiguration(
-    this.callback,
-    this.message,
-    this.resultPort,
-    this.debugLabel,
-    this.flowId,
-  );
-  final ComputeCallback<Q, R> callback;
-  final Q message;
-  final SendPort resultPort;
-  final String debugLabel;
-  final int flowId;
-
-  R apply() => callback(message);
-}
-
-Future<void> _spawn<Q, R>(_IsolateConfiguration<Q, FutureOr<R>> configuration) async {
-  R result;
-  await Timeline.timeSync(
-    '${configuration.debugLabel}',
-    () async { result = await configuration.apply(); },
-    flow: Flow.step(configuration.flowId),
-  );
-  Timeline.timeSync(
-    '${configuration.debugLabel}: returning result',
-    () { configuration.resultPort.send(result); },
-    flow: Flow.step(configuration.flowId),
-  );
-}
+// Remove when https://github.com/dart-lang/sdk/issues/37149 is fixed.
+// ignore: prefer_const_declarations
+final _ComputeImpl compute = _isolates.compute;
diff --git a/packages/flutter/lib/src/foundation/platform.dart b/packages/flutter/lib/src/foundation/platform.dart
index aaf6529..90b618a 100644
--- a/packages/flutter/lib/src/foundation/platform.dart
+++ b/packages/flutter/lib/src/foundation/platform.dart
@@ -2,23 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' show Platform;
-
-import 'assertions.dart';
-
-/// The platform that user interaction should adapt to target.
-///
-/// The [defaultTargetPlatform] getter returns the current platform.
-enum TargetPlatform {
-  /// Android: <https://www.android.com/>
-  android,
-
-  /// Fuchsia: <https://fuchsia.googlesource.com/>
-  fuchsia,
-
-  /// iOS: <http://www.apple.com/ios/>
-  iOS,
-}
+import '_platform_io.dart'
+  if (dart.library.html) '_platform_web.dart' as _platform;
 
 /// The [TargetPlatform] that matches the platform on which the framework is
 /// currently executing.
@@ -48,36 +33,20 @@
 // that would mean we'd be stuck with that platform forever emulating the other,
 // and we'd never be able to introduce dedicated behavior for that platform
 // (since doing so would be a big breaking change).
-TargetPlatform get defaultTargetPlatform {
-  // TODO(jonahwilliams): consider where this constant should live.
-  const bool kIsWeb = identical(1, 1.0);
-  TargetPlatform result;
-  if (kIsWeb) {
-    result = TargetPlatform.android;
-  } else {
-    if (Platform.isIOS) {
-      result = TargetPlatform.iOS;
-    } else if (Platform.isAndroid) {
-      result = TargetPlatform.android;
-    } else if (Platform.isFuchsia) {
-      result = TargetPlatform.fuchsia;
-    }
-  }
-  assert(() {
-    if (!kIsWeb && Platform.environment.containsKey('FLUTTER_TEST'))
-      result = TargetPlatform.android;
-    return true;
-  }());
-  if (debugDefaultTargetPlatformOverride != null)
-    result = debugDefaultTargetPlatformOverride;
-  if (result == null) {
-    throw FlutterError(
-      'Unknown platform.\n'
-      '${Platform.operatingSystem} was not recognized as a target platform. '
-      'Consider updating the list of TargetPlatforms to include this platform.'
-    );
-  }
-  return result;
+TargetPlatform get defaultTargetPlatform => _platform.defaultTargetPlatform;
+
+/// The platform that user interaction should adapt to target.
+///
+/// The [defaultTargetPlatform] getter returns the current platform.
+enum TargetPlatform {
+  /// Android: <https://www.android.com/>
+  android,
+
+  /// Fuchsia: <https://fuchsia.googlesource.com/>
+  fuchsia,
+
+  /// iOS: <http://www.apple.com/ios/>
+  iOS,
 }
 
 /// Override the [defaultTargetPlatform].
diff --git a/packages/flutter/lib/src/foundation/profile.dart b/packages/flutter/lib/src/foundation/profile.dart
index d1d5ff2..f063c74 100644
--- a/packages/flutter/lib/src/foundation/profile.dart
+++ b/packages/flutter/lib/src/foundation/profile.dart
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:ui' show VoidCallback;
-
+import 'basic_types.dart';
 import 'constants.dart';
 
 /// DEPRECATED. `function` cannot be treeshaken out of release builds.
diff --git a/packages/flutter/lib/src/painting/basic_types.dart b/packages/flutter/lib/src/painting/basic_types.dart
index 0a1af23..7815f34 100644
--- a/packages/flutter/lib/src/painting/basic_types.dart
+++ b/packages/flutter/lib/src/painting/basic_types.dart
@@ -41,10 +41,11 @@
   TextPosition,
   TileMode,
   VertexMode,
-  VoidCallback,
   hashValues,
   hashList;
 
+export 'package:flutter/foundation.dart' show VoidCallback;
+
 // Intentionally not exported:
 //  - Image, instantiateImageCodec, decodeImageFromList:
 //      We use ui.* to make it very explicit that these are low-level image APIs.
diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart
index 733db60..a8b674b 100644
--- a/packages/flutter/lib/src/rendering/object.dart
+++ b/packages/flutter/lib/src/rendering/object.dart
@@ -9,7 +9,6 @@
 import 'package:flutter/foundation.dart';
 import 'package:flutter/gestures.dart';
 import 'package:flutter/painting.dart';
-import 'package:flutter/scheduler.dart';
 import 'package:flutter/semantics.dart';
 import 'package:vector_math/vector_math_64.dart';
 
diff --git a/packages/flutter/lib/src/widgets/scroll_position_with_single_context.dart b/packages/flutter/lib/src/widgets/scroll_position_with_single_context.dart
index 6c39b2b..7fc59bd 100644
--- a/packages/flutter/lib/src/widgets/scroll_position_with_single_context.dart
+++ b/packages/flutter/lib/src/widgets/scroll_position_with_single_context.dart
@@ -7,7 +7,6 @@
 import 'package:flutter/gestures.dart';
 import 'package:flutter/physics.dart';
 import 'package:flutter/rendering.dart';
-import 'package:flutter/scheduler.dart';
 
 import 'basic.dart';
 import 'framework.dart';
diff --git a/packages/flutter/test/foundation/capture_output.dart b/packages/flutter/test/foundation/capture_output.dart
index 8bd3bef..63fb5f4 100644
--- a/packages/flutter/test/foundation/capture_output.dart
+++ b/packages/flutter/test/foundation/capture_output.dart
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:ui' show VoidCallback;
+import 'package:flutter/foundation.dart';
 
 List<String> captureOutput(VoidCallback fn) {
   final List<String> log = <String>[];
diff --git a/packages/flutter/test/material/feedback_test.dart b/packages/flutter/test/material/feedback_test.dart
index 603ed2c..d35b421 100644
--- a/packages/flutter/test/material/feedback_test.dart
+++ b/packages/flutter/test/material/feedback_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:ui';
-
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';