Skip to content

Commit

Permalink
Raven.uninstall also restores builtin methods
Browse files Browse the repository at this point in the history
  • Loading branch information
benvinegar committed Jan 5, 2016
1 parent 03e8fc1 commit dd94eb5
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 11 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"grunt-release": "~0.6.0",
"grunt-s3": "~0.2.0-alpha.3",
"grunt-sri": "mattrobenolt/grunt-sri#pretty",
"jquery": "^2.1.4",
"lodash": "~2.4.0",
"proxyquireify": "^3.0.0",
"sinon": "~1.7.3",
Expand Down
35 changes: 28 additions & 7 deletions src/raven.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function Raven() {
this._originalConsoleMethods = {};
this._plugins = [];
this._startTime = now();
this._wrappedBuiltIns = [];

for (var method in this._originalConsole) {
this._originalConsoleMethods[method] = this._originalConsole[method];
Expand Down Expand Up @@ -267,6 +268,9 @@ Raven.prototype = {
*/
uninstall: function() {
TraceKit.report.uninstall();

this._restoreBuiltIns();

this._isRavenInstalled = false;

return this;
Expand Down Expand Up @@ -545,9 +549,12 @@ Raven.prototype = {
_wrapBuiltIns: function() {
var self = this;

function fill(obj, name, replacement) {
function fill(obj, name, replacement, noUndo) {
var orig = obj[name];
obj[name] = replacement(orig);
if (!noUndo) { // xhr instances can't undo otherwise mem leaks
self._wrappedBuiltIns.push([obj, name, orig]);
}
}

function wrapTimeFn(orig) {
Expand Down Expand Up @@ -613,20 +620,34 @@ Raven.prototype = {
if (prop in xhr && Object.prototype.toString.call(xhr[prop]) === '[object Function]') {
fill(xhr, prop, function (orig) {
return self.wrap(orig);
});
}, true);
}
});
origOpen.apply(this, arguments);
};
}

var $ = window.jQuery || window.$;
var origReady;
if ($ && $.fn && $.fn.ready) {
origReady = $.fn.ready;
$.fn.ready = function ravenjQueryReadyWrapper(fn) {
return origReady.call(this, self.wrap(fn));
};
fill($.fn, 'ready', function (orig) {
return function (fn) {
orig.call(this, self.wrap(fn));
};
});
}
},

_restoreBuiltIns: function () {
// restore any wrapped builtins
var builtin;
while (this._wrappedBuiltIns.length) {
builtin = this._wrappedBuiltIns.shift();

var obj = builtin[0],
name = builtin[1],
orig = builtin[2];

obj[name] = orig;
}
},

Expand Down
8 changes: 7 additions & 1 deletion test/integration/frame.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,20 @@
};
}());
</script>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="../../build/raven.js"></script>
<script>
// stub _makeRequest so we don't actually transmit any data
Raven._makeRequest = function () {};

// get a reference to the original, unwrapped setTimeout (used for
// making "clean" stack traces that don't originate from mocha)
window.origSetTimeout = setTimeout;
// and other built-ins
window.originalBuiltIns = {
setTimeout: setTimeout,
setInterval: setInterval,
requestAnimationFrame: requestAnimationFrame
};

window.ravenData = [];
Raven.config('https://[email protected]/1', {
Expand Down
71 changes: 68 additions & 3 deletions test/integration/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ function iframeExecute(iframe, done, execute, assertCallback) {
} catch (e) {
done(e);
}
}
};
// use setTimeout so stack trace doesn't go all the way back to mocha test runner
iframe.contentWindow.eval('origSetTimeout(' + execute.toString() + ');');
iframe.contentWindow.eval('window.originalBuiltIns.setTimeout.call(window, ' + execute.toString() + ');');
}

function createIframe(done) {
Expand Down Expand Up @@ -248,7 +248,7 @@ describe('integration', function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
foo();
}
};
xhr.open('GET', 'example.json');
xhr.send();
},
Expand All @@ -259,5 +259,70 @@ describe('integration', function () {
}
);
});

it('should capture exceptions from $.fn.ready (jQuery)', function (done) {
var iframe = this.iframe;

iframeExecute(iframe, done,
function () {
setTimeout(done);

$(function () {
foo();
});
},
function () {
var ravenData = iframe.contentWindow.ravenData[0];
// # of frames alter significantly between chrome/firefox & safari
assert.isAbove(ravenData.exception.values[0].stacktrace.frames.length, 2);
}
);
});
});

describe('uninstall', function () {
it('should restore original built-ins', function (done) {
var iframe = this.iframe;

iframeExecute(iframe, done,
function () {
setTimeout(done);
Raven.uninstall();
window.isRestored = {
setTimeout: originalBuiltIns.setTimeout === setTimeout,
setInterval: originalBuiltIns.setInterval === setInterval,
requestAnimationFrame: originalBuiltIns.requestAnimationFrame === requestAnimationFrame
};
},
function () {
var isRestored = iframe.contentWindow.isRestored;
assert.isTrue(isRestored.setTimeout);
assert.isTrue(isRestored.setInterval);
assert.isTrue(isRestored.requestAnimationFrame);
}
);
});

it('should not restore XMLHttpRequest instance methods', function (done) {
var iframe = this.iframe;

iframeExecute(iframe, done,
function () {
setTimeout(done);

var xhr = new XMLHttpRequest();
var origOnReadyStateChange = xhr.onreadystatechange = function () {};
xhr.open('GET', '/foo/');
xhr.abort();

Raven.uninstall();

window.isOnReadyStateChangeRestored = xhr.onready === origOnReadyStateChange;
},
function () {
assert.isFalse(iframe.contentWindow.isOnReadyStateChangeRestored);
}
);
});
});
});

0 comments on commit dd94eb5

Please sign in to comment.