Skip to content

Instantly share code, notes, and snippets.

@spiralx
Forked from johan/README.md
Created October 12, 2015 11:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spiralx/34ce7494c5cad71ce5fd to your computer and use it in GitHub Desktop.
Save spiralx/34ce7494c5cad71ce5fd to your computer and use it in GitHub Desktop.
JS debug breakpoint / log snippets

stopBefore.js

2min screencast

These tools inject a breakpoint, console.log or console.count in any function you want to spy on via stopBefore('Element.prototype.removeChild') or ditto stopAfter, logBefore / logAfter / logAround / logCount.

Works in Chrome DevTools and Safari Inspector; Firefox dev tools reportedly less so.

Examples

stopBefore('document.getElementById') // typical use
stopBefore(document, 'getElementById') // object ref and member name also works
stopBefore(Element.prototype, 'removeChild')

stopAfter(Element.prototype, 'querySelectorAll')

logBefore('alert')
logAfter('confirm')
logAround('prompt')

...will `console.log()` the method name before, after, or before and after a call,
latter two also logging the result returned afterwards:

> prompt("How's that?", "pretty cool");
-> prompt(2 args)
<- prompt(2 args): "really excellent!"

logCount('document.getElementById') just console.count()s the number of calls.

To revert back, call <methodname>.undo(), as many times as you have wrapped it.
(function(global) {
function resolvePath(path, name) {
if (name !== undefined || typeof path !== 'string')
return { self: path
, name: name
, func: path[name]
};
var obj = global, parts = path.split('.'), i, n;
for (i = 0, n = parts.length - 1; i < n; i++)
obj = obj[parts[i]];
return { self: obj
, name: name = parts[n]
, func: obj[name]
, path: path
};
}
function patch(old, now) {
now.undo = function() { return old.self[old.name] = old.func; };
return old.self[old.name] = now;
}
function callName(old) {
return old.path || old.self+'.'+old.name;
}
function callSign(old, args) {
var n = args.length, params = n ? n +' arg'+ (n===1? '' : 's') : '';
return callName(old) +'('+ params + ')';
}
global.stopBefore = function stopBefore(self, name) {
var old = resolvePath(self, name)
, now = function patched() {
debugger;
var res = old.func.apply(this, arguments);
return res;
};
return patch(old, now);
};
global.stopAfter = function stopAfter(self, name) {
var old = resolvePath(self, name)
, now = function patched() {
var res = old.func.apply(this, arguments);
debugger;
return res;
};
return patch(old, now);
};
global.logBefore = function logBefore(self, name) {
var old = resolvePath(self, name)
, now = function patched() {
console.log('-> '+ callSign(old, arguments));
var res = old.func.apply(this, arguments);
return res;
};
return patch(old, now);
};
global.logAfter = function logAfter(self, name) {
var old = resolvePath(self, name)
, now = function patched() {
var res = old.func.apply(this, arguments);
console.log('<- '+ callSign(old, arguments) +':', res);
return res;
};
return patch(old, now);
};
global.logAround = function logAround(self, name) {
var old = resolvePath(self, name)
, now = function patched() {
console.log('-> '+ callSign(old, arguments));
var res = old.func.apply(this, arguments);
console.log('<- '+ callSign(old, arguments) +':', res);
return res;
};
return patch(old, now);
};
global.logCount = function logCount(self, name) {
var old = resolvePath(self, name)
, now = function patched() {
console.count('-> '+ callName(old));
var res = old.func.apply(this, arguments);
return res;
};
return patch(old, now);
};
})(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment