From db9de349938eba9acb2113618d63f071577c01e2 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 17 Nov 2014 18:11:39 -0800 Subject: [PATCH 1/4] Add onWillThrowError --- src/atom.coffee | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 944e5049d..0a0497fbe 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -173,11 +173,21 @@ class Atom extends Model require('grim').deprecate = -> window.onerror = => - @openDevTools() - @executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()') @lastUncaughtError = Array::slice.call(arguments) + [message, url, line, column, originalError] = @lastUncaughtError + eventObject = {message, url, line, column, originalError} + + openDevTools = true + eventObject.preventDefault = -> openDevTools = false + + @emitter.emit 'will-throw-error', eventObject + + if openDevTools + @openDevTools() + @executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()') + @emit 'uncaught-error', arguments... - @emitter.emit 'did-throw-error', arguments... + @emitter.emit 'did-throw-error', message @unsubscribe() @setBodyPlatformClass() @@ -248,6 +258,22 @@ class Atom extends Model onDidBeep: (callback) -> @emitter.on 'did-beep', callback + # Extended: Invoke the given callback when there is an unhandled error, but + # before the devtools pop open + # + # * `callback` {Function} to be called whenever there is an unhandled error + # * `event` {Object} + # * `originalError` {Object} the original error object + # * `message` {String} the original error object + # * `url` {String} Url to the file where the error originated. + # * `line` {Number} + # * `column` {Number} + # * `preventDefault` {Function} call this to avoid popping up the dev tools. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onWillThrowError: (callback) -> + @emitter.on 'will-throw-error', callback + # Extended: Invoke the given callback whenever there is an unhandled error. # # * `callback` {Function} to be called whenever there is an unhandled error From e534997bf9a4fbbbc4ef0465c822cf87cb997173 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 18 Nov 2014 11:42:25 -0800 Subject: [PATCH 2/4] Specs for the error handler. --- spec/atom-spec.coffee | 64 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 615e510f7..aca2be885 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -52,3 +52,67 @@ describe "the `atom` global", -> it 'loads the default core config', -> expect(atom.config.get('core.excludeVcsIgnoredPaths')).toBe true expect(atom.config.get('editor.showInvisibles')).toBe false + + describe "window onerror handler", -> + beforeEach -> + spyOn atom, 'openDevTools' + spyOn atom, 'executeJavaScriptInDevTools' + + it "will open the dev tools when an error is triggered", -> + try + a + 1 + catch e + window.onerror.call(window, e.toString(), 'abc', 2, 3, e) + + expect(atom.openDevTools).toHaveBeenCalled() + expect(atom.executeJavaScriptInDevTools).toHaveBeenCalled() + + describe "::onWillThrowError", -> + willThrowSpy = null + beforeEach -> + willThrowSpy = jasmine.createSpy() + + it "is called when there is an error", -> + error = null + atom.onWillThrowError(willThrowSpy) + try + a + 1 + catch e + error = e + window.onerror.call(window, e.toString(), 'abc', 2, 3, e) + + delete willThrowSpy.mostRecentCall.args[0].preventDefault + expect(willThrowSpy).toHaveBeenCalledWith + message: error.toString() + url: 'abc' + line: 2 + column: 3 + originalError: error + + it "will not show the devtools when preventDefault() is called", -> + willThrowSpy.andCallFake (errorObject) -> errorObject.preventDefault() + atom.onWillThrowError(willThrowSpy) + + try + a + 1 + catch e + window.onerror.call(window, e.toString(), 'abc', 2, 3, e) + + expect(willThrowSpy).toHaveBeenCalled() + expect(atom.openDevTools).not.toHaveBeenCalled() + expect(atom.executeJavaScriptInDevTools).not.toHaveBeenCalled() + + describe "::onDidThrowError", -> + didThrowSpy = null + beforeEach -> + didThrowSpy = jasmine.createSpy() + + it "is called when there is an error", -> + error = null + atom.onDidThrowError(didThrowSpy) + try + a + 1 + catch e + error = e + window.onerror.call(window, e.toString(), 'abc', 2, e) + expect(didThrowSpy).toHaveBeenCalledWith(error.toString()) From 74966bd547b52c7f4325154c3ffeb0b652a2c9d0 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 19 Nov 2014 11:28:01 -0800 Subject: [PATCH 3/4] Emit an event object from atom.onDidThrowError --- spec/atom-spec.coffee | 9 +++++++-- src/atom.coffee | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index aca2be885..d802ee2cc 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -114,5 +114,10 @@ describe "the `atom` global", -> a + 1 catch e error = e - window.onerror.call(window, e.toString(), 'abc', 2, e) - expect(didThrowSpy).toHaveBeenCalledWith(error.toString()) + window.onerror.call(window, e.toString(), 'abc', 2, 3, e) + expect(didThrowSpy).toHaveBeenCalledWith + message: error.toString() + url: 'abc' + line: 2 + column: 3 + originalError: error diff --git a/src/atom.coffee b/src/atom.coffee index 0a0497fbe..be23d1cf6 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -187,7 +187,7 @@ class Atom extends Model @executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()') @emit 'uncaught-error', arguments... - @emitter.emit 'did-throw-error', message + @emitter.emit 'did-throw-error', {message, url, line, column, originalError} @unsubscribe() @setBodyPlatformClass() @@ -277,7 +277,12 @@ class Atom extends Model # Extended: Invoke the given callback whenever there is an unhandled error. # # * `callback` {Function} to be called whenever there is an unhandled error - # * `errorMessage` {String} + # * `event` {Object} + # * `originalError` {Object} the original error object + # * `message` {String} the original error object + # * `url` {String} Url to the file where the error originated. + # * `line` {Number} + # * `column` {Number} # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidThrowError: (callback) -> From db811cfa9e6c60b58b1368cb8a4812c69ed54df6 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 19 Nov 2014 11:38:50 -0800 Subject: [PATCH 4/4] Upgrade metrics to use the new onDidThrowError arg --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 030c566ec..50674f508 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "keybinding-resolver": "0.20.0", "link": "0.26.0", "markdown-preview": "0.110.0", - "metrics": "0.38.0", + "metrics": "0.39.0", "open-on-github": "0.30.0", "package-generator": "0.32.0", "release-notes": "0.36.0",