diff options
author | Andrew Dolgov <[email protected]> | 2013-03-18 10:26:24 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2013-03-18 10:26:26 +0400 |
commit | f0cfe83e3725f9a3928da97a6e3085e79cb25309 (patch) | |
tree | 4b0af188defaa807c7bc6ff3a101b41c9166c463 /lib/dojo/aspect.js.uncompressed.js | |
parent | 9a2885da170ffd64358b99194095851a2d09c1b6 (diff) |
upgrade dojo to 1.8.3 (refs #570)
Diffstat (limited to 'lib/dojo/aspect.js.uncompressed.js')
-rw-r--r-- | lib/dojo/aspect.js.uncompressed.js | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/lib/dojo/aspect.js.uncompressed.js b/lib/dojo/aspect.js.uncompressed.js new file mode 100644 index 000000000..6752aedcf --- /dev/null +++ b/lib/dojo/aspect.js.uncompressed.js @@ -0,0 +1,216 @@ +define("dojo/aspect", [], function(){ + + // module: + // dojo/aspect + + "use strict"; + var undefined, nextId = 0; + function advise(dispatcher, type, advice, receiveArguments){ + var previous = dispatcher[type]; + var around = type == "around"; + var signal; + if(around){ + var advised = advice(function(){ + return previous.advice(this, arguments); + }); + signal = { + remove: function(){ + signal.cancelled = true; + }, + advice: function(target, args){ + return signal.cancelled ? + previous.advice(target, args) : // cancelled, skip to next one + advised.apply(target, args); // called the advised function + } + }; + }else{ + // create the remove handler + signal = { + remove: function(){ + var previous = signal.previous; + var next = signal.next; + if(!next && !previous){ + delete dispatcher[type]; + }else{ + if(previous){ + previous.next = next; + }else{ + dispatcher[type] = next; + } + if(next){ + next.previous = previous; + } + } + }, + id: nextId++, + advice: advice, + receiveArguments: receiveArguments + }; + } + if(previous && !around){ + if(type == "after"){ + // add the listener to the end of the list + // note that we had to change this loop a little bit to workaround a bizarre IE10 JIT bug + while(previous.next && (previous = previous.next)){} + previous.next = signal; + signal.previous = previous; + }else if(type == "before"){ + // add to beginning + dispatcher[type] = signal; + signal.next = previous; + previous.previous = signal; + } + }else{ + // around or first one just replaces + dispatcher[type] = signal; + } + return signal; + } + function aspect(type){ + return function(target, methodName, advice, receiveArguments){ + var existing = target[methodName], dispatcher; + if(!existing || existing.target != target){ + // no dispatcher in place + target[methodName] = dispatcher = function(){ + var executionId = nextId; + // before advice + var args = arguments; + var before = dispatcher.before; + while(before){ + args = before.advice.apply(this, args) || args; + before = before.next; + } + // around advice + if(dispatcher.around){ + var results = dispatcher.around.advice(this, args); + } + // after advice + var after = dispatcher.after; + while(after && after.id < executionId){ + if(after.receiveArguments){ + var newResults = after.advice.apply(this, args); + // change the return value only if a new value was returned + results = newResults === undefined ? results : newResults; + }else{ + results = after.advice.call(this, results, args); + } + after = after.next; + } + return results; + }; + if(existing){ + dispatcher.around = {advice: function(target, args){ + return existing.apply(target, args); + }}; + } + dispatcher.target = target; + } + var results = advise((dispatcher || existing), type, advice, receiveArguments); + advice = null; + return results; + }; + } + + // TODOC: after/before/around return object + + var after = aspect("after"); + /*===== + after = function(target, methodName, advice, receiveArguments){ + // summary: + // The "after" export of the aspect module is a function that can be used to attach + // "after" advice to a method. This function will be executed after the original method + // is executed. By default the function will be called with a single argument, the return + // value of the original method, or the the return value of the last executed advice (if a previous one exists). + // The fourth (optional) argument can be set to true to so the function receives the original + // arguments (from when the original method was called) rather than the return value. + // If there are multiple "after" advisors, they are executed in the order they were registered. + // target: Object + // This is the target object + // methodName: String + // This is the name of the method to attach to. + // advice: Function + // This is function to be called after the original method + // receiveArguments: Boolean? + // If this is set to true, the advice function receives the original arguments (from when the original mehtod + // was called) rather than the return value of the original/previous method. + // returns: + // A signal object that can be used to cancel the advice. If remove() is called on this signal object, it will + // stop the advice function from being executed. + }; + =====*/ + + var before = aspect("before"); + /*===== + before = function(target, methodName, advice){ + // summary: + // The "before" export of the aspect module is a function that can be used to attach + // "before" advice to a method. This function will be executed before the original method + // is executed. This function will be called with the arguments used to call the method. + // This function may optionally return an array as the new arguments to use to call + // the original method (or the previous, next-to-execute before advice, if one exists). + // If the before method doesn't return anything (returns undefined) the original arguments + // will be preserved. + // If there are multiple "before" advisors, they are executed in the reverse order they were registered. + // target: Object + // This is the target object + // methodName: String + // This is the name of the method to attach to. + // advice: Function + // This is function to be called before the original method + }; + =====*/ + + var around = aspect("around"); + /*===== + around = function(target, methodName, advice){ + // summary: + // The "around" export of the aspect module is a function that can be used to attach + // "around" advice to a method. The advisor function is immediately executed when + // the around() is called, is passed a single argument that is a function that can be + // called to continue execution of the original method (or the next around advisor). + // The advisor function should return a function, and this function will be called whenever + // the method is called. It will be called with the arguments used to call the method. + // Whatever this function returns will be returned as the result of the method call (unless after advise changes it). + // example: + // If there are multiple "around" advisors, the most recent one is executed first, + // which can then delegate to the next one and so on. For example: + // | around(obj, "foo", function(originalFoo){ + // | return function(){ + // | var start = new Date().getTime(); + // | var results = originalFoo.apply(this, arguments); // call the original + // | var end = new Date().getTime(); + // | console.log("foo execution took " + (end - start) + " ms"); + // | return results; + // | }; + // | }); + // target: Object + // This is the target object + // methodName: String + // This is the name of the method to attach to. + // advice: Function + // This is function to be called around the original method + }; + =====*/ + + return { + // summary: + // provides aspect oriented programming functionality, allowing for + // one to add before, around, or after advice on existing methods. + // example: + // | define(["dojo/aspect"], function(aspect){ + // | var signal = aspect.after(targetObject, "methodName", function(someArgument){ + // | this will be called when targetObject.methodName() is called, after the original function is called + // | }); + // + // example: + // The returned signal object can be used to cancel the advice. + // | signal.remove(); // this will stop the advice from being executed anymore + // | aspect.before(targetObject, "methodName", function(someArgument){ + // | // this will be called when targetObject.methodName() is called, before the original function is called + // | }); + + before: before, + around: around, + after: after + }; +}); |