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