Unverified Commit a0248ebd authored by Pierre-Louis's avatar Pierre-Louis Committed by GitHub

Use `curly_braces_in_flow_control_structures` for `services`, `scheduler`, `semantics` (#104616)

parent e71eb183
...@@ -25,8 +25,9 @@ double _timeDilation = 1.0; ...@@ -25,8 +25,9 @@ double _timeDilation = 1.0;
/// It is safe to set this before initializing the binding. /// It is safe to set this before initializing the binding.
set timeDilation(double value) { set timeDilation(double value) {
assert(value > 0.0); assert(value > 0.0);
if (_timeDilation == value) if (_timeDilation == value) {
return; return;
}
// If the binding has been created, we need to resetEpoch first so that we // If the binding has been created, we need to resetEpoch first so that we
// capture start of the epoch with the current time dilation. // capture start of the epoch with the current time dilation.
SchedulerBinding._instance?.resetEpoch(); SchedulerBinding._instance?.resetEpoch();
...@@ -409,16 +410,18 @@ mixin SchedulerBinding on BindingBase { ...@@ -409,16 +410,18 @@ mixin SchedulerBinding on BindingBase {
flow, flow,
); );
_taskQueue.add(entry); _taskQueue.add(entry);
if (isFirstTask && !locked) if (isFirstTask && !locked) {
_ensureEventLoopCallback(); _ensureEventLoopCallback();
}
return entry.completer.future; return entry.completer.future;
} }
@override @override
void unlocked() { void unlocked() {
super.unlocked(); super.unlocked();
if (_taskQueue.isNotEmpty) if (_taskQueue.isNotEmpty) {
_ensureEventLoopCallback(); _ensureEventLoopCallback();
}
} }
// Whether this scheduler already requested to be called from the event loop. // Whether this scheduler already requested to be called from the event loop.
...@@ -429,8 +432,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -429,8 +432,9 @@ mixin SchedulerBinding on BindingBase {
void _ensureEventLoopCallback() { void _ensureEventLoopCallback() {
assert(!locked); assert(!locked);
assert(_taskQueue.isNotEmpty); assert(_taskQueue.isNotEmpty);
if (_hasRequestedAnEventLoopCallback) if (_hasRequestedAnEventLoopCallback) {
return; return;
}
_hasRequestedAnEventLoopCallback = true; _hasRequestedAnEventLoopCallback = true;
Timer.run(_runTasks); Timer.run(_runTasks);
} }
...@@ -438,8 +442,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -438,8 +442,9 @@ mixin SchedulerBinding on BindingBase {
// Scheduled by _ensureEventLoopCallback. // Scheduled by _ensureEventLoopCallback.
void _runTasks() { void _runTasks() {
_hasRequestedAnEventLoopCallback = false; _hasRequestedAnEventLoopCallback = false;
if (handleEventLoopCallback()) if (handleEventLoopCallback()) {
_ensureEventLoopCallback(); // runs next task when there's time _ensureEventLoopCallback();
} // runs next task when there's time
} }
/// Execute the highest-priority task, if it is of a high enough priority. /// Execute the highest-priority task, if it is of a high enough priority.
...@@ -455,8 +460,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -455,8 +460,9 @@ mixin SchedulerBinding on BindingBase {
@visibleForTesting @visibleForTesting
@pragma('vm:notify-debugger-on-exception') @pragma('vm:notify-debugger-on-exception')
bool handleEventLoopCallback() { bool handleEventLoopCallback() {
if (_taskQueue.isEmpty || locked) if (_taskQueue.isEmpty || locked) {
return false; return false;
}
final _TaskEntry<dynamic> entry = _taskQueue.first; final _TaskEntry<dynamic> entry = _taskQueue.first;
if (schedulingStrategy(priority: entry.priority, scheduler: this)) { if (schedulingStrategy(priority: entry.priority, scheduler: this)) {
try { try {
...@@ -690,8 +696,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -690,8 +696,9 @@ mixin SchedulerBinding on BindingBase {
/// off. /// off.
Future<void> get endOfFrame { Future<void> get endOfFrame {
if (_nextFrameCompleter == null) { if (_nextFrameCompleter == null) {
if (schedulerPhase == SchedulerPhase.idle) if (schedulerPhase == SchedulerPhase.idle) {
scheduleFrame(); scheduleFrame();
}
_nextFrameCompleter = Completer<void>(); _nextFrameCompleter = Completer<void>();
addPostFrameCallback((Duration timeStamp) { addPostFrameCallback((Duration timeStamp) {
_nextFrameCompleter!.complete(); _nextFrameCompleter!.complete();
...@@ -716,11 +723,13 @@ mixin SchedulerBinding on BindingBase { ...@@ -716,11 +723,13 @@ mixin SchedulerBinding on BindingBase {
bool _framesEnabled = true; bool _framesEnabled = true;
void _setFramesEnabledState(bool enabled) { void _setFramesEnabledState(bool enabled) {
if (_framesEnabled == enabled) if (_framesEnabled == enabled) {
return; return;
}
_framesEnabled = enabled; _framesEnabled = enabled;
if (enabled) if (enabled) {
scheduleFrame(); scheduleFrame();
}
} }
/// Ensures callbacks for [PlatformDispatcher.onBeginFrame] and /// Ensures callbacks for [PlatformDispatcher.onBeginFrame] and
...@@ -785,11 +794,13 @@ mixin SchedulerBinding on BindingBase { ...@@ -785,11 +794,13 @@ mixin SchedulerBinding on BindingBase {
/// * [scheduleWarmUpFrame], which ignores the "Vsync" signal entirely and /// * [scheduleWarmUpFrame], which ignores the "Vsync" signal entirely and
/// triggers a frame immediately. /// triggers a frame immediately.
void scheduleFrame() { void scheduleFrame() {
if (_hasScheduledFrame || !framesEnabled) if (_hasScheduledFrame || !framesEnabled) {
return; return;
}
assert(() { assert(() {
if (debugPrintScheduleFrameStacks) if (debugPrintScheduleFrameStacks) {
debugPrintStack(label: 'scheduleFrame() called. Current phase is $schedulerPhase.'); debugPrintStack(label: 'scheduleFrame() called. Current phase is $schedulerPhase.');
}
return true; return true;
}()); }());
ensureFrameCallbacksRegistered(); ensureFrameCallbacksRegistered();
...@@ -818,11 +829,13 @@ mixin SchedulerBinding on BindingBase { ...@@ -818,11 +829,13 @@ mixin SchedulerBinding on BindingBase {
/// Consider using [scheduleWarmUpFrame] instead if the goal is to update the /// Consider using [scheduleWarmUpFrame] instead if the goal is to update the
/// rendering as soon as possible (e.g. at application startup). /// rendering as soon as possible (e.g. at application startup).
void scheduleForcedFrame() { void scheduleForcedFrame() {
if (_hasScheduledFrame) if (_hasScheduledFrame) {
return; return;
}
assert(() { assert(() {
if (debugPrintScheduleFrameStacks) if (debugPrintScheduleFrameStacks) {
debugPrintStack(label: 'scheduleForcedFrame() called. Current phase is $schedulerPhase.'); debugPrintStack(label: 'scheduleForcedFrame() called. Current phase is $schedulerPhase.');
}
return true; return true;
}()); }());
ensureFrameCallbacksRegistered(); ensureFrameCallbacksRegistered();
...@@ -848,8 +861,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -848,8 +861,9 @@ mixin SchedulerBinding on BindingBase {
/// ///
/// Prefer [scheduleFrame] to update the display in normal operation. /// Prefer [scheduleFrame] to update the display in normal operation.
void scheduleWarmUpFrame() { void scheduleWarmUpFrame() {
if (_warmUpFrame || schedulerPhase != SchedulerPhase.idle) if (_warmUpFrame || schedulerPhase != SchedulerPhase.idle) {
return; return;
}
_warmUpFrame = true; _warmUpFrame = true;
final TimelineTask timelineTask = TimelineTask()..start('Warm-up frame'); final TimelineTask timelineTask = TimelineTask()..start('Warm-up frame');
...@@ -872,8 +886,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -872,8 +886,9 @@ mixin SchedulerBinding on BindingBase {
// then skipping every frame and finishing in the new time. // then skipping every frame and finishing in the new time.
resetEpoch(); resetEpoch();
_warmUpFrame = false; _warmUpFrame = false;
if (hadScheduledFrame) if (hadScheduledFrame) {
scheduleFrame(); scheduleFrame();
}
}); });
// Lock events so touch events etc don't insert themselves until the // Lock events so touch events etc don't insert themselves until the
...@@ -1026,8 +1041,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -1026,8 +1041,9 @@ mixin SchedulerBinding on BindingBase {
_frameTimelineTask?.start('Frame'); _frameTimelineTask?.start('Frame');
_firstRawTimeStampInEpoch ??= rawTimeStamp; _firstRawTimeStampInEpoch ??= rawTimeStamp;
_currentFrameTimeStamp = _adjustForEpoch(rawTimeStamp ?? _lastRawTimeStamp); _currentFrameTimeStamp = _adjustForEpoch(rawTimeStamp ?? _lastRawTimeStamp);
if (rawTimeStamp != null) if (rawTimeStamp != null) {
_lastRawTimeStamp = rawTimeStamp; _lastRawTimeStamp = rawTimeStamp;
}
assert(() { assert(() {
_debugFrameNumber += 1; _debugFrameNumber += 1;
...@@ -1040,8 +1056,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -1040,8 +1056,9 @@ mixin SchedulerBinding on BindingBase {
frameTimeStampDescription.write('(warm-up frame)'); frameTimeStampDescription.write('(warm-up frame)');
} }
_debugBanner = '▄▄▄▄▄▄▄▄ Frame ${_debugFrameNumber.toString().padRight(7)} ${frameTimeStampDescription.toString().padLeft(18)} ▄▄▄▄▄▄▄▄'; _debugBanner = '▄▄▄▄▄▄▄▄ Frame ${_debugFrameNumber.toString().padRight(7)} ${frameTimeStampDescription.toString().padLeft(18)} ▄▄▄▄▄▄▄▄';
if (debugPrintBeginFrameBanner) if (debugPrintBeginFrameBanner) {
debugPrint(_debugBanner); debugPrint(_debugBanner);
}
} }
return true; return true;
}()); }());
...@@ -1055,8 +1072,9 @@ mixin SchedulerBinding on BindingBase { ...@@ -1055,8 +1072,9 @@ mixin SchedulerBinding on BindingBase {
final Map<int, _FrameCallbackEntry> callbacks = _transientCallbacks; final Map<int, _FrameCallbackEntry> callbacks = _transientCallbacks;
_transientCallbacks = <int, _FrameCallbackEntry>{}; _transientCallbacks = <int, _FrameCallbackEntry>{};
callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) { callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) {
if (!_removedIds.contains(id)) if (!_removedIds.contains(id)) {
_invokeFrameCallback(callbackEntry.callback, _currentFrameTimeStamp!, callbackEntry.debugStack); _invokeFrameCallback(callbackEntry.callback, _currentFrameTimeStamp!, callbackEntry.debugStack);
}
}); });
_removedIds.clear(); _removedIds.clear();
} finally { } finally {
...@@ -1079,22 +1097,25 @@ mixin SchedulerBinding on BindingBase { ...@@ -1079,22 +1097,25 @@ mixin SchedulerBinding on BindingBase {
try { try {
// PERSISTENT FRAME CALLBACKS // PERSISTENT FRAME CALLBACKS
_schedulerPhase = SchedulerPhase.persistentCallbacks; _schedulerPhase = SchedulerPhase.persistentCallbacks;
for (final FrameCallback callback in _persistentCallbacks) for (final FrameCallback callback in _persistentCallbacks) {
_invokeFrameCallback(callback, _currentFrameTimeStamp!); _invokeFrameCallback(callback, _currentFrameTimeStamp!);
}
// POST-FRAME CALLBACKS // POST-FRAME CALLBACKS
_schedulerPhase = SchedulerPhase.postFrameCallbacks; _schedulerPhase = SchedulerPhase.postFrameCallbacks;
final List<FrameCallback> localPostFrameCallbacks = final List<FrameCallback> localPostFrameCallbacks =
List<FrameCallback>.of(_postFrameCallbacks); List<FrameCallback>.of(_postFrameCallbacks);
_postFrameCallbacks.clear(); _postFrameCallbacks.clear();
for (final FrameCallback callback in localPostFrameCallbacks) for (final FrameCallback callback in localPostFrameCallbacks) {
_invokeFrameCallback(callback, _currentFrameTimeStamp!); _invokeFrameCallback(callback, _currentFrameTimeStamp!);
}
} finally { } finally {
_schedulerPhase = SchedulerPhase.idle; _schedulerPhase = SchedulerPhase.idle;
_frameTimelineTask?.finish(); // end the Frame _frameTimelineTask?.finish(); // end the Frame
assert(() { assert(() {
if (debugPrintEndFrameBanner) if (debugPrintEndFrameBanner) {
debugPrint('▀' * _debugBanner!.length); debugPrint('▀' * _debugBanner!.length);
}
_debugBanner = null; _debugBanner = null;
return true; return true;
}()); }());
...@@ -1114,18 +1135,23 @@ mixin SchedulerBinding on BindingBase { ...@@ -1114,18 +1135,23 @@ mixin SchedulerBinding on BindingBase {
} }
static void _debugDescribeTimeStamp(Duration timeStamp, StringBuffer buffer) { static void _debugDescribeTimeStamp(Duration timeStamp, StringBuffer buffer) {
if (timeStamp.inDays > 0) if (timeStamp.inDays > 0) {
buffer.write('${timeStamp.inDays}d '); buffer.write('${timeStamp.inDays}d ');
if (timeStamp.inHours > 0) }
if (timeStamp.inHours > 0) {
buffer.write('${timeStamp.inHours - timeStamp.inDays * Duration.hoursPerDay}h '); buffer.write('${timeStamp.inHours - timeStamp.inDays * Duration.hoursPerDay}h ');
if (timeStamp.inMinutes > 0) }
if (timeStamp.inMinutes > 0) {
buffer.write('${timeStamp.inMinutes - timeStamp.inHours * Duration.minutesPerHour}m '); buffer.write('${timeStamp.inMinutes - timeStamp.inHours * Duration.minutesPerHour}m ');
if (timeStamp.inSeconds > 0) }
if (timeStamp.inSeconds > 0) {
buffer.write('${timeStamp.inSeconds - timeStamp.inMinutes * Duration.secondsPerMinute}s '); buffer.write('${timeStamp.inSeconds - timeStamp.inMinutes * Duration.secondsPerMinute}s ');
}
buffer.write('${timeStamp.inMilliseconds - timeStamp.inSeconds * Duration.millisecondsPerSecond}'); buffer.write('${timeStamp.inMilliseconds - timeStamp.inSeconds * Duration.millisecondsPerSecond}');
final int microseconds = timeStamp.inMicroseconds - timeStamp.inMilliseconds * Duration.microsecondsPerMillisecond; final int microseconds = timeStamp.inMicroseconds - timeStamp.inMilliseconds * Duration.microsecondsPerMillisecond;
if (microseconds > 0) if (microseconds > 0) {
buffer.write('.${microseconds.toString().padLeft(3, "0")}'); buffer.write('.${microseconds.toString().padLeft(3, "0")}');
}
buffer.write('ms'); buffer.write('ms');
} }
...@@ -1175,7 +1201,8 @@ mixin SchedulerBinding on BindingBase { ...@@ -1175,7 +1201,8 @@ mixin SchedulerBinding on BindingBase {
/// a [Priority] of [Priority.animation] or higher. Otherwise, runs /// a [Priority] of [Priority.animation] or higher. Otherwise, runs
/// all tasks. /// all tasks.
bool defaultSchedulingStrategy({ required int priority, required SchedulerBinding scheduler }) { bool defaultSchedulingStrategy({ required int priority, required SchedulerBinding scheduler }) {
if (scheduler.transientCallbackCount > 0) if (scheduler.transientCallbackCount > 0) {
return priority >= Priority.animation.value; return priority >= Priority.animation.value;
}
return true; return true;
} }
...@@ -88,8 +88,9 @@ class Ticker { ...@@ -88,8 +88,9 @@ class Ticker {
/// created the [Ticker] (typically a [TickerProvider]), not the object that /// created the [Ticker] (typically a [TickerProvider]), not the object that
/// listens to the ticker's ticks. /// listens to the ticker's ticks.
set muted(bool value) { set muted(bool value) {
if (value == muted) if (value == muted) {
return; return;
}
_muted = value; _muted = value;
if (value) { if (value) {
unscheduleTick(); unscheduleTick();
...@@ -109,14 +110,18 @@ class Ticker { ...@@ -109,14 +110,18 @@ class Ticker {
/// that indicates the application is not currently visible (e.g. if the /// that indicates the application is not currently visible (e.g. if the
/// device's screen is turned off). /// device's screen is turned off).
bool get isTicking { bool get isTicking {
if (_future == null) if (_future == null) {
return false; return false;
if (muted) }
if (muted) {
return false; return false;
if (SchedulerBinding.instance.framesEnabled) }
if (SchedulerBinding.instance.framesEnabled) {
return true; return true;
if (SchedulerBinding.instance.schedulerPhase != SchedulerPhase.idle) }
return true; // for example, we might be in a warm-up frame or forced frame if (SchedulerBinding.instance.schedulerPhase != SchedulerPhase.idle) {
return true;
} // for example, we might be in a warm-up frame or forced frame
return false; return false;
} }
...@@ -162,8 +167,9 @@ class Ticker { ...@@ -162,8 +167,9 @@ class Ticker {
scheduleTick(); scheduleTick();
} }
if (SchedulerBinding.instance.schedulerPhase.index > SchedulerPhase.idle.index && if (SchedulerBinding.instance.schedulerPhase.index > SchedulerPhase.idle.index &&
SchedulerBinding.instance.schedulerPhase.index < SchedulerPhase.postFrameCallbacks.index) SchedulerBinding.instance.schedulerPhase.index < SchedulerPhase.postFrameCallbacks.index) {
_startTime = SchedulerBinding.instance.currentFrameTimeStamp; _startTime = SchedulerBinding.instance.currentFrameTimeStamp;
}
return _future!; return _future!;
} }
...@@ -189,8 +195,9 @@ class Ticker { ...@@ -189,8 +195,9 @@ class Ticker {
/// By convention, this method is used by the object that receives the ticks /// By convention, this method is used by the object that receives the ticks
/// (as opposed to the [TickerProvider] which created the ticker). /// (as opposed to the [TickerProvider] which created the ticker).
void stop({ bool canceled = false }) { void stop({ bool canceled = false }) {
if (!isActive) if (!isActive) {
return; return;
}
// We take the _future into a local variable so that isTicking is false // We take the _future into a local variable so that isTicking is false
// when we actually complete the future (isTicking uses _future to // when we actually complete the future (isTicking uses _future to
...@@ -239,8 +246,9 @@ class Ticker { ...@@ -239,8 +246,9 @@ class Ticker {
// The onTick callback may have scheduled another tick already, for // The onTick callback may have scheduled another tick already, for
// example by calling stop then start again. // example by calling stop then start again.
if (shouldScheduleTick) if (shouldScheduleTick) {
scheduleTick(rescheduling: true); scheduleTick(rescheduling: true);
}
} }
/// Schedules a tick for the next frame. /// Schedules a tick for the next frame.
...@@ -286,8 +294,9 @@ class Ticker { ...@@ -286,8 +294,9 @@ class Ticker {
if (originalTicker._future != null) { if (originalTicker._future != null) {
_future = originalTicker._future; _future = originalTicker._future;
_startTime = originalTicker._startTime; _startTime = originalTicker._startTime;
if (shouldScheduleTick) if (shouldScheduleTick) {
scheduleTick(); scheduleTick();
}
originalTicker._future = null; // so that it doesn't get disposed when we dispose of originalTicker originalTicker._future = null; // so that it doesn't get disposed when we dispose of originalTicker
originalTicker.unscheduleTick(); originalTicker.unscheduleTick();
} }
...@@ -474,8 +483,9 @@ class TickerCanceled implements Exception { ...@@ -474,8 +483,9 @@ class TickerCanceled implements Exception {
@override @override
String toString() { String toString() {
if (ticker != null) if (ticker != null) {
return 'This ticker was canceled: $ticker'; return 'This ticker was canceled: $ticker';
}
return 'The ticker was canceled before the "orCancel" property was first used.'; return 'The ticker was canceled before the "orCancel" property was first used.';
} }
} }
...@@ -64,8 +64,9 @@ mixin SemanticsBinding on BindingBase { ...@@ -64,8 +64,9 @@ mixin SemanticsBinding on BindingBase {
bool get disableAnimations { bool get disableAnimations {
bool value = _accessibilityFeatures.disableAnimations; bool value = _accessibilityFeatures.disableAnimations;
assert(() { assert(() {
if (debugSemanticsDisableAnimations != null) if (debugSemanticsDisableAnimations != null) {
value = debugSemanticsDisableAnimations!; value = debugSemanticsDisableAnimations!;
}
return true; return true;
}()); }());
return value; return value;
......
...@@ -34,8 +34,9 @@ abstract class SemanticsEvent { ...@@ -34,8 +34,9 @@ abstract class SemanticsEvent {
'type': type, 'type': type,
'data': getDataMap(), 'data': getDataMap(),
}; };
if (nodeId != null) if (nodeId != null) {
event['nodeId'] = nodeId; event['nodeId'] = nodeId;
}
return event; return event;
} }
...@@ -48,8 +49,9 @@ abstract class SemanticsEvent { ...@@ -48,8 +49,9 @@ abstract class SemanticsEvent {
final List<String> pairs = <String>[]; final List<String> pairs = <String>[];
final Map<String, dynamic> dataMap = getDataMap(); final Map<String, dynamic> dataMap = getDataMap();
final List<String> sortedKeys = dataMap.keys.toList()..sort(); final List<String> sortedKeys = dataMap.keys.toList()..sort();
for (final String key in sortedKeys) for (final String key in sortedKeys) {
pairs.add('$key: ${dataMap[key]}'); pairs.add('$key: ${dataMap[key]}');
}
return '${objectRuntimeType(this, 'SemanticsEvent')}(${pairs.join(', ')})'; return '${objectRuntimeType(this, 'SemanticsEvent')}(${pairs.join(', ')})';
} }
} }
......
...@@ -70,8 +70,9 @@ abstract class AssetBundle { ...@@ -70,8 +70,9 @@ abstract class AssetBundle {
/// isolate to avoid jank on the main thread. /// isolate to avoid jank on the main thread.
Future<String> loadString(String key, { bool cache = true }) async { Future<String> loadString(String key, { bool cache = true }) async {
final ByteData data = await load(key); final ByteData data = await load(key);
if (data == null) if (data == null) {
throw FlutterError('Unable to load asset: $key'); throw FlutterError('Unable to load asset: $key');
}
// 50 KB of data should take 2-3 ms to parse on a Moto G4, and about 400 μs // 50 KB of data should take 2-3 ms to parse on a Moto G4, and about 400 μs
// on a Pixel 4. // on a Pixel 4.
if (data.lengthInBytes < 50 * 1024) { if (data.lengthInBytes < 50 * 1024) {
...@@ -125,11 +126,12 @@ class NetworkAssetBundle extends AssetBundle { ...@@ -125,11 +126,12 @@ class NetworkAssetBundle extends AssetBundle {
Future<ByteData> load(String key) async { Future<ByteData> load(String key) async {
final HttpClientRequest request = await _httpClient.getUrl(_urlFromKey(key)); final HttpClientRequest request = await _httpClient.getUrl(_urlFromKey(key));
final HttpClientResponse response = await request.close(); final HttpClientResponse response = await request.close();
if (response.statusCode != HttpStatus.ok) if (response.statusCode != HttpStatus.ok) {
throw FlutterError.fromParts(<DiagnosticsNode>[ throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('Unable to load asset: $key'), ErrorSummary('Unable to load asset: $key'),
IntProperty('HTTP status code', response.statusCode), IntProperty('HTTP status code', response.statusCode),
]); ]);
}
final Uint8List bytes = await consolidateHttpClientResponseBytes(response); final Uint8List bytes = await consolidateHttpClientResponseBytes(response);
return bytes.buffer.asByteData(); return bytes.buffer.asByteData();
} }
...@@ -168,8 +170,9 @@ abstract class CachingAssetBundle extends AssetBundle { ...@@ -168,8 +170,9 @@ abstract class CachingAssetBundle extends AssetBundle {
@override @override
Future<String> loadString(String key, { bool cache = true }) { Future<String> loadString(String key, { bool cache = true }) {
if (cache) if (cache) {
return _stringCache.putIfAbsent(key, () => super.loadString(key)); return _stringCache.putIfAbsent(key, () => super.loadString(key));
}
return super.loadString(key); return super.loadString(key);
} }
...@@ -187,8 +190,9 @@ abstract class CachingAssetBundle extends AssetBundle { ...@@ -187,8 +190,9 @@ abstract class CachingAssetBundle extends AssetBundle {
Future<T> loadStructuredData<T>(String key, Future<T> Function(String value) parser) { Future<T> loadStructuredData<T>(String key, Future<T> Function(String value) parser) {
assert(key != null); assert(key != null);
assert(parser != null); assert(parser != null);
if (_structuredDataCache.containsKey(key)) if (_structuredDataCache.containsKey(key)) {
return _structuredDataCache[key]! as Future<T>; return _structuredDataCache[key]! as Future<T>;
}
Completer<T>? completer; Completer<T>? completer;
Future<T>? result; Future<T>? result;
loadString(key, cache: false).then<T>(parser).then<void>((T value) { loadString(key, cache: false).then<T>(parser).then<void>((T value) {
...@@ -233,8 +237,9 @@ class PlatformAssetBundle extends CachingAssetBundle { ...@@ -233,8 +237,9 @@ class PlatformAssetBundle extends CachingAssetBundle {
final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path); final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path);
final ByteData? asset = final ByteData? asset =
await ServicesBinding.instance.defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData()); await ServicesBinding.instance.defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData());
if (asset == null) if (asset == null) {
throw FlutterError('Unable to load asset: $key'); throw FlutterError('Unable to load asset: $key');
}
return asset; return asset;
} }
} }
......
...@@ -338,8 +338,9 @@ class _DefaultBinaryMessenger extends BinaryMessenger { ...@@ -338,8 +338,9 @@ class _DefaultBinaryMessenger extends BinaryMessenger {
ui.PlatformMessageResponseCallback? callback, ui.PlatformMessageResponseCallback? callback,
) async { ) async {
ui.channelBuffers.push(channel, message, (ByteData? data) { ui.channelBuffers.push(channel, message, (ByteData? data) {
if (callback != null) if (callback != null) {
callback(data); callback(data);
}
}); });
} }
......
...@@ -55,8 +55,9 @@ class Clipboard { ...@@ -55,8 +55,9 @@ class Clipboard {
'Clipboard.getData', 'Clipboard.getData',
format, format,
); );
if (result == null) if (result == null) {
return null; return null;
}
return ClipboardData(text: result['text'] as String?); return ClipboardData(text: result['text'] as String?);
} }
......
...@@ -34,8 +34,9 @@ class FontLoader { ...@@ -34,8 +34,9 @@ class FontLoader {
/// The [bytes] argument specifies the actual font asset bytes. Currently, /// The [bytes] argument specifies the actual font asset bytes. Currently,
/// only OpenType (OTF) and TrueType (TTF) fonts are supported. /// only OpenType (OTF) and TrueType (TTF) fonts are supported.
void addFont(Future<ByteData> bytes) { void addFont(Future<ByteData> bytes) {
if (_loaded) if (_loaded) {
throw StateError('FontLoader is already loaded'); throw StateError('FontLoader is already loaded');
}
_fontFutures.add(bytes.then( _fontFutures.add(bytes.then(
(ByteData data) => Uint8List.view(data.buffer, data.offsetInBytes, data.lengthInBytes), (ByteData data) => Uint8List.view(data.buffer, data.offsetInBytes, data.lengthInBytes),
...@@ -53,8 +54,9 @@ class FontLoader { ...@@ -53,8 +54,9 @@ class FontLoader {
/// The returned future will complete with an error if any of the font asset /// The returned future will complete with an error if any of the font asset
/// futures yield an error. /// futures yield an error.
Future<void> load() async { Future<void> load() async {
if (_loaded) if (_loaded) {
throw StateError('FontLoader is already loaded'); throw StateError('FontLoader is already loaded');
}
_loaded = true; _loaded = true;
final Iterable<Future<void>> loadFutures = _fontFutures.map( final Iterable<Future<void>> loadFutures = _fontFutures.map(
......
...@@ -166,10 +166,12 @@ class LogicalKeyboardKey extends KeyboardKey { ...@@ -166,10 +166,12 @@ class LogicalKeyboardKey extends KeyboardKey {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is LogicalKeyboardKey return other is LogicalKeyboardKey
&& other.keyId == keyId; && other.keyId == keyId;
} }
...@@ -3539,10 +3541,12 @@ class PhysicalKeyboardKey extends KeyboardKey { ...@@ -3539,10 +3541,12 @@ class PhysicalKeyboardKey extends KeyboardKey {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is PhysicalKeyboardKey return other is PhysicalKeyboardKey
&& other.usbHidUsage == usbHidUsage; && other.usbHidUsage == usbHidUsage;
} }
......
...@@ -41,15 +41,17 @@ class StringCodec implements MessageCodec<String> { ...@@ -41,15 +41,17 @@ class StringCodec implements MessageCodec<String> {
@override @override
String? decodeMessage(ByteData? message) { String? decodeMessage(ByteData? message) {
if (message == null) if (message == null) {
return null; return null;
}
return utf8.decoder.convert(message.buffer.asUint8List(message.offsetInBytes, message.lengthInBytes)); return utf8.decoder.convert(message.buffer.asUint8List(message.offsetInBytes, message.lengthInBytes));
} }
@override @override
ByteData? encodeMessage(String? message) { ByteData? encodeMessage(String? message) {
if (message == null) if (message == null) {
return null; return null;
}
final Uint8List encoded = utf8.encoder.convert(message); final Uint8List encoded = utf8.encoder.convert(message);
return encoded.buffer.asByteData(); return encoded.buffer.asByteData();
} }
...@@ -89,15 +91,17 @@ class JSONMessageCodec implements MessageCodec<Object?> { ...@@ -89,15 +91,17 @@ class JSONMessageCodec implements MessageCodec<Object?> {
@override @override
ByteData? encodeMessage(Object? message) { ByteData? encodeMessage(Object? message) {
if (message == null) if (message == null) {
return null; return null;
}
return const StringCodec().encodeMessage(json.encode(message)); return const StringCodec().encodeMessage(json.encode(message));
} }
@override @override
dynamic decodeMessage(ByteData? message) { dynamic decodeMessage(ByteData? message) {
if (message == null) if (message == null) {
return message; return message;
}
return json.decode(const StringCodec().decodeMessage(message)!); return json.decode(const StringCodec().decodeMessage(message)!);
} }
} }
...@@ -135,40 +139,46 @@ class JSONMethodCodec implements MethodCodec { ...@@ -135,40 +139,46 @@ class JSONMethodCodec implements MethodCodec {
@override @override
MethodCall decodeMethodCall(ByteData? methodCall) { MethodCall decodeMethodCall(ByteData? methodCall) {
final Object? decoded = const JSONMessageCodec().decodeMessage(methodCall); final Object? decoded = const JSONMessageCodec().decodeMessage(methodCall);
if (decoded is! Map) if (decoded is! Map) {
throw FormatException('Expected method call Map, got $decoded'); throw FormatException('Expected method call Map, got $decoded');
}
final Object? method = decoded['method']; final Object? method = decoded['method'];
final Object? arguments = decoded['args']; final Object? arguments = decoded['args'];
if (method is String) if (method is String) {
return MethodCall(method, arguments); return MethodCall(method, arguments);
}
throw FormatException('Invalid method call: $decoded'); throw FormatException('Invalid method call: $decoded');
} }
@override @override
dynamic decodeEnvelope(ByteData envelope) { dynamic decodeEnvelope(ByteData envelope) {
final Object? decoded = const JSONMessageCodec().decodeMessage(envelope); final Object? decoded = const JSONMessageCodec().decodeMessage(envelope);
if (decoded is! List) if (decoded is! List) {
throw FormatException('Expected envelope List, got $decoded'); throw FormatException('Expected envelope List, got $decoded');
if (decoded.length == 1) }
if (decoded.length == 1) {
return decoded[0]; return decoded[0];
}
if (decoded.length == 3 if (decoded.length == 3
&& decoded[0] is String && decoded[0] is String
&& (decoded[1] == null || decoded[1] is String)) && (decoded[1] == null || decoded[1] is String)) {
throw PlatformException( throw PlatformException(
code: decoded[0] as String, code: decoded[0] as String,
message: decoded[1] as String?, message: decoded[1] as String?,
details: decoded[2], details: decoded[2],
); );
}
if (decoded.length == 4 if (decoded.length == 4
&& decoded[0] is String && decoded[0] is String
&& (decoded[1] == null || decoded[1] is String) && (decoded[1] == null || decoded[1] is String)
&& (decoded[3] == null || decoded[3] is String)) && (decoded[3] == null || decoded[3] is String)) {
throw PlatformException( throw PlatformException(
code: decoded[0] as String, code: decoded[0] as String,
message: decoded[1] as String?, message: decoded[1] as String?,
details: decoded[2], details: decoded[2],
stacktrace: decoded[3] as String?, stacktrace: decoded[3] as String?,
); );
}
throw FormatException('Invalid envelope: $decoded'); throw FormatException('Invalid envelope: $decoded');
} }
...@@ -310,8 +320,9 @@ class StandardMessageCodec implements MessageCodec<Object?> { ...@@ -310,8 +320,9 @@ class StandardMessageCodec implements MessageCodec<Object?> {
@override @override
ByteData? encodeMessage(Object? message) { ByteData? encodeMessage(Object? message) {
if (message == null) if (message == null) {
return null; return null;
}
final WriteBuffer buffer = WriteBuffer(startCapacity: _writeBufferStartCapacity); final WriteBuffer buffer = WriteBuffer(startCapacity: _writeBufferStartCapacity);
writeValue(buffer, message); writeValue(buffer, message);
return buffer.done(); return buffer.done();
...@@ -319,12 +330,14 @@ class StandardMessageCodec implements MessageCodec<Object?> { ...@@ -319,12 +330,14 @@ class StandardMessageCodec implements MessageCodec<Object?> {
@override @override
dynamic decodeMessage(ByteData? message) { dynamic decodeMessage(ByteData? message) {
if (message == null) if (message == null) {
return null; return null;
}
final ReadBuffer buffer = ReadBuffer(message); final ReadBuffer buffer = ReadBuffer(message);
final Object? result = readValue(buffer); final Object? result = readValue(buffer);
if (buffer.hasRemaining) if (buffer.hasRemaining) {
throw const FormatException('Message corrupted'); throw const FormatException('Message corrupted');
}
return result; return result;
} }
...@@ -453,8 +466,9 @@ class StandardMessageCodec implements MessageCodec<Object?> { ...@@ -453,8 +466,9 @@ class StandardMessageCodec implements MessageCodec<Object?> {
/// This method is intended for use by subclasses overriding /// This method is intended for use by subclasses overriding
/// [readValueOfType]. /// [readValueOfType].
Object? readValue(ReadBuffer buffer) { Object? readValue(ReadBuffer buffer) {
if (!buffer.hasRemaining) if (!buffer.hasRemaining) {
throw const FormatException('Message corrupted'); throw const FormatException('Message corrupted');
}
final int type = buffer.getUint8(); final int type = buffer.getUint8();
return readValueOfType(type, buffer); return readValueOfType(type, buffer);
} }
...@@ -500,14 +514,16 @@ class StandardMessageCodec implements MessageCodec<Object?> { ...@@ -500,14 +514,16 @@ class StandardMessageCodec implements MessageCodec<Object?> {
case _valueList: case _valueList:
final int length = readSize(buffer); final int length = readSize(buffer);
final List<Object?> result = List<Object?>.filled(length, null); final List<Object?> result = List<Object?>.filled(length, null);
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++) {
result[i] = readValue(buffer); result[i] = readValue(buffer);
}
return result; return result;
case _valueMap: case _valueMap:
final int length = readSize(buffer); final int length = readSize(buffer);
final Map<Object?, Object?> result = <Object?, Object?>{}; final Map<Object?, Object?> result = <Object?, Object?>{};
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++) {
result[readValue(buffer)] = readValue(buffer); result[readValue(buffer)] = readValue(buffer);
}
return result; return result;
default: throw const FormatException('Message corrupted'); default: throw const FormatException('Message corrupted');
} }
...@@ -588,10 +604,11 @@ class StandardMethodCodec implements MethodCodec { ...@@ -588,10 +604,11 @@ class StandardMethodCodec implements MethodCodec {
final ReadBuffer buffer = ReadBuffer(methodCall!); final ReadBuffer buffer = ReadBuffer(methodCall!);
final Object? method = messageCodec.readValue(buffer); final Object? method = messageCodec.readValue(buffer);
final Object? arguments = messageCodec.readValue(buffer); final Object? arguments = messageCodec.readValue(buffer);
if (method is String && !buffer.hasRemaining) if (method is String && !buffer.hasRemaining) {
return MethodCall(method, arguments); return MethodCall(method, arguments);
else } else {
throw const FormatException('Invalid method call'); throw const FormatException('Invalid method call');
}
} }
@override @override
...@@ -615,18 +632,21 @@ class StandardMethodCodec implements MethodCodec { ...@@ -615,18 +632,21 @@ class StandardMethodCodec implements MethodCodec {
@override @override
dynamic decodeEnvelope(ByteData envelope) { dynamic decodeEnvelope(ByteData envelope) {
// First byte is zero in success case, and non-zero otherwise. // First byte is zero in success case, and non-zero otherwise.
if (envelope.lengthInBytes == 0) if (envelope.lengthInBytes == 0) {
throw const FormatException('Expected envelope, got nothing'); throw const FormatException('Expected envelope, got nothing');
}
final ReadBuffer buffer = ReadBuffer(envelope); final ReadBuffer buffer = ReadBuffer(envelope);
if (buffer.getUint8() == 0) if (buffer.getUint8() == 0) {
return messageCodec.readValue(buffer); return messageCodec.readValue(buffer);
}
final Object? errorCode = messageCodec.readValue(buffer); final Object? errorCode = messageCodec.readValue(buffer);
final Object? errorMessage = messageCodec.readValue(buffer); final Object? errorMessage = messageCodec.readValue(buffer);
final Object? errorDetails = messageCodec.readValue(buffer); final Object? errorDetails = messageCodec.readValue(buffer);
final String? errorStacktrace = (buffer.hasRemaining) ? messageCodec.readValue(buffer) as String? : null; final String? errorStacktrace = (buffer.hasRemaining) ? messageCodec.readValue(buffer) as String? : null;
if (errorCode is String && (errorMessage == null || errorMessage is String) && !buffer.hasRemaining) if (errorCode is String && (errorMessage == null || errorMessage is String) && !buffer.hasRemaining) {
throw PlatformException(code: errorCode, message: errorMessage as String?, details: errorDetails, stacktrace: errorStacktrace); throw PlatformException(code: errorCode, message: errorMessage as String?, details: errorDetails, stacktrace: errorStacktrace);
else } else {
throw const FormatException('Invalid envelope'); throw const FormatException('Invalid envelope');
}
} }
} }
...@@ -66,8 +66,9 @@ class MouseCursorManager { ...@@ -66,8 +66,9 @@ class MouseCursorManager {
final MouseCursor nextCursor = _DeferringMouseCursor.firstNonDeferred(cursorCandidates) final MouseCursor nextCursor = _DeferringMouseCursor.firstNonDeferred(cursorCandidates)
?? fallbackMouseCursor; ?? fallbackMouseCursor;
assert(nextCursor is! _DeferringMouseCursor); assert(nextCursor is! _DeferringMouseCursor);
if (lastSession?.cursor == nextCursor) if (lastSession?.cursor == nextCursor) {
return; return;
}
final MouseCursorSession nextSession = nextCursor.createSession(device); final MouseCursorSession nextSession = nextCursor.createSession(device);
_lastSession[device] = nextSession; _lastSession[device] = nextSession;
...@@ -211,8 +212,9 @@ abstract class MouseCursor with Diagnosticable { ...@@ -211,8 +212,9 @@ abstract class MouseCursor with Diagnosticable {
@override @override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
final String debugDescription = this.debugDescription; final String debugDescription = this.debugDescription;
if (minLevel.index >= DiagnosticLevel.info.index && debugDescription != null) if (minLevel.index >= DiagnosticLevel.info.index && debugDescription != null) {
return debugDescription; return debugDescription;
}
return super.toString(minLevel: minLevel); return super.toString(minLevel: minLevel);
} }
...@@ -258,8 +260,9 @@ class _DeferringMouseCursor extends MouseCursor { ...@@ -258,8 +260,9 @@ class _DeferringMouseCursor extends MouseCursor {
static MouseCursor? firstNonDeferred(Iterable<MouseCursor> cursors) { static MouseCursor? firstNonDeferred(Iterable<MouseCursor> cursors) {
for (final MouseCursor cursor in cursors) { for (final MouseCursor cursor in cursors) {
assert(cursor != null); assert(cursor != null);
if (cursor != MouseCursor.defer) if (cursor != MouseCursor.defer) {
return cursor; return cursor;
}
} }
return null; return null;
} }
...@@ -368,8 +371,9 @@ class SystemMouseCursor extends MouseCursor { ...@@ -368,8 +371,9 @@ class SystemMouseCursor extends MouseCursor {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is SystemMouseCursor return other is SystemMouseCursor
&& other.kind == kind; && other.kind == kind;
} }
......
...@@ -860,16 +860,18 @@ abstract class AndroidViewController extends PlatformViewController { ...@@ -860,16 +860,18 @@ abstract class AndroidViewController extends PlatformViewController {
'trying to set a layout direction for a disposed UIView. View id: $viewId', 'trying to set a layout direction for a disposed UIView. View id: $viewId',
); );
if (layoutDirection == _layoutDirection) if (layoutDirection == _layoutDirection) {
return; return;
}
assert(layoutDirection != null); assert(layoutDirection != null);
_layoutDirection = layoutDirection; _layoutDirection = layoutDirection;
// If the view was not yet created we just update _layoutDirection and return, as the new // If the view was not yet created we just update _layoutDirection and return, as the new
// direction will be used in _create. // direction will be used in _create.
if (_state == _AndroidViewState.waitingForSize) if (_state == _AndroidViewState.waitingForSize) {
return; return;
}
await SystemChannels.platform_views await SystemChannels.platform_views
.invokeMethod<void>('setDirection', <String, dynamic>{ .invokeMethod<void>('setDirection', <String, dynamic>{
...@@ -931,8 +933,9 @@ abstract class AndroidViewController extends PlatformViewController { ...@@ -931,8 +933,9 @@ abstract class AndroidViewController extends PlatformViewController {
/// disposed. /// disposed.
@override @override
Future<void> dispose() async { Future<void> dispose() async {
if (_state == _AndroidViewState.creating || _state == _AndroidViewState.created) if (_state == _AndroidViewState.creating || _state == _AndroidViewState.created) {
await _sendDisposeMessage(); await _sendDisposeMessage();
}
_platformViewCreatedCallbacks.clear(); _platformViewCreatedCallbacks.clear();
_state = _AndroidViewState.disposed; _state = _AndroidViewState.disposed;
PlatformViewsService._instance._focusCallbacks.remove(viewId); PlatformViewsService._instance._focusCallbacks.remove(viewId);
...@@ -1058,8 +1061,9 @@ class TextureAndroidViewController extends AndroidViewController { ...@@ -1058,8 +1061,9 @@ class TextureAndroidViewController extends AndroidViewController {
@override @override
Future<void> create({Size? size}) async { Future<void> create({Size? size}) async {
if (size == null) if (size == null) {
return; return;
}
assert(_state == _AndroidViewState.waitingForSize, 'Android view is already sized. View id: $viewId'); assert(_state == _AndroidViewState.waitingForSize, 'Android view is already sized. View id: $viewId');
assert(!size.isEmpty); assert(!size.isEmpty);
return super.create(size: size); return super.create(size: size);
...@@ -1067,14 +1071,16 @@ class TextureAndroidViewController extends AndroidViewController { ...@@ -1067,14 +1071,16 @@ class TextureAndroidViewController extends AndroidViewController {
@override @override
Future<void> setOffset(Offset off) async { Future<void> setOffset(Offset off) async {
if (off == _off) if (off == _off) {
return; return;
}
// Don't set the offset unless the Android view has been created. // Don't set the offset unless the Android view has been created.
// The implementation of this method channel throws if the Android view for this viewId // The implementation of this method channel throws if the Android view for this viewId
// isn't addressable. // isn't addressable.
if (_state != _AndroidViewState.created) if (_state != _AndroidViewState.created) {
return; return;
}
_off = off; _off = off;
...@@ -1090,8 +1096,9 @@ class TextureAndroidViewController extends AndroidViewController { ...@@ -1090,8 +1096,9 @@ class TextureAndroidViewController extends AndroidViewController {
@override @override
Future<void> _sendCreateMessage({Size? size}) async { Future<void> _sendCreateMessage({Size? size}) async {
if (size == null) if (size == null) {
return; return;
}
assert(!size.isEmpty, 'trying to create $TextureAndroidViewController without setting a valid size.'); assert(!size.isEmpty, 'trying to create $TextureAndroidViewController without setting a valid size.');
...@@ -1149,8 +1156,9 @@ class UiKitViewController { ...@@ -1149,8 +1156,9 @@ class UiKitViewController {
Future<void> setLayoutDirection(TextDirection layoutDirection) async { Future<void> setLayoutDirection(TextDirection layoutDirection) async {
assert(!_debugDisposed, 'trying to set a layout direction for a disposed iOS UIView. View id: $id'); assert(!_debugDisposed, 'trying to set a layout direction for a disposed iOS UIView. View id: $id');
if (layoutDirection == _layoutDirection) if (layoutDirection == _layoutDirection) {
return; return;
}
assert(layoutDirection != null); assert(layoutDirection != null);
_layoutDirection = layoutDirection; _layoutDirection = layoutDirection;
......
...@@ -527,8 +527,9 @@ abstract class RawKeyEvent with Diagnosticable { ...@@ -527,8 +527,9 @@ abstract class RawKeyEvent with Diagnosticable {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<LogicalKeyboardKey>('logicalKey', logicalKey)); properties.add(DiagnosticsProperty<LogicalKeyboardKey>('logicalKey', logicalKey));
properties.add(DiagnosticsProperty<PhysicalKeyboardKey>('physicalKey', physicalKey)); properties.add(DiagnosticsProperty<PhysicalKeyboardKey>('physicalKey', physicalKey));
if (this is RawKeyDownEvent) if (this is RawKeyDownEvent) {
properties.add(DiagnosticsProperty<bool>('repeat', repeat)); properties.add(DiagnosticsProperty<bool>('repeat', repeat));
}
} }
} }
...@@ -651,8 +652,9 @@ class RawKeyboard { ...@@ -651,8 +652,9 @@ class RawKeyboard {
_cachedKeyMessageHandler = handler == null ? _cachedKeyMessageHandler = handler == null ?
null : null :
(KeyMessage message) { (KeyMessage message) {
if (message.rawEvent != null) if (message.rawEvent != null) {
return handler(message.rawEvent!); return handler(message.rawEvent!);
}
return false; return false;
}; };
ServicesBinding.instance.keyEventManager.keyMessageHandler = _cachedKeyMessageHandler; ServicesBinding.instance.keyEventManager.keyMessageHandler = _cachedKeyMessageHandler;
...@@ -783,8 +785,9 @@ class RawKeyboard { ...@@ -783,8 +785,9 @@ class RawKeyboard {
ModifierKey? thisKeyModifier; ModifierKey? thisKeyModifier;
for (final ModifierKey key in ModifierKey.values) { for (final ModifierKey key in ModifierKey.values) {
final Set<PhysicalKeyboardKey>? thisModifierKeys = _modifierKeyMap[_ModifierSidePair(key, KeyboardSide.all)]; final Set<PhysicalKeyboardKey>? thisModifierKeys = _modifierKeyMap[_ModifierSidePair(key, KeyboardSide.all)];
if (thisModifierKeys == null) if (thisModifierKeys == null) {
continue; continue;
}
if (thisModifierKeys.contains(event.physicalKey)) { if (thisModifierKeys.contains(event.physicalKey)) {
thisKeyModifier = key; thisKeyModifier = key;
} }
...@@ -869,8 +872,9 @@ class _ModifierSidePair { ...@@ -869,8 +872,9 @@ class _ModifierSidePair {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is _ModifierSidePair return other is _ModifierSidePair
&& other.modifier == modifier && other.modifier == modifier
&& other.side == side; && other.side == side;
......
...@@ -298,10 +298,12 @@ class RawKeyEventDataAndroid extends RawKeyEventData { ...@@ -298,10 +298,12 @@ class RawKeyEventDataAndroid extends RawKeyEventData {
@override @override
bool operator==(Object other) { bool operator==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RawKeyEventDataAndroid return other is RawKeyEventDataAndroid
&& other.flags == flags && other.flags == flags
&& other.codePoint == codePoint && other.codePoint == codePoint
......
...@@ -168,10 +168,12 @@ class RawKeyEventDataFuchsia extends RawKeyEventData { ...@@ -168,10 +168,12 @@ class RawKeyEventDataFuchsia extends RawKeyEventData {
@override @override
bool operator==(Object other) { bool operator==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RawKeyEventDataFuchsia return other is RawKeyEventDataFuchsia
&& other.hidUsage == hidUsage && other.hidUsage == hidUsage
&& other.codePoint == codePoint && other.codePoint == codePoint
......
...@@ -264,10 +264,12 @@ class RawKeyEventDataIos extends RawKeyEventData { ...@@ -264,10 +264,12 @@ class RawKeyEventDataIos extends RawKeyEventData {
@override @override
bool operator==(Object other) { bool operator==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RawKeyEventDataIos return other is RawKeyEventDataIos
&& other.characters == characters && other.characters == characters
&& other.charactersIgnoringModifiers == charactersIgnoringModifiers && other.charactersIgnoringModifiers == charactersIgnoringModifiers
......
...@@ -143,10 +143,12 @@ class RawKeyEventDataLinux extends RawKeyEventData { ...@@ -143,10 +143,12 @@ class RawKeyEventDataLinux extends RawKeyEventData {
@override @override
bool operator==(Object other) { bool operator==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RawKeyEventDataLinux return other is RawKeyEventDataLinux
&& other.keyHelper.runtimeType == keyHelper.runtimeType && other.keyHelper.runtimeType == keyHelper.runtimeType
&& other.unicodeScalarValues == unicodeScalarValues && other.unicodeScalarValues == unicodeScalarValues
......
...@@ -13,8 +13,9 @@ int runeToLowerCase(int rune) { ...@@ -13,8 +13,9 @@ int runeToLowerCase(int rune) {
// Assume only Basic Multilingual Plane runes have lower and upper cases. // Assume only Basic Multilingual Plane runes have lower and upper cases.
// For other characters, return them as is. // For other characters, return them as is.
const int utf16BmpUpperBound = 0xD7FF; const int utf16BmpUpperBound = 0xD7FF;
if (rune > utf16BmpUpperBound) if (rune > utf16BmpUpperBound) {
return rune; return rune;
}
return String.fromCharCode(rune).toLowerCase().codeUnitAt(0); return String.fromCharCode(rune).toLowerCase().codeUnitAt(0);
} }
...@@ -251,10 +252,12 @@ class RawKeyEventDataMacOs extends RawKeyEventData { ...@@ -251,10 +252,12 @@ class RawKeyEventDataMacOs extends RawKeyEventData {
@override @override
bool operator==(Object other) { bool operator==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RawKeyEventDataMacOs return other is RawKeyEventDataMacOs
&& other.characters == characters && other.characters == characters
&& other.charactersIgnoringModifiers == charactersIgnoringModifiers && other.charactersIgnoringModifiers == charactersIgnoringModifiers
......
...@@ -98,8 +98,9 @@ class RawKeyEventDataWeb extends RawKeyEventData { ...@@ -98,8 +98,9 @@ class RawKeyEventDataWeb extends RawKeyEventData {
// Look to see if the keyCode is a key based on location. Typically they are // Look to see if the keyCode is a key based on location. Typically they are
// numpad keys (versus main area keys) and left/right modifiers. // numpad keys (versus main area keys) and left/right modifiers.
final LogicalKeyboardKey? maybeLocationKey = kWebLocationMap[key]?[location]; final LogicalKeyboardKey? maybeLocationKey = kWebLocationMap[key]?[location];
if (maybeLocationKey != null) if (maybeLocationKey != null) {
return maybeLocationKey; return maybeLocationKey;
}
// Look to see if the [code] is one we know about and have a mapping for. // Look to see if the [code] is one we know about and have a mapping for.
final LogicalKeyboardKey? newKey = kWebToLogicalKey[code]; final LogicalKeyboardKey? newKey = kWebToLogicalKey[code];
...@@ -108,8 +109,9 @@ class RawKeyEventDataWeb extends RawKeyEventData { ...@@ -108,8 +109,9 @@ class RawKeyEventDataWeb extends RawKeyEventData {
} }
final bool isPrintable = key.length == 1; final bool isPrintable = key.length == 1;
if (isPrintable) if (isPrintable) {
return LogicalKeyboardKey(key.toLowerCase().codeUnitAt(0)); return LogicalKeyboardKey(key.toLowerCase().codeUnitAt(0));
}
// This is a non-printable key that we don't know about, so we mint a new // This is a non-printable key that we don't know about, so we mint a new
// key from `code`. Don't mint with `key`, because the `key` will always be // key from `code`. Don't mint with `key`, because the `key` will always be
...@@ -166,10 +168,12 @@ class RawKeyEventDataWeb extends RawKeyEventData { ...@@ -166,10 +168,12 @@ class RawKeyEventDataWeb extends RawKeyEventData {
@override @override
bool operator==(Object other) { bool operator==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RawKeyEventDataWeb return other is RawKeyEventDataWeb
&& other.code == code && other.code == code
&& other.key == key && other.key == key
......
...@@ -209,10 +209,12 @@ class RawKeyEventDataWindows extends RawKeyEventData { ...@@ -209,10 +209,12 @@ class RawKeyEventDataWindows extends RawKeyEventData {
@override @override
bool operator==(Object other) { bool operator==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other.runtimeType != runtimeType) }
if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is RawKeyEventDataWindows return other is RawKeyEventDataWindows
&& other.keyCode == keyCode && other.keyCode == keyCode
&& other.scanCode == scanCode && other.scanCode == scanCode
......
...@@ -333,8 +333,9 @@ class SystemUiOverlayStyle { ...@@ -333,8 +333,9 @@ class SystemUiOverlayStyle {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is SystemUiOverlayStyle return other is SystemUiOverlayStyle
&& other.systemNavigationBarColor == systemNavigationBarColor && other.systemNavigationBarColor == systemNavigationBarColor
&& other.systemNavigationBarDividerColor == systemNavigationBarDividerColor && other.systemNavigationBarDividerColor == systemNavigationBarDividerColor
......
...@@ -140,10 +140,12 @@ class TextSelection extends TextRange { ...@@ -140,10 +140,12 @@ class TextSelection extends TextRange {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (other is! TextSelection) }
if (other is! TextSelection) {
return false; return false;
}
if (!isValid) { if (!isValid) {
return !other.isValid; return !other.isValid;
} }
......
...@@ -916,8 +916,9 @@ class TextEditingValue { ...@@ -916,8 +916,9 @@ class TextEditingValue {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
}
return other is TextEditingValue return other is TextEditingValue
&& other.text == text && other.text == text
&& other.selection == selection && other.selection == selection
...@@ -1165,10 +1166,12 @@ class SelectionRect { ...@@ -1165,10 +1166,12 @@ class SelectionRect {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) if (identical(this, other)) {
return true; return true;
if (runtimeType != other.runtimeType) }
if (runtimeType != other.runtimeType) {
return false; return false;
}
return other is SelectionRect return other is SelectionRect
&& other.position == position && other.position == position
&& other.bounds == bounds; && other.bounds == bounds;
...@@ -1330,8 +1333,9 @@ class TextInputConnection { ...@@ -1330,8 +1333,9 @@ class TextInputConnection {
/// platform. /// platform.
void setComposingRect(Rect rect) { void setComposingRect(Rect rect) {
assert(rect != null); assert(rect != null);
if (rect == _cachedRect) if (rect == _cachedRect) {
return; return;
}
_cachedRect = rect; _cachedRect = rect;
final Rect validRect = rect.isFinite ? rect : Offset.zero & const Size(-1, -1); final Rect validRect = rect.isFinite ? rect : Offset.zero & const Size(-1, -1);
TextInput._instance._setComposingTextRect( TextInput._instance._setComposingTextRect(
...@@ -1348,8 +1352,9 @@ class TextInputConnection { ...@@ -1348,8 +1352,9 @@ class TextInputConnection {
/// the accent selection menu. /// the accent selection menu.
void setCaretRect(Rect rect) { void setCaretRect(Rect rect) {
assert(rect != null); assert(rect != null);
if (rect == _cachedCaretRect) if (rect == _cachedCaretRect) {
return; return;
}
_cachedCaretRect = rect; _cachedCaretRect = rect;
final Rect validRect = rect.isFinite ? rect : Offset.zero & const Size(-1, -1); final Rect validRect = rect.isFinite ? rect : Offset.zero & const Size(-1, -1);
TextInput._instance._setCaretRect( TextInput._instance._setCaretRect(
...@@ -1662,8 +1667,9 @@ class TextInput { ...@@ -1662,8 +1667,9 @@ class TextInput {
final List<double> args = (methodCall.arguments as List<dynamic>).cast<num>().map<double>((num value) => value.toDouble()).toList(); final List<double> args = (methodCall.arguments as List<dynamic>).cast<num>().map<double>((num value) => value.toDouble()).toList();
return _scribbleClients.keys.where((String elementIdentifier) { return _scribbleClients.keys.where((String elementIdentifier) {
final Rect rect = Rect.fromLTWH(args[0], args[1], args[2], args[3]); final Rect rect = Rect.fromLTWH(args[0], args[1], args[2], args[3]);
if (!(_scribbleClients[elementIdentifier]?.isInScribbleRect(rect) ?? false)) if (!(_scribbleClients[elementIdentifier]?.isInScribbleRect(rect) ?? false)) {
return false; return false;
}
final Rect bounds = _scribbleClients[elementIdentifier]?.bounds ?? Rect.zero; final Rect bounds = _scribbleClients[elementIdentifier]?.bounds ?? Rect.zero;
return !(bounds == Rect.zero || bounds.hasNaN || bounds.isInfinite); return !(bounds == Rect.zero || bounds.hasNaN || bounds.isInfinite);
}).map((String elementIdentifier) { }).map((String elementIdentifier) {
...@@ -1677,8 +1683,9 @@ class TextInput { ...@@ -1677,8 +1683,9 @@ class TextInput {
_scribbleInProgress = false; _scribbleInProgress = false;
return; return;
} }
if (_currentConnection == null) if (_currentConnection == null) {
return; return;
}
// The requestExistingInputState request needs to be handled regardless of // The requestExistingInputState request needs to be handled regardless of
// the client ID, as long as we have a _currentConnection. // the client ID, as long as we have a _currentConnection.
...@@ -1723,12 +1730,14 @@ class TextInput { ...@@ -1723,12 +1730,14 @@ class TextInput {
// In debug builds we allow "-1" as a magical client ID that ignores // In debug builds we allow "-1" as a magical client ID that ignores
// this verification step so that tests can always get through, even // this verification step so that tests can always get through, even
// when they are not mocking the engine side of text input. // when they are not mocking the engine side of text input.
if (client == -1) if (client == -1) {
debugAllowAnyway = true; debugAllowAnyway = true;
}
return true; return true;
}()); }());
if (!debugAllowAnyway) if (!debugAllowAnyway) {
return; return;
}
} }
switch (method) { switch (method) {
...@@ -1787,8 +1796,9 @@ class TextInput { ...@@ -1787,8 +1796,9 @@ class TextInput {
bool _hidePending = false; bool _hidePending = false;
void _scheduleHide() { void _scheduleHide() {
if (_hidePending) if (_hidePending) {
return; return;
}
_hidePending = true; _hidePending = true;
// Schedule a deferred task that hides the text input. If someone else // Schedule a deferred task that hides the text input. If someone else
...@@ -1796,8 +1806,9 @@ class TextInput { ...@@ -1796,8 +1806,9 @@ class TextInput {
// nothing. // nothing.
scheduleMicrotask(() { scheduleMicrotask(() {
_hidePending = false; _hidePending = false;
if (_currentConnection == null) if (_currentConnection == null) {
_channel.invokeMethod<void>('TextInput.hide'); _channel.invokeMethod<void>('TextInput.hide');
}
}); });
} }
......
...@@ -52,20 +52,23 @@ void main() { ...@@ -52,20 +52,23 @@ void main() {
input.forEach(scheduleAddingTask); input.forEach(scheduleAddingTask);
strategy.allowedPriority = 100; strategy.allowedPriority = 100;
for (int i = 0; i < 3; i += 1) for (int i = 0; i < 3; i += 1) {
expect(scheduler.handleEventLoopCallback(), isFalse); expect(scheduler.handleEventLoopCallback(), isFalse);
}
expect(executedTasks.isEmpty, isTrue); expect(executedTasks.isEmpty, isTrue);
strategy.allowedPriority = 50; strategy.allowedPriority = 50;
for (int i = 0; i < 3; i += 1) for (int i = 0; i < 3; i += 1) {
expect(scheduler.handleEventLoopCallback(), i == 0 ? isTrue : isFalse); expect(scheduler.handleEventLoopCallback(), i == 0 ? isTrue : isFalse);
}
expect(executedTasks, hasLength(1)); expect(executedTasks, hasLength(1));
expect(executedTasks.single, equals(80)); expect(executedTasks.single, equals(80));
executedTasks.clear(); executedTasks.clear();
strategy.allowedPriority = 20; strategy.allowedPriority = 20;
for (int i = 0; i < 3; i += 1) for (int i = 0; i < 3; i += 1) {
expect(scheduler.handleEventLoopCallback(), i < 2 ? isTrue : isFalse); expect(scheduler.handleEventLoopCallback(), i < 2 ? isTrue : isFalse);
}
expect(executedTasks, hasLength(2)); expect(executedTasks, hasLength(2));
expect(executedTasks[0], equals(23)); expect(executedTasks[0], equals(23));
expect(executedTasks[1], equals(23)); expect(executedTasks[1], equals(23));
...@@ -75,24 +78,27 @@ void main() { ...@@ -75,24 +78,27 @@ void main() {
scheduleAddingTask(19); scheduleAddingTask(19);
scheduleAddingTask(5); scheduleAddingTask(5);
scheduleAddingTask(97); scheduleAddingTask(97);
for (int i = 0; i < 3; i += 1) for (int i = 0; i < 3; i += 1) {
expect(scheduler.handleEventLoopCallback(), i < 2 ? isTrue : isFalse); expect(scheduler.handleEventLoopCallback(), i < 2 ? isTrue : isFalse);
}
expect(executedTasks, hasLength(2)); expect(executedTasks, hasLength(2));
expect(executedTasks[0], equals(99)); expect(executedTasks[0], equals(99));
expect(executedTasks[1], equals(97)); expect(executedTasks[1], equals(97));
executedTasks.clear(); executedTasks.clear();
strategy.allowedPriority = 10; strategy.allowedPriority = 10;
for (int i = 0; i < 3; i += 1) for (int i = 0; i < 3; i += 1) {
expect(scheduler.handleEventLoopCallback(), i < 2 ? isTrue : isFalse); expect(scheduler.handleEventLoopCallback(), i < 2 ? isTrue : isFalse);
}
expect(executedTasks, hasLength(2)); expect(executedTasks, hasLength(2));
expect(executedTasks[0], equals(19)); expect(executedTasks[0], equals(19));
expect(executedTasks[1], equals(11)); expect(executedTasks[1], equals(11));
executedTasks.clear(); executedTasks.clear();
strategy.allowedPriority = 1; strategy.allowedPriority = 1;
for (int i = 0; i < 4; i += 1) for (int i = 0; i < 4; i += 1) {
expect(scheduler.handleEventLoopCallback(), i < 3 ? isTrue : isFalse); expect(scheduler.handleEventLoopCallback(), i < 3 ? isTrue : isFalse);
}
expect(executedTasks, hasLength(3)); expect(executedTasks, hasLength(3));
expect(executedTasks[0], equals(5)); expect(executedTasks[0], equals(5));
expect(executedTasks[1], equals(3)); expect(executedTasks[1], equals(3));
......
...@@ -842,18 +842,24 @@ class TestRender extends RenderProxyBox { ...@@ -842,18 +842,24 @@ class TestRender extends RenderProxyBox {
super.describeSemanticsConfiguration(config); super.describeSemanticsConfiguration(config);
config.isSemanticBoundary = isSemanticBoundary; config.isSemanticBoundary = isSemanticBoundary;
if (hasTapAction) if (hasTapAction) {
config.onTap = () { }; config.onTap = () { };
if (hasLongPressAction) }
if (hasLongPressAction) {
config.onLongPress = () { }; config.onLongPress = () { };
if (hasScrollLeftAction) }
if (hasScrollLeftAction) {
config.onScrollLeft = () { }; config.onScrollLeft = () { };
if (hasScrollRightAction) }
if (hasScrollRightAction) {
config.onScrollRight = () { }; config.onScrollRight = () { };
if (hasScrollUpAction) }
if (hasScrollUpAction) {
config.onScrollUp = () { }; config.onScrollUp = () { };
if (hasScrollDownAction) }
if (hasScrollDownAction) {
config.onScrollDown = () { }; config.onScrollDown = () { };
}
} }
} }
......
...@@ -16,11 +16,13 @@ class TestAssetBundle extends CachingAssetBundle { ...@@ -16,11 +16,13 @@ class TestAssetBundle extends CachingAssetBundle {
@override @override
Future<ByteData> load(String key) async { Future<ByteData> load(String key) async {
loadCallCount[key] = loadCallCount[key] ?? 0 + 1; loadCallCount[key] = loadCallCount[key] ?? 0 + 1;
if (key == 'AssetManifest.json') if (key == 'AssetManifest.json') {
return ByteData.view(Uint8List.fromList(const Utf8Encoder().convert('{"one": ["one"]}')).buffer); return ByteData.view(Uint8List.fromList(const Utf8Encoder().convert('{"one": ["one"]}')).buffer);
}
if (key == 'one') if (key == 'one') {
return ByteData(1)..setInt8(0, 49); return ByteData(1)..setInt8(0, 49);
}
throw FlutterError('key not found'); throw FlutterError('key not found');
} }
} }
......
...@@ -186,17 +186,19 @@ class FakeAndroidPlatformViewsController { ...@@ -186,17 +186,19 @@ class FakeAndroidPlatformViewsController {
final bool? hybrid = args['hybrid'] as bool?; final bool? hybrid = args['hybrid'] as bool?;
final Uint8List? creationParams = args['params'] as Uint8List?; final Uint8List? creationParams = args['params'] as Uint8List?;
if (_views.containsKey(id)) if (_views.containsKey(id)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to create an already created platform view, view id: $id', message: 'Trying to create an already created platform view, view id: $id',
); );
}
if (!_registeredViewTypes.contains(viewType)) if (!_registeredViewTypes.contains(viewType)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to create a platform view of unregistered type: $viewType', message: 'Trying to create a platform view of unregistered type: $viewType',
); );
}
if (createCompleter != null) { if (createCompleter != null) {
await createCompleter!.future; await createCompleter!.future;
...@@ -225,11 +227,12 @@ class FakeAndroidPlatformViewsController { ...@@ -225,11 +227,12 @@ class FakeAndroidPlatformViewsController {
throw ArgumentError('An $AndroidViewController not using hybrid composition must pass `hybrid: false`'); throw ArgumentError('An $AndroidViewController not using hybrid composition must pass `hybrid: false`');
} }
if (!_views.containsKey(id)) if (!_views.containsKey(id)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to dispose a platform view with unknown id: $id', message: 'Trying to dispose a platform view with unknown id: $id',
); );
}
_views.remove(id); _views.remove(id);
return Future<dynamic>.sync(() => null); return Future<dynamic>.sync(() => null);
...@@ -241,11 +244,12 @@ class FakeAndroidPlatformViewsController { ...@@ -241,11 +244,12 @@ class FakeAndroidPlatformViewsController {
final double width = args['width'] as double; final double width = args['width'] as double;
final double height = args['height'] as double; final double height = args['height'] as double;
if (!_views.containsKey(id)) if (!_views.containsKey(id)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to resize a platform view with unknown id: $id', message: 'Trying to resize a platform view with unknown id: $id',
); );
}
if (resizeCompleter != null) { if (resizeCompleter != null) {
await resizeCompleter!.future; await resizeCompleter!.future;
...@@ -279,8 +283,9 @@ class FakeAndroidPlatformViewsController { ...@@ -279,8 +283,9 @@ class FakeAndroidPlatformViewsController {
pointerOffsets.add(Offset(x, y)); pointerOffsets.add(Offset(x, y));
} }
if (!motionEvents.containsKey(id)) if (!motionEvents.containsKey(id)) {
motionEvents[id] = <FakeAndroidMotionEvent> []; motionEvents[id] = <FakeAndroidMotionEvent> [];
}
motionEvents[id]!.add(FakeAndroidMotionEvent(action, pointerIds, pointerOffsets)); motionEvents[id]!.add(FakeAndroidMotionEvent(action, pointerIds, pointerOffsets));
return Future<dynamic>.sync(() => null); return Future<dynamic>.sync(() => null);
...@@ -291,11 +296,12 @@ class FakeAndroidPlatformViewsController { ...@@ -291,11 +296,12 @@ class FakeAndroidPlatformViewsController {
final int id = args['id'] as int; final int id = args['id'] as int;
final int layoutDirection = args['direction'] as int; final int layoutDirection = args['direction'] as int;
if (!_views.containsKey(id)) if (!_views.containsKey(id)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to resize a platform view with unknown id: $id', message: 'Trying to resize a platform view with unknown id: $id',
); );
}
_views[id] = _views[id]!.copyWith(layoutDirection: layoutDirection); _views[id] = _views[id]!.copyWith(layoutDirection: layoutDirection);
...@@ -305,11 +311,12 @@ class FakeAndroidPlatformViewsController { ...@@ -305,11 +311,12 @@ class FakeAndroidPlatformViewsController {
Future<dynamic> _clearFocus(MethodCall call) { Future<dynamic> _clearFocus(MethodCall call) {
final int id = call.arguments as int; final int id = call.arguments as int;
if (!_views.containsKey(id)) if (!_views.containsKey(id)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to clear the focus on a platform view with unknown id: $id', message: 'Trying to clear the focus on a platform view with unknown id: $id',
); );
}
lastClearedFocusViewId = id; lastClearedFocusViewId = id;
return Future<dynamic>.sync(() => null); return Future<dynamic>.sync(() => null);
...@@ -362,8 +369,9 @@ class FakeIosPlatformViewsController { ...@@ -362,8 +369,9 @@ class FakeIosPlatformViewsController {
} }
Future<dynamic> _create(MethodCall call) async { Future<dynamic> _create(MethodCall call) async {
if (creationDelay != null) if (creationDelay != null) {
await creationDelay!.future; await creationDelay!.future;
}
final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>; final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>;
final int id = args['id'] as int; final int id = args['id'] as int;
final String viewType = args['viewType'] as String; final String viewType = args['viewType'] as String;
...@@ -451,17 +459,19 @@ class FakeHtmlPlatformViewsController { ...@@ -451,17 +459,19 @@ class FakeHtmlPlatformViewsController {
final int id = args['id'] as int; final int id = args['id'] as int;
final String viewType = args['viewType'] as String; final String viewType = args['viewType'] as String;
if (_views.containsKey(id)) if (_views.containsKey(id)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to create an already created platform view, view id: $id', message: 'Trying to create an already created platform view, view id: $id',
); );
}
if (!_registeredViewTypes.contains(viewType)) if (!_registeredViewTypes.contains(viewType)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to create a platform view of unregistered type: $viewType', message: 'Trying to create a platform view of unregistered type: $viewType',
); );
}
if (createCompleter != null) { if (createCompleter != null) {
await createCompleter!.future; await createCompleter!.future;
...@@ -474,11 +484,12 @@ class FakeHtmlPlatformViewsController { ...@@ -474,11 +484,12 @@ class FakeHtmlPlatformViewsController {
Future<dynamic> _dispose(MethodCall call) { Future<dynamic> _dispose(MethodCall call) {
final int id = call.arguments as int; final int id = call.arguments as int;
if (!_views.containsKey(id)) if (!_views.containsKey(id)) {
throw PlatformException( throw PlatformException(
code: 'error', code: 'error',
message: 'Trying to dispose a platform view with unknown id: $id', message: 'Trying to dispose a platform view with unknown id: $id',
); );
}
_views.remove(id); _views.remove(id);
return Future<dynamic>.sync(() => null); return Future<dynamic>.sync(() => null);
...@@ -507,8 +518,9 @@ class FakeAndroidPlatformView { ...@@ -507,8 +518,9 @@ class FakeAndroidPlatformView {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is FakeAndroidPlatformView return other is FakeAndroidPlatformView
&& other.id == id && other.id == id
&& other.type == type && other.type == type
...@@ -570,8 +582,9 @@ class FakeUiKitView { ...@@ -570,8 +582,9 @@ class FakeUiKitView {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is FakeUiKitView return other is FakeUiKitView
&& other.id == id && other.id == id
&& other.type == type && other.type == type
...@@ -596,8 +609,9 @@ class FakeHtmlPlatformView { ...@@ -596,8 +609,9 @@ class FakeHtmlPlatformView {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is FakeHtmlPlatformView return other is FakeHtmlPlatformView
&& other.id == id && other.id == id
&& other.type == type; && other.type == type;
......
...@@ -32,14 +32,18 @@ void checkEncodeDecode<T>(MessageCodec<T> codec, T message) { ...@@ -32,14 +32,18 @@ void checkEncodeDecode<T>(MessageCodec<T> codec, T message) {
} }
bool deepEquals(dynamic valueA, dynamic valueB) { bool deepEquals(dynamic valueA, dynamic valueB) {
if (valueA is TypedData) if (valueA is TypedData) {
return valueB is TypedData && deepEqualsTypedData(valueA, valueB); return valueB is TypedData && deepEqualsTypedData(valueA, valueB);
if (valueA is List) }
if (valueA is List) {
return valueB is List && deepEqualsList(valueA, valueB); return valueB is List && deepEqualsList(valueA, valueB);
if (valueA is Map) }
if (valueA is Map) {
return valueB is Map && deepEqualsMap(valueA, valueB); return valueB is Map && deepEqualsMap(valueA, valueB);
if (valueA is double && valueA.isNaN) }
if (valueA is double && valueA.isNaN) {
return valueB is double && valueB.isNaN; return valueB is double && valueB.isNaN;
}
return valueA == valueB; return valueA == valueB;
} }
...@@ -48,35 +52,44 @@ bool deepEqualsTypedData(TypedData valueA, TypedData valueB) { ...@@ -48,35 +52,44 @@ bool deepEqualsTypedData(TypedData valueA, TypedData valueB) {
return valueB is ByteData return valueB is ByteData
&& deepEqualsList(valueA.buffer.asUint8List(), valueB.buffer.asUint8List()); && deepEqualsList(valueA.buffer.asUint8List(), valueB.buffer.asUint8List());
} }
if (valueA is Uint8List) if (valueA is Uint8List) {
return valueB is Uint8List && deepEqualsList(valueA, valueB); return valueB is Uint8List && deepEqualsList(valueA, valueB);
if (valueA is Int32List) }
if (valueA is Int32List) {
return valueB is Int32List && deepEqualsList(valueA, valueB); return valueB is Int32List && deepEqualsList(valueA, valueB);
if (valueA is Int64List) }
if (valueA is Int64List) {
return valueB is Int64List && deepEqualsList(valueA, valueB); return valueB is Int64List && deepEqualsList(valueA, valueB);
if (valueA is Float32List) }
if (valueA is Float32List) {
return valueB is Float32List && deepEqualsList(valueA, valueB); return valueB is Float32List && deepEqualsList(valueA, valueB);
if (valueA is Float64List) }
if (valueA is Float64List) {
return valueB is Float64List && deepEqualsList(valueA, valueB); return valueB is Float64List && deepEqualsList(valueA, valueB);
}
throw 'Unexpected typed data: $valueA'; throw 'Unexpected typed data: $valueA';
} }
bool deepEqualsList(List<dynamic> valueA, List<dynamic> valueB) { bool deepEqualsList(List<dynamic> valueA, List<dynamic> valueB) {
if (valueA.length != valueB.length) if (valueA.length != valueB.length) {
return false; return false;
}
for (int i = 0; i < valueA.length; i++) { for (int i = 0; i < valueA.length; i++) {
if (!deepEquals(valueA[i], valueB[i])) if (!deepEquals(valueA[i], valueB[i])) {
return false; return false;
}
} }
return true; return true;
} }
bool deepEqualsMap(Map<dynamic, dynamic> valueA, Map<dynamic, dynamic> valueB) { bool deepEqualsMap(Map<dynamic, dynamic> valueA, Map<dynamic, dynamic> valueB) {
if (valueA.length != valueB.length) if (valueA.length != valueB.length) {
return false; return false;
}
for (final dynamic key in valueA.keys) { for (final dynamic key in valueA.keys) {
if (!valueB.containsKey(key) || !deepEquals(valueA[key], valueB[key])) if (!valueB.containsKey(key) || !deepEquals(valueA[key], valueB[key])) {
return false; return false;
}
} }
return true; return true;
} }
...@@ -19,8 +19,9 @@ class MockRestorationManager extends TestRestorationManager { ...@@ -19,8 +19,9 @@ class MockRestorationManager extends TestRestorationManager {
@override @override
void initChannels() { void initChannels() {
if (enableChannels) if (enableChannels) {
super.initChannels(); super.initChannels();
}
} }
@override @override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment