X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=node_modules%2Fhooker%2Fdist%2Fba-hooker.js;fp=node_modules%2Fhooker%2Fdist%2Fba-hooker.js;h=d10a3216b5ffd91891b83f034a2be7bf57c6815b;hp=0000000000000000000000000000000000000000;hb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;hpb=57c063afa3f66b07c4bbddc2d6129a96d90f0aad diff --git a/node_modules/hooker/dist/ba-hooker.js b/node_modules/hooker/dist/ba-hooker.js new file mode 100644 index 000000000..d10a3216b --- /dev/null +++ b/node_modules/hooker/dist/ba-hooker.js @@ -0,0 +1,169 @@ +/*! JavaScript Hooker - v0.2.3 - 1/29/2012 +* http://github.com/cowboy/javascript-hooker +* Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */ + +(function(exports) { + // Get an array from an array-like object with slice.call(arrayLikeObject). + var slice = [].slice; + // Get an "[object [[Class]]]" string with toString.call(value). + var toString = {}.toString; + + // I can't think of a better way to ensure a value is a specific type other + // than to create instances and use the `instanceof` operator. + function HookerOverride(v) { this.value = v; } + function HookerPreempt(v) { this.value = v; } + function HookerFilter(c, a) { this.context = c; this.args = a; } + + // When a pre- or post-hook returns the result of this function, the value + // passed will be used in place of the original function's return value. Any + // post-hook override value will take precedence over a pre-hook override + // value. + exports.override = function(value) { + return new HookerOverride(value); + }; + + // When a pre-hook returns the result of this function, the value passed will + // be used in place of the original function's return value, and the original + // function will NOT be executed. + exports.preempt = function(value) { + return new HookerPreempt(value); + }; + + // When a pre-hook returns the result of this function, the context and + // arguments passed will be applied into the original function. + exports.filter = function(context, args) { + return new HookerFilter(context, args); + }; + + // Execute callback(s) for properties of the specified object. + function forMethods(obj, props, callback) { + var prop; + if (typeof props === "string") { + // A single prop string was passed. Create an array. + props = [props]; + } else if (props == null) { + // No props were passed, so iterate over all properties, building an + // array. Unfortunately, Object.keys(obj) doesn't work everywhere yet, so + // this has to be done manually. + props = []; + for (prop in obj) { + if (obj.hasOwnProperty(prop)) { + props.push(prop); + } + } + } + // Execute callback for every method in the props array. + var i = props.length; + while (i--) { + // If the property isn't a function... + if (toString.call(obj[props[i]]) !== "[object Function]" || + // ...or the callback returns false... + callback(obj, props[i]) === false) { + // ...remove it from the props array to be returned. + props.splice(i, 1); + } + } + // Return an array of method names for which the callback didn't fail. + return props; + } + + // Monkey-patch (hook) a method of an object. + exports.hook = function(obj, props, options) { + // If the props argument was omitted, shuffle the arguments. + if (options == null) { + options = props; + props = null; + } + // If just a function is passed instead of an options hash, use that as a + // pre-hook function. + if (typeof options === "function") { + options = {pre: options}; + } + + // Hook the specified method of the object. + return forMethods(obj, props, function(obj, prop) { + // The original (current) method. + var orig = obj[prop]; + // The new hooked function. + function hooked() { + var result, origResult, tmp; + + // Get an array of arguments. + var args = slice.call(arguments); + + // If passName option is specified, prepend prop to the args array, + // passing it as the first argument to any specified hook functions. + if (options.passName) { + args.unshift(prop); + } + + // If a pre-hook function was specified, invoke it in the current + // context with the passed-in arguments, and store its result. + if (options.pre) { + result = options.pre.apply(this, args); + } + + if (result instanceof HookerFilter) { + // If the pre-hook returned hooker.filter(context, args), invoke the + // original function with that context and arguments, and store its + // result. + origResult = result = orig.apply(result.context, result.args); + } else if (result instanceof HookerPreempt) { + // If the pre-hook returned hooker.preempt(value) just use the passed + // value and don't execute the original function. + origResult = result = result.value; + } else { + // Invoke the original function in the current context with the + // passed-in arguments, and store its result. + origResult = orig.apply(this, arguments); + // If the pre-hook returned hooker.override(value), use the passed + // value, otherwise use the original function's result. + result = result instanceof HookerOverride ? result.value : origResult; + } + + if (options.post) { + // If a post-hook function was specified, invoke it in the current + // context, passing in the result of the original function as the + // first argument, followed by any passed-in arguments. + tmp = options.post.apply(this, [origResult].concat(args)); + if (tmp instanceof HookerOverride) { + // If the post-hook returned hooker.override(value), use the passed + // value, otherwise use the previously computed result. + result = tmp.value; + } + } + + // Unhook if the "once" option was specified. + if (options.once) { + exports.unhook(obj, prop); + } + + // Return the result! + return result; + } + // Re-define the method. + obj[prop] = hooked; + // Fail if the function couldn't be hooked. + if (obj[prop] !== hooked) { return false; } + // Store a reference to the original method as a property on the new one. + obj[prop]._orig = orig; + }); + }; + + // Get a reference to the original method from a hooked function. + exports.orig = function(obj, prop) { + return obj[prop]._orig; + }; + + // Un-monkey-patch (unhook) a method of an object. + exports.unhook = function(obj, props) { + return forMethods(obj, props, function(obj, prop) { + // Get a reference to the original method, if it exists. + var orig = exports.orig(obj, prop); + // If there's no original method, it can't be unhooked, so fail. + if (!orig) { return false; } + // Unhook the method. + obj[prop] = orig; + }); + }; +}(typeof exports === "object" && exports || this));