| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 | define("dojo/aspect", [], function(){// TODOC: after/before/around return object// TODOC: after/before/around param types. /*=====	dojo.aspect = {		// 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		//	|	 });				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.		},				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	 		},		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		}	};=====*/	"use strict";	var 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(){					if(advised){						advised = dispatcher = advice = null;					}				},				advice: function(target, args){					return advised ?						advised.apply(target, args) :  // called the advised function						previous.advice(target, args); // cancelled, skip to next one				}			};		}else{			// create the remove handler			signal = {				remove: function(){					if(signal.advice){						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;							}						}						// remove the advice to signal that this signal has been removed						dispatcher = advice = signal.advice = null;					}				},				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){						results = after.receiveArguments ? after.advice.apply(this, args) || results :								after.advice.call(this, results);						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;		};	}	return {		before: aspect("before"),		around: aspect("around"),		after: aspect("after")	};});
 |