Commit ed189ba9 authored by Ian Hickson's avatar Ian Hickson

Merge pull request #1653 from Hixie/debugging

Sundry debugging aids and fixes
parents c701ad6a d0d84e16
...@@ -7,6 +7,7 @@ library rendering; ...@@ -7,6 +7,7 @@ library rendering;
export 'src/rendering/auto_layout.dart'; export 'src/rendering/auto_layout.dart';
export 'src/rendering/basic_types.dart'; export 'src/rendering/basic_types.dart';
export 'src/rendering/binding.dart';
export 'src/rendering/block.dart'; export 'src/rendering/block.dart';
export 'src/rendering/box.dart'; export 'src/rendering/box.dart';
export 'src/rendering/debug.dart'; export 'src/rendering/debug.dart';
...@@ -22,7 +23,6 @@ export 'src/rendering/object.dart'; ...@@ -22,7 +23,6 @@ export 'src/rendering/object.dart';
export 'src/rendering/paragraph.dart'; export 'src/rendering/paragraph.dart';
export 'src/rendering/proxy_box.dart'; export 'src/rendering/proxy_box.dart';
export 'src/rendering/shifted_box.dart'; export 'src/rendering/shifted_box.dart';
export 'src/rendering/binding.dart';
export 'src/rendering/stack.dart'; export 'src/rendering/stack.dart';
export 'src/rendering/statistics_box.dart'; export 'src/rendering/statistics_box.dart';
export 'src/rendering/toggleable.dart'; export 'src/rendering/toggleable.dart';
......
...@@ -31,6 +31,8 @@ typedef void PerformanceStatusListener(PerformanceStatus status); ...@@ -31,6 +31,8 @@ typedef void PerformanceStatusListener(PerformanceStatus status);
/// want to watch a performance but should not be able to change the /// want to watch a performance but should not be able to change the
/// performance's state. /// performance's state.
abstract class PerformanceView { abstract class PerformanceView {
const PerformanceView();
/// Update the given variable according to the current progress of the performance /// Update the given variable according to the current progress of the performance
void updateVariable(Animatable variable); void updateVariable(Animatable variable);
/// Calls the listener every time the progress of the performance changes /// Calls the listener every time the progress of the performance changes
...@@ -45,6 +47,10 @@ abstract class PerformanceView { ...@@ -45,6 +47,10 @@ abstract class PerformanceView {
/// The current status of this animation /// The current status of this animation
PerformanceStatus get status; PerformanceStatus get status;
/// The current progress of this animation (a value from 0.0 to 1.0).
/// This is the value that is used to update any variables when using updateVariable().
double get progress;
/// Whether this animation is stopped at the beginning /// Whether this animation is stopped at the beginning
bool get isDismissed => status == PerformanceStatus.dismissed; bool get isDismissed => status == PerformanceStatus.dismissed;
...@@ -61,12 +67,16 @@ abstract class PerformanceView { ...@@ -61,12 +67,16 @@ abstract class PerformanceView {
/// [fling] the timeline causing a physics-based simulation to take over the /// [fling] the timeline causing a physics-based simulation to take over the
/// progression. /// progression.
class Performance extends PerformanceView { class Performance extends PerformanceView {
Performance({ this.duration, double progress }) { Performance({ this.duration, double progress, this.debugLabel }) {
_timeline = new SimulationStepper(_tick); _timeline = new SimulationStepper(_tick);
if (progress != null) if (progress != null)
_timeline.value = progress.clamp(0.0, 1.0); _timeline.value = progress.clamp(0.0, 1.0);
} }
/// A label that is used in the toString() output. Intended to aid with
/// identifying performance instances in debug output.
final String debugLabel;
/// Returns a [PerformanceView] for this performance, /// Returns a [PerformanceView] for this performance,
/// so that a pointer to this object can be passed around without /// so that a pointer to this object can be passed around without
/// allowing users of that pointer to mutate the AnimationPerformance state. /// allowing users of that pointer to mutate the AnimationPerformance state.
...@@ -220,6 +230,12 @@ class Performance extends PerformanceView { ...@@ -220,6 +230,12 @@ class Performance extends PerformanceView {
_notifyListeners(); _notifyListeners();
_checkStatusChanged(); _checkStatusChanged();
} }
String toString() {
if (debugLabel != null)
return '$runtimeType at $progress for $debugLabel';
return '$runtimeType at $progress';
}
} }
/// An animation performance with an animated variable with a concrete type /// An animation performance with an animated variable with a concrete type
......
...@@ -106,7 +106,7 @@ class _DrawerRoute extends Route { ...@@ -106,7 +106,7 @@ class _DrawerRoute extends Route {
final int level; final int level;
PerformanceView get performance => _performance?.view; PerformanceView get performance => _performance?.view;
Performance _performance = new Performance(duration: _kBaseSettleDuration); Performance _performance = new Performance(duration: _kBaseSettleDuration, debugLabel: 'Drawer');
bool get opaque => false; bool get opaque => false;
......
...@@ -6,6 +6,7 @@ import 'dart:ui' as ui; ...@@ -6,6 +6,7 @@ import 'dart:ui' as ui;
import 'package:flutter/animation.dart'; import 'package:flutter/animation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'box.dart'; import 'box.dart';
import 'hit_test.dart'; import 'hit_test.dart';
...@@ -252,5 +253,5 @@ class FlutterBinding extends HitTestTarget { ...@@ -252,5 +253,5 @@ class FlutterBinding extends HitTestTarget {
/// Prints a textual representation of the entire render tree /// Prints a textual representation of the entire render tree
void debugDumpRenderTree() { void debugDumpRenderTree() {
FlutterBinding.instance.renderView.toStringDeep().split('\n').forEach(print); debugPrint(FlutterBinding.instance.renderView.toStringDeep());
} }
...@@ -359,9 +359,11 @@ abstract class RenderBox extends RenderObject { ...@@ -359,9 +359,11 @@ abstract class RenderBox extends RenderObject {
final _DebugSize _size = this._size; final _DebugSize _size = this._size;
assert(_size._owner == this); assert(_size._owner == this);
if (RenderObject.debugActiveLayout != null) { if (RenderObject.debugActiveLayout != null) {
// we are always allowed to access our own size (for print debugging and asserts if nothing else) // We are always allowed to access our own size (for print debugging
// other than us, the only object that's allowed to read our size is our parent, if they're said they will // and asserts if nothing else). Other than us, the only object that's
// if you hit this assert trying to access a child's size, pass parentUsesSize: true in layout() // allowed to read our size is our parent, if they've said they will.
// If you hit this assert trying to access a child's size, pass
// "parentUsesSize: true" to that child's layout().
assert(debugDoingThisResize || debugDoingThisLayout || assert(debugDoingThisResize || debugDoingThisLayout ||
(RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent)); (RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent));
} }
...@@ -377,8 +379,12 @@ abstract class RenderBox extends RenderObject { ...@@ -377,8 +379,12 @@ abstract class RenderBox extends RenderObject {
assert((sizedByParent && debugDoingThisResize) || assert((sizedByParent && debugDoingThisResize) ||
(!sizedByParent && debugDoingThisLayout)); (!sizedByParent && debugDoingThisLayout));
assert(() { assert(() {
if (value is _DebugSize) if (value is _DebugSize) {
return value._canBeUsedByParent && value._owner.parent == this; if (value._owner != this) {
assert(value._owner.parent == this);
assert(value._canBeUsedByParent);
}
}
return true; return true;
}); });
_size = value; _size = value;
...@@ -389,6 +395,11 @@ abstract class RenderBox extends RenderObject { ...@@ -389,6 +395,11 @@ abstract class RenderBox extends RenderObject {
assert(debugDoesMeetConstraints()); assert(debugDoesMeetConstraints());
} }
void debugResetSize() {
// updates the value of size._canBeUsedByParent if necessary
size = size;
}
Map<TextBaseline, double> _cachedBaselines; Map<TextBaseline, double> _cachedBaselines;
bool _ancestorUsesBaseline = false; bool _ancestorUsesBaseline = false;
static bool _debugDoingBaseline = false; static bool _debugDoingBaseline = false;
...@@ -473,7 +484,7 @@ abstract class RenderBox extends RenderObject { ...@@ -473,7 +484,7 @@ abstract class RenderBox extends RenderObject {
}); });
bool result = constraints.isSatisfiedBy(_size); bool result = constraints.isSatisfiedBy(_size);
if (!result) if (!result)
print("${this.runtimeType} does not meet its constraints. Constraints: $constraints, size: $_size"); debugPrint("${this.runtimeType} does not meet its constraints. Constraints: $constraints, size: $_size");
return result; return result;
} }
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'dart:async';
import 'dart:collection';
/// Causes each RenderBox to paint a box around its bounds. /// Causes each RenderBox to paint a box around its bounds.
bool debugPaintSizeEnabled = false; bool debugPaintSizeEnabled = false;
...@@ -30,3 +32,34 @@ bool debugPaintBoundsEnabled = false; ...@@ -30,3 +32,34 @@ bool debugPaintBoundsEnabled = false;
/// The color to use when painting RenderError boxes in checked mode. /// The color to use when painting RenderError boxes in checked mode.
ui.Color debugErrorBoxColor = const ui.Color(0xFFFF0000); ui.Color debugErrorBoxColor = const ui.Color(0xFFFF0000);
/// Prints a message to the console, which you can access using the "flutter"
/// tool's "logs" command ("flutter logs").
///
/// This function very crudely attempts to throttle the rate at which messages
/// are sent to avoid data loss on Android. This means that interleaving calls
/// to this function (directly or indirectly via [debugDumpRenderTree] or
/// [debugDumpApp]) and to the Dart [print] method can result in out-of-order
/// messages in the logs.
void debugPrint(String message) {
_debugPrintBuffer.addAll(message.split('\n'));
if (!_debugPrintScheduled)
_debugPrintTask();
}
int _debugPrintedCharacters = 0;
int _kDebugPrintCapacity = 32 * 1024;
Queue<String> _debugPrintBuffer = new Queue<String>();
bool _debugPrintScheduled = false;
void _debugPrintTask() {
_debugPrintScheduled = false;
while (_debugPrintedCharacters < _kDebugPrintCapacity && _debugPrintBuffer.length > 0) {
String line = _debugPrintBuffer.removeFirst();
_debugPrintedCharacters += line.length; // TODO(ianh): Use the UTF-8 byte length instead
print(line);
}
if (_debugPrintBuffer.length > 0) {
_debugPrintScheduled = true;
_debugPrintedCharacters = 0;
new Timer(new Duration(seconds: 1), _debugPrintTask);
}
}
...@@ -513,14 +513,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -513,14 +513,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
dynamic debugExceptionContext = ''; dynamic debugExceptionContext = '';
void _debugReportException(String method, dynamic exception, StackTrace stack) { void _debugReportException(String method, dynamic exception, StackTrace stack) {
print('-- EXCEPTION --'); debugPrint('-- EXCEPTION --');
print('The following exception was raised during $method():'); debugPrint('The following exception was raised during $method():');
print('$exception'); debugPrint('$exception');
print('Stack trace:'); debugPrint('Stack trace:');
print('$stack'); debugPrint('$stack');
print('The following RenderObject was being processed when the exception was fired:\n${this}'); debugPrint('The following RenderObject was being processed when the exception was fired:\n${this}');
if (debugExceptionContext != '') if (debugExceptionContext != '')
'That RenderObject had the following exception context:\n$debugExceptionContext'.split('\n').forEach(print); debugPrint('That RenderObject had the following exception context:\n$debugExceptionContext');
if (debugRenderingExceptionHandler != null) if (debugRenderingExceptionHandler != null)
debugRenderingExceptionHandler(this, method, exception, stack); debugRenderingExceptionHandler(this, method, exception, stack);
} }
...@@ -723,15 +723,30 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -723,15 +723,30 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
else else
relayoutSubtreeRoot = parent._relayoutSubtreeRoot; relayoutSubtreeRoot = parent._relayoutSubtreeRoot;
assert(parent == this.parent); assert(parent == this.parent);
if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _relayoutSubtreeRoot) assert(() {
_debugCanParentUseSize = parentUsesSize;
return true;
});
if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _relayoutSubtreeRoot) {
assert(() {
// in case parentUsesSize changed since the last invocation, set size
// to itself, so it has the right internal debug values.
_debugDoingThisLayout = true;
RenderObject debugPreviousActiveLayout = _debugActiveLayout;
_debugActiveLayout = this;
debugResetSize();
_debugActiveLayout = debugPreviousActiveLayout;
_debugDoingThisLayout = false;
return true;
});
return; return;
}
_constraints = constraints; _constraints = constraints;
_relayoutSubtreeRoot = relayoutSubtreeRoot; _relayoutSubtreeRoot = relayoutSubtreeRoot;
assert(!_debugMutationsLocked); assert(!_debugMutationsLocked);
assert(!_doingThisLayoutWithCallback); assert(!_doingThisLayoutWithCallback);
assert(() { assert(() {
_debugMutationsLocked = true; _debugMutationsLocked = true;
_debugCanParentUseSize = parentUsesSize;
return true; return true;
}); });
if (sizedByParent) { if (sizedByParent) {
...@@ -768,6 +783,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -768,6 +783,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
assert(parent == this.parent); assert(parent == this.parent);
} }
/// If a subclass has a "size" (the state controlled by "parentUsesSize",
/// whatever it is in the subclass, e.g. the actual "size" property of
/// RenderBox), and the subclass verifies that in checked mode this "size"
/// property isn't used when debugCanParentUseSize isn't set, then that
/// subclass should override debugResetSize() to reapply the current values of
/// debugCanParentUseSize to that state.
void debugResetSize() { }
/// Whether the constraints are the only input to the sizing algorithm (in /// Whether the constraints are the only input to the sizing algorithm (in
/// particular, child nodes have no impact) /// particular, child nodes have no impact)
/// ///
......
...@@ -1018,7 +1018,7 @@ class RenderTransform extends RenderProxyBox { ...@@ -1018,7 +1018,7 @@ class RenderTransform extends RenderProxyBox {
String debugDescribeSettings(String prefix) { String debugDescribeSettings(String prefix) {
List<String> result = _transform.toString().split('\n').map((String s) => '$prefix $s\n').toList(); List<String> result = _transform.toString().split('\n').map((String s) => '$prefix $s\n').toList();
result.removeLast(); result.removeLast();
return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}\n${prefix}origin: $origin\nalignment: $alignment\n'; return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}\n${prefix}origin: $origin\n${prefix}alignment: $alignment\n';
} }
} }
......
...@@ -76,6 +76,11 @@ class Opacity extends OneChildRenderObjectWidget { ...@@ -76,6 +76,11 @@ class Opacity extends OneChildRenderObjectWidget {
void updateRenderObject(RenderOpacity renderObject, Opacity oldWidget) { void updateRenderObject(RenderOpacity renderObject, Opacity oldWidget) {
renderObject.opacity = opacity; renderObject.opacity = opacity;
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('opacity: $opacity');
}
} }
class ColorFilter extends OneChildRenderObjectWidget { class ColorFilter extends OneChildRenderObjectWidget {
...@@ -283,6 +288,14 @@ class SizedBox extends OneChildRenderObjectWidget { ...@@ -283,6 +288,14 @@ class SizedBox extends OneChildRenderObjectWidget {
void updateRenderObject(RenderConstrainedBox renderObject, SizedBox oldWidget) { void updateRenderObject(RenderConstrainedBox renderObject, SizedBox oldWidget) {
renderObject.additionalConstraints = _additionalConstraints; renderObject.additionalConstraints = _additionalConstraints;
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (width != null)
description.add('width: $width');
if (height != null)
description.add('height: $height');
}
} }
class ConstrainedBox extends OneChildRenderObjectWidget { class ConstrainedBox extends OneChildRenderObjectWidget {
...@@ -298,6 +311,11 @@ class ConstrainedBox extends OneChildRenderObjectWidget { ...@@ -298,6 +311,11 @@ class ConstrainedBox extends OneChildRenderObjectWidget {
void updateRenderObject(RenderConstrainedBox renderObject, ConstrainedBox oldWidget) { void updateRenderObject(RenderConstrainedBox renderObject, ConstrainedBox oldWidget) {
renderObject.additionalConstraints = constraints; renderObject.additionalConstraints = constraints;
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('constraints: $constraints');
}
} }
class FractionallySizedBox extends OneChildRenderObjectWidget { class FractionallySizedBox extends OneChildRenderObjectWidget {
...@@ -316,6 +334,14 @@ class FractionallySizedBox extends OneChildRenderObjectWidget { ...@@ -316,6 +334,14 @@ class FractionallySizedBox extends OneChildRenderObjectWidget {
renderObject.widthFactor = width; renderObject.widthFactor = width;
renderObject.heightFactor = height; renderObject.heightFactor = height;
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (width != null)
description.add('width: $width');
if (height != null)
description.add('height: $height');
}
} }
class OverflowBox extends OneChildRenderObjectWidget { class OverflowBox extends OneChildRenderObjectWidget {
...@@ -355,6 +381,11 @@ class AspectRatio extends OneChildRenderObjectWidget { ...@@ -355,6 +381,11 @@ class AspectRatio extends OneChildRenderObjectWidget {
void updateRenderObject(RenderAspectRatio renderObject, AspectRatio oldWidget) { void updateRenderObject(RenderAspectRatio renderObject, AspectRatio oldWidget) {
renderObject.aspectRatio = aspectRatio; renderObject.aspectRatio = aspectRatio;
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('aspectRatio: $aspectRatio');
}
} }
class IntrinsicWidth extends OneChildRenderObjectWidget { class IntrinsicWidth extends OneChildRenderObjectWidget {
...@@ -644,6 +675,18 @@ class Positioned extends ParentDataWidget { ...@@ -644,6 +675,18 @@ class Positioned extends ParentDataWidget {
if (needsLayout) if (needsLayout)
renderObject.markNeedsLayout(); renderObject.markNeedsLayout();
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (left != null)
description.add('left: $left');
if (top != null)
description.add('top: $top');
if (right != null)
description.add('right: $right');
if (bottom != null)
description.add('bottom: $bottom');
}
} }
class Grid extends MultiChildRenderObjectWidget { class Grid extends MultiChildRenderObjectWidget {
...@@ -728,6 +771,11 @@ class Flexible extends ParentDataWidget { ...@@ -728,6 +771,11 @@ class Flexible extends ParentDataWidget {
renderObject.markNeedsLayout(); renderObject.markNeedsLayout();
} }
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('flex: $flex');
}
} }
class Paragraph extends LeafRenderObjectWidget { class Paragraph extends LeafRenderObjectWidget {
...@@ -1077,6 +1125,11 @@ class MetaData extends OneChildRenderObjectWidget { ...@@ -1077,6 +1125,11 @@ class MetaData extends OneChildRenderObjectWidget {
void updateRenderObject(RenderMetaData renderObject, MetaData oldWidget) { void updateRenderObject(RenderMetaData renderObject, MetaData oldWidget) {
renderObject.metaData = metaData; renderObject.metaData = metaData;
} }
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$metaData');
}
} }
class KeyedSubtree extends StatelessComponent { class KeyedSubtree extends StatelessComponent {
......
...@@ -94,8 +94,8 @@ void debugDumpApp() { ...@@ -94,8 +94,8 @@ void debugDumpApp() {
assert(WidgetFlutterBinding.instance.renderViewElement != null); assert(WidgetFlutterBinding.instance.renderViewElement != null);
String mode = 'RELEASE MODE'; String mode = 'RELEASE MODE';
assert(() { mode = 'CHECKED MODE'; return true; }); assert(() { mode = 'CHECKED MODE'; return true; });
print('${WidgetFlutterBinding.instance.runtimeType} - $mode'); debugPrint('${WidgetFlutterBinding.instance.runtimeType} - $mode');
WidgetFlutterBinding.instance.renderViewElement.toStringDeep().split('\n').forEach(print); debugPrint(WidgetFlutterBinding.instance.renderViewElement.toStringDeep());
} }
/// This class provides a bridge from a RenderObject to an Element tree. The /// This class provides a bridge from a RenderObject to an Element tree. The
......
...@@ -7,6 +7,8 @@ import 'dart:collection'; ...@@ -7,6 +7,8 @@ import 'dart:collection';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
export 'package:flutter/rendering.dart' show debugPrint;
// KEYS // KEYS
/// A Key is an identifier for [Widget]s and [Element]s. A new Widget will only /// A Key is an identifier for [Widget]s and [Element]s. A new Widget will only
...@@ -184,7 +186,7 @@ class GlobalObjectKey extends GlobalKey { ...@@ -184,7 +186,7 @@ class GlobalObjectKey extends GlobalKey {
return identical(value, typedOther.value); return identical(value, typedOther.value);
} }
int get hashCode => identityHashCode(value); int get hashCode => identityHashCode(value);
String toString() => '[GlobalKey ${value.runtimeType}(${value.hashCode})]'; String toString() => '[$runtimeType ${value.runtimeType}(${value.hashCode})]';
} }
...@@ -823,10 +825,13 @@ abstract class Element<T extends Widget> implements BuildContext { ...@@ -823,10 +825,13 @@ abstract class Element<T extends Widget> implements BuildContext {
void debugFillDescription(List<String> description) { void debugFillDescription(List<String> description) {
if (depth == null) if (depth == null)
description.add('no depth'); description.add('no depth');
if (widget == null) if (widget == null) {
description.add('no widget'); description.add('no widget');
else } else {
if (widget.key != null)
description.add('${widget.key}');
widget.debugFillDescription(description); widget.debugFillDescription(description);
}
} }
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) { String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
...@@ -1090,7 +1095,7 @@ class StatefulComponentElement<T extends StatefulComponent, U extends State<T>> ...@@ -1090,7 +1095,7 @@ class StatefulComponentElement<T extends StatefulComponent, U extends State<T>>
assert(() { assert(() {
if (_state._debugLifecycleState == _StateLifecycle.initialized) if (_state._debugLifecycleState == _StateLifecycle.initialized)
return true; return true;
print('${_state.runtimeType}.initState failed to call super.initState'); debugPrint('${_state.runtimeType}.initState failed to call super.initState');
return false; return false;
}); });
assert(() { _state._debugLifecycleState = _StateLifecycle.ready; return true; }); assert(() { _state._debugLifecycleState = _StateLifecycle.ready; return true; });
...@@ -1123,7 +1128,7 @@ class StatefulComponentElement<T extends StatefulComponent, U extends State<T>> ...@@ -1123,7 +1128,7 @@ class StatefulComponentElement<T extends StatefulComponent, U extends State<T>>
assert(() { assert(() {
if (_state._debugLifecycleState == _StateLifecycle.defunct) if (_state._debugLifecycleState == _StateLifecycle.defunct)
return true; return true;
print('${_state.runtimeType}.dispose failed to call super.dispose'); debugPrint('${_state.runtimeType}.dispose failed to call super.dispose');
return false; return false;
}); });
assert(!dirty); // See BuildableElement.unmount for why this is important. assert(!dirty); // See BuildableElement.unmount for why this is important.
...@@ -1267,7 +1272,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab ...@@ -1267,7 +1272,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab
// dirty, e.g. if they have a builder callback. (Builder callbacks have a // dirty, e.g. if they have a builder callback. (Builder callbacks have a
// 'BuildContext' argument which you can pass to Theme.of() and other // 'BuildContext' argument which you can pass to Theme.of() and other
// InheritedWidget APIs which eventually trigger a rebuild.) // InheritedWidget APIs which eventually trigger a rebuild.)
print('$runtimeType failed to implement reinvokeBuilders(), but got marked dirty'); debugPrint('$runtimeType failed to implement reinvokeBuilders(), but got marked dirty');
assert(() { assert(() {
'reinvokeBuilders() not implemented'; 'reinvokeBuilders() not implemented';
return false; return false;
...@@ -1609,11 +1614,11 @@ void _debugReportException(String context, dynamic exception, StackTrace stack) ...@@ -1609,11 +1614,11 @@ void _debugReportException(String context, dynamic exception, StackTrace stack)
if (debugWidgetsExceptionHandler != null) { if (debugWidgetsExceptionHandler != null) {
debugWidgetsExceptionHandler(context, exception, stack); debugWidgetsExceptionHandler(context, exception, stack);
} else { } else {
print('------------------------------------------------------------------------'); debugPrint('------------------------------------------------------------------------');
'Exception caught while $context'.split('\n').forEach(print); debugPrint('Exception caught while $context');
print('$exception'); debugPrint('$exception');
print('Stack trace:'); debugPrint('Stack trace:');
'$stack'.split('\n').forEach(print); debugPrint('$stack');
print('------------------------------------------------------------------------'); debugPrint('------------------------------------------------------------------------');
} }
} }
...@@ -333,7 +333,7 @@ class _MixedViewportElement extends RenderObjectElement<MixedViewport> { ...@@ -333,7 +333,7 @@ class _MixedViewportElement extends RenderObjectElement<MixedViewport> {
double newExtent = _getElementExtent(element, innerConstraints); double newExtent = _getElementExtent(element, innerConstraints);
bool result = _childExtents[index] == newExtent; bool result = _childExtents[index] == newExtent;
if (!result) if (!result)
print("Element $element at index $index was size ${_childExtents[index]} but is now size $newExtent yet no invalidate() was received to that effect"); debugPrint("Element $element at index $index was size ${_childExtents[index]} but is now size $newExtent yet no invalidate() was received to that effect");
return result; return result;
} }
......
...@@ -14,7 +14,7 @@ void main() { ...@@ -14,7 +14,7 @@ void main() {
routes: <String, RouteBuilder>{ routes: <String, RouteBuilder>{
'/': (RouteArguments args) { '/': (RouteArguments args) {
navigator = args.navigator; navigator = args.navigator;
new Container(); return new Container();
} }
} }
) )
...@@ -43,7 +43,7 @@ void main() { ...@@ -43,7 +43,7 @@ void main() {
routes: <String, RouteBuilder>{ routes: <String, RouteBuilder>{
'/': (RouteArguments args) { '/': (RouteArguments args) {
navigator = args.navigator; navigator = args.navigator;
new Container(); return new Container();
} }
} }
) )
......
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