| Index: dart/site/try/src/iframe_error_handler.dart
|
| diff --git a/dart/site/try/src/iframe_error_handler.dart b/dart/site/try/src/iframe_error_handler.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a1077be5455f386eb83bd1ea3452391f2413fcc4
|
| --- /dev/null
|
| +++ b/dart/site/try/src/iframe_error_handler.dart
|
| @@ -0,0 +1,96 @@
|
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library trydart.iframe_error_handler;
|
| +
|
| +// TODO(ahe): Remove this import if issue 17936 is fixed.
|
| +import 'dart:js' as hack;
|
| +
|
| +import 'dart:html' show
|
| + Event,
|
| + IFrameElement,
|
| + window;
|
| +
|
| +import 'dart:async' show
|
| + Stream,
|
| + StreamController;
|
| +
|
| +class ErrorMessage {
|
| + final String message;
|
| + final String filename;
|
| + final num lineno;
|
| + final num colno;
|
| + final String stack;
|
| +
|
| + ErrorMessage(
|
| + this.message, this.filename, this.lineno, this.colno, this.stack);
|
| +
|
| + String toString() {
|
| + String result = filename == null ? '' : filename;
|
| + if (lineno != null && lineno != 0 && !lineno.isNaN) {
|
| + result += ':$lineno';
|
| + }
|
| + if (colno != null && colno != 0 && !colno.isNaN) {
|
| + result += ':$colno';
|
| + }
|
| + if (message != null && !message.isEmpty) {
|
| + if (!result.isEmpty) {
|
| + result += ': ';
|
| + }
|
| + result += message;
|
| + }
|
| + if (stack != null && !stack.isEmpty) {
|
| + if (!result.isEmpty) {
|
| + result += '\n';
|
| + }
|
| + result += stack;
|
| + }
|
| + return result;
|
| + }
|
| +}
|
| +
|
| +Stream<ErrorMessage> errorStream(IFrameElement iframe) {
|
| + StreamController<ErrorMessage> controller =
|
| + new StreamController<ErrorMessage>();
|
| + void onError(
|
| + String message,
|
| + String filename,
|
| + int lineno,
|
| + [int colno,
|
| + error]) {
|
| + // See:
|
| + // https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
|
| + String stack;
|
| + if (error != null) {
|
| + var jsStack = error['stack'];
|
| + if (jsStack != null) {
|
| + stack = hack.context.callMethod('String', [jsStack]);
|
| + }
|
| + }
|
| + controller.add(new ErrorMessage(message, filename, lineno, colno, stack));
|
| + }
|
| +
|
| + void installErrorHandler() {
|
| + // This method uses dart:js to install an error event handler on the content
|
| + // window of [iframe]. This is a workaround for http://dartbug.com/17936.
|
| + var iframeProxy = new hack.JsObject.fromBrowserObject(iframe);
|
| + var contentWindowProxy = iframeProxy['contentWindow'];
|
| + if (contentWindowProxy == null) {
|
| + String message =
|
| + 'No contentWindow, call this method *after* adding iframe to'
|
| + ' document.';
|
| + window.console.error(message);
|
| + throw message;
|
| + }
|
| +
|
| + // Note: we have two options, use "iframe.contentWindow.onerror = ..." or
|
| + // "iframe.contentWindow.addEventListener('error', ...)". The former seems
|
| + // to provide more details on both Chrome and Firefox (which provides no
|
| + // information at all in error events).
|
| + contentWindowProxy['onerror'] = onError;
|
| + }
|
| + iframe.onLoad.listen((Event event) => installErrorHandler());
|
| + installErrorHandler();
|
| + return controller.stream;
|
| +}
|
|
|