You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jb...@apache.org on 2010/08/17 18:45:19 UTC

svn commit: r986382 - /commons/sandbox/gsoc/2010/scxml-js/trunk/src/xslt/backends/js/AbstractStatechartGenerator.xsl

Author: jbeard
Date: Tue Aug 17 16:45:19 2010
New Revision: 986382

URL: http://svn.apache.org/viewvc?rev=986382&view=rev
Log:
Intermediate commit. Removing functional methods (forEach,map,filter and some) and replacing them with for loops, which are faster.
This commit will break support for IE only.

Modified:
    commons/sandbox/gsoc/2010/scxml-js/trunk/src/xslt/backends/js/AbstractStatechartGenerator.xsl

Modified: commons/sandbox/gsoc/2010/scxml-js/trunk/src/xslt/backends/js/AbstractStatechartGenerator.xsl
URL: http://svn.apache.org/viewvc/commons/sandbox/gsoc/2010/scxml-js/trunk/src/xslt/backends/js/AbstractStatechartGenerator.xsl?rev=986382&r1=986381&r2=986382&view=diff
==============================================================================
--- commons/sandbox/gsoc/2010/scxml-js/trunk/src/xslt/backends/js/AbstractStatechartGenerator.xsl (original)
+++ commons/sandbox/gsoc/2010/scxml-js/trunk/src/xslt/backends/js/AbstractStatechartGenerator.xsl Tue Aug 17 16:45:19 2010
@@ -23,11 +23,6 @@
 
 	<param name="log" select="false()"/>
 	<param name="genListenerHooks" select="true()"/>
-	<param name="noIndexOf" select="false()"/>
-	<param name="noMap" select="false()"/>
-	<param name="noForEach" select="false()"/>
-	<param name="noSome" select="false()"/>
-	<param name="noFilter" select="false()"/>
 
 	<!-- these variables get overridden by subclasses -->
 	<variable name="enumeratedEventDispatchInvocation"/>
@@ -67,6 +62,37 @@
 
 	<variable name="abstractStateName" select="'AbstractState'"/>
 
+	<variable name="defaultIteratorVarName" select="concat(generate-id(),'_iterator')"/>
+	<variable name="defaultHoistVarName" select="concat(generate-id(),'_hoist')"/>
+
+	<template name="genForEach">
+		<param name="var"/>
+		<param name="in"/>
+		<param name="when"/>
+		<param name="do"/>
+		<param name="iteratorVarName" select="$defaultIteratorVarName"/>
+		<param name="hoistVarName" select="$defaultHoistVarName"/>
+
+		for(var <value-of select="$iteratorVarName"/>=0, 
+			<value-of select="$hoistVarName"/>=<value-of select="$in"/>.length;
+				<value-of select="$iteratorVarName"/> &lt; <value-of select="$hoistVarName"/>;
+				<value-of select="$iteratorVarName"/>++){
+			<value-of select="$var"/> = <value-of select="$in"/>[<value-of select="$iteratorVarName"/>];
+
+			<choose>
+				<when test="$when">
+					if(<value-of select="$when"/>){
+						<value-of select="$do"/>
+					}
+				</when>
+				<otherwise>
+					<value-of select="$do"/>
+				</otherwise>
+			</choose>
+		}
+	
+	</template>
+
 	<!-- helper template to safely get a state's parent's name -->
 	<template name="getParentNameFromState">
 		<param name="s"/>
@@ -83,26 +109,6 @@
 
 	<template match="/s:scxml">
 
-		<if test="$noIndexOf">
-			<call-template name="genNoIndexOfArrayPrototypeExtension"/>
-		</if>
-
-		<if test="$noMap">
-			<call-template name="genNoMapArrayPrototypeExtension"/>
-		</if>
-
-		<if test="$noForEach">
-			<call-template name="genNoForEachArrayPrototypeExtension"/>
-		</if>
-
-		<if test="$noSome">
-			<call-template name="genNoSomeArrayPrototypeExtension"/>
-		</if>
-
-		<if test="$noFilter">
-			<call-template name="genNoFilterArrayPrototypeExtension"/>
-		</if>
-
 		function <value-of select="@name"/>StatechartExecutionContext(){
 
 				var self = this;	//used in the rare occasions we call public functions from inside this class
@@ -558,31 +564,39 @@
 		function microstep(e,data,isEnumeratedEvent){
 			if(isEnumeratedEvent){
 				//e does not contain a dot, so dispatch as an enumerated event
-				currentConfiguration.forEach(function(state){
-					if(!isPreempted){ 
-						//we set the event as a global, rather than passing it into the function invocation as a parameter,
-						//because in cases of default events, the event object will be populated with previous event's data
-						if(e !== <value-of select="$defaultEventLiteral"/> ){
-							_event.name=<value-of select="$eventToNameMap"/>;
-							_event.data=data;
+				<call-template name="genForEach">
+					<with-param name="var" select="'state'"/>
+					<with-param name="in" select="'currentConfiguration'"/>
+					<with-param name="do">
+						if(!isPreempted){ 
+							//we set the event as a global, rather than passing it into the function invocation as a parameter,
+							//because in cases of default events, the event object will be populated with previous event's data
+							if(e !== <value-of select="$defaultEventLiteral"/> ){
+								_event.name=<value-of select="$eventToNameMap"/>;
+								_event.data=data;
+							}
+							<value-of select="$enumeratedEventDispatchInvocation"/>
 						}
-						<value-of select="$enumeratedEventDispatchInvocation"/>
-					}
-				});
+					</with-param>
+				</call-template>
 			}else{
 				//e contains a dot, so dispatch as a prefix event
-				currentConfiguration.forEach(function(state){
-					if(!isPreempted){ 
-						//we set the event as a global, rather than passing it into the function invocation as a parameter,
-						//because in cases of default events, the event object will be populated with previous event's data
-						//NOTE: e will always be a string here, even in enumerated techniques
-						if(e !== <value-of select="$defaultEventLiteral"/> ){
-							_event.name=e;
-							_event.data=data;
+				<call-template name="genForEach">
+					<with-param name="var" select="'state'"/>
+					<with-param name="in" select="'currentConfiguration'"/>
+					<with-param name="do">
+						if(!isPreempted){ 
+							//we set the event as a global, rather than passing it into the function invocation as a parameter,
+							//because in cases of default events, the event object will be populated with previous event's data
+							//NOTE: e will always be a string here, even in enumerated techniques
+							if(e !== <value-of select="$defaultEventLiteral"/> ){
+								_event.name=e;
+								_event.data=data;
+							}
+							<value-of select="$prefixEventDispatchInvocation"/>
 						}
-						<value-of select="$prefixEventDispatchInvocation"/>
-					}
-				});
+					</with-param>
+				</call-template>
 			}
 
 			//reset the isPreempted flag
@@ -652,15 +666,19 @@
 			<apply-templates select="$t/*[self::s:if or self::s:raise or self::s:log or self::s:script or self::s:send or self::s:cancel or self::s:invoke or self::s:finalize or self::s:assign or self::s:validate ]"/>
 
 			<if test="$genListenerHooks">
-				listeners.forEach(function(l){
-					//transition id
-					<for-each select="$t/c:targets/c:target">
-						l.onTransition(
-							"<value-of select="../../../@id"/>",
-							"<value-of select="c:targetState"/>",
-							"<value-of select="@c:id"/>" );
-					</for-each>
-				});
+				<call-template name="genForEach">
+					<with-param name="var" select="'l'"/>
+					<with-param name="in" select="'listeners'"/>
+					<with-param name="do">
+						//transition id
+						<for-each select="$t/c:targets/c:target">
+							l.onTransition(
+								"<value-of select="../../../@id"/>",
+								"<value-of select="c:targetState"/>",
+								"<value-of select="@c:id"/>" );
+						</for-each>
+					</with-param>
+				</call-template>
 			</if>
 
 
@@ -689,17 +707,22 @@
 
 			var historyStateParent = <value-of select="$historyStateReference"/>.parent;
 
-			<value-of select="$historyStateReference"/>.lastConfiguration
-				.filter(function(state){
-					return <value-of select="$genHistoryTriggerDispatcherInnerForEachStateReference"/>
-						.ancestors.indexOf(historyStateParent)!=-1
-				})
-				.forEach(function(state){
+			<call-template name="genForEach">
+				<with-param name="var" select="'state'"/>
+				<with-param name="in">
+					<value-of select="$historyStateReference"/>.lastConfiguration
+				</with-param>
+				<with-param name="do">
 					<call-template name="genHistoryTriggerDispatcherInnerForEach">
 						<with-param name="isDeep" select="$isDeep"/>
 						<with-param name="isChildOfParallel" select="$isChildOfParallel"/>
 					</call-template>
-			});
+				</with-param>
+				<with-param name="when">
+					<value-of select="$genHistoryTriggerDispatcherInnerForEachStateReference"/>
+						.ancestors.indexOf(historyStateParent)!=-1
+				</with-param>
+			</call-template>
 			
 			<choose>
 				<when test="$isDeep">
@@ -771,30 +794,48 @@
 		var statesExited = [];
 		var lca = <value-of select="$t/c:lca"/>;
 
-		<value-of select="$genNonBasicTriggerDispatcherExitBlockIteratorExpression"/>
-			.filter(function(state){return state.ancestors.indexOf(lca) !== -1})
-			.forEach(function(state){
-			do{
-				statesExited.push(state);
-			}while((state = state.parent) &amp;&amp;
-				state != lca &amp;&amp; 
-				statesExited.indexOf(state) == -1)
-		});
+
+		<call-template name="genForEach">
+			<with-param name="var" select="'state'"/>
+			<with-param name="in" select="$genNonBasicTriggerDispatcherExitBlockIteratorExpression"/>
+			<with-param name="do">
+				do{
+					statesExited.push(state);
+				}while((state = state.parent) &amp;&amp;
+					state != lca &amp;&amp; 
+					statesExited.indexOf(state) == -1)
+			</with-param>
+			<with-param name="when">
+				state.ancestors.indexOf(lca) !== -1
+			</with-param>
+		</call-template>
 
 		//sort by depth
 		statesExited.sort(sortByDepthDeepToShallow);
 
 		//execute actions for each of these states
-		statesExited.forEach(function(state){
-			state.exitAction();
 
-			<if test="$genListenerHooks">
-				listeners.forEach(function(l){
-					//from
-					l.onExit(state.toString());
-				});
-			</if>
-		});
+		<call-template name="genForEach">
+			<with-param name="var" select="'state'"/>
+			<with-param name="in" select="'statesExited'"/>
+			<with-param name="do">
+				state.exitAction();
+
+				<if test="$genListenerHooks">
+					<call-template name="genForEach">
+						<with-param name="var" select="'listener'"/>
+						<with-param name="in" select="'listeners'"/>
+						<with-param name="do">
+							//from
+							listener.onExit(state.toString());
+						</with-param>
+						<!-- inner loop; assign these so we don't have a collision -->
+						<with-param name="iteratorVarName" select="concat(generate-id(),'_iterator')"/>
+						<with-param name="hoistVarName" select="concat(generate-id(),'_hoist')"/>
+					</call-template>
+				</if>
+			</with-param>
+		</call-template>
 	</template>
 
 	<template name="genTriggerDispatcherContents">
@@ -863,12 +904,14 @@
 				<for-each select="$t/c:exitpath/c:state">
 					<value-of select="."/>.exitAction();
 
-					<if test="$genListenerHooks">
-						listeners.forEach(function(l){
+					<call-template name="genForEach">
+						<with-param name="var" select="'listener'"/>
+						<with-param name="in" select="'listeners'"/>
+						<with-param name="do">
 							//from
-							l.onExit("<value-of select="."/>");
-						});
-					</if>
+							listener.onExit("<value-of select="."/>");
+						</with-param>
+					</call-template>
 				</for-each>
 			</when>
 			<otherwise>
@@ -881,15 +924,20 @@
 		//transition action
 		<apply-templates select="$t/*[self::s:if or self::s:raise or self::s:log or self::s:script or self::s:send or self::s:cancel or self::s:invoke or self::s:finalize or self::s:assign or self::s:validate ]"/>
 		<if test="$genListenerHooks">
-			listeners.forEach(function(l){
-				//transition id
-				<for-each select="$t/c:targets/c:target">
-					l.onTransition(
-						"<value-of select="../../../@id"/>",
-						"<value-of select="c:targetState"/>",
-						"<value-of select="@c:id"/>" );
-				</for-each>
-			});
+
+			<call-template name="genForEach">
+				<with-param name="var" select="'listener'"/>
+				<with-param name="in" select="'listeners'"/>
+				<with-param name="do">
+					//transition id
+					<for-each select="$t/c:targets/c:target">
+						listener.onTransition(
+							"<value-of select="../../../@id"/>",
+							"<value-of select="c:targetState"/>",
+							"<value-of select="@c:id"/>" );
+					</for-each>
+				</with-param>
+			</call-template>
 		</if>
 
 		//enter states
@@ -899,10 +947,15 @@
 			<value-of select="."/>.enterAction();
 
 			<if test="$genListenerHooks">
-				listeners.forEach(function(l){
-					//to
-					l.onEntry("<value-of select="."/>");
-				});
+
+				<call-template name="genForEach">
+					<with-param name="var" select="'listener'"/>
+					<with-param name="in" select="'listeners'"/>
+					<with-param name="do">
+						//to
+						listener.onEntry("<value-of select="."/>");
+					</with-param>
+				</call-template>
 			</if>
 		</for-each>
 
@@ -937,65 +990,6 @@
 		return;
 	</template>
 
-	<template name="genNoForEachArrayPrototypeExtension">
-		if(!Array.forEach){
-			Array.prototype.forEach = function(fn){
-				for(var i=0; i &lt; this.length; i++){
-					fn(this[i]);
-				}
-				return undefined;
-			}
-		}
-	</template>
-
-	<template name="genNoIndexOfArrayPrototypeExtension">
-		if(!Array.indexOf){
-			Array.prototype.indexOf = function(obj){
-				for(var i=0; i &lt; this.length; i++){
-					if(this[i]==obj){
-						return i;
-					}
-				}
-				return -1;
-			}
-		}
-	</template>
-
-	<template name="genNoMapArrayPrototypeExtension">
-		if(!Array.map){
-			Array.prototype.map = function(fn){
-				var toReturn = [];
-				for(var i=0; i &lt; this.length; i++){
-					toReturn[i]=fn(this[i]);
-				}
-				return toReturn;
-			}
-		}
-	</template>
-
-	<template name="genNoSomeArrayPrototypeExtension">
-		if(!Array.some){
-			Array.prototype.some = function(fn){
-				for(var i=0; i &lt; this.length; i++){
-					if(fn(this[i])) return true;
-				}
-				return false;
-			}
-		}
-	</template>
-
-	<template name="genNoFilterArrayPrototypeExtension">
-		if(!Array.filter){
-			Array.prototype.filter = function(fn){
-				var toReturn = [];
-				for(var i=0; i &lt; this.length; i++){
-					if(fn(this[i])) toReturn.push(this[i]);
-				}
-				return toReturn;
-			}
-		}
-	</template>
-
 	<variable name="genInPredicateFunction">
 		function In(state){
 			state = typeof state == "string" ? self._states[state] : state;