Created
May 14, 2009 12:16
-
-
Save voloko/111639 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/** | |
* Aspects for js (Function call interception) | |
* Released under the MIT License | |
* @copyright 2009 Vladimir Kolesnikov | |
* @author Vladimir Kolesnikov <[email protected]> | |
*/ | |
var Aspect = new function() { | |
this.add = function(obj, aspectName, aspect) { | |
for (var selector in aspect) { | |
if (!aspect.hasOwnProperty(selector)) continue; | |
wrapMethod(obj, selector, aspect[selector]) | |
} | |
obj.__aspects = obj.__aspects || {}; | |
obj.__aspects[aspectName] = aspect; | |
}, | |
this.remove = function(obj, aspectName) { | |
var aspect = obj.__aspects[aspectName], | |
selector; | |
for (selector in aspect) { | |
if (!aspect.hasOwnProperty(selector)) continue; | |
unwrapMethod(obj, selector, aspect[selector]); | |
} | |
delete obj.__aspects[aspectName]; | |
} | |
function wrapMethod(obj, selector, wrapper) { | |
var wrapperDescription = getWrapperDescription(selector), | |
method, runBefore = false; | |
method = obj[wrapperDescription.methodName]; | |
if (!method.__wrappers) { | |
method = obj[wrapperDescription.methodName] = createInterceptor(method); | |
}; | |
method.__wrappers[wrapperDescription.runBefore ? 'before' : 'after'].push(wrapper); | |
} | |
function unwrapMethod(obj, selector, wrapper) { | |
var wrapperDescription = getWrapperDescription(selector), | |
method = obj[wrapperDescription.methodName], | |
wrappers = method.__wrappers; | |
wrappers.before = without(wrappers.before, wrapper); | |
wrappers.after = without(wrappers.after, wrapper); | |
} | |
function getWrapperDescription(selector) { | |
var match = selector.match(/^((after|before) )?(.*)$/); | |
return { | |
runBefore: !match || match[2] != "after", | |
methodName: match ? match[3] : selector | |
} | |
} | |
function without(array, item) { | |
var result = []; | |
for (var i=0, l = array.length; i < l; i++) { | |
if (array[i] != item) result[result.length] = array[i]; | |
}; | |
return result; | |
} | |
function createInterceptor(method) { | |
var interceptor = function() { | |
for (var items = interceptor.__wrappers.before, l = items.length, i = 0; i < l; i++) { | |
try{ | |
items[i].apply(this, arguments); | |
} catch (e) { | |
if (e instanceof AspectReturnException) return e.value; | |
throw e | |
} | |
} | |
var result = method.apply(this, arguments); | |
for (items = interceptor.__wrappers.after, l = items.length, i = 0; i < l; i++) { | |
try { | |
items[i].apply(this, arguments); | |
} catch (e) { | |
throw e; | |
} | |
} | |
return result; | |
} | |
interceptor.__wrappers = { | |
before: [], | |
after: [] | |
} | |
return interceptor; | |
} | |
}; | |
var AspectReturnException = function(value) { this.value = value } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment