Skip to content

Instantly share code, notes, and snippets.

@marlun78
Last active August 29, 2015 14:08
Show Gist options
  • Save marlun78/3a79b98370c05e982696 to your computer and use it in GitHub Desktop.
Save marlun78/3a79b98370c05e982696 to your computer and use it in GitHub Desktop.
Simple meta-programming for methods
/**
* Intercept.js
* Simple meta-programming for methods
* Copyright (c) 2014 marlun78
* MIT License, https://gist.github.com/marlun78/bd0800cf5e8053ba9f83
*
* The intercept-function provides a pre and a post hook that
* will run before and after the original implementation
* respectively. In the pre-hook you have access to the
* arguments passed, and in the post-hook you have access to
* both the arguments and the value returned by the original
* implementation.
*
* @example
* var math = { add: function add(a, b) { return a + b; } };
* var revert = intercept(math, 'add', pre, post);
* function pre(config) { console.log('Pre', config); }
* function post(config) { console.log('Post', config); }
* math.add(1, 2);
* // Pre, { args: [1, 2] }
* // Post, { args: [1, 2], returned: 3 }
* // 3
* revert();
* math.add(2, 3);
* // 5
*
* @param {Object} host - The object where the method lives in
* @param {String} name - The name of the method to intercept
* @param {Function} pre - A function to be called _before_ the original implementation
* @param {Function} post - A function to be called _after_ the original implementation
* @param {Boolean} once - Should this be reverted after the first call?
* @returns {Function} - A revert function
*/
var intercept = (function () {
'use strict';
var slice = Array.prototype.slice;
return function intercept(host, name, pre, post, once) {
var originalMethod = host[name];
if (isFunction(originalMethod)) {
host[name] = intercepted;
return revert;
}
return noop;
function intercepted() {
var config = { args: toArray(arguments) };
if (once === true) revert();
if (isFunction(pre)) pre.call(this, config);
config.returned = originalMethod.apply(this, config.args || []);
if (isFunction(post)) post.call(this, config);
return config.returned;
}
function revert() {
host[name] = originalMethod;
}
};
function noop() {}
function isFunction(value) {
return typeof value === 'function';
}
function toArray(value) {
return slice.call(value);
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment