Merge pull request #781 from Hixie/better-exceptions
Better exception handling for rendering library.
This commit is contained in:
commit
1393b4c6b0
@ -512,7 +512,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||||||
|
|
||||||
String toStringName() {
|
String toStringName() {
|
||||||
String header = super.toStringName();
|
String header = super.toStringName();
|
||||||
if (_overflow > 0.0)
|
if (_overflow is double && _overflow > 0.0)
|
||||||
header += ' OVERFLOWING';
|
header += ' OVERFLOWING';
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
@ -318,6 +318,24 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
// Override in subclasses with children and call the visitor for each child.
|
// Override in subclasses with children and call the visitor for each child.
|
||||||
void visitChildren(RenderObjectVisitor visitor) { }
|
void visitChildren(RenderObjectVisitor visitor) { }
|
||||||
|
|
||||||
|
dynamic debugExceptionContext = '';
|
||||||
|
static dynamic _debugLastException;
|
||||||
|
bool _debugReportException(dynamic exception, String method) {
|
||||||
|
if (!inDebugBuild) {
|
||||||
|
print('Uncaught exception in ${method}():\n$exception');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!identical(exception, _debugLastException)) {
|
||||||
|
print('-- EXCEPTION --');
|
||||||
|
print('An exception was raised during ${method}().');
|
||||||
|
'The following RenderObject was being processed when the exception was fired:\n${this}'.split('\n').forEach(print);
|
||||||
|
if (debugExceptionContext != '')
|
||||||
|
'The RenderObject had the following exception context:\n${debugExceptionContext}'.split('\n').forEach(print);
|
||||||
|
_debugLastException = exception;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool _debugDoingLayout = false;
|
static bool _debugDoingLayout = false;
|
||||||
static bool get debugDoingLayout => _debugDoingLayout;
|
static bool get debugDoingLayout => _debugDoingLayout;
|
||||||
bool _debugDoingThisResize = false;
|
bool _debugDoingThisResize = false;
|
||||||
@ -443,10 +461,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Exception raised during layout:\n${e}\nContext:\n${this}');
|
if (_debugReportException(e, 'layoutWithoutResize'))
|
||||||
if (inDebugBuild)
|
|
||||||
rethrow;
|
rethrow;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
_needsLayout = false;
|
_needsLayout = false;
|
||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
@ -482,6 +498,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
_debugActiveLayout = this;
|
_debugActiveLayout = this;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
performLayout();
|
performLayout();
|
||||||
assert(() {
|
assert(() {
|
||||||
_debugActiveLayout = debugPreviousActiveLayout;
|
_debugActiveLayout = debugPreviousActiveLayout;
|
||||||
@ -490,6 +507,10 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
assert(debugDoesMeetConstraints());
|
assert(debugDoesMeetConstraints());
|
||||||
|
} catch (e) {
|
||||||
|
if (_debugReportException(e, 'layout'))
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
_needsLayout = false;
|
_needsLayout = false;
|
||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer
|
assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer
|
||||||
@ -666,10 +687,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
_paintWithContext(context, Offset.zero);
|
_paintWithContext(context, Offset.zero);
|
||||||
context.endRecording();
|
context.endRecording();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Exception raised during _paintLayer:\n${e}\nContext:\n${this}');
|
if (_debugReportException(e, '_repaint'))
|
||||||
if (inDebugBuild)
|
|
||||||
rethrow;
|
rethrow;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void _paintWithContext(PaintingContext context, Offset offset) {
|
void _paintWithContext(PaintingContext context, Offset offset) {
|
||||||
|
@ -6,6 +6,7 @@ import 'dart:async';
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:sky' as sky;
|
import 'dart:sky' as sky;
|
||||||
|
|
||||||
|
import 'package:sky/base/debug.dart';
|
||||||
import 'package:sky/base/hit_test.dart';
|
import 'package:sky/base/hit_test.dart';
|
||||||
import 'package:sky/base/scheduler.dart' as scheduler;
|
import 'package:sky/base/scheduler.dart' as scheduler;
|
||||||
import 'package:sky/mojo/activity.dart';
|
import 'package:sky/mojo/activity.dart';
|
||||||
@ -955,6 +956,13 @@ abstract class RenderObjectWrapper extends Widget {
|
|||||||
_ancestor = old._ancestor;
|
_ancestor = old._ancestor;
|
||||||
assert(_renderObject != null);
|
assert(_renderObject != null);
|
||||||
}
|
}
|
||||||
|
if (inDebugBuild) {
|
||||||
|
try {
|
||||||
|
throw null;
|
||||||
|
} catch (_, stack) {
|
||||||
|
_renderObject.debugExceptionContext = stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
assert(_renderObject == renderObject); // in case a subclass reintroduces it
|
assert(_renderObject == renderObject); // in case a subclass reintroduces it
|
||||||
assert(renderObject != null);
|
assert(renderObject != null);
|
||||||
assert(mounted);
|
assert(mounted);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user