Commit 1393b4c6 authored by Ian Hickson's avatar Ian Hickson

Merge pull request #781 from Hixie/better-exceptions

Better exception handling for rendering library.
parents a4182561 d99641dd
......@@ -512,7 +512,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
String toStringName() {
String header = super.toStringName();
if (_overflow > 0.0)
if (_overflow is double && _overflow > 0.0)
header += ' OVERFLOWING';
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.
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 get debugDoingLayout => _debugDoingLayout;
bool _debugDoingThisResize = false;
......@@ -443,10 +461,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
return true;
});
} catch (e) {
print('Exception raised during layout:\n${e}\nContext:\n${this}');
if (inDebugBuild)
if (_debugReportException(e, 'layoutWithoutResize'))
rethrow;
return;
}
_needsLayout = false;
markNeedsPaint();
......@@ -482,14 +498,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
_debugActiveLayout = this;
return true;
});
performLayout();
assert(() {
_debugActiveLayout = debugPreviousActiveLayout;
_debugDoingThisLayout = false;
_debugMutationsLocked = false;
return true;
});
assert(debugDoesMeetConstraints());
try {
performLayout();
assert(() {
_debugActiveLayout = debugPreviousActiveLayout;
_debugDoingThisLayout = false;
_debugMutationsLocked = false;
return true;
});
assert(debugDoesMeetConstraints());
} catch (e) {
if (_debugReportException(e, 'layout'))
rethrow;
}
_needsLayout = false;
markNeedsPaint();
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);
context.endRecording();
} catch (e) {
print('Exception raised during _paintLayer:\n${e}\nContext:\n${this}');
if (inDebugBuild)
if (_debugReportException(e, '_repaint'))
rethrow;
return;
}
}
void _paintWithContext(PaintingContext context, Offset offset) {
......
......@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:collection';
import 'dart:sky' as sky;
import 'package:sky/base/debug.dart';
import 'package:sky/base/hit_test.dart';
import 'package:sky/base/scheduler.dart' as scheduler;
import 'package:sky/mojo/activity.dart';
......@@ -955,6 +956,13 @@ abstract class RenderObjectWrapper extends Widget {
_ancestor = old._ancestor;
assert(_renderObject != null);
}
if (inDebugBuild) {
try {
throw null;
} catch (_, stack) {
_renderObject.debugExceptionContext = stack;
}
}
assert(_renderObject == renderObject); // in case a subclass reintroduces it
assert(renderObject != null);
assert(mounted);
......
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