public
Last active

Improved way of temporarily replacing a method on an object

  • Download Gist
hook_method.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
var install_hook_to = function(obj) {
if (obj.hook || obj.unhook) {
throw new Error('Object already has properties hook and/or unhook');
}
obj.hook = function(_meth_name, _fn, _is_async) {
var self = this,
meth_ref;
// Make sure method exists
if (! (Object.prototype.toString.call(self[_meth_name]) === '[object Function]')) {
throw new Error('Invalid method: ' + _meth_name);
}
 
// We should not hook a hook
if (self.unhook.methods[_meth_name]) {
throw new Error('Method already hooked: ' + _meth_name);
}
 
// Reference default method
meth_ref = (self.unhook.methods[_meth_name] = self[_meth_name]);
 
self[_meth_name] = function() {
var args = Array.prototype.slice.call(arguments);
 
// Our hook should take the same number of arguments
// as the original method so we must fill with undefined
// optional args not provided in the call
while (args.length < meth_ref.length) {
args.push(undefined);
}
 
// Last argument is always original method call
args.push(function() {
var args = arguments;
if (_is_async) {
process.nextTick(function() {
meth_ref.apply(self, args);
});
} else {
meth_ref.apply(self, args);
}
});
 
_fn.apply(self, args);
};
};
obj.unhook = function(_meth_name) {
var self = this,
ref = self.unhook.methods[_meth_name];
 
if (ref) {
self[_meth_name] = self.unhook.methods[_meth_name];
delete self.unhook.methods[_meth_name];
} else {
throw new Error('Method not hooked: ' + _meth_name);
}
};
 
obj.unhook.methods = {};
};
 
//// Example ////
 
var stdout = process.stdout;
 
install_hook_to(stdout);
 
console.log('-- Sync');
 
stdout.hook('write', function(string, encoding, fd, write) {
write('caught: ' + string);
});
 
console.log('foo');
 
stdout.unhook('write');
 
console.log('-- Async');
 
stdout.hook('write', function(string, encoding, fd, write) {
write('caught async: ' + string);
}, true);
 
console.log('bar');
 
stdout.unhook('write');
 
console.log('baz');

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.