Permalink
Browse files

Updated Makefile and stitch build file to put files in folder dist/. …

…Checked in contents of dist/ to make distribution easier.
  • Loading branch information...
1 parent f0549be commit 3a3092ad9124e09383c91bab4126dbe282aed77b @jbeard4 committed Dec 21, 2012
Showing with 2,359 additions and 8 deletions.
  1. +5 −6 Makefile
  2. +1 −0 dist/scion-min.js
  3. +2,349 −0 dist/scion.js
  4. +4 −2 lib/browser/build/stitch.js
View
11 Makefile
@@ -1,13 +1,12 @@
js = $(shell find lib/ -name "*.js")
+dist/scion.js : $(js)
+ mkdir -p dist && node lib/browser/build/stitch.js dist/scion.js
-scion-browser.js : $(js)
- node lib/browser/build/stitch.js
-
-scion-browser-min.js : scion-browser.js
- uglifyjs scion-browser.js > scion-browser-min.js
+dist/scion-min.js : dist/scion.js
+ uglifyjs dist/scion.js > dist/scion-min.js
clean :
- rm scion-browser.js scion-browser-min.js
+ rm -rf dist
.PHONY : clean
View
1 dist/scion-min.js
@@ -0,0 +1 @@
+(function(){if(!this.require){var a={},b={},c=function(f,g){var h=d(g,f),i=b[h],j;if(i)return i.exports;if(!(j=a[h]||a[h=d(h,"./index")]))throw"module '"+f+"' not found";i={id:h,exports:{}};try{return b[h]=i,j(i.exports,function(a){return c(a,e(h))},i),i.exports}catch(k){throw delete b[h],k}},d=function(a,b){var c=[],d,e;/^\.\.?(\/|$)/.test(b)?d=[a,b].join("/").split("/"):d=b.split("/");for(var f=0,g=d.length;f<g;f++)e=d[f],e==".."?c.pop():e!="."&&e!=""&&c.push(e);return c.join("/")},e=function(a){return a.split("/").slice(0,-1).join("/")};this.require=function(a){return c(a,"")},this.require.define=function(b){for(var c in b)a[c]=b[c]}}return this.require.define}).call(this)({"base-platform/dom":function(a,b,c){"use strict",c.exports={getChildren:function(a){return Array.prototype.slice.call(a.childNodes)},localName:function(a){return a.localName},getAttribute:function(a,b){return a.getAttribute(b)},hasAttribute:function(a,b){return a.hasAttribute(b)},namespaceURI:function(a){return a.namespaceURI},createElementNS:function(a,b,c){return a.createElementNS(b,c)},setAttribute:function(a,b,c){return a.setAttribute(b,c)},appendChild:function(a,b){return a.appendChild(b)},textContent:function(a,b){if(b===undefined)return a.nodeType===1?a.textContent!==undefined?a.textContent:this.getChildren(a).map(function(a){return this.textContent(a)},this).join(""):a.nodeType===3||a.nodeType===4?a.data:"";if(a.nodeType===1){if(a.textContent!==undefined)return a.textContent=b;var c=a.ownerDocument.createTextNode(b);return a.appendChild(c),b}if(a.nodeType===3)return a.data=b},getElementChildren:function(a){return this.getChildren(a).filter(function(a){return a.nodeType===1})}}},"base-platform/eval":function(exports,require,module){module.exports=function(content,name){return eval("(function(){\nreturn "+content+";})()")}},"base-platform/path":function(a,b,c){"use strict",c.exports={sep:"/",join:function(a,b){return a+"/"+b},dirname:function(a){return a.split(this.sep).slice(0,-1).join(this.sep)},basename:function(a,b){var c=a.split(this.sep).slice(-1);if(b){var d=this.extname(c);d[1]===b&&(c=d[1])}return c},extname:function(a){return a.split(/\\.(?=[^\\.]+$)/)[1]}}},"browser/browser-listener-client":function(a,b,c){},"browser/dom":function(a,b,c){function e(a,b){return"item"in a?a.item(b):a[b]}"use strict";var d=b("../base-platform/dom"),f=Object.create(d);f.hasAttribute=function(a,b){return a.hasAttribute?a.hasAttribute(b):a.getAttribute(b)},f.localName=function(a){return a.localName||a.tagName},f.createElementNS=function(a,b,c){return a.createElementNS?a.createElementNS(b,c):a.createElement(c)},f.getChildren=function(a){var b=[];for(var c=0;c<a.childNodes.length;c++)b.push(e(a.childNodes,c));return b},f.serializeToString=function(a){return a.xml||(new XMLSerializer).serializeToString(a)},c.exports=f},"browser/platform":function(a,b,c){"use strict";var d=b("../core/util/util");a.platform={ajax:window.jQuery,eval:b("../base-platform/eval"),getDocumentFromUrl:function(a,b){this.ajax.get(a,function(a){b(null,a)},"xml").error(function(a){b(a)})},parseDocumentFromString:function(a){return(new window.DOMParser).parseFromString(a,"application/xml")},getDocumentFromFilesystem:function(a,b){this.getDocumentFromUrl(a,b)},getResourceFromUrl:function(a,b){this.ajax.get(a,function(a){b(null,a)}).error(function(a){b(a)})},postDataToUrl:function(a,b,c){this.ajax.post(a,b,function(a){c(null,a)}).error(function(a){c(a)})},setTimeout:function(a,b){return window.setTimeout(a,b)},clearTimeout:function(a){window.clearTimeout(a)},log:window.console&&window.console.log&&(window.console.log.bind?window.console.log.bind(window.console):window.console.log),path:b("../base-platform/path"),url:b("./url"),dom:b("./dom")}},"browser/url":function(a,b,c){function d(a){var b=document.createElement("a");return b.href=a,b}"use strict",c.exports={getPathFromUrl:function(a){var b=d(a);return b.pathname},changeUrlPath:function(a,b){var c=d(a);return c.protocol+"//"+c.hostname+":"+c.port+b}}},"core/constants":function(a,b,c){"use strict",c.exports={SCXML_NS:"http://www.w3.org/2005/07/scxml"}},"core/scxml/SCXML":function(a,b,c){function i(a){return function(a){var b=a[0],c=a[1];return b.source.depth<c.source.depth?c:c.source.depth<b.source.depth?b:b.documentOrder<c.documentOrder?b:c}}function k(a,b){this.model=a,this.opts=b,this.opts.log=this.opts.log||h.platform.log,this.opts.StateIdSet=this.opts.StateIdSet||d,this.opts.EventSet=this.opts.EventSet||d,this.opts.TransitionPairSet=this.opts.TransitionPairSet||d,this.opts.priorityComparisonFn=this.opts.priorityComparisonFn||i(this.opts.model),this._configuration=new this.opts.BasicStateSet,this._historyValue={},this._innerEventQueue=[],this._isInFinalState=!1,this._timeoutMap={},this._listeners=[]}function l(a,b){b=b||{},f(b),this._isStepping=!1,this._send=b.send||this._send,this._cancel=b.cancel||this._cancel,k.call(this,a,b)}"use strict";var d=b("./set/ArraySet"),e=b("./state-kinds-enum"),f=b("./setup-default-opts"),g=b("./scxml-dynamic-name-match-transition-selector"),h=b("../../platform"),j=!1;k.prototype={start:function(){j&&h.platform.log("performing initial big step"),this._configuration.add(this.model.root.initial);var a=this.opts.require||c.parent&&c.parent.parent&&c.parent.parent.require&&c.parent.parent.require.bind(c.parent.parent)||b.main&&b.main.require&&b.main.require.bind(b.main)||b,d=this.model.actionFactory(this.opts.log,this._cancel.bind(this),this._send.bind(this),this.opts.origin,this.isIn.bind(this),a,h.platform.parseDocumentFromString);return this._actions=d.actions,this._datamodel=d.datamodel,this._performBigStep(),this.getConfiguration()},_getOrSetData:function(a,b,c){var d=this._datamodel[b];if(!d)throw new Error("Variable "+b+" not declared in datamodel.");return d[a](c)},_getData:function(a){return this._getOrSetData("get",a)},_setData:function(a,b){return this._getOrSetData("set",a,b)},getConfiguration:function(){return this._configuration.iter().map(function(a){return a.id})},getFullConfiguration:function(){return this._configuration.iter().map(function(a){return[a].concat(this.opts.model.getAncestors(a))},this).reduce(function(a,b){return a.concat(b)},[]).map(function(a){return a.id}).reduce(function(a,b){return a.indexOf(b)>-1?a:a.concat(b)},[])},isIn:function(a){return this.getFullConfiguration().indexOf(a)>-1},_performBigStep:function(a){a&&this._innerEventQueue.push(new this.opts.EventSet([a]));var b=!0;while(b){var c=this._innerEventQueue.length?this._innerEventQueue.shift():new this.opts.EventSet,d={},f=this._performSmallStep(c,d);b=!f.isEmpty()}this._isInFinalState=this._configuration.iter().every(function(a){return a.kind===e.FINAL})},_performSmallStep:function(a,b){j&&h.platform.log("selecting transitions with eventSet: ",a);var c=this._selectTransitions(a,b);j&&h.platform.log("selected transitions: ",c);if(!c.isEmpty()){j&&h.platform.log("sorted transitions: ",c);var d=new this.opts.TransitionSet(c.iter().filter(function(a){return a.targets})),f=this._getStatesExited(d),g=f[0],i=f[1],k=this._getStatesEntered(d),l=k[0],m=k[1];j&&h.platform.log("basicStatesExited ",g),j&&h.platform.log("basicStatesEntered ",l),j&&h.platform.log("statesExited ",i),j&&h.platform.log("statesEntered ",m);var n=new this.opts.EventSet;j&&h.platform.log("executing state exit actions"),i.forEach(function(c){(j||this.opts.logStatesEnteredAndExited)&&h.platform.log("exiting ",c.id),this._listeners.forEach(function(a){a.onExit&&a.onExit(c.id)}),c.onexit!==undefined&&this._evaluateAction(c.onexit,a,b,n);var d;c.history&&(c.history.isDeep?d=function(a){return a.kind===e.BASIC&&c.descendants.indexOf(a)>-1}:d=function(a){return a.parent===c},this._historyValue[c.history.id]=i.filter(d))},this);var o=c.iter().sort(function(a,b){return a.documentOrder-b.documentOrder});j&&h.platform.log("executing transitition actions"),o.forEach(function(c){var d=c.targets&&c.targets.map(function(a){return a.id});this._listeners.forEach(function(a){a.onTransition&&a.onTransition(c.source.id,d)}),c.actions!==undefined&&this._evaluateAction(c.actions,a,b,n)},this),j&&h.platform.log("executing state enter actions"),m.forEach(function(c){(j||this.opts.logStatesEnteredAndExited)&&h.platform.log("entering",c.id),this._listeners.forEach(function(a){a.onEntry&&a.onEntry(c.id)}),c.onentry!==undefined&&this._evaluateAction(c.onentry,a,b,n)},this),j&&h.platform.log("updating configuration "),j&&h.platform.log("old configuration ",this._configuration),this._configuration.difference(g),this._configuration.union(l),j&&h.platform.log("new configuration ",this._configuration),n.isEmpty()||(j&&h.platform.log("adding triggered events to inner queue ",n),this._innerEventQueue.push(n)),j&&h.platform.log("updating datamodel for next small step :");for(var p in b)this._setData(p,b[p])}return c},_evaluateAction:function(a,b,c,d){function e(a){d.add(a)}var f=this._getScriptingInterface(c,b,!0);return this._actions[a].call(this.opts.evaluationContext,f.getData,f.setData,f.events,e)},_getScriptingInterface:function(a,b,c){return{setData:c?function(b,c){return a[b]=c}:function(){},getData:this._getData.bind(this),events:b.iter()}},_getStatesExited:function(a){var b=new this.opts.StateSet,c=new this.opts.BasicStateSet;a.iter().forEach(function(a){var d=a.lca,e=d.descendants;this._configuration.iter().forEach(function(a){e.indexOf(a)>-1&&(c.add(a),b.add(a),this.opts.model.getAncestors(a,d).forEach(function(a){b.add(a)}))},this)},this);var d=b.iter().sort(function(a,b){return b.depth-a.depth});return[c,d]},_getStatesEntered:function(a){var b=new this.opts.StateSet,c=new this.opts.BasicStateSet,d=new this.opts.StateSet,f=[],g=function(a,c){h(c);var f=this.opts.model.getLCA(a,c);this.opts.model.getAncestors(c,f).forEach(function(a){a.kind===e.COMPOSITE?(b.add(a),d.add(a)):h(a)})}.bind(this),h=function(a){if(d.contains(a))return;a.kind===e.HISTORY?a.id in this._historyValue?this._historyValue[a.id].forEach(function(b){g(a,b)}):(b.add(a),c.add(a)):(b.add(a),a.kind===e.PARALLEL?f.push.apply(f,a.children.filter(function(a){return a.kind!==e.HISTORY})):a.kind===e.COMPOSITE?f.push(a.initial):(a.kind===e.INITIAL||a.kind===e.BASIC||a.kind===e.FINAL)&&c.add(a)),d.add(a)}.bind(this);a.iter().forEach(function(a){a.targets.forEach(function(b){g(a.source,b)})});var i;while(i=f.pop())h(i);var j=b.iter().sort(function(a,b){return a.depth-b.depth});return[c,j]},_selectTransitions:function(a,b){if(this.opts.onlySelectFromBasicStates)var c=this._configuration.iter();else{var d=new this.opts.StateSet;this._configuration.iter().forEach(function(a){d.add(a),this.opts.model.getAncestors(a).forEach(function(a){d.add(a)})},this),c=d.iter()}var e=this._getScriptingInterface(b,a),f=function(a){return this._actions[a.conditionActionRef].call(this.opts.evaluationContext,e.getData,e.setData,e.events)}.bind(this),i=a.iter().map(function(a){return a.name}),k=i.filter(function(a){return a.search(".")}).length,l=k?g:this.opts.transitionSelector,m=new this.opts.TransitionSet;c.forEach(function(a){l(a,i,f).forEach(function(a){m.add(a)})});var n=this._selectPriorityEnabledTransitions(m);return j&&h.platform.log("priorityEnabledTransitions",n),n},_selectPriorityEnabledTransitions:function(a){var b=new this.opts.TransitionSet,c=this._getInconsistentTransitions(a),d=c[0],e=c[1];b.union(d),j&&h.platform.log("enabledTransitions",a),j&&h.platform.log("consistentTransitions",d),j&&h.platform.log("inconsistentTransitionsPairs",e),j&&h.platform.log("priorityEnabledTransitions",b);while(!e.isEmpty())a=new this.opts.TransitionSet(e.iter().map(function(a){return this.opts.priorityComparisonFn(a)},this)),c=this._getInconsistentTransitions(a),d=c[0],e=c[1],b.union(d),j&&h.platform.log("enabledTransitions",a),j&&h.platform.log("consistentTransitions",d),j&&h.platform.log("inconsistentTransitionsPairs",e),j&&h.platform.log("priorityEnabledTransitions",b);return b},_getInconsistentTransitions:function(a){var b=new this.opts.TransitionSet,c=new this.opts.TransitionPairSet,d=a.iter();j&&h.platform.log("transitions",d);for(var e=0;e<d.length;e++)for(var f=e+1;f<d.length;f++){var g=d[e],i=d[f];this._conflicts(g,i)&&(b.add(g),b.add(i),c.add([g,i]))}var k=a.difference(b);return[k,c]},_conflicts:function(a,b){return!this._isArenaOrthogonal(a,b)},_isArenaOrthogonal:function(a,b){var c=a.targets?a.lca:a.source,d=b.targets?b.lca:b.source,e=this.opts.model.isOrthogonalTo(c,d);return j&&(h.platform.log("transition LCAs",c.id,d.id),h.platform.log("transition LCAs are orthogonal?",e)),e},registerListener:function(a){return this._listeners.push(a)},unregisterListener:function(a){return this._listeners.splice(this._listeners.indexOf(a),1)}},l.prototype=Object.create(k.prototype),l.prototype.gen=function(a,b){var c;switch(typeof a){case"string":c={name:a,data:b};break;case"object":if(typeof a.name!="string")throw new Error('Event object must have "name" property of type string.');c=a;break;default:throw new Error("First argument to gen must be a string or object.")}if(this._isStepping)throw new Error("gen called before previous call to gen could complete. If executed in single-threaded environment, this means it was called recursively, which is illegal, as it would break SCION step semantics.");return this._isStepping=!0,this._performBigStep(c),this._isStepping=!1,this.getConfiguration()},l.prototype._send=function(a,b){var c,d,e=this;if(!h.platform.setTimeout)throw new Error("setTimeout function not set");j&&h.platform.log("sending event",a.name,"with content",a.data,"after delay",b.delay),c=function(){return e.gen(a)},d=h.platform.setTimeout(c,b.delay);if(b.sendid)return this._timeoutMap[b.sendid]=d},l.prototype._cancel=function(a){if(!h.platform.clearTimeout)throw new Error("clearTimeout function not set");if(a in this._timeoutMap)return j&&h.platform.log("cancelling ",a," with timeout id ",this._timeoutMap[a]),h.platform.clearTimeout(this._timeoutMap[a])},c.exports={SCXMLInterpreter:k,SimpleInterpreter:l}},"core/scxml/default-transition-selector":function(a,b,c){"use strict",c.exports=function(a,b,c){return a.transitions.filter(function(a){return!a.event||b.indexOf(a.event)>-1&&(!a.cond||c(a))})}},"core/scxml/json2model":function(a,b,c){function f(a){function b(a,b){return d.push(e.gen.util.wrapFunctionBodyInDeclaration(a,b))-1}function c(a){return f[a]}var d=[],f={};a.states.forEach(function(a){f[a.id]=a}),a.transitions.forEach(function(a){a.cond&&(a.conditionActionRef=b(a.cond,!0))}),a.states.forEach(function(d){d.transitions=d.transitions.map(function(b){return a.transitions[b]});var e=[];d.onentry&&(d.onentry=b(d.onentry)),d.onexit&&(d.onexit=b(d.onexit)),d.transitions.forEach(function(a){a.actions&&(a.actions=b(a.actions)),a.lca&&(a.lca=f[a.lca])}),d.initial=f[d.initial],d.history=f[d.history],d.children=d.children.map(c),d.parent=f[d.parent],d.ancestors&&(d.ancestors=d.ancestors.map(c)),d.descendants&&(d.descendants=d.descendants.map(c)),d.transitions.forEach(function(a){a.source=f[a.source],a.targets=a.targets&&a.targets.map(c)})}),a.root=f[a.root];var g=e.gen.util.makeActionFactory(a.scripts,d,a.datamodel);return g}function g(a,b){var c=f(a);try{a.actionFactory=d.platform.eval(c,b)}catch(e){throw d.platform.log("Failed to evaluate action factory."),d.platform.log("Generated js code to evaluate\n",c),e}}"use strict";var d=b("../../platform"),e=b("../util/code-gen");c.exports=function(a,b){return g(a,b),a};if(b.main===c){var h=process.argv[2],i=function(a,b){if(a)throw a;process.stdout.write(f(JSON.parse(b)))};if(h==="-"){var j="";process.stdin.resume(),process.stdin.on("data",function(a){j+=a}),process.stdin.on("end",function(a){i(null,j)})}else{var k=b("fs");k.readFile(h,"utf8",i)}}},"core/scxml/model":function(a,b,c){"use strict";var d=b("./state-kinds-enum"),e={getAncestors:function(a,b){var c,d,e;return d=a.ancestors.indexOf(b),d>-1?a.ancestors.slice(0,d):a.ancestors},getAncestorsOrSelf:function(a,b){return[a].concat(this.getAncestors(a,b))},getDescendantsOrSelf:function(a){return[a].concat(a.descendants)},isOrthogonalTo:function(a,b){return!this.isAncestrallyRelatedTo(a,b)&&this.getLCA(a,b).kind===d.PARALLEL},isAncestrallyRelatedTo:function(a,b){return this.getAncestorsOrSelf(b).indexOf(a)>-1||this.getAncestorsOrSelf(a).indexOf(b)>-1},getLCA:function(a,b){var c=this.getAncestors(a).filter(function(a){return a.descendants.indexOf(b)>-1},this);return c[0]}};c.exports=e},"core/scxml/scxml-dynamic-name-match-transition-selector":function(a,b,c){function e(a){return new RegExp("^"+a.replace(/\./g,"\\.")+"(\\.[0-9a-zA-Z]+)*$")}function f(a){return d[a]?d[a]:d[a]=e(a)}function g(a,b){var c=a.events,d=c.indexOf("*")>-1?function(){return!0}:function(a){return c.filter(function(b){return f(b).test(a)}).length};return b.filter(d).length}"use strict";var d={};c.exports=function(a,b,c){return a.transitions.filter(function(a){return(!a.events||g(a,b))&&(!a.cond||c(a))})}},"core/scxml/set/ArraySet":function(a,b,c){function d(a){a=a||[],this.o=[],a.forEach(function(a){this.add(a)},this)}"use strict",d.prototype={add:function(a){if(!this.contains(a))return this.o.push(a)},remove:function(a){var b=this.o.indexOf(a);return b===-1?!1:(this.o.splice(b,1),!0)},union:function(a){return a=a.iter?a.iter():a,a.forEach(function(a){this.add(a)},this),this},difference:function(a){return a=a.iter?a.iter():a,a.forEach(function(a){this.remove(a)},this),this},contains:function(a){return this.o.indexOf(a)>-1},iter:function(){return this.o},isEmpty:function(){return!this.o.length},equals:function(a){var b=a.iter(),c=this.o;return c.every(function(a){return b.indexOf(a)>-1})&&b.every(function(a){return c.indexOf(a)>-1})},toString:function(){return"Set("+this.o.toString()+")"}},c.exports=d},"core/scxml/setup-default-opts":function(a,b,c){"use strict";var d=b("./scxml-dynamic-name-match-transition-selector"),e=b("./set/ArraySet"),f=b("./model");c.exports=function(a){return a=a||{},a.TransitionSet=a.TransitionSet||e,a.StateSet=a.StateSet||e,a.BasicStateSet=a.BasicStateSet||e,a.transitionSelector=a.transitionSelector||d,a.model=a.model||f,a}},"core/scxml/state-kinds-enum":function(a,b,c){"use strict",c.exports={BASIC:0,COMPOSITE:1,PARALLEL:2,HISTORY:3,INITIAL:4,FINAL:5}},"core/util/annotate-scxml-json":function(a,b,c){function t(a){return f.platform.dom.getChildren(a).filter(function(a){return f.platform.dom.localName(a)==="script"}).map(function(a){return f.platform.dom.textContent(a)})}function u(a){var b,c,d;c=0,d={};for(b in a)d[b]={name:b,documentOrder:c++};return d}function w(a,b){if(f.platform.dom.hasAttribute(a,"event")){var c,e=f.platform.dom.getAttribute(a,"event");e==="*"?c=[e]:c=e.trim().split(/\s+/).map(function(a){var b=a.match(v);if(b){var c=b[1];if(!b||!c)throw new Error("Unable to parse event: "+a);return c}}),c.filter(function(a){return a!=="*"}).forEach(function(a){l[a]=!0});if(c.indexOf(undefined)>-1)throw new Error("Error parsing event attribute attributes.event")}var g={documentOrder:m.length,id:m.length,source:b.id,cond:f.platform.dom.getAttribute(a,"cond"),events:c,targets:f.platform.dom.hasAttribute(a,"target")?f.platform.dom.getAttribute(a,"target").trim().split(/\s+/):null};return f.platform.dom.getElementChildren(a).length&&(g.actions=d.gen.parentToFnBody(a)),m.push(g),g}function x(a,b){f.platform.dom.getChildren(a).filter(function(a){return f.platform.dom.localName(a)==="data"}).forEach(function(a){if(f.platform.dom.hasAttribute(a,"id")){var b,c=f.platform.dom.getAttribute(a,"id");if(f.platform.dom.hasAttribute(a,"expr"))b={content:f.platform.dom.getAttribute(a,"expr"),type:"expr"};else{var d=f.platform.dom.hasAttribute(a,"type");if(d){var e=f.platform.dom.getAttribute(a,"type"),g=e==="xml"?f.platform.dom.serializeToString(a):f.platform.dom.textContent(a);b={content:g,type:e}}else g=f.platform.dom.textContent(a),b=g.length?{content:g,type:"text"}:null}p[c]=b}})}function y(a,b){var c=f.platform.dom.hasAttribute(a,"id")?f.platform.dom.getAttribute(a,"id"):B(f.platform.dom.localName(a)),l;switch(f.platform.dom.localName(a)){case"state":f.platform.dom.getChildren(a).filter(function(a){return i.indexOf(f.platform.dom.localName(a))>-1}).length?l=g.COMPOSITE:l=g.BASIC;break;case"scxml":l=g.COMPOSITE;break;case"initial":l=g.INITIAL;break;case"parallel":l=g.PARALLEL;break;case"final":l=g.FINAL;break;case"history":l=g.HISTORY;break;default:}var m={id:c,kind:l,descendants:[]};n[c]=m,b.length&&(m.parent=b[b.length-1]),l===g.HISTORY&&(m.isDeep=f.platform.dom.getAttribute(a,"type")==="deep"?!0:!1),m.documentOrder=j.length,j.push(m);if(l===g.BASIC||l===g.INITIAL||l===g.HISTORY)m.basicDocumentOrder=k.length,k.push(m);m.depth=b.length,m.ancestors=b.slice(),b.forEach(function(a){n[a].descendants.push(m.id)});var o,p,r=[],s=[],t=b.concat(m.id),u=!1,v=null,z=function(a){var b=y(a,t);return m.initial=b.id,s.push(b),u=!0};f.platform.dom.getElementChildren(a).forEach(function(a){switch(f.platform.dom.localName(a)){case"transition":r.push(w(a,m));break;case"onentry":p=d.gen.parentToFnBody(a);break;case"onexit":o=d.gen.parentToFnBody(a);break;case"initial":if(!!u)throw new Error("Encountered duplicate initial states in state "+m.id);z(a);break;case"history":var b=y(a,t);m.history=b.id,s.push(b);break;case"datamodel":x(a,t);break;default:if(h.indexOf(f.platform.dom.localName(a))>-1){var c=y(a,t);v===null&&(v=c),s.push(c)}}});if(!u&&f.platform.dom.localName(a)!=="parallel"){var A=f.platform.dom.hasAttribute(a,"initial"),C=function(a){var b=f.platform.dom.createElementNS(q,e.SCXML_NS,"initial"),c=f.platform.dom.createElementNS(q,e.SCXML_NS,"transition");return f.platform.dom.setAttribute(c,"target",a),f.platform.dom.appendChild(b,c),z(b)};A?C(f.platform.dom.getAttribute(a,"initial")):v&&C(v.id)}return m.onexit=o,m.onentry=p,m.transitions=r.map(function(a){return a.documentOrder}),m.children=s.map(function(a){return a.id}),m}function B(a){return A[a]=A[a]||0,""+z+"-"+a+"-"+A[a]++}function C(a,b){var c,d,e,f,g,h,i;e=[],a.ancestors.forEach(function(a){d=n[a],d.descendants.indexOf(b.id)>-1&&e.push(a)});if(!e.length)throw new Error("Could not find LCA for states.");return e[0]}"use strict";var d=b("./code-gen"),e=b("../constants"),f=b("../../platform"),g=b("../scxml/state-kinds-enum"),h=["state","parallel","history","final","initial"],i=h.concat("scxml"),j,k,l,m,n,o,p,q,r=a.transformAndSerialize=r=function(a){return JSON.stringify(s(a))},s=a.transform=function(a){q=a;var b=q.documentElement;j=[],k=[],l={},m=[],n={},o=[],p={};var c=y(b,[]);return j.forEach(function(a){a.ancestors.reverse()}),j.forEach(function(a){a.descendants.reverse()}),m.filter(function(a){return a.targets}).forEach(function(a){var b=n[a.source],c=a.targets.map(function(a){var b=n[a];if(!b)throw new Error("Transition targets state id '"+a+"' but state does not exist.");return b});a.lca=C(b,c[0])}),{states:j,transitions:m,root:c.id,events:u(l),scripts:t(b),profile:f.platform.dom.getAttribute(b,"profile"),version:f.platform.dom.getAttribute(b,"version"),datamodel:p}},v=/^((([^.]+)\.)*([^.]+))(\.\*)?$/,z="$generated",A={};b.main===c&&console.log(JSON.stringify(s((new(b("xmldom").DOMParser)).parseFromString(b("fs").readFileSync(process.argv[2],"utf8"))),4,4))},"core/util/code-gen":function(a,b,c){function f(a){return d.platform.dom.getElementChildren(a).map(g).join("\n;;\n")}function g(a){var b=h[d.platform.dom.namespaceURI(a)],c=b&&b[d.platform.dom.localName(a)];if(!b||!c)throw new Error("Element "+d.platform.dom.namespaceURI(a)+":"+d.platform.dom.localName(a)+" not yet supported");return c(a)}function i(a){return a?a.slice(-2)==="ms"?parseFloat(a.slice(0,-2)):a.slice(-1)==="s"?parseFloat(a.slice(0,-1))*1e3:parseFloat(a):0}function j(a,b){var c=a;if(b){c+=" = ";switch(b.type){case"xml":c+="$parseXml("+JSON.stringify(b.content)+")";break;case"json":c+="JSON.parse("+JSON.stringify(b.content)+")";break;case"expr":c+=b.content;break;default:c+=JSON.stringify(b.content)}}return c}function k(a){var b="var ",c=[];for(var d in a){var e=a[d];c.push(j(d,e))}return c.length?b+c.join(", ")+";":""}function l(a){var b=[];for(var c in a)b.push('"'+c+'" : {\n'+'"set" : function(v){ return '+c+" = v; },\n"+'"get" : function(){ return '+c+";}"+"\n}");return"{\n"+b.join(",\n")+"\n}"}function m(a,b){return"function(getData,setData,_events,$raise){var _event = _events[0];\n"+(b?"return":"")+" "+a+"\n}"}function n(a,b,c,d){return a+(b.length?b.join("\n"):"")+"var $datamodel = "+c+";\n"+"return {\n"+"datamodel:$datamodel,\n"+"actions:[\n"+d.join(",\n")+"\n]"+"\n};"}function o(a){return"function($log,$cancel,$send,$origin,In,require,$parseXml){\n"+a+"\n}"}function p(a,b,c){var d=k(c),e=l(c),f=n(d,a,e,b),g=o(f);return g}function q(a){var b=d.platform.dom.hasAttribute(a,"namelist")?d.platform.dom.getAttribute(a,"namelist").trim().split(/ +/):null,c=d.platform.dom.getChildren(a).filter(function(a){return d.platform.dom.localName(a)==="param"}),e=d.platform.dom.getChildren(a).filter(function(a){return d.platform.dom.localName(a)==="content"});if(e.length)return e=e[0],d.platform.dom.getAttribute(e,"type")==="application/json"?d.platform.dom.textContent(e):JSON.stringify(d.platform.dom.textContent(e));if(d.platform.dom.hasAttribute(a,"contentexpr"))return d.platform.dom.getAttribute(a,"contentexpr");var f="{";return b&&b.forEach(function(a){f+='"'+a+'"'+":"+a+",\n"}),c.length&&c.map(function(a){return r(a)}).forEach(function(a){a.expr?f+='"'+a.name+'"'+":"+a.expr+",\n":a.location&&(f+='"'+a.name+'"'+":"+a.location+",\n")}),f+="}",f}function r(a){return{name:d.platform.dom.getAttribute(a,"name"),expr:d.platform.dom.getAttribute(a,"expr"),location:d.platform.dom.getAttribute(a,"location")}}"use strict";var d=b("../../platform"),e=b("../constants"),h={"":{script:function(a){return d.platform.dom.textContent(a)},assign:function(a){return d.platform.dom.getAttribute(a,"location")+" = "+d.platform.dom.getAttribute(a,"expr")+";"},"if":function(a){var b="";b+="if("+d.platform.dom.getAttribute(a,"cond")+"){\n";var c=d.platform.dom.getElementChildren(a);for(var e=0;e<c.length;e++){var f=c[e];if(d.platform.dom.localName(f)==="elseif"||d.platform.dom.localName(f)==="else")break;b+=g(f)+"\n;;\n"}for(;e<c.length;e++){f=c[e];if(d.platform.dom.localName(f)==="elseif")b+="}else if("+d.platform.dom.getAttribute(f,"cond")+"){\n";else{if(d.platform.dom.localName(f)==="else"){b+="}";break}b+=g(f)+"\n;;\n"}}for(;e<c.length;e++)f=c[e],d.platform.dom.localName(f)==="else"?b+="else{\n":b+=g(f)+"\n;;\n";return b+="}",b},elseif:function(){throw new Error("Encountered unexpected elseif tag.")},"else":function(){throw new Error("Encountered unexpected else tag.")},log:function(a){var b=[];return d.platform.dom.hasAttribute(a,"label")&&b.push(JSON.stringify(d.platform.dom.getAttribute(a,"label"))),d.platform.dom.hasAttribute(a,"expr")&&b.push(d.platform.dom.getAttribute(a,"expr")),"$log("+b.join(",")+");"},raise:function(a){return"$raise({ name:"+JSON.stringify(d.platform.dom.getAttribute(a,"event"))+", data : {}});"},cancel:function(a){return"$cancel("+JSON.stringify(d.platform.dom.getAttribute(a,"sendid"))+");"},send:function(a){var b=d.platform.dom.hasAttribute(a,"targetexpr")?d.platform.dom.getAttribute(a,"targetexpr"):JSON.stringify(d.platform.dom.getAttribute(a,"target")),c="{\ntarget: "+b+",\n"+"name: "+(d.platform.dom.hasAttribute(a,"eventexpr")?d.platform.dom.getAttribute(a,"eventexpr"):JSON.stringify(d.platform.dom.getAttribute(a,"event")))+",\n"+"type: "+(d.platform.dom.hasAttribute(a,"typeexpr")?d.platform.dom.getAttribute(a,"typeexpr"):JSON.stringify(d.platform.dom.getAttribute(a,"type")))+",\n"+"data: "+q(a)+",\n"+"origin: $origin\n"+"}",e="if("+b+" === '#_internal'){\n"+"$raise("+c+");\n"+"}else{\n"+"$send("+c+", {\n"+"delay: "+(d.platform.dom.hasAttribute(a,"delayexpr")?d.platform.dom.getAttribute(a,"delayexpr"):i(d.platform.dom.getAttribute(a,"delay")))+",\n"+"sendId: "+(d.platform.dom.hasAttribute(a,"idlocation")?d.platform.dom.getAttribute(a,"idlocation"):JSON.stringify(d.platform.dom.getAttribute(a,"id")))+"\n"+"});"+"}";return e},foreach:function(a){var b=d.platform.dom.hasAttribute(a,"index"),c=d.platform.dom.getAttribute(a,"index")||"$i",e=d.platform.dom.getAttribute(a,"item"),f=d.platform.dom.getAttribute(a,"array"),h=d.platform.dom.getElementChildren(a).map(g).join("\n;;\n");return"(function(){\nif(Array.isArray("+f+")){\n"+f+".forEach(function("+e+","+c+"){\n"+h+"\n});\n"+"}else{\n"+"Object.keys("+f+").forEach(function("+c+"){\n"+e+" = "+f+"["+c+"];\n"+h+"\n});\n"+"}\n"+"})();"}}};h[e.SCXML_NS]=h[""],c.exports={gen:{parentToFnBody:f,actionTagToFnBody:g,actionTags:h,util:{makeDatamodelDeclaration:k,makeDatamodelClosures:l,wrapFunctionBodyInDeclaration:m,makeTopLevelFunctionBody:n,wrapTopLevelFunctionBodyInDeclaration:o,makeActionFactory:p}}}},"core/util/docToModel":function(a,b,c){function g(a,b,c){f.platform.getResourceFromUrl?i(a,b,function(d){d&&f.platform.log("Errors downloading src attributes",d),h(b,a,c)}):h(b,a,c)}function h(a,b,c){try{var f=d.transform(a),g=e(f,b);c(null,g)}catch(h){c(h)}}function i(a,b,c){function g(){var b=d.pop();if(b){var h=f.platform.dom.getAttribute(b,"src");if(a){var i=f.platform.url.getPathFromUrl(a),j=f.platform.path.dirname(i),k=f.platform.path.join(j,h);h=f.platform.url.changeUrlPath(a,k)}f.platform.getResourceFromUrl(h,function(a,c){a?(f.platform.log("Error downloading document "+h+" : "+a.message),e.push(a)):f.platform.dom.textContent(b,c),g()})}else c(e.length?e:null)}var d=[],e=[];j(b.documentElement,d),g()}function j(a,b){(f.platform.dom.localName(a)==="script"||f.platform.dom.localName(a)==="data")&&f.platform.dom.hasAttribute(a,"src")&&b.push(a),f.platform.dom.getElementChildren(a).forEach(function(a){j(a,b)})}"use strict";var d=b("./annotate-scxml-json"),e=b("../scxml/json2model"),f=b("../../platform");c.exports=g},"core/util/util":function(a,b,c){"use strict",c.exports={merge:function(a){for(var b=1;b<arguments.length;b++){var c=arguments[b];for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}return a}}},platform:function(a,b,c){function d(){return typeof Packages!="undefined"}function e(){return typeof process!="undefined"&&typeof c!="undefined"}function f(){return typeof window!="undefined"&&typeof document!="undefined"}"use strict";var g;f()?c.exports=b("./browser/platform"):e()?c.exports=b("./node/platform"):d()&&(c.exports=b("./rhino/platform"))},scion:function(a,b,c){function g(a,b){if(!d.platform.getDocumentFromUrl)throw new Error("Platform does not support getDocumentFromUrl");d.platform.getDocumentFromUrl(a,function(c,d){c?b(c,null):f(a,d,b)})}function h(a,b){if(!d.platform.getDocumentFromFilesystem)throw new Error("Platform does not support getDocumentFromFilesystem");d.platform.getDocumentFromFilesystem(a,function(c,d){c?b(c,null):f(a,d,b)})}function i(a,b){if(!d.platform.parseDocumentFromString)throw new Error("Platform does not support parseDocumentFromString");f(null,d.platform.parseDocumentFromString(a),b)}"use strict";var d=b("./platform"),e=b("./core/scxml/SCXML"),f=b("./core/util/docToModel"),j=c.exports={pathToModel:h,urlToModel:g,documentStringToModel:i,documentToModel:f,SCXML:e.SimpleInterpreter,ext:{platformModule:d,actionCodeGeneratorModule:b("./core/util/code-gen")}}}});
View
2,349 dist/scion.js
@@ -0,0 +1,2349 @@
+
+(function(/*! Stitch !*/) {
+ if (!this.require) {
+ var modules = {}, cache = {}, require = function(name, root) {
+ var path = expand(root, name), module = cache[path], fn;
+ if (module) {
+ return module.exports;
+ } else if (fn = modules[path] || modules[path = expand(path, './index')]) {
+ module = {id: path, exports: {}};
+ try {
+ cache[path] = module;
+ fn(module.exports, function(name) {
+ return require(name, dirname(path));
+ }, module);
+ return module.exports;
+ } catch (err) {
+ delete cache[path];
+ throw err;
+ }
+ } else {
+ throw 'module \'' + name + '\' not found';
+ }
+ }, expand = function(root, name) {
+ var results = [], parts, part;
+ if (/^\.\.?(\/|$)/.test(name)) {
+ parts = [root, name].join('/').split('/');
+ } else {
+ parts = name.split('/');
+ }
+ for (var i = 0, length = parts.length; i < length; i++) {
+ part = parts[i];
+ if (part == '..') {
+ results.pop();
+ } else if (part != '.' && part != '') {
+ results.push(part);
+ }
+ }
+ return results.join('/');
+ }, dirname = function(path) {
+ return path.split('/').slice(0, -1).join('/');
+ };
+ /** @expose */
+ this.require = function(name) {
+ return require(name, '');
+ }
+ this.require.define = function(bundle) {
+ for (var key in bundle)
+ modules[key] = bundle[key];
+ };
+ }
+ return this.require.define;
+}).call(this)({"base-platform/dom": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+"use strict";
+
+//a small DOM helper/compatibility layer
+
+module.exports = {
+
+ getChildren : function(node){
+ return Array.prototype.slice.call(node.childNodes);
+ },
+
+ localName : function(node){
+ return node.localName;
+ },
+
+ getAttribute : function(node,attribute){
+ return node.getAttribute(attribute);
+ },
+
+ hasAttribute : function(node,attribute){
+ return node.hasAttribute(attribute);
+ },
+
+ namespaceURI : function(node){
+ return node.namespaceURI;
+ },
+
+ createElementNS : function(doc,ns,localName){
+ return doc.createElementNS(ns,localName);
+ },
+
+ setAttribute : function(node,name,value){
+ return node.setAttribute(name,value);
+ },
+
+ appendChild : function(parent,child){
+ return parent.appendChild(child);
+ },
+
+ textContent : function(node,txt){
+ if(txt === undefined){
+ if(node.nodeType === 1){
+ //element
+ if(node.textContent !== undefined){
+ return node.textContent;
+ }else{
+ //IE
+ return this.getChildren(node).
+ map(function(textNode){return this.textContent(textNode);},this).join("");
+ }
+ }else if(node.nodeType === 3 || node.nodeType === 4){
+ //textnode
+ return node.data;
+ }
+ return "";
+ }else{
+ if(node.nodeType === 1){
+ //element node
+ if(node.textContent !== undefined){
+ return node.textContent = txt;
+ }else{
+ //IE
+ var textNode = node.ownerDocument.createTextNode(txt);
+ node.appendChild(textNode);
+ return txt;
+ }
+ }else if(node.nodeType === 3){
+ //textnode
+ return node.data = txt;
+ }
+ }
+ },
+
+ getElementChildren : function(node){
+ return this.getChildren(node).filter(function(c){return c.nodeType === 1;});
+ }
+
+};
+}, "base-platform/eval": function(exports, require, module) {module.exports = function(content,name){
+ //JScript doesn't return functions from evaled function expression strings,
+ //so we wrap it here in a trivial self-executing function which gets eval'd
+ return eval('(function(){\nreturn ' + content + ';})()');
+};
+}, "base-platform/path": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+"use strict";
+
+//these are quick-and-dirty implementations
+//there may be missing edge cases
+module.exports = {
+
+ sep : "/",
+
+ join : function(path1,path2){
+ return path1 + "/" + path2;
+ },
+
+ dirname : function(path){
+ return path.split(this.sep).slice(0,-1).join(this.sep);
+ },
+
+ basename : function(path,ext){
+ var name = path.split(this.sep).slice(-1);
+ if(ext){
+ var names = this.extname(name);
+ if(names[1] === ext){
+ name = names[1];
+ }
+ }
+
+ return name;
+ },
+
+ extname : function(path){
+ //http://stackoverflow.com/a/4546093/366856
+ return path.split(/\\.(?=[^\\.]+$)/)[1];
+ }
+};
+}, "browser/browser-listener-client": function(exports, require, module) {//TODO: this will be like node-listener-client.js, except will use jquery/AJAX for its remoting
+}, "browser/dom": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+"use strict";
+
+var baseDom = require('../base-platform/dom');
+
+function getItem(nodeList,index){
+ return "item" in nodeList ? nodeList.item(index) : nodeList[index];
+}
+
+var dom = Object.create(baseDom);
+
+dom.hasAttribute = function(node,attribute){
+ return node.hasAttribute ? node.hasAttribute(attribute) : node.getAttribute(attribute);
+};
+
+dom.localName = function(node){
+ return node.localName || node.tagName;
+};
+
+dom.createElementNS = function(doc,ns,localName){
+ return doc.createElementNS ? doc.createElementNS(ns,localName) : doc.createElement(localName);
+};
+
+dom.getChildren = function(node){
+ var toReturn = [];
+ for(var i = 0; i < node.childNodes.length; i++){
+ toReturn.push(getItem(node.childNodes,i));
+ }
+ return toReturn;
+};
+
+dom.serializeToString = function(node){
+ return node.xml || (new XMLSerializer()).serializeToString(node);
+};
+
+module.exports = dom;
+}, "browser/platform": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+"use strict";
+
+var util = require('../core/util/util');
+
+//browser mostly just inherits path from basePlatform
+exports.platform = {
+
+ /** @expose */
+ ajax : window.jQuery, //this can be overridden
+
+ //used in parsing
+ eval : require('../base-platform/eval'),
+
+ /** @this {platform} */
+ getDocumentFromUrl : function(url,cb){
+ this.ajax.get(url,function(r){
+ cb(null,r);
+ },"xml").error(function(e){
+ cb(e);
+ });
+ },
+
+ parseDocumentFromString : function(str){
+ return (new window.DOMParser()).parseFromString(str,"application/xml");
+ },
+
+ /** @this {platform} */
+ getDocumentFromFilesystem : function(url,cb){
+ this.getDocumentFromUrl(url,cb);
+ },
+
+ //TODO: the callback is duplicate code. move this out.
+ /** @this {platform} */
+ getResourceFromUrl : function(url,cb){
+ this.ajax.get(url,function(r){
+ cb(null,r);
+ }).error(function(e){
+ cb(e);
+ });
+ },
+
+ //used at runtime
+ /** @this {platform} */
+ postDataToUrl : function(url,data,cb){
+ //by default, assume jQuery loaded
+ this.ajax.post(url,data,function(r){
+ cb(null,r);
+ }).error(function(e){
+ cb(e);
+ });
+ },
+
+ setTimeout : function(f,d){
+ return window.setTimeout(f,d);
+ },
+
+ clearTimeout : function(timeoutId){
+ window.clearTimeout(timeoutId);
+ },
+
+ log : window.console && window.console.log && (window.console.log.bind ? window.console.log.bind(window.console) : window.console.log),
+
+ path : require('../base-platform/path'),
+
+ url : require('./url'),
+ dom : require('./dom')
+
+};
+}, "browser/url": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+"use strict";
+
+//this url parsing technique is derived from http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
+
+function createAnchor(url){
+ var a = document.createElement('a');
+ a.href = url;
+ return a;
+}
+
+module.exports = {
+ getPathFromUrl : function(url){
+ var a = createAnchor(url);
+ return a.pathname;
+ },
+
+ changeUrlPath : function(url,newPath){
+ var a = createAnchor(url);
+ return a.protocol + "//" + a.hostname + ":" + a.port + newPath;
+ }
+};
+
+
+}, "core/constants": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+"use strict";
+
+module.exports = {
+ SCXML_NS : "http://www.w3.org/2005/07/scxml"
+};
+}, "core/scxml/SCXML": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+var ArraySet = require('./set/ArraySet'),
+ stateKinds = require('./state-kinds-enum'),
+ setupDefaultOpts = require('./setup-default-opts'),
+ scxmlPrefixTransitionSelector = require('./scxml-dynamic-name-match-transition-selector'),
+ pm = require('../../platform');
+
+function getTransitionWithHigherSourceChildPriority(model) {
+ return function(_arg) {
+ var t1 = _arg[0], t2 = _arg[1];
+ //compare transitions based first on depth, then based on document order
+ if (t1.source.depth < t2.source.depth) {
+ return t2;
+ } else if (t2.source.depth < t1.source.depth) {
+ return t1;
+ } else {
+ if (t1.documentOrder < t2.documentOrder) {
+ return t1;
+ } else {
+ return t2;
+ }
+ }
+ };
+}
+
+/** @const */
+var printTrace = false;
+
+/** @constructor */
+function SCXMLInterpreter(model, opts){
+ this.model = model;
+ this.opts = opts;
+
+ this.opts.log = this.opts.log || pm.platform.log; //rely on global console if this console is undefined
+ this.opts.StateIdSet = this.opts.StateIdSet || ArraySet;
+ this.opts.EventSet = this.opts.EventSet || ArraySet;
+ this.opts.TransitionPairSet = this.opts.TransitionPairSet || ArraySet;
+ this.opts.priorityComparisonFn = this.opts.priorityComparisonFn || getTransitionWithHigherSourceChildPriority(this.opts.model);
+
+ this._configuration = new this.opts.BasicStateSet();
+ this._historyValue = {};
+ this._innerEventQueue = [];
+ this._isInFinalState = false;
+ this._timeoutMap = {};
+
+ this._listeners = [];
+}
+
+SCXMLInterpreter.prototype = {
+
+ /** @expose */
+ start : function() {
+ //perform big step without events to take all default transitions and reach stable initial state
+ if (printTrace) pm.platform.log("performing initial big step");
+ this._configuration.add(this.model.root.initial);
+
+ //figure out which require to use when evaluating action code, in the following order:
+ //the one specified when instantiating the interpreter
+ //the require of the module importing SCION
+ //the require of the main module
+ //this module's require
+ var actionCodeRequire =
+ this.opts.require ||
+ (module.parent &&
+ module.parent.parent &&
+ module.parent.parent.require &&
+ module.parent.parent.require.bind(module.parent.parent)) ||
+ (require.main &&
+ require.main.require &&
+ require.main.require.bind(require.main)) ||
+ require;
+
+ //set up scope for action code embedded in the document
+ var tmp = this.model.actionFactory(
+ this.opts.log,
+ this._cancel.bind(this),
+ this._send.bind(this),
+ this.opts.origin,
+ this.isIn.bind(this),
+ actionCodeRequire,
+ pm.platform.parseDocumentFromString);
+ this._actions = tmp.actions;
+ this._datamodel = tmp.datamodel;
+
+ this._performBigStep();
+ return this.getConfiguration();
+ },
+
+ _getOrSetData : function(fnName,name,value){
+ var data = this._datamodel[name];
+ if(!data) throw new Error("Variable " + name + " not declared in datamodel.");
+ return data[fnName](value);
+ },
+
+ _getData : function(name){
+ return this._getOrSetData("get",name);
+ },
+
+ _setData : function(name,value){
+ return this._getOrSetData("set",name,value);
+ },
+
+ /** @expose */
+ getConfiguration : function() {
+ return this._configuration.iter().map(function(s){return s.id;});
+ },
+
+ /** @expose */
+ getFullConfiguration : function() {
+ return this._configuration.iter().
+ map(function(s){ return [s].concat(this.opts.model.getAncestors(s));},this).
+ reduce(function(a,b){return a.concat(b);},[]). //flatten
+ map(function(s){return s.id;}).
+ reduce(function(a,b){return a.indexOf(b) > -1 ? a : a.concat(b);},[]); //uniq
+ },
+
+
+ /** @expose */
+ isIn : function(stateName) {
+ return this.getFullConfiguration().indexOf(stateName) > -1;
+ },
+
+ /** @private */
+ _performBigStep : function(e) {
+ if (e) this._innerEventQueue.push(new this.opts.EventSet([e]));
+ var keepGoing = true;
+ while (keepGoing) {
+ var eventSet = this._innerEventQueue.length ? this._innerEventQueue.shift() : new this.opts.EventSet();
+
+ //create new datamodel cache for the next small step
+ var datamodelForNextStep = {};
+ var selectedTransitions = this._performSmallStep(eventSet, datamodelForNextStep);
+ keepGoing = !selectedTransitions.isEmpty();
+ }
+ this._isInFinalState = this._configuration.iter().every(function(s){ return s.kind === stateKinds.FINAL; });
+ },
+
+ /** @private */
+ _performSmallStep : function(eventSet, datamodelForNextStep) {
+
+ if (printTrace) pm.platform.log("selecting transitions with eventSet: ", eventSet);
+
+ var selectedTransitions = this._selectTransitions(eventSet, datamodelForNextStep);
+
+ if (printTrace) pm.platform.log("selected transitions: ", selectedTransitions);
+
+ if (!selectedTransitions.isEmpty()) {
+
+ if (printTrace) pm.platform.log("sorted transitions: ", selectedTransitions);
+
+ //we only want to enter and exit states from transitions with targets
+ //filter out targetless transitions here - we will only use these to execute transition actions
+ var selectedTransitionsWithTargets = new this.opts.TransitionSet(selectedTransitions.iter().filter(function(t){return t.targets;}));
+
+ var exitedTuple = this._getStatesExited(selectedTransitionsWithTargets),
+ basicStatesExited = exitedTuple[0],
+ statesExited = exitedTuple[1];
+
+ var enteredTuple = this._getStatesEntered(selectedTransitionsWithTargets),
+ basicStatesEntered = enteredTuple[0],
+ statesEntered = enteredTuple[1];
+
+ if (printTrace) pm.platform.log("basicStatesExited ", basicStatesExited);
+ if (printTrace) pm.platform.log("basicStatesEntered ", basicStatesEntered);
+ if (printTrace) pm.platform.log("statesExited ", statesExited);
+ if (printTrace) pm.platform.log("statesEntered ", statesEntered);
+
+ var eventsToAddToInnerQueue = new this.opts.EventSet();
+
+ //update history states
+ if (printTrace) pm.platform.log("executing state exit actions");
+
+ statesExited.forEach(function(state){
+
+ if (printTrace || this.opts.logStatesEnteredAndExited) pm.platform.log("exiting ", state.id);
+
+ //invoke listeners
+ this._listeners.forEach(function(l){
+ if(l.onExit) l.onExit(state.id);
+ });
+
+ if(state.onexit !== undefined) this._evaluateAction(state.onexit,eventSet, datamodelForNextStep, eventsToAddToInnerQueue);
+
+ var f;
+ if (state.history) {
+ if (state.history.isDeep) {
+ f = function(s0) {
+ return s0.kind === stateKinds.BASIC && state.descendants.indexOf(s0) > -1;
+ };
+ } else {
+ f = function(s0) {
+ return s0.parent === state;
+ };
+ }
+ //update history
+ this._historyValue[state.history.id] = statesExited.filter(f);
+ }
+ },this);
+
+
+ // -> Concurrency: Number of transitions: Multiple
+ // -> Concurrency: Order of transitions: Explicitly defined
+ var sortedTransitions = selectedTransitions.iter().sort(function(t1, t2) {
+ return t1.documentOrder - t2.documentOrder;
+ });
+
+ if (printTrace) pm.platform.log("executing transitition actions");
+
+
+ sortedTransitions.forEach(function(transition){
+
+ var targetIds = transition.targets && transition.targets.map(function(target){return target.id;});
+
+ this._listeners.forEach(function(l){
+ if(l.onTransition) l.onTransition(transition.source.id,targetIds);
+ });
+
+ if(transition.actions !== undefined) this._evaluateAction(transition.actions,eventSet, datamodelForNextStep, eventsToAddToInnerQueue);
+ },this);
+
+ if (printTrace) pm.platform.log("executing state enter actions");
+
+ statesEntered.forEach(function(state){
+
+ if (printTrace || this.opts.logStatesEnteredAndExited) pm.platform.log("entering", state.id);
+
+ this._listeners.forEach(function(l){
+ if(l.onEntry) l.onEntry(state.id);
+ });
+
+ if(state.onentry !== undefined) this._evaluateAction(state.onentry, eventSet, datamodelForNextStep, eventsToAddToInnerQueue);
+ },this);
+
+ if (printTrace) pm.platform.log("updating configuration ");
+ if (printTrace) pm.platform.log("old configuration ", this._configuration);
+
+ //update configuration by removing basic states exited, and adding basic states entered
+ this._configuration.difference(basicStatesExited);
+ this._configuration.union(basicStatesEntered);
+
+ if (printTrace) pm.platform.log("new configuration ", this._configuration);
+
+ //add set of generated events to the innerEventQueue -> Event Lifelines: Next small-step
+ if (!eventsToAddToInnerQueue.isEmpty()) {
+ if (printTrace) pm.platform.log("adding triggered events to inner queue ", eventsToAddToInnerQueue);
+ this._innerEventQueue.push(eventsToAddToInnerQueue);
+ }
+
+ if (printTrace) pm.platform.log("updating datamodel for next small step :");
+
+ //update the datamodel
+ for (var key in datamodelForNextStep) {
+ this._setData(key,datamodelForNextStep[key]);
+ }
+ }
+
+ //if selectedTransitions is empty, we have reached a stable state, and the big-step will stop, otherwise will continue -> Maximality: Take-Many
+ return selectedTransitions;
+ },
+
+ /** @private */
+ _evaluateAction : function(actionRef, eventSet, datamodelForNextStep, eventsToAddToInnerQueue) {
+ function $raise(event){
+ eventsToAddToInnerQueue.add(event);
+ }
+
+ var n = this._getScriptingInterface(datamodelForNextStep, eventSet, true);
+ return this._actions[actionRef].call(this.opts.evaluationContext, n.getData, n.setData, n.events, $raise);
+ },
+
+ /** @private */
+ _getScriptingInterface : function(datamodelForNextStep, eventSet, allowWrite) {
+ return {
+ setData: allowWrite ? function(name, value) {
+ return datamodelForNextStep[name] = value;
+ } : function() {},
+ getData: this._getData.bind(this),
+ events: eventSet.iter()
+ };
+ },
+
+ /** @private */
+ _getStatesExited : function(transitions) {
+ var statesExited = new this.opts.StateSet();
+ var basicStatesExited = new this.opts.BasicStateSet();
+
+ transitions.iter().forEach(function(transition){
+ var lca = transition.lca;
+ var desc = lca.descendants;
+
+ this._configuration.iter().forEach(function(state){
+ if(desc.indexOf(state) > -1){
+ basicStatesExited.add(state);
+ statesExited.add(state);
+ this.opts.model.getAncestors(state,lca).forEach(function(anc){
+ statesExited.add(anc);
+ });
+ }
+ },this);
+ },this);
+
+ var sortedStatesExited = statesExited.iter().sort(function(s1, s2) {
+ return s2.depth - s1.depth;
+ });
+ return [basicStatesExited, sortedStatesExited];
+ },
+
+ /** @private */
+ _getStatesEntered : function(transitions) {
+
+ var statesToEnter = new this.opts.StateSet();
+ var basicStatesToEnter = new this.opts.BasicStateSet();
+ var statesProcessed = new this.opts.StateSet();
+ var statesToProcess = [];
+
+ var processTransitionSourceAndTarget = (function(source,target){
+ //process each target
+ processState(target);
+
+ //and process ancestors of targets up to LCA, but according to special rules
+ var lca = this.opts.model.getLCA(source,target);
+ this.opts.model.getAncestors(target,lca).forEach(function(s){
+ if (s.kind === stateKinds.COMPOSITE) {
+ //just add him to statesToEnter, and declare him processed
+ //this is to prevent adding his initial state later on
+ statesToEnter.add(s);
+
+ statesProcessed.add(s);
+ }else{
+ //everything else can just be passed through as normal
+ processState(s);
+ }
+ });
+ }).bind(this);
+
+ var processState = (function(s){
+
+ if(statesProcessed.contains(s)) return;
+
+ if (s.kind === stateKinds.HISTORY) {
+ if (s.id in this._historyValue) {
+ this._historyValue[s.id].forEach(function(stateFromHistory){
+ processTransitionSourceAndTarget(s,stateFromHistory);
+ });
+ } else {
+ statesToEnter.add(s);
+ basicStatesToEnter.add(s);
+ }
+ } else {
+ statesToEnter.add(s);
+
+ if (s.kind === stateKinds.PARALLEL) {
+ statesToProcess.push.apply(statesToProcess,
+ s.children.filter(function(s){return s.kind !== stateKinds.HISTORY;}));
+ } else if (s.kind === stateKinds.COMPOSITE) {
+ statesToProcess.push(s.initial);
+ } else if (s.kind === stateKinds.INITIAL || s.kind === stateKinds.BASIC || s.kind === stateKinds.FINAL) {
+ basicStatesToEnter.add(s);
+ }
+ }
+
+ statesProcessed.add(s);
+
+ }).bind(this);
+
+ //do the initial setup
+ transitions.iter().forEach(function(transition){
+ transition.targets.forEach(function(target){
+ processTransitionSourceAndTarget(transition.source,target);
+ });
+ });
+
+ //loop and add states until there are no more to add (we reach a stable state)
+ var s;
+ /*jsl:ignore*/
+ while(s = statesToProcess.pop()){
+ /*jsl:end*/
+ processState(s);
+ }
+
+ //sort based on depth
+ var sortedStatesEntered = statesToEnter.iter().sort(function(s1, s2) {
+ return s1.depth - s2.depth;
+ });
+
+ return [basicStatesToEnter, sortedStatesEntered];
+ },
+
+ /** @private */
+ _selectTransitions : function(eventSet, datamodelForNextStep) {
+ if (this.opts.onlySelectFromBasicStates) {
+ var states = this._configuration.iter();
+ } else {
+ var statesAndParents = new this.opts.StateSet;
+
+ //get full configuration, unordered
+ //this means we may select transitions from parents before children
+
+ this._configuration.iter().forEach(function(basicState){
+ statesAndParents.add(basicState);
+ this.opts.model.getAncestors(basicState).forEach(function(ancestor){
+ statesAndParents.add(ancestor);
+ });
+ },this);
+
+ states = statesAndParents.iter();
+ }
+ var n = this._getScriptingInterface(datamodelForNextStep, eventSet);
+ var e = (function(t) {
+ return this._actions[t.conditionActionRef].call(this.opts.evaluationContext, n.getData, n.setData, n.events);
+ }).bind(this);
+
+ var eventNames = eventSet.iter().map(function(event){return event.name;});
+
+ var usePrefixMatchingAlgorithm = eventNames.filter(function(name){return name.search(".");}).length;
+
+ var transitionSelector = usePrefixMatchingAlgorithm ? scxmlPrefixTransitionSelector : this.opts.transitionSelector;
+ var enabledTransitions = new this.opts.TransitionSet();
+
+ states.forEach(function(state){
+ transitionSelector(state,eventNames,e).forEach(function(t){
+ enabledTransitions.add(t);
+ });
+ });
+
+ var priorityEnabledTransitions = this._selectPriorityEnabledTransitions(enabledTransitions);
+
+ if (printTrace) pm.platform.log("priorityEnabledTransitions", priorityEnabledTransitions);
+
+ return priorityEnabledTransitions;
+ },
+
+ /** @private */
+ _selectPriorityEnabledTransitions : function(enabledTransitions) {
+ var priorityEnabledTransitions = new this.opts.TransitionSet();
+
+ var tuple = this._getInconsistentTransitions(enabledTransitions),
+ consistentTransitions = tuple[0],
+ inconsistentTransitionsPairs = tuple[1];
+
+ priorityEnabledTransitions.union(consistentTransitions);
+
+ if (printTrace) pm.platform.log("enabledTransitions", enabledTransitions);
+ if (printTrace) pm.platform.log("consistentTransitions", consistentTransitions);
+ if (printTrace) pm.platform.log("inconsistentTransitionsPairs", inconsistentTransitionsPairs);
+ if (printTrace) pm.platform.log("priorityEnabledTransitions", priorityEnabledTransitions);
+
+ while (!inconsistentTransitionsPairs.isEmpty()) {
+ enabledTransitions = new this.opts.TransitionSet(
+ inconsistentTransitionsPairs.iter().map(function(t){return this.opts.priorityComparisonFn(t);},this));
+
+ tuple = this._getInconsistentTransitions(enabledTransitions);
+ consistentTransitions = tuple[0];
+ inconsistentTransitionsPairs = tuple[1];
+
+ priorityEnabledTransitions.union(consistentTransitions);
+
+ if (printTrace) pm.platform.log("enabledTransitions", enabledTransitions);
+ if (printTrace) pm.platform.log("consistentTransitions", consistentTransitions);
+ if (printTrace) pm.platform.log("inconsistentTransitionsPairs", inconsistentTransitionsPairs);
+ if (printTrace) pm.platform.log("priorityEnabledTransitions", priorityEnabledTransitions);
+
+ }
+ return priorityEnabledTransitions;
+ },
+
+ /** @private */
+ _getInconsistentTransitions : function(transitions) {
+ var allInconsistentTransitions = new this.opts.TransitionSet();
+ var inconsistentTransitionsPairs = new this.opts.TransitionPairSet();
+ var transitionList = transitions.iter();
+
+ if (printTrace) pm.platform.log("transitions", transitionList);
+
+ for(var i = 0; i < transitionList.length; i++){
+ for(var j = i+1; j < transitionList.length; j++){
+ var t1 = transitionList[i];
+ var t2 = transitionList[j];
+ if (this._conflicts(t1, t2)) {
+ allInconsistentTransitions.add(t1);
+ allInconsistentTransitions.add(t2);
+ inconsistentTransitionsPairs.add([t1, t2]);
+ }
+ }
+ }
+
+ var consistentTransitions = transitions.difference(allInconsistentTransitions);
+ return [consistentTransitions, inconsistentTransitionsPairs];
+ },
+
+ /** @private */
+ _conflicts : function(t1, t2) {
+ return !this._isArenaOrthogonal(t1, t2);
+ },
+
+ /** @private */
+ _isArenaOrthogonal : function(t1, t2) {
+ var t1LCA = t1.targets ? t1.lca : t1.source;
+ var t2LCA = t2.targets ? t2.lca : t2.source;
+ var isOrthogonal = this.opts.model.isOrthogonalTo(t1LCA, t2LCA);
+
+ if (printTrace) {
+ pm.platform.log("transition LCAs", t1LCA.id, t2LCA.id);
+ pm.platform.log("transition LCAs are orthogonal?", isOrthogonal);
+ }
+
+ return isOrthogonal;
+ },
+
+
+ /*
+ registerListener provides a generic mechanism to subscribe to state change notifications.
+ Can be used for logging and debugging. For example, can attache a logger that simply logs the state changes.
+ Or can attach a network debugging client that sends state change notifications to a debugging server.
+
+ listener is of the form:
+ {
+ onEntry : function(stateId){},
+ onExit : function(stateId){},
+ onTransition : function(sourceStateId,targetStatesIds[]){}
+ }
+ */
+
+ /** @expose */
+ registerListener : function(listener){
+ return this._listeners.push(listener);
+ },
+
+ /** @expose */
+ unregisterListener : function(listener){
+ return this._listeners.splice(this._listeners.indexOf(listener),1);
+ }
+
+};
+
+
+/**
+ * @constructor
+ * @extends SCXMLInterpreter
+ */
+function SimpleInterpreter(model, opts) {
+ opts = opts || {};
+ setupDefaultOpts(opts);
+
+ this._isStepping = false;
+
+ this._send = opts.send || this._send;
+
+ this._cancel = opts.cancel || this._cancel;
+
+ SCXMLInterpreter.call(this,model,opts); //call super constructor
+}
+SimpleInterpreter.prototype = Object.create(SCXMLInterpreter.prototype);
+
+/** @expose */
+SimpleInterpreter.prototype.gen = function(evtObjOrName,optionalData) {
+
+ var e;
+ switch(typeof evtObjOrName){
+ case 'string':
+ e = {name : evtObjOrName, data : optionalData};
+ break;
+ case 'object':
+ if(typeof evtObjOrName.name === 'string'){
+ e = evtObjOrName;
+ }else{
+ throw new Error('Event object must have "name" property of type string.');
+ }
+ break;
+ default:
+ throw new Error('First argument to gen must be a string or object.');
+ }
+
+ if (this._isStepping) {
+ throw new Error("gen called before previous call to gen could complete. If executed in single-threaded environment, this means it was called recursively, which is illegal, as it would break SCION step semantics.");
+ }
+
+ this._isStepping = true;
+ this._performBigStep(e);
+ this._isStepping = false;
+ return this.getConfiguration();
+};
+
+/** @private */
+SimpleInterpreter.prototype._send = function(event, options) {
+ var callback, timeoutId,
+ _this = this;
+ if (pm.platform.setTimeout) {
+ if (printTrace) {
+ pm.platform.log("sending event", event.name, "with content", event.data, "after delay", options.delay);
+ }
+ callback = function() {
+ return _this.gen(event);
+ };
+ timeoutId = pm.platform.setTimeout(callback, options.delay);
+ if (options.sendid) return this._timeoutMap[options.sendid] = timeoutId;
+ } else {
+ throw new Error("setTimeout function not set");
+ }
+};
+
+/** @private */
+SimpleInterpreter.prototype._cancel = function(sendid){
+ if (pm.platform.clearTimeout) {
+ if (sendid in this._timeoutMap) {
+ if (printTrace) {
+ pm.platform.log("cancelling ", sendid, " with timeout id ", this._timeoutMap[sendid]);
+ }
+ return pm.platform.clearTimeout(this._timeoutMap[sendid]);
+ }
+ } else {
+ throw new Error("clearTimeout function not set");
+ }
+};
+
+module.exports = {
+ SCXMLInterpreter: SCXMLInterpreter,
+ SimpleInterpreter: SimpleInterpreter
+};
+}, "core/scxml/default-transition-selector": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+module.exports = function(state,eventNames,evaluator){
+ return state.transitions.filter(function(t){
+ return !t.event || ( eventNames.indexOf(t.event) > -1 && (!t.cond || evaluator(t)) );
+ });
+};
+}, "core/scxml/json2model": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+var pm = require('../../platform'),
+ cg = require('../util/code-gen');
+
+function linkReferencesAndGenerateActionFactory(json){
+
+ function makeEvaluationFn(action,isExpression){
+ return actionStrings.push(cg.gen.util.wrapFunctionBodyInDeclaration(action,isExpression)) - 1;
+ }
+
+ function stateIdToReference(stateId){
+ return idToStateMap[stateId];
+ }
+
+ var actionStrings = [];
+ var idToStateMap = {};
+ json.states.forEach(function(state){
+ idToStateMap[state.id] = state;
+ });
+
+ json.transitions.forEach(function(transition){
+ if(transition.cond) transition.conditionActionRef = makeEvaluationFn(transition.cond,true);
+ });
+
+ json.states.forEach(function(state){
+ state.transitions = state.transitions.map(function(transitionNum){ return json.transitions[transitionNum];});
+
+ var actions = [];
+
+ if(state.onentry) state.onentry = makeEvaluationFn(state.onentry);
+ if(state.onexit) state.onexit = makeEvaluationFn(state.onexit);
+
+ state.transitions.forEach(function(transition){
+ if(transition.actions) transition.actions = makeEvaluationFn(transition.actions);
+
+ if(transition.lca){
+ transition.lca = idToStateMap[transition.lca];
+ }
+ });
+
+ state.initial = idToStateMap[state.initial];
+ state.history = idToStateMap[state.history];
+
+ state.children = state.children.map(stateIdToReference);
+
+ state.parent = idToStateMap[state.parent];
+
+ if (state.ancestors) {
+ state.ancestors = state.ancestors.map(stateIdToReference);
+ }
+
+ if (state.descendants) {
+ state.descendants = state.descendants.map(stateIdToReference);
+ }
+
+ state.transitions.forEach(function(t){
+ t.source = idToStateMap[t.source];
+ t.targets = t.targets && t.targets.map(stateIdToReference);
+ });
+ });
+
+ json.root = idToStateMap[json.root];
+
+ var actionFactoryString = cg.gen.util.makeActionFactory(json.scripts,actionStrings,json.datamodel);
+
+ return actionFactoryString;
+}
+
+function annotatedJsonToModel(json,documentUrl) {
+ var actionFactoryString = linkReferencesAndGenerateActionFactory(json);
+ try {
+ json.actionFactory = pm.platform.eval(actionFactoryString,documentUrl);
+ }catch(e){
+ pm.platform.log("Failed to evaluate action factory.");
+ pm.platform.log("Generated js code to evaluate\n",actionFactoryString);
+ //require('fs').writeFileSync('out.js',actionFactoryString,'utf8');
+ throw e;
+ }
+}
+
+module.exports = function(json,documentUrl){
+ annotatedJsonToModel(json,documentUrl);
+ return json;
+};
+
+//TODO: get google closure to compile this out as dead code in the browser build
+if(require.main === module){
+ var fileName = process.argv[2];
+
+ //this prints out the generated code from a json file which is the output of annotate-scxml-json
+ var done = function(err,annotatedJsonStr){
+ if(err) throw err;
+ process.stdout.write(linkReferencesAndGenerateActionFactory(JSON.parse(annotatedJsonStr)));
+ };
+
+ if(fileName === "-"){
+ //read from stdin
+ var s = "";
+ process.stdin.resume();
+ process.stdin.on("data",function(data){
+ s += data;
+ });
+ process.stdin.on("end",function(data){
+ done(null,s);
+ });
+ }else{
+ //read from fs
+ var fs = require('fs');
+ fs.readFile(fileName,'utf8',done);
+ }
+
+}
+}, "core/scxml/model": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+var stateKinds = require('./state-kinds-enum');
+
+var model = {
+ getAncestors: function(s, root) {
+ var ancestors, index, state;
+ index = s.ancestors.indexOf(root);
+ if (index > -1) {
+ return s.ancestors.slice(0, index);
+ } else {
+ return s.ancestors;
+ }
+ },
+ /** @this {model} */
+ getAncestorsOrSelf: function(s, root) {
+ return [s].concat(this.getAncestors(s, root));
+ },
+ getDescendantsOrSelf: function(s) {
+ return [s].concat(s.descendants);
+ },
+ /** @this {model} */
+ isOrthogonalTo: function(s1, s2) {
+ //Two control states are orthogonal if they are not ancestrally
+ //related, and their smallest, mutual parent is a Concurrent-state.
+ return !this.isAncestrallyRelatedTo(s1, s2) && this.getLCA(s1, s2).kind === stateKinds.PARALLEL;
+ },
+ /** @this {model} */
+ isAncestrallyRelatedTo: function(s1, s2) {
+ //Two control states are ancestrally related if one is child/grandchild of another.
+ return this.getAncestorsOrSelf(s2).indexOf(s1) > -1 || this.getAncestorsOrSelf(s1).indexOf(s2) > -1;
+ },
+ /** @this {model} */
+ getLCA: function(s1, s2) {
+ var commonAncestors = this.getAncestors(s1).filter(function(a){
+ return a.descendants.indexOf(s2) > -1;
+ },this);
+ return commonAncestors[0];
+ }
+};
+
+module.exports = model;
+}, "core/scxml/scxml-dynamic-name-match-transition-selector": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+var eventNameReCache = {};
+
+function eventNameToRe(name) {
+ return new RegExp("^" + (name.replace(/\./g, "\\.")) + "(\\.[0-9a-zA-Z]+)*$");
+}
+
+function retrieveEventRe(name) {
+ return eventNameReCache[name] ? eventNameReCache[name] : eventNameReCache[name] = eventNameToRe(name);
+}
+
+function nameMatch(t, eventNames) {
+ var tEvents = t.events;
+ var f =
+ tEvents.indexOf("*") > -1 ?
+ function() { return true; } :
+ function(name) {
+ return tEvents.filter(function(tEvent){
+ return retrieveEventRe(tEvent).test(name);
+ }).length;
+ };
+ return eventNames.filter(f).length;
+}
+
+module.exports = function(state, eventNames, evaluator) {
+ return state.transitions.filter(function(t){
+ return (!t.events || nameMatch(t,eventNames)) && (!t.cond || evaluator(t));
+ });
+};
+}, "core/scxml/set/ArraySet": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+/** @constructor */
+function ArraySet(l) {
+ l = l || [];
+ this.o = [];
+
+ l.forEach(function(x){
+ this.add(x);
+ },this);
+}
+
+ArraySet.prototype = {
+
+ add : function(x) {
+ if (!this.contains(x)) return this.o.push(x);
+ },
+
+ remove : function(x) {
+ var i = this.o.indexOf(x);
+ if(i === -1){
+ return false;
+ }else{
+ this.o.splice(i, 1);
+ }
+ return true;
+ },
+
+ union : function(l) {
+ l = l.iter ? l.iter() : l;
+ l.forEach(function(x){
+ this.add(x);
+ },this);
+ return this;
+ },
+
+ difference : function(l) {
+ l = l.iter ? l.iter() : l;
+
+ l.forEach(function(x){
+ this.remove(x);
+ },this);
+ return this;
+ },
+
+ contains : function(x) {
+ return this.o.indexOf(x) > -1;
+ },
+
+ iter : function() {
+ return this.o;
+ },
+
+ isEmpty : function() {
+ return !this.o.length;
+ },
+
+ equals : function(s2) {
+ var l2 = s2.iter();
+ var l1 = this.o;
+
+ return l1.every(function(x){
+ return l2.indexOf(x) > -1;
+ }) && l2.every(function(x){
+ return l1.indexOf(x) > -1;
+ });
+ },
+
+ toString : function() {
+ return "Set(" + this.o.toString() + ")";
+ }
+};
+
+module.exports = ArraySet;
+}, "core/scxml/setup-default-opts": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+var selector = require('./scxml-dynamic-name-match-transition-selector'),
+ ArraySet = require('./set/ArraySet'),
+ m = require('./model');
+
+module.exports = function(opts) {
+ opts = opts || {};
+ opts.TransitionSet = opts.TransitionSet || ArraySet;
+ opts.StateSet = opts.StateSet || ArraySet;
+ opts.BasicStateSet = opts.BasicStateSet || ArraySet;
+ opts.transitionSelector = opts.transitionSelector || selector;
+ opts.model = opts.model || m;
+ return opts;
+};
+
+}, "core/scxml/state-kinds-enum": function(exports, require, module) {// Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+"use strict";
+
+module.exports = {
+ BASIC: 0,
+ COMPOSITE: 1,
+ PARALLEL: 2,
+ HISTORY: 3,
+ INITIAL: 4,
+ FINAL: 5
+};
+}, "core/util/annotate-scxml-json": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+This module transforms an SCXML document to a proprietary JSON-based intermediate representation.
+*/
+
+
+"use strict";
+
+var codeGen = require('./code-gen'),
+ constants = require('../constants'),
+ pm = require('../../platform');
+
+var stateKinds = require("../scxml/state-kinds-enum");
+
+var STATES_THAT_CAN_BE_CHILDREN = ["state", "parallel", "history", "final", "initial"],
+ STATE_TAGS = STATES_THAT_CAN_BE_CHILDREN.concat("scxml");
+
+
+var states, basicStates, uniqueEvents, transitions, idToStateMap, onFoundStateIdCallbacks, datamodel, doc;
+
+var transformAndSerialize = exports.transformAndSerialize = transformAndSerialize = function(root) {
+ return JSON.stringify(transform(root));
+};
+
+var transform = exports.transform = function(scxmlDoc) {
+
+ doc = scxmlDoc;
+
+ var root = doc.documentElement;
+
+ states = [];
+ basicStates = [];
+ uniqueEvents = {};
+ transitions = [];
+ idToStateMap = {};
+ onFoundStateIdCallbacks = [];
+ datamodel = {};
+
+ var rootState = transformStateNode(root, []);
+
+ states.forEach(function(state){
+ state.ancestors.reverse();
+ });
+
+ states.forEach(function(state){
+ state.descendants.reverse();
+ });
+
+ transitions.filter(function(t){return t.targets;}).forEach(function(transition){
+ var source = idToStateMap[transition.source];
+ var targets = transition.targets.map(function(target){
+ var state = idToStateMap[target];
+ if(!state) throw new Error("Transition targets state id '" + target + "' but state does not exist.");
+ return state;
+ });
+
+ transition.lca = getLCA(source, targets[0]);
+ });
+
+ return {
+ states: states,
+ transitions: transitions,
+ root: rootState.id,
+ events: genEventsEnum(uniqueEvents),
+ scripts: genRootScripts(root),
+ profile: pm.platform.dom.getAttribute(root,"profile"),
+ version: pm.platform.dom.getAttribute(root,"version"),
+ datamodel: datamodel
+ };
+};
+
+function genRootScripts(root) {
+ return pm.platform.dom.getChildren(root).filter(function(c){return pm.platform.dom.localName(c) === "script";}).map(function(c){return pm.platform.dom.textContent(c);});
+}
+
+function genEventsEnum(uniqueEvents) {
+ var event, eventDocumentOrder, toReturn;
+ eventDocumentOrder = 0;
+ toReturn = {};
+ for (event in uniqueEvents) {
+ toReturn[event] = {
+ name: event,
+ documentOrder: eventDocumentOrder++
+ };
+ }
+ return toReturn;
+}
+
+
+var stripStarFromEventNameRe = /^((([^.]+)\.)*([^.]+))(\.\*)?$/;
+
+function transformTransitionNode (transitionNode, parentState) {
+
+ //wildcard "*" event will show up on transition.events, but will not show up in uniqueEvents
+ //default transitions (those without events) will have events set to undefined (rather than empty array)
+ if (pm.platform.dom.hasAttribute(transitionNode,'event')) {
+ var events;
+
+ var event = pm.platform.dom.getAttribute(transitionNode,'event');
+ if (event === "*") {
+ events = [event];
+ } else {
+ events = event.trim().split(/\s+/).map(function(event){
+ var m = event.match(stripStarFromEventNameRe);
+ if (m) {
+ var normalizedEvent = m[1];
+ if (!(m && normalizedEvent)) {
+ throw new Error("Unable to parse event: " + event);
+ }else{
+ return normalizedEvent;
+ }
+ }
+ });
+ }
+
+ events.
+ filter(function(event){return event !== "*";}).
+ forEach(function(event){uniqueEvents[event] = true;});
+
+ if(events.indexOf(undefined) > -1){
+ throw new Error("Error parsing event attribute attributes.event");
+ }
+ }
+
+ var transition = {
+ documentOrder: transitions.length,
+ id: transitions.length,
+ source: parentState.id,
+ cond: pm.platform.dom.getAttribute(transitionNode,"cond"),
+ events: events,
+ targets: pm.platform.dom.hasAttribute(transitionNode,"target") ? pm.platform.dom.getAttribute(transitionNode,"target").trim().split(/\s+/) : null
+ };
+
+ if(pm.platform.dom.getElementChildren(transitionNode).length) transition.actions = codeGen.gen.parentToFnBody(transitionNode);
+
+ transitions.push(transition);
+
+ //set up LCA later
+
+ return transition;
+}
+
+function transformDatamodel(node, ancestors) {
+ pm.platform.dom.getChildren(node).filter(function(child){return pm.platform.dom.localName(child) === 'data';}).forEach(function(child){
+ if (pm.platform.dom.hasAttribute(child,"id")) {
+
+ var datamodelObject;
+
+ var id = pm.platform.dom.getAttribute(child,"id");
+
+ if(pm.platform.dom.hasAttribute(child,"expr")){
+ datamodelObject = {
+ content : pm.platform.dom.getAttribute(child,"expr"),
+ type : 'expr'
+ };
+ }else{
+ var hasType = pm.platform.dom.hasAttribute(child,'type');
+
+
+ //fetch the first text node to get the text content
+ if(hasType){
+ var type = pm.platform.dom.getAttribute(child,'type');
+
+ var textContent = type === 'xml' ?
+ pm.platform.dom.serializeToString(child) :
+ pm.platform.dom.textContent(child);
+
+ datamodelObject = {
+ content : textContent,
+ type : type
+ };
+ }else{
+ textContent = pm.platform.dom.textContent(child);
+ datamodelObject = textContent.length ?
+ {
+ content : textContent,
+ type : 'text'
+ } : null;
+ }
+ }
+
+ datamodel[id] = datamodelObject;
+ }
+ });
+}
+
+function transformStateNode(node, ancestors) {
+ var id = pm.platform.dom.hasAttribute(node,"id") ? pm.platform.dom.getAttribute(node,"id") : genId(pm.platform.dom.localName(node));
+ var kind;
+
+ switch (pm.platform.dom.localName(node)) {
+ case "state":
+ if( pm.platform.dom.getChildren(node).filter(function(child){return STATE_TAGS.indexOf(pm.platform.dom.localName(child)) > -1;}).length){
+ kind = stateKinds.COMPOSITE;
+ } else {
+ kind = stateKinds.BASIC;
+ }
+ break;
+ case "scxml":
+ kind = stateKinds.COMPOSITE;
+ break;
+ case "initial":
+ kind = stateKinds.INITIAL;
+ break;
+ case "parallel":
+ kind = stateKinds.PARALLEL;
+ break;
+ case "final":
+ kind = stateKinds.FINAL;
+ break;
+ case "history":
+ kind = stateKinds.HISTORY;
+ break;
+ default : break;
+ }
+ var state = {
+ id: id,
+ kind: kind,
+ descendants: []
+ };
+ idToStateMap[id] = state;
+ if (ancestors.length) state.parent = ancestors[ancestors.length - 1];
+ if (kind === stateKinds.HISTORY) {
+ state.isDeep = pm.platform.dom.getAttribute(node,"type") === "deep" ? true : false;
+ }
+ state.documentOrder = states.length;
+ states.push(state);
+ if (kind === stateKinds.BASIC || kind === stateKinds.INITIAL || kind === stateKinds.HISTORY) {
+ state.basicDocumentOrder = basicStates.length;
+ basicStates.push(state);
+ }
+ state.depth = ancestors.length;
+ state.ancestors = ancestors.slice();
+
+ //walk back up ancestors and add this state to lists of descendants
+ ancestors.forEach(function(anc){
+ idToStateMap[anc].descendants.push(state.id);
+ });
+
+ //need to do some work on his children
+ var onExitChildren,
+ onEntryChildren;
+ var transitionChildren = [];
+ var stateChildren = [];
+
+ var nextAncestors = ancestors.concat(state.id);
+
+ var processedInitial = false;
+ var firstStateChild = null;
+
+ var processInitialState = function(initialState) {
+ var child = transformStateNode(initialState, nextAncestors);
+ state.initial = child.id;
+ stateChildren.push(child);
+ return processedInitial = true;
+ };
+
+ //process all sub-elements
+ pm.platform.dom.getElementChildren(node).forEach(function(child){
+
+ //var tuple = util.deconstructNode(child, true), childTagName = tuple[0], childAttributes = tuple[1], childChildren = tuple[2];
+ switch (pm.platform.dom.localName(child)) {
+ case "transition":
+ transitionChildren.push(transformTransitionNode(child, state));
+ break;
+ case "onentry":
+ onEntryChildren = codeGen.gen.parentToFnBody(child);
+ break;
+ case "onexit":
+ onExitChildren = codeGen.gen.parentToFnBody(child);
+ break;
+ case "initial":
+ if (!processedInitial) {
+ processInitialState(child);
+ } else {
+ throw new Error("Encountered duplicate initial states in state " + state.id);
+ }
+ break;
+ case "history":
+ var c = transformStateNode(child, nextAncestors);
+ state.history = c.id;
+ stateChildren.push(c);
+ break;
+ case "datamodel":
+ transformDatamodel(child, nextAncestors);
+ break;
+ default:
+ if(STATES_THAT_CAN_BE_CHILDREN.indexOf(pm.platform.dom.localName(child)) > -1){
+ var transformedStateNode = transformStateNode(child, nextAncestors);
+ //this is used to set default initial state, if initial state is not specified
+ if (firstStateChild === null) firstStateChild = transformedStateNode;
+ stateChildren.push(transformedStateNode);
+ }
+ break;
+ }
+
+ });
+
+ if (!processedInitial && pm.platform.dom.localName(node) !== "parallel") {
+ var hasInitialAttribute = pm.platform.dom.hasAttribute(node,"initial");
+
+ //create a fake initial state and process him
+ var generateFakeInitialState = function(targetId) {
+ var initial = pm.platform.dom.createElementNS(doc,constants.SCXML_NS,"initial");
+ var transition = pm.platform.dom.createElementNS(doc,constants.SCXML_NS,"transition");
+ pm.platform.dom.setAttribute(transition,"target",targetId);
+ pm.platform.dom.appendChild(initial,transition);
+
+ return processInitialState(initial);
+ };
+
+ if (hasInitialAttribute) {
+ generateFakeInitialState(pm.platform.dom.getAttribute(node,"initial"));
+ } else {
+ if (firstStateChild) generateFakeInitialState(firstStateChild.id);
+ }
+ }
+
+ state.onexit = onExitChildren;
+ state.onentry = onEntryChildren;
+ state.transitions = transitionChildren.map(function(transition){return transition.documentOrder;});
+ state.children = stateChildren.map(function(child){return child.id;});
+
+ return state;
+}
+
+var idRoot = "$generated";
+
+var idCounter = {};
+
+function genId(tagName) {
+ idCounter[tagName] = idCounter[tagName] || 0;
+ return "" + idRoot + "-" + tagName + "-" + (idCounter[tagName]++);
+}
+
+function getLCA(s1, s2) {
+ var a, anc, commonAncestors, _i, _len, _ref, _ref2;
+ commonAncestors = [];
+ s1.ancestors.forEach(function(a){
+ anc = idToStateMap[a];
+ if(anc.descendants.indexOf(s2.id) > -1){
+ commonAncestors.push(a);
+ }
+ });
+ if(!commonAncestors.length) throw new Error("Could not find LCA for states.");
+ return commonAncestors[0];
+}
+
+//epic one-liner
+//this script can be called as a main script to convert an xml file to annotated scxml.
+//TODO: get google closure to compile this out as dead code in the browser build
+if(require.main === module) console.log(JSON.stringify(transform((new (require('xmldom').DOMParser)).parseFromString(require('fs').readFileSync(process.argv[2],'utf8'))),4,4));
+}, "core/util/code-gen": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+//this model handles code generation for action code
+//it should be possible to extend this to support custom actions
+
+"use strict";
+
+var pm = require('../../platform'),
+ constants = require('../constants');
+
+function parentToFnBody(action){
+ return pm.platform.dom.getElementChildren(action).map(actionTagToFnBody).join("\n;;\n");
+}
+
+function actionTagToFnBody(action){
+
+ var generator = actionTags[pm.platform.dom.namespaceURI(action)];
+ var generatorFn = generator && generator[pm.platform.dom.localName(action)];
+
+ if(!(generator && generatorFn)) throw new Error("Element " + pm.platform.dom.namespaceURI(action) + ':' + pm.platform.dom.localName(action) + " not yet supported");
+
+ return generatorFn(action);
+}
+
+var actionTags = {
+ "" : {
+ "script" : function(action){
+ return pm.platform.dom.textContent(action);
+ },
+
+ "assign" : function(action){
+ return pm.platform.dom.getAttribute(action,"location") + " = " + pm.platform.dom.getAttribute(action,"expr") + ";";
+ },
+
+ "if" : function(action){
+ var s = "";
+ s += "if(" + pm.platform.dom.getAttribute(action,"cond") + "){\n";
+
+ var childNodes = pm.platform.dom.getElementChildren(action);
+
+ for(var i = 0; i < childNodes.length; i++){
+ var child = childNodes[i];
+
+ if(pm.platform.dom.localName(child) === "elseif" || pm.platform.dom.localName(child) === "else"){
+ break;
+ }else{
+ s += actionTagToFnBody(child) + "\n;;\n";
+ }
+ }
+
+ //process if/else-if, and recurse
+ for(; i < childNodes.length; i++){
+ child = childNodes[i];
+
+ if(pm.platform.dom.localName(child) === "elseif"){
+ s+= "}else if(" + pm.platform.dom.getAttribute(child,"cond") + "){\n";
+ }else if(pm.platform.dom.localName(child) === "else"){
+ s += "}";
+ break;
+ }else{
+ s+= actionTagToFnBody(child) + "\n;;\n";
+ }
+ }
+
+ for(; i < childNodes.length; i++){
+ child = childNodes[i];
+
+ //this should get encountered first
+ if(pm.platform.dom.localName(child) === "else"){
+ s+= "else{\n";
+ }else{
+ s+= actionTagToFnBody(child) + "\n;;\n";
+ }
+ }
+ s+= "}";
+
+ return s;
+ },
+
+ "elseif" : function(){
+ throw new Error("Encountered unexpected elseif tag.");
+ },
+
+ "else" : function(){
+ throw new Error("Encountered unexpected else tag.");
+ },
+
+ "log" : function(action){
+ var params = [];
+
+ if(pm.platform.dom.hasAttribute(action,"label")) params.push( JSON.stringify(pm.platform.dom.getAttribute(action,"label")));
+ if(pm.platform.dom.hasAttribute(action,"expr")) params.push( pm.platform.dom.getAttribute(action,"expr"));
+
+ return "$log(" + params.join(",") + ");";
+ },
+
+ "raise" : function(action){
+ return "$raise({ name:" + JSON.stringify(pm.platform.dom.getAttribute(action,"event")) + ", data : {}});";
+ },
+
+ "cancel" : function(action){
+ return "$cancel(" + JSON.stringify(pm.platform.dom.getAttribute(action,"sendid")) + ");";
+ },
+
+ "send" : function(action){
+ var target = (pm.platform.dom.hasAttribute(action,"targetexpr") ? pm.platform.dom.getAttribute(action,"targetexpr") : JSON.stringify(pm.platform.dom.getAttribute(action,"target")));
+ var event = "{\n" +
+ "target: " + target + ",\n" +
+ "name: " + (pm.platform.dom.hasAttribute(action,"eventexpr") ? pm.platform.dom.getAttribute(action,"eventexpr") : JSON.stringify(pm.platform.dom.getAttribute(action,"event"))) + ",\n" +
+ "type: " + (pm.platform.dom.hasAttribute(action,"typeexpr") ? pm.platform.dom.getAttribute(action,"typeexpr") : JSON.stringify(pm.platform.dom.getAttribute(action,"type"))) + ",\n" +
+ "data: " + constructSendEventData(action) + ",\n" +
+ "origin: $origin\n" +
+ "}";
+
+ var send =
+ "if(" + target + " === '#_internal'){\n" +
+ "$raise(" + event + ");\n" +
+ "}else{\n" +
+ "$send(" + event + ", {\n" +
+ "delay: " + (pm.platform.dom.hasAttribute(action,"delayexpr") ? pm.platform.dom.getAttribute(action,"delayexpr") : getDelayInMs(pm.platform.dom.getAttribute(action,"delay"))) + ",\n" +
+ "sendId: " + (pm.platform.dom.hasAttribute(action,"idlocation") ? pm.platform.dom.getAttribute(action,"idlocation") : JSON.stringify(pm.platform.dom.getAttribute(action,"id"))) + "\n" +
+ "});" +
+ "}";
+
+ return send;
+ },
+
+ "foreach" : function(action){
+ var isIndexDefined = pm.platform.dom.hasAttribute(action,"index"),
+ index = pm.platform.dom.getAttribute(action,"index") || "$i", //FIXME: the index variable could shadow the datamodel. We should pick a unique temperorary variable name
+ item = pm.platform.dom.getAttribute(action,"item"),
+ arr = pm.platform.dom.getAttribute(action,"array"),
+ foreachBody = pm.platform.dom.getElementChildren(action).map(actionTagToFnBody).join("\n;;\n");
+
+ return "(function(){\n" +
+ "if(Array.isArray(" + arr + ")){\n" +
+ arr + ".forEach(function(" + item + "," + index + "){\n" +
+ foreachBody +
+ "\n});\n" +
+ "}else{\n" +
+ //assume object
+ "Object.keys(" + arr + ").forEach(function(" + index + "){\n" +
+ item + " = " + arr + "[" + index + "];\n" +
+ foreachBody +
+ "\n});\n" +
+ "}\n" +
+ "})();";
+ }
+ }
+};
+
+actionTags[constants.SCXML_NS] = actionTags[""]; //alias SCXML namespace to default namespace
+
+function getDelayInMs(delayString){
+ if (!delayString) {
+ return 0;
+ } else {
+ if (delayString.slice(-2) === "ms") {
+ return parseFloat(delayString.slice(0, -2));
+ } else if (delayString.slice(-1) === "s") {
+ return parseFloat(delayString.slice(0, -1)) * 1000;
+ } else {
+ return parseFloat(delayString);
+ }
+ }
+}
+
+function getDatamodelExpression(id, datamodelObject){
+ var s = id;
+
+ if(datamodelObject){
+ s += ' = ';
+
+ switch(datamodelObject.type){
+ case 'xml' :
+ s += '$parseXml(' + JSON.stringify(datamodelObject.content) + ')';
+ break;
+ case 'json' :
+ s += 'JSON.parse(' + JSON.stringify(datamodelObject.content) + ')';
+ break;
+ case 'expr' :
+ s += datamodelObject.content;
+ break;
+ default :
+ s += JSON.stringify(datamodelObject.content);
+ break;
+ }
+ }
+
+ return s;
+}
+
+//utility functions
+//this creates the string which declares the datamodel in the document scope
+function makeDatamodelDeclaration(datamodel){
+ var s = "var ";
+ var vars = [];
+ for(var id in datamodel){
+ var datamodelObject = datamodel[id];
+ vars.push(getDatamodelExpression(id,datamodelObject));
+ }
+ return vars.length ? (s + vars.join(", ") + ";") : "";
+}
+
+//this exposes a getter and setter API on the datamodel in the document scope
+function makeDatamodelClosures(datamodel){
+ var vars = [];
+ for(var id in datamodel){
+ vars.push( '"' + id + '" : {\n' +
+ '"set" : function(v){ return ' + id + ' = v; },\n' +
+ '"get" : function(){ return ' + id + ';}' +
+ '\n}');
+ }
+ return '{\n' + vars.join(',\n') + '\n}';
+}
+
+function wrapFunctionBodyInDeclaration(action,isExpression){
+ return "function(getData,setData,_events,$raise){var _event = _events[0];\n" +
+ (isExpression ? "return" : "") + " " + action +
+ "\n}";
+}
+
+
+function makeTopLevelFunctionBody(datamodelDeclaration,topLevelScripts,datamodelClosures,actionStrings){
+ return datamodelDeclaration +
+ (topLevelScripts.length ? topLevelScripts.join("\n") : "") +
+ "var $datamodel = " + datamodelClosures + ";\n" +
+ "return {\n" +
+ "datamodel:$datamodel,\n" +
+ "actions:[\n" + actionStrings.join(",\n") + "\n]" + //return all functions which get called during execution
+ "\n};";
+}
+
+function wrapTopLevelFunctionBodyInDeclaration(fnBody){
+ return "function($log,$cancel,$send,$origin,In,require,$parseXml){\n" + fnBody + "\n}";
+}
+
+//this function ensures that the code in each SCXML document will run in "document scope".
+//SCXML embeds js code as strings in the document, hence the use of "eval" to dynamically evaluate things.
+//This function ensures that eval() is only called once, when the model is parsed. It will not be called during execution of the statechart.
+//However, each SCXML interpreter instance will have its own copies of the functions declared in the document.
+//This is similar to the way HTML works - each page has its own copies of evaluated scripts.
+function makeActionFactory(topLevelScripts,actionStrings,datamodel){
+ var datamodelDeclaration = makeDatamodelDeclaration(datamodel);
+ var datamodelClosures = makeDatamodelClosures(datamodel);
+ var topLevelFnBody = makeTopLevelFunctionBody(datamodelDeclaration,topLevelScripts,datamodelClosures,actionStrings);
+ var fnStr = wrapTopLevelFunctionBodyInDeclaration(topLevelFnBody);
+ //require('fs').writeFileSync('out.js',fnStr);
+ return fnStr;
+}
+
+
+function constructSendEventData(action){
+
+ var namelist = pm.platform.dom.hasAttribute(action,"namelist") ? pm.platform.dom.getAttribute(action,"namelist").trim().split(/ +/) : null,
+ params = pm.platform.dom.getChildren(action).filter(function(child){return pm.platform.dom.localName(child) === 'param';}),
+ content = pm.platform.dom.getChildren(action).filter(function(child){return pm.platform.dom.localName(child) === 'content';});
+
+ if(content.length){
+ //TODO: instead of using textContent, serialize the XML
+ content = content[0];
+ if(pm.platform.dom.getAttribute(content,'type') === 'application/json'){
+ return pm.platform.dom.textContent(content);
+ }else{
+ return JSON.stringify(pm.platform.dom.textContent(content));
+ }
+ }else if(pm.platform.dom.hasAttribute(action,"contentexpr")){
+ return pm.platform.dom.getAttribute(action,"contentexpr");
+ }else{
+ var s = "{";
+ //namelist
+ if(namelist){
+ namelist.forEach(function(name){
+ s += '"' + name + '"' + ":" + name + ",\n";
+ });
+ }
+
+ //params
+ if(params.length){
+ params.map(function(child){return processParam(child);}).forEach(function(param){
+ if(param.expr){
+ s += '"' + param.name + '"' + ":" + param.expr + ",\n";
+ }else if(param.location){
+ s += '"' + param.name + '"' + ":" + param.location + ",\n";
+ }
+ });
+ }
+
+ s += "}";
+ return s;
+ }
+}
+
+function processParam(param) {
+ return {
+ name: pm.platform.dom.getAttribute(param,"name"),
+ expr: pm.platform.dom.getAttribute(param,"expr"),
+ location: pm.platform.dom.getAttribute(param,"location")
+ };
+}
+
+
+module.exports = {
+ gen : {
+ parentToFnBody : parentToFnBody,
+ actionTagToFnBody : actionTagToFnBody,
+ actionTags : actionTags,
+ util : {
+ makeDatamodelDeclaration : makeDatamodelDeclaration,
+ makeDatamodelClosures : makeDatamodelClosures,
+ wrapFunctionBodyInDeclaration : wrapFunctionBodyInDeclaration,
+ makeTopLevelFunctionBody : makeTopLevelFunctionBody,
+ wrapTopLevelFunctionBodyInDeclaration : wrapTopLevelFunctionBodyInDeclaration,
+ makeActionFactory : makeActionFactory
+ }
+ }
+};
+}, "core/util/docToModel": function(exports, require, module) {/*
+ Copyright 2011-2012 Jacob Beard, INFICON, and other SCION contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+"use strict";
+
+var annotator = require('./annotate-scxml-json'),
+ json2model = require('../scxml/json2model'),
+ pm = require('../../platform');
+
+function documentToModel(url,doc,cb){
+ //do whatever transforms
+ //inline script tags
+ //platformGet may be undefined, and we can continue without it, hence the guard
+ if(pm.platform.getResourceFromUrl){
+ inlineSrcs(url,doc,function(errors){
+ if(errors){
+ //I think we should probably just log any of these errors
+ pm.platform.log("Errors downloading src attributes",errors);
+ }
+ docToModel(doc,url,cb);
+ });
+ }else{
+ docToModel(doc,url,cb);
+ }
+}
+
+function docToModel(doc,url,cb){
+ try {
+ var annotatedScxmlJson = annotator.transform(doc);
+ var model = json2model(annotatedScxmlJson,url);
+ cb(null,model);
+ }catch(e){
+ cb(e);
+ }
+}
+
+function inlineSrcs(url,doc,cb){
+ //console.log('inlining scripts');
+
+ var scriptActionsWithSrcAttributes = [], errors = [];
+
+ traverse(doc.documentElement,scriptActionsWithSrcAttributes);
+
+ //async forEach
+ function retrieveScripts(){
+ var script = scriptActionsWithSrcAttributes.pop();
+ if(script){
+ //quick and dirty for now:
+ //to be totally correct, what we need to do here is:
+ //parse the url, extract the pathname, call dirname on path, and join that with the path to the file
+ var scriptUrl = pm.platform.dom.getAttribute(script,"src");
+ if(url){
+ var documentUrlPath = pm.platform.url.getPathFromUrl(url);
+ var documentDir = pm.platform.path.dirname(documentUrlPath);
+ var scriptPath = pm.platform.path.join(documentDir,scriptUrl);
+ scriptUrl = pm.platform.url.changeUrlPath(url,scriptPath);
+ }
+ //platform.log('fetching script src',scriptUrl);
+ pm.platform.getResourceFromUrl(scriptUrl,function(err,text){
+ if(err){
+ //just capture the error, and continue on
+ pm.platform.log("Error downloading document " + scriptUrl + " : " + err.message);
+ errors.push(err);