Use conditional imports for flutter foundation libraries (#33663)
This commit is contained in:
parent
52fc807dd2
commit
90500a5dc4
@ -35,6 +35,7 @@ export 'src/foundation/annotations.dart';
|
|||||||
export 'src/foundation/assertions.dart';
|
export 'src/foundation/assertions.dart';
|
||||||
export 'src/foundation/basic_types.dart';
|
export 'src/foundation/basic_types.dart';
|
||||||
export 'src/foundation/binding.dart';
|
export 'src/foundation/binding.dart';
|
||||||
|
export 'src/foundation/bitfield.dart';
|
||||||
export 'src/foundation/change_notifier.dart';
|
export 'src/foundation/change_notifier.dart';
|
||||||
export 'src/foundation/collections.dart';
|
export 'src/foundation/collections.dart';
|
||||||
export 'src/foundation/consolidate_response.dart';
|
export 'src/foundation/consolidate_response.dart';
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:ui' show VoidCallback;
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:ui' show VoidCallback;
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:ui' show VoidCallback;
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'animation.dart';
|
import 'animation.dart';
|
||||||
|
48
packages/flutter/lib/src/foundation/_bitfield_io.dart
Normal file
48
packages/flutter/lib/src/foundation/_bitfield_io.dart
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -2,32 +2,34 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
/// Unsupported.
|
import 'bitfield.dart' as bitfield;
|
||||||
|
|
||||||
|
/// The dart:html implementation of [bitfield.kMaxUnsignedSMI].
|
||||||
const int kMaxUnsignedSMI = 0;
|
const int kMaxUnsignedSMI = 0;
|
||||||
|
|
||||||
/// Unsupported.
|
/// The dart:html implementation of [bitfield.Bitfield].
|
||||||
class BitField<T extends dynamic> {
|
class BitField<T extends dynamic> implements bitfield.BitField<T> {
|
||||||
/// Unsupported.
|
/// The dart:html implementation of [bitfield.Bitfield].
|
||||||
// Ignored so that both bitfield implementations have the same API.
|
// Can remove when we have metaclasses.
|
||||||
// ignore: avoid_unused_constructor_parameters
|
// ignore: avoid_unused_constructor_parameters
|
||||||
BitField(int length);
|
BitField(int length);
|
||||||
|
|
||||||
/// Unsupported.
|
/// The dart:html implementation of [bitfield.Bitfield.filled].
|
||||||
// Ignored so that both bitfield implementations have the same API.
|
// Can remove when we have metaclasses.
|
||||||
// ignore: avoid_unused_constructor_parameters
|
// ignore: avoid_unused_constructor_parameters
|
||||||
BitField.filled(int length, bool value);
|
BitField.filled(int length, bool value);
|
||||||
|
|
||||||
/// Unsupported.
|
@override
|
||||||
bool operator [](T index) {
|
bool operator [](T index) {
|
||||||
throw UnsupportedError('Not supported when compiling to JavaScript');
|
throw UnsupportedError('Not supported when compiling to JavaScript');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsupported.
|
@override
|
||||||
void operator []=(T index, bool value) {
|
void operator []=(T index, bool value) {
|
||||||
throw UnsupportedError('Not supported when compiling to JavaScript');
|
throw UnsupportedError('Not supported when compiling to JavaScript');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsupported.
|
@override
|
||||||
void reset([ bool value = false ]) {
|
void reset([ bool value = false ]) {
|
||||||
throw UnsupportedError('Not supported when compiling to JavaScript');
|
throw UnsupportedError('Not supported when compiling to JavaScript');
|
||||||
}
|
}
|
92
packages/flutter/lib/src/foundation/_isolates_io.dart
Normal file
92
packages/flutter/lib/src/foundation/_isolates_io.dart
Normal file
@ -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),
|
||||||
|
);
|
||||||
|
}
|
14
packages/flutter/lib/src/foundation/_isolates_web.dart
Normal file
14
packages/flutter/lib/src/foundation/_isolates_web.dart
Normal file
@ -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);
|
||||||
|
}
|
34
packages/flutter/lib/src/foundation/_platform_io.dart
Normal file
34
packages/flutter/lib/src/foundation/_platform_io.dart
Normal file
@ -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;
|
||||||
|
}
|
24
packages/flutter/lib/src/foundation/_platform_web.dart
Normal file
24
packages/flutter/lib/src/foundation/_platform_web.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Can remove once analyzer summary includes dart:html.
|
||||||
|
import 'dart:html' as html; // ignore: uri_does_not_exist
|
||||||
|
import 'platform.dart' as platform;
|
||||||
|
|
||||||
|
/// The dart:html implementation of [platform.defaultTargetPlatform].
|
||||||
|
platform.TargetPlatform get defaultTargetPlatform {
|
||||||
|
platform.TargetPlatform result;
|
||||||
|
// The existence of this method is tested via the dart2js compile test.
|
||||||
|
final String userAgent = html.window.navigator.userAgent;
|
||||||
|
if (userAgent.contains('iPhone')
|
||||||
|
|| userAgent.contains('iPad')
|
||||||
|
|| userAgent.contains('iPod')) {
|
||||||
|
result = platform.TargetPlatform.iOS;
|
||||||
|
} else {
|
||||||
|
result = platform.TargetPlatform.android;
|
||||||
|
}
|
||||||
|
if (platform.debugDefaultTargetPlatformOverride != null)
|
||||||
|
result = platform.debugDefaultTargetPlatformOverride;
|
||||||
|
return result;
|
||||||
|
}
|
@ -8,7 +8,6 @@ import 'dart:collection';
|
|||||||
// COMMON SIGNATURES
|
// COMMON SIGNATURES
|
||||||
|
|
||||||
export 'dart:ui' show VoidCallback;
|
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.
|
/// Signature for callbacks that report that an underlying value has changed.
|
||||||
///
|
///
|
||||||
|
@ -6,8 +6,8 @@ import 'dart:async';
|
|||||||
import 'dart:convert' show json;
|
import 'dart:convert' show json;
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'dart:io' show exit;
|
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;
|
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';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
@ -2,25 +2,26 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import '_bitfield_io.dart'
|
||||||
|
if (dart.library.html) '_bitfield_web.dart' as _bitfield;
|
||||||
|
|
||||||
/// The largest SMI value.
|
/// 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
|
/// When compiling to JavaScript, this value is not supported since it is
|
||||||
/// larger than the maximum safe 32bit integer.
|
/// 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").
|
/// 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.
|
/// Only the first 62 values of the enum can be used as indices.
|
||||||
///
|
///
|
||||||
/// When compiling to JavaScript, this class is not supported.
|
/// 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.
|
/// Creates a bit field of all zeros.
|
||||||
///
|
///
|
||||||
/// The given length must be at most 62.
|
/// The given length must be at most 62.
|
||||||
BitField(this._length)
|
factory BitField(int length) = _bitfield.BitField<T>;
|
||||||
: assert(_length <= _smiBits),
|
|
||||||
_bits = _allZeros;
|
|
||||||
|
|
||||||
/// Creates a bit field filled with a particular value.
|
/// Creates a bit field filled with a particular value.
|
||||||
///
|
///
|
||||||
@ -28,40 +29,20 @@ class BitField<T extends dynamic> {
|
|||||||
/// the bits are filled with zeros.
|
/// the bits are filled with zeros.
|
||||||
///
|
///
|
||||||
/// The given length must be at most 62.
|
/// The given length must be at most 62.
|
||||||
BitField.filled(this._length, bool value)
|
factory BitField.filled(int length, bool value) = _bitfield.BitField<T>.filled;
|
||||||
: 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
|
|
||||||
|
|
||||||
/// Returns whether the bit with the given index is set to one.
|
/// Returns whether the bit with the given index is set to one.
|
||||||
bool operator [](T index) {
|
bool operator [](T index);
|
||||||
assert(index.index < _length);
|
|
||||||
return (_bits & 1 << index.index) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the bit with the given index to the given value.
|
/// 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,
|
/// If value is true, the bit with the given index is set to one. Otherwise,
|
||||||
/// the bit is set to zero.
|
/// the bit is set to zero.
|
||||||
void operator []=(T index, bool value) {
|
void operator []=(T index, bool value);
|
||||||
assert(index.index < _length);
|
|
||||||
if (value)
|
|
||||||
_bits = _bits | (1 << index.index);
|
|
||||||
else
|
|
||||||
_bits = _bits & ~(1 << index.index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets all the bits to the given 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
|
/// 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.
|
/// all set to zero. Defaults to setting all the bits to zero.
|
||||||
void reset([ bool value = false ]) {
|
void reset([ bool value = false ]);
|
||||||
_bits = value ? _allOnes : _allZeros;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,9 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer' show Timeline, Flow;
|
|
||||||
import 'dart:isolate';
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import '_isolates_io.dart'
|
||||||
|
if (dart.library.html) '_isolates_web.dart' as _isolates;
|
||||||
import 'constants.dart';
|
|
||||||
|
|
||||||
/// Signature for the callback passed to [compute].
|
/// Signature for the callback passed to [compute].
|
||||||
///
|
///
|
||||||
@ -20,6 +17,9 @@ import 'constants.dart';
|
|||||||
/// {@macro flutter.foundation.compute.limitations}
|
/// {@macro flutter.foundation.compute.limitations}
|
||||||
typedef ComputeCallback<Q, R> = FutureOr<R> Function(Q message);
|
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
|
/// Spawn an isolate, run `callback` on that isolate, passing it `message`, and
|
||||||
/// (eventually) return the value returned by `callback`.
|
/// (eventually) return the value returned by `callback`.
|
||||||
///
|
///
|
||||||
@ -44,82 +44,6 @@ typedef ComputeCallback<Q, R> = FutureOr<R> Function(Q message);
|
|||||||
///
|
///
|
||||||
/// The `debugLabel` argument can be specified to provide a name to add to the
|
/// The `debugLabel` argument can be specified to provide a name to add to the
|
||||||
/// [Timeline]. This is useful when profiling an application.
|
/// [Timeline]. This is useful when profiling an application.
|
||||||
Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debugLabel }) async {
|
// Remove when https://github.com/dart-lang/sdk/issues/37149 is fixed.
|
||||||
if (!kReleaseMode) {
|
// ignore: prefer_const_declarations
|
||||||
debugLabel ??= callback.toString();
|
final _ComputeImpl compute = _isolates.compute;
|
||||||
}
|
|
||||||
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),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
@ -2,23 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:io' show Platform;
|
import '_platform_io.dart'
|
||||||
|
if (dart.library.html) '_platform_web.dart' as _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,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The [TargetPlatform] that matches the platform on which the framework is
|
/// The [TargetPlatform] that matches the platform on which the framework is
|
||||||
/// currently executing.
|
/// currently executing.
|
||||||
@ -48,36 +33,20 @@ enum TargetPlatform {
|
|||||||
// that would mean we'd be stuck with that platform forever emulating the other,
|
// 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
|
// and we'd never be able to introduce dedicated behavior for that platform
|
||||||
// (since doing so would be a big breaking change).
|
// (since doing so would be a big breaking change).
|
||||||
TargetPlatform get defaultTargetPlatform {
|
TargetPlatform get defaultTargetPlatform => _platform.defaultTargetPlatform;
|
||||||
// TODO(jonahwilliams): consider where this constant should live.
|
|
||||||
const bool kIsWeb = identical(1, 1.0);
|
/// The platform that user interaction should adapt to target.
|
||||||
TargetPlatform result;
|
///
|
||||||
if (kIsWeb) {
|
/// The [defaultTargetPlatform] getter returns the current platform.
|
||||||
result = TargetPlatform.android;
|
enum TargetPlatform {
|
||||||
} else {
|
/// Android: <https://www.android.com/>
|
||||||
if (Platform.isIOS) {
|
android,
|
||||||
result = TargetPlatform.iOS;
|
|
||||||
} else if (Platform.isAndroid) {
|
/// Fuchsia: <https://fuchsia.googlesource.com/>
|
||||||
result = TargetPlatform.android;
|
fuchsia,
|
||||||
} else if (Platform.isFuchsia) {
|
|
||||||
result = TargetPlatform.fuchsia;
|
/// iOS: <http://www.apple.com/ios/>
|
||||||
}
|
iOS,
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Override the [defaultTargetPlatform].
|
/// Override the [defaultTargetPlatform].
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:ui' show VoidCallback;
|
import 'basic_types.dart';
|
||||||
|
|
||||||
import 'constants.dart';
|
import 'constants.dart';
|
||||||
|
|
||||||
/// DEPRECATED. `function` cannot be treeshaken out of release builds.
|
/// DEPRECATED. `function` cannot be treeshaken out of release builds.
|
||||||
|
@ -41,10 +41,11 @@ export 'dart:ui' show
|
|||||||
TextPosition,
|
TextPosition,
|
||||||
TileMode,
|
TileMode,
|
||||||
VertexMode,
|
VertexMode,
|
||||||
VoidCallback,
|
|
||||||
hashValues,
|
hashValues,
|
||||||
hashList;
|
hashList;
|
||||||
|
|
||||||
|
export 'package:flutter/foundation.dart' show VoidCallback;
|
||||||
|
|
||||||
// Intentionally not exported:
|
// Intentionally not exported:
|
||||||
// - Image, instantiateImageCodec, decodeImageFromList:
|
// - Image, instantiateImageCodec, decodeImageFromList:
|
||||||
// We use ui.* to make it very explicit that these are low-level image APIs.
|
// We use ui.* to make it very explicit that these are low-level image APIs.
|
||||||
|
@ -9,7 +9,6 @@ import 'package:flutter/animation.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
|
||||||
import 'package:flutter/semantics.dart';
|
import 'package:flutter/semantics.dart';
|
||||||
import 'package:vector_math/vector_math_64.dart';
|
import 'package:vector_math/vector_math_64.dart';
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import 'dart:async';
|
|||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/physics.dart';
|
import 'package:flutter/physics.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
|
||||||
|
|
||||||
import 'basic.dart';
|
import 'basic.dart';
|
||||||
import 'framework.dart';
|
import 'framework.dart';
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:ui' show VoidCallback;
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
List<String> captureOutput(VoidCallback fn) {
|
List<String> captureOutput(VoidCallback fn) {
|
||||||
final List<String> log = <String>[];
|
final List<String> log = <String>[];
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user