Commit 19fb068d authored by Ian Hickson's avatar Ian Hickson

Merge pull request #1108 from Hixie/canFlex-error

Rationalise all our exception catching and reporting code
parents 07ed3fbf 13d6cc32
...@@ -82,8 +82,8 @@ abstract class Gesturer extends BindingBase implements HitTestTarget, HitTestabl ...@@ -82,8 +82,8 @@ abstract class Gesturer extends BindingBase implements HitTestTarget, HitTestabl
/// binding. The 'event' argument is the pointer event that was being routed. /// binding. The 'event' argument is the pointer event that was being routed.
/// The 'target' argument is the class whose handleEvent function threw the /// The 'target' argument is the class whose handleEvent function threw the
/// exception. The 'exception' argument contains the object that was thrown, /// exception. The 'exception' argument contains the object that was thrown,
/// and the 'stack' argument contains the stack trace. The callback is invoked /// and the 'stack' argument contains the stack trace. If no handler is
/// after the information is printed to the console. /// registered, then the information will be printed to the console instead.
GesturerExceptionHandler debugGesturerExceptionHandler; GesturerExceptionHandler debugGesturerExceptionHandler;
/// Dispatch the given event to the path of the given hit test result /// Dispatch the given event to the path of the given hit test result
...@@ -93,17 +93,20 @@ abstract class Gesturer extends BindingBase implements HitTestTarget, HitTestabl ...@@ -93,17 +93,20 @@ abstract class Gesturer extends BindingBase implements HitTestTarget, HitTestabl
try { try {
entry.target.handleEvent(event, entry); entry.target.handleEvent(event, entry);
} catch (exception, stack) { } catch (exception, stack) {
debugPrint('-- EXCEPTION --'); if (debugGesturerExceptionHandler != null) {
debugPrint('The following exception was raised while dispatching a pointer event:');
debugPrint('$exception');
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('Event:');
debugPrint('$event');
debugPrint('Target:');
debugPrint('${entry.target}');
if (debugGesturerExceptionHandler != null)
debugGesturerExceptionHandler(event, entry.target, exception, stack); debugGesturerExceptionHandler(event, entry.target, exception, stack);
} else {
debugPrint('-- EXCEPTION CAUGHT BY GESTURE LIBRARY ---------------------------------');
debugPrint('The following exception was raised while dispatching a pointer event:');
debugPrint('$exception');
debugPrint('Event:');
debugPrint('$event');
debugPrint('Target:');
debugPrint('${entry.target}');
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('------------------------------------------------------------------------');
}
} }
} }
} }
......
...@@ -43,9 +43,9 @@ class PointerRouter { ...@@ -43,9 +43,9 @@ class PointerRouter {
/// the exception. The 'event' argument is the pointer event that was being /// the exception. The 'event' argument is the pointer event that was being
/// routed. The 'route' argument is the callback that threw the exception. The /// routed. The 'route' argument is the callback that threw the exception. The
/// 'exception' argument contains the object that was thrown, and the 'stack' /// 'exception' argument contains the object that was thrown, and the 'stack'
/// argument contains the stack trace. The callback is invoked after the /// argument contains the stack trace. If no handler is registered, then the
/// information (exception, stack trace, and event; not the route callback /// human-readable parts of this information (the exception, event, and stack
/// itself) is printed to the console. /// trace) will be printed to the console instead.
PointerExceptionHandler debugPointerExceptionHandler; PointerExceptionHandler debugPointerExceptionHandler;
/// Calls the routes registered for this pointer event. /// Calls the routes registered for this pointer event.
...@@ -60,15 +60,18 @@ class PointerRouter { ...@@ -60,15 +60,18 @@ class PointerRouter {
try { try {
route(event); route(event);
} catch (exception, stack) { } catch (exception, stack) {
debugPrint('-- EXCEPTION --'); if (debugPointerExceptionHandler != null) {
debugPrint('The following exception was raised while routing a pointer event:');
debugPrint('$exception');
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('Event:');
debugPrint('$event');
if (debugPointerExceptionHandler != null)
debugPointerExceptionHandler(this, event, route, exception, stack); debugPointerExceptionHandler(this, event, route, exception, stack);
} else {
debugPrint('-- EXCEPTION CAUGHT BY GESTURE LIBRARY ---------------------------------');
debugPrint('The following exception was raised while routing a pointer event:');
debugPrint('$exception');
debugPrint('Event:');
debugPrint('$event');
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('------------------------------------------------------------------------');
}
} }
} }
} }
......
...@@ -381,9 +381,8 @@ typedef void RenderingExceptionHandler(RenderObject source, String method, dynam ...@@ -381,9 +381,8 @@ typedef void RenderingExceptionHandler(RenderObject source, String method, dynam
/// exception. The 'method' argument is the method in which the exception /// exception. The 'method' argument is the method in which the exception
/// occurred; it will be one of 'performResize', 'performLayout, or 'paint'. The /// occurred; it will be one of 'performResize', 'performLayout, or 'paint'. The
/// 'exception' argument contains the object that was thrown, and the 'stack' /// 'exception' argument contains the object that was thrown, and the 'stack'
/// argument contains the stack trace. The callback is invoked after the /// argument contains the stack trace. If no handler is registered, then the
/// information is printed to the console, and could be used to print additional /// information will be printed to the console instead.
/// information, such as from [debugDumpRenderTree()].
RenderingExceptionHandler debugRenderingExceptionHandler; RenderingExceptionHandler debugRenderingExceptionHandler;
/// An object in the render tree. /// An object in the render tree.
...@@ -461,16 +460,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -461,16 +460,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
dynamic debugOwner; dynamic debugOwner;
void _debugReportException(String method, dynamic exception, StackTrace stack) { void _debugReportException(String method, dynamic exception, StackTrace stack) {
debugPrint('-- EXCEPTION --'); if (debugRenderingExceptionHandler != null) {
debugPrint('The following exception was raised during $method():');
debugPrint('$exception');
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('The following RenderObject was being processed when the exception was fired:\n${this}');
if (debugOwner != null)
debugPrint('That RenderObject had the following owner:\n$debugOwner');
if (debugRenderingExceptionHandler != null)
debugRenderingExceptionHandler(this, method, exception, stack); debugRenderingExceptionHandler(this, method, exception, stack);
} else {
debugPrint('-- EXCEPTION CAUGHT BY RENDERING LIBRARY -------------------------------');
debugPrint('The following exception was raised during $method():');
debugPrint('$exception');
debugPrint('The following RenderObject was being processed when the exception was fired:\n${this}');
if (debugOwner != null)
debugPrint('That RenderObject had the following owner:\n$debugOwner');
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('------------------------------------------------------------------------');
}
} }
static bool _debugDoingLayout = false; static bool _debugDoingLayout = false;
......
...@@ -271,10 +271,12 @@ abstract class Scheduler extends BindingBase { ...@@ -271,10 +271,12 @@ abstract class Scheduler extends BindingBase {
if (debugSchedulerExceptionHandler != null) { if (debugSchedulerExceptionHandler != null) {
debugSchedulerExceptionHandler(exception, stack); debugSchedulerExceptionHandler(exception, stack);
} else { } else {
print('-- EXCEPTION IN SCHEDULER CALLBACK --'); debugPrint('-- EXCEPTION CAUGHT BY SCHEDULER LIBRARY -------------------------------');
print('$exception'); debugPrint('An exception was raised during a scheduler callback:');
print('Stack trace:'); debugPrint('$exception');
print('$stack'); debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('------------------------------------------------------------------------');
} }
} }
} }
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'print.dart';
/// A callback for when the image is available. /// A callback for when the image is available.
typedef void ImageListener(ui.Image image); typedef void ImageListener(ui.Image image);
...@@ -15,7 +17,7 @@ typedef void ImageListener(ui.Image image); ...@@ -15,7 +17,7 @@ typedef void ImageListener(ui.Image image);
/// or because the underlying image resource was mutated. /// or because the underlying image resource was mutated.
class ImageResource { class ImageResource {
ImageResource(this._futureImage) { ImageResource(this._futureImage) {
_futureImage.then(_handleImageLoaded, onError: _handleImageError); _futureImage.then(_handleImageLoaded, onError: (exception, stack) => _handleImageError('Failed to load image:', exception, stack));
} }
bool _resolved = false; bool _resolved = false;
...@@ -34,8 +36,13 @@ class ImageResource { ...@@ -34,8 +36,13 @@ class ImageResource {
/// this object will call the listener synchronously. /// this object will call the listener synchronously.
void addListener(ImageListener listener) { void addListener(ImageListener listener) {
_listeners.add(listener); _listeners.add(listener);
if (_resolved) if (_resolved) {
listener(_image); try {
listener(_image);
} catch (exception, stack) {
_handleImageError('The following exception was thrown by a synchronously-invoked image listener:', exception, stack);
}
}
} }
/// Stop listening for new concrete [ui.Image] objects. /// Stop listening for new concrete [ui.Image] objects.
...@@ -49,19 +56,24 @@ class ImageResource { ...@@ -49,19 +56,24 @@ class ImageResource {
_notifyListeners(); _notifyListeners();
} }
void _handleImageError(e, stackTrace) {
print('Failed to load image: $e\nStack trace: $stackTrace');
}
void _notifyListeners() { void _notifyListeners() {
assert(_resolved); assert(_resolved);
List<ImageListener> localListeners = new List<ImageListener>.from(_listeners); List<ImageListener> localListeners = new List<ImageListener>.from(_listeners);
for (ImageListener listener in localListeners) { for (ImageListener listener in localListeners) {
try { try {
listener(_image); listener(_image);
} catch(e) { } catch (exception, stack) {
print('Image listener had exception: $e'); _handleImageError('The following exception was thrown by an image listener:', exception, stack);
} }
} }
} }
void _handleImageError(String message, dynamic exception, dynamic stack) {
debugPrint('-- EXCEPTION CAUGHT BY SERVICES LIBRARY --------------------------------');
debugPrint(message);
debugPrint('$exception');
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('------------------------------------------------------------------------');
}
} }
...@@ -1404,6 +1404,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab ...@@ -1404,6 +1404,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab
void mount(Element parent, dynamic newSlot) { void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot); super.mount(parent, newSlot);
assert(_slot == newSlot); assert(_slot == newSlot);
assert(() { debugUpdateRenderObjectOwner(); return true; });
attachRenderObject(newSlot); attachRenderObject(newSlot);
_dirty = false; _dirty = false;
} }
...@@ -1788,7 +1789,7 @@ void _debugReportException(String context, dynamic exception, StackTrace stack) ...@@ -1788,7 +1789,7 @@ void _debugReportException(String context, dynamic exception, StackTrace stack)
if (debugWidgetsExceptionHandler != null) { if (debugWidgetsExceptionHandler != null) {
debugWidgetsExceptionHandler(context, exception, stack); debugWidgetsExceptionHandler(context, exception, stack);
} else { } else {
debugPrint('------------------------------------------------------------------------'); debugPrint('-- EXCEPTION CAUGHT BY WIDGETS LIBRARY ---------------------------------');
debugPrint('Exception caught while $context'); debugPrint('Exception caught while $context');
debugPrint('$exception'); debugPrint('$exception');
debugPrint('Stack trace:'); debugPrint('Stack trace:');
......
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