Skip to content

Instantly share code, notes, and snippets.

@tnolet
Forked from iamkvein/hook_method.js
Created January 15, 2018 21:00
Show Gist options
  • Select an option

  • Save tnolet/97a57ed9ee630443909cc60da3154231 to your computer and use it in GitHub Desktop.

Select an option

Save tnolet/97a57ed9ee630443909cc60da3154231 to your computer and use it in GitHub Desktop.

Revisions

  1. @iamkvein iamkvein created this gist Mar 9, 2012.
    92 changes: 92 additions & 0 deletions hook_method.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,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');