123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- (function(exports) {
-
- var slice = [].slice;
-
- var toString = {}.toString;
-
-
- function HookerOverride(v) { this.value = v; }
- function HookerPreempt(v) { this.value = v; }
- function HookerFilter(c, a) { this.context = c; this.args = a; }
-
-
-
-
- exports.override = function(value) {
- return new HookerOverride(value);
- };
-
-
-
- exports.preempt = function(value) {
- return new HookerPreempt(value);
- };
-
-
- exports.filter = function(context, args) {
- return new HookerFilter(context, args);
- };
-
- function forMethods(obj, props, callback) {
- var prop;
- if (typeof props === "string") {
-
- props = [props];
- } else if (props == null) {
-
-
-
- props = [];
- for (prop in obj) {
- if (obj.hasOwnProperty(prop)) {
- props.push(prop);
- }
- }
- }
-
- var i = props.length;
- while (i--) {
-
- if (toString.call(obj[props[i]]) !== "[object Function]" ||
-
- callback(obj, props[i]) === false) {
-
- props.splice(i, 1);
- }
- }
-
- return props;
- }
-
- exports.hook = function(obj, props, options) {
-
- if (options == null) {
- options = props;
- props = null;
- }
-
-
- if (typeof options === "function") {
- options = {pre: options};
- }
-
- return forMethods(obj, props, function(obj, prop) {
-
- var orig = obj[prop];
-
- function hooked() {
- var result, origResult, tmp;
-
- var args = slice.call(arguments);
-
-
- if (options.passName) {
- args.unshift(prop);
- }
-
-
- if (options.pre) {
- result = options.pre.apply(this, args);
- }
- if (result instanceof HookerFilter) {
-
-
-
- origResult = result = orig.apply(result.context, result.args);
- } else if (result instanceof HookerPreempt) {
-
-
- origResult = result = result.value;
- } else {
-
-
- origResult = orig.apply(this, arguments);
-
-
- result = result instanceof HookerOverride ? result.value : origResult;
- }
- if (options.post) {
-
-
-
- tmp = options.post.apply(this, [origResult].concat(args));
- if (tmp instanceof HookerOverride) {
-
-
- result = tmp.value;
- }
- }
-
- if (options.once) {
- exports.unhook(obj, prop);
- }
-
- return result;
- }
-
- obj[prop] = hooked;
-
- if (obj[prop] !== hooked) { return false; }
-
- obj[prop]._orig = orig;
- });
- };
-
- exports.orig = function(obj, prop) {
- return obj[prop]._orig;
- };
-
- exports.unhook = function(obj, props) {
- return forMethods(obj, props, function(obj, prop) {
-
- var orig = exports.orig(obj, prop);
-
- if (!orig) { return false; }
-
- obj[prop] = orig;
- });
- };
- }(typeof exports === "object" && exports || this));
|