Created
March 9, 2012 14:32
-
-
Save iamkvein/2006752 to your computer and use it in GitHub Desktop.
Improved way of temporarily replacing a method on an object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment