Skip to content

Commit 44c2e89

Browse files
committed
Wrap builtins automatically ...
* Wrap setTimeout, setInterval, requestAnimationFrame * Don't capture errors via onerror that have already been caught via wrap
1 parent 2c21c0b commit 44c2e89

File tree

2 files changed

+60
-16
lines changed

2 files changed

+60
-16
lines changed

src/raven.js

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function Raven() {
4747
collectWindowErrors: true,
4848
maxMessageLength: 100
4949
};
50+
this._ignoreOnError = 0;
5051
this._isRavenInstalled = false;
5152
// capture references to window.console *and* all its methods first
5253
// before the console plugin has a chance to monkey patch
@@ -153,8 +154,11 @@ Raven.prototype = {
153154
if (this.isSetup() && !this._isRavenInstalled) {
154155
TraceKit.report.subscribe(function () {
155156
// maintain 'self'
156-
self._handleStackInfo.apply(self, arguments);
157+
if (!self._ignoreOnError) {
158+
self._handleStackInfo.apply(self, arguments);
159+
}
157160
});
161+
this._wrapBuiltIns();
158162

159163
// Install all of the plugins
160164
this._drainPlugins();
@@ -228,6 +232,7 @@ Raven.prototype = {
228232
/*jshint -W040*/
229233
return func.apply(this, args);
230234
} catch(e) {
235+
self._ignoreNextOnError();
231236
self.captureException(e, options);
232237
throw e;
233238
}
@@ -484,6 +489,14 @@ Raven.prototype = {
484489
},
485490

486491
/**** Private functions ****/
492+
_ignoreNextOnError: function () {
493+
this._ignoreOnError += 1;
494+
setTimeout(function () {
495+
// onerror should trigger before setTimeout
496+
this._ignoreOnError -= 1;
497+
});
498+
},
499+
487500
_triggerEvent: function(eventType, options) {
488501
// NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it
489502
var evt, key;
@@ -522,6 +535,37 @@ Raven.prototype = {
522535
/**
523536
* Install any queued plugins
524537
*/
538+
_wrapBuiltIns: function() {
539+
var self = this;
540+
541+
var _helper = function _helper(fnName) {
542+
var originalFn = window[fnName];
543+
window[fnName] = function ravenAsyncExtension() {
544+
// Make a copy of the arguments
545+
var args = [].slice.call(arguments);
546+
var originalCallback = args[0];
547+
if (typeof (originalCallback) === 'function') {
548+
args[0] = self.wrap(originalCallback);
549+
}
550+
551+
// IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it
552+
// also supports only two arguments and doesn't care what this is, so we
553+
// can just call the original function directly.
554+
if (originalFn.apply) {
555+
return originalFn.apply(this, args);
556+
} else {
557+
return originalFn(args[0], args[1]);
558+
}
559+
};
560+
};
561+
562+
_helper('setTimeout');
563+
_helper('setInterval');
564+
if (window.requestAnimationFrame) {
565+
_helper('requestAnimationFrame');
566+
}
567+
},
568+
525569
_drainPlugins: function() {
526570
var self = this;
527571

@@ -676,21 +720,21 @@ Raven.prototype = {
676720
if (!!this._globalOptions.ignoreUrls.test && this._globalOptions.ignoreUrls.test(fileurl)) return;
677721
if (!!this._globalOptions.whitelistUrls.test && !this._globalOptions.whitelistUrls.test(fileurl)) return;
678722

723+
var data = objectMerge({
724+
// sentry.interfaces.Exception
725+
exception: {
726+
values: [{
727+
type: type,
728+
value: message,
729+
stacktrace: stacktrace
730+
}]
731+
},
732+
culprit: fileurl,
733+
message: fullMessage
734+
}, options);
735+
679736
// Fire away!
680-
this._send(
681-
objectMerge({
682-
// sentry.interfaces.Exception
683-
exception: {
684-
values: [{
685-
type: type,
686-
value: message,
687-
stacktrace: stacktrace
688-
}]
689-
},
690-
culprit: fileurl,
691-
message: fullMessage
692-
}, options)
693-
);
737+
this._send(data);
694738
},
695739

696740
_trimPacket: function(data) {

test/integration/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function iframeExecute(iframe, done, execute, assertCallback) {
88
done(e);
99
}
1010
}
11-
iframe.contentWindow.eval('setTimeout(' + execute.toString() + ');');
11+
iframe.contentWindow.eval('(' + execute.toString() + ')();');
1212
}
1313

1414
describe('integration', function () {

0 commit comments

Comments
 (0)