"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
5 | }b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write(""),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
--------------------------------------------------------------------------------
/lib/interpreter.coffee:
--------------------------------------------------------------------------------
1 | esprima = require 'esprima'
2 | {Util, Map} = require './util'
3 |
4 | root = exports
5 |
6 | class InterpreterException
7 |
8 | class ReturnException extends InterpreterException
9 | constructor: (@value) ->
10 |
11 | class BreakException extends InterpreterException
12 |
13 | class ContinueException extends InterpreterException
14 |
15 | class YieldException extends InterpreterException
16 | constructor: (@cont, @errCont, @value) ->
17 |
18 | class JSException
19 | constructor: (@error, @node, @env) ->
20 | toString: -> @error.toString()
21 |
22 | class StopIteration
23 | constructor: (@value) ->
24 | toString: -> "StopIteration"
25 |
26 | root.Environment = class Environment
27 | constructor: (@scopeChain=[new Map], @currentScope=0, @strict=false) ->
28 | @global = {}
29 | if global?
30 | nativeGlobal = global
31 | globalName = 'global'
32 | else
33 | nativeGlobal = window
34 | globalName = 'window'
35 | @global[k] = v for k, v of nativeGlobal
36 | nonEnumerable = ['Object', 'String', 'Function', 'RegExp', 'Number', 'Boolean',
37 | 'Date', 'Math', 'Error', 'JSON', 'eval', 'toString', 'undefined']
38 | Util.defineNonEnumerable @global, k, nativeGlobal[k] for k in nonEnumerable
39 | Util.defineNonEnumerable @global, globalName, @global
40 | Util.defineNonEnumerable @global, 'StopIteration', StopIteration
41 |
42 | copy: -> new Environment @scopeChain[..], @currentScope, @strict
43 |
44 | getGlobalEnv: -> new Environment @scopeChain[..0], 0, @strict
45 |
46 | increaseScope: (lexicalOnly) ->
47 | @scopeChain.push new Map
48 | @currentScope++ unless lexicalOnly
49 | Util.last(@scopeChain)
50 |
51 | decreaseScope: ->
52 | @scopeChain.pop()
53 | @currentScope = Math.min @currentScope, @scopeChain.length - 1
54 | Util.last(@scopeChain)
55 |
56 | insert: (name, value) ->
57 | if name is 'this' and not @strict
58 | if not value?
59 | value = @global
60 | else if (t = typeof value) not in ['object', 'function']
61 | value = new @global[t.charAt(0).toUpperCase() + t[1..]] value
62 | @scopeChain[@currentScope].set(name, value)
63 |
64 | update: (name, value) ->
65 | for i in [@scopeChain.length - 1 .. 0] by -1
66 | if @scopeChain[i].has(name)
67 | return @scopeChain[i].set(name, value)
68 | throw new ReferenceError "Tried to update nonexistent var '#{name}'"
69 |
70 | globalInsert: (name, value) ->
71 | @scopeChain[0].set(name, value)
72 |
73 | has: (name) ->
74 | for i in [@scopeChain.length - 1 .. 0] by -1
75 | return true if @scopeChain[i].has(name)
76 | name of @global
77 |
78 | resolve: (name) ->
79 | for i in [@scopeChain.length - 1 .. 0] by -1
80 | return @scopeChain[i].get(name) if @scopeChain[i].has(name)
81 | return @global[name] if name of @global
82 | throw new ReferenceError "Unable to resolve #{JSON.stringify name}"
83 |
84 | toString: -> scope.cache for scope in @scopeChain
85 |
86 | makeArgsObject = (argsArray) ->
87 | argsObject = {}
88 | argsObject[i] = arg for arg, i in argsArray
89 | Util.defineNonEnumerable argsObject, 'length', argsArray.length
90 |
91 | root.CPSFunction = class CPSFunction
92 | constructor: (@name, @__env__, __apply__) ->
93 | @__apply__ ?= __apply__
94 | @__ctor__ = (new Function "return function #{@name}() {}")()
95 | @prototype = @__ctor__.prototype
96 |
97 | apply: (thisArg, args) ->
98 | await this.__apply__ thisArg, args, defer(result), errCont
99 | return result
100 |
101 | class InterpretedFunction extends CPSFunction
102 | constructor: (name, __env__, @__node__) ->
103 | super(name, __env__)
104 |
105 | __apply__: (thisArg, args, cont, errCont) ->
106 | @__env__.increaseScope()
107 | @__env__.insert 'arguments', makeArgsObject args
108 | # must be called after makeArgsObject in case there is a param named
109 | # 'arguments'
110 | @__env__.insert(param.name, args[i]) for param, i in @__node__.params
111 | @__env__.insert 'this', thisArg
112 | await root.evaluate @__node__.body, @__env__, defer(result), (e) =>
113 | if e instanceof ReturnException
114 | @__env__.decreaseScope()
115 | cont(e.value)
116 | else
117 | errCont(e)
118 | @__env__.decreaseScope()
119 | cont(result)
120 |
121 | class GeneratorFunction extends InterpretedFunction
122 | __apply__: (thisArg, args, cont, errCont) ->
123 | cont new Generator thisArg, args, @__node__, @__env__.copy()
124 |
125 | class Generator
126 | NEWBORN = {}
127 | EXECUTING = {}
128 | CLOSED = {}
129 | SUSPENDED = {}
130 |
131 | constructor: (thisArg, args, @__node__, @__env__) ->
132 | @__cont__ = null
133 | @__state__ = NEWBORN
134 | @__env__.increaseScope()
135 | @__env__.insert 'arguments', makeArgsObject args
136 | @__env__.insert(param.name, args[i]) for param, i in @__node__.params
137 | @__env__.insert 'this', thisArg
138 |
139 | send: new CPSFunction('send', null, (thisArg, args, cont, errCont) ->
140 | v = args[0]
141 | thisArg.__calleeCont__ = cont
142 | thisArg.__calleeErrCont__ = errCont
143 | switch thisArg.__state__
144 | when EXECUTING
145 | errCont new Error "Generator is already executing"
146 | when CLOSED
147 | errCont new StopIteration
148 | when NEWBORN
149 | if v isnt undefined then throw new TypeError
150 | thisArg.__state__ = EXECUTING
151 | await root.evaluate thisArg.__node__.body, thisArg.__env__, bodyCont = defer(rv), (e) ->
152 | if e instanceof YieldException
153 | thisArg.__state__ = SUSPENDED
154 | thisArg.__cont__ = e.cont
155 | thisArg.__errCont__ = e.errCont
156 | thisArg.__calleeCont__ e.value
157 | else if e instanceof ReturnException
158 | bodyCont(e.value)
159 | else
160 | thisArg.__calleeErrCont__ e
161 | thisArg.__state__ = CLOSED
162 | thisArg.__calleeErrCont__ new StopIteration rv
163 | else # SUSPENDED
164 | thisArg.__cont__ v)
165 |
166 | next: new CPSFunction('next', null, (thisArg, args, cont, errCont) ->
167 | thisArg.send.__apply__ thisArg, [], cont, errCont)
168 |
169 | close: new CPSFunction('close', null, (thisArg, args, cont, errCont) ->
170 | thisArg.__calleeCont__ = cont
171 | thisArg.__calleeErrCont__ = (e) ->
172 | if e instanceof StopIteration
173 | cont()
174 | else
175 | errCont(e)
176 | switch thisArg.__state__
177 | when EXECUTING
178 | errCont new Error "Generator is currently executing"
179 | when NEWBORN
180 | thisArg.__state__ = CLOSED
181 | when SUSPENDED
182 | thisArg.__state__ = EXECUTING
183 | thisArg.__errCont__ new ReturnException
184 | when CLOSED
185 | cont())
186 |
187 | throw: new CPSFunction('_throw', null, (thisArg, args, cont, errCont) ->
188 | thisArg.__calleeCont__ = cont
189 | thisArg.__calleeErrCont__ = errCont
190 | switch thisArg.__state__
191 | when EXECUTING
192 | errCont new Error "Generator is currently executing"
193 | when CLOSED
194 | errCont new Error "Generator is closed"
195 | when NEWBORN
196 | thisArg.__state__ = CLOSED
197 | thisArg.__calleeErrCont__ args[0]
198 | when SUSPENDED
199 | thisArg.__state__ = EXECUTING
200 | thisArg.__errCont__ args[0])
201 |
202 | iterator: new CPSFunction('iterator', null, (thisArg, args, cont, errCont) ->
203 | cont thisArg)
204 |
205 | root.evaluate = (node, env, cont, errCont) ->
206 | try
207 | switch node.type
208 | when 'EmptyStatement'
209 | cont()
210 | when 'Program', 'BlockStatement'
211 | for stmt, i in node.body
212 | env.strict ||= i == 0 and stmt.expression?.value is 'use strict'
213 | await root.evaluate stmt, env, defer(v), errCont
214 | return cont(v) if node.type is 'Program' and i == node.body.length - 1 # for eval's return value
215 | process.nextTick cont # avoid stack overflow
216 | when 'FunctionDeclaration', 'FunctionExpression'
217 | name = node.id?.name ? ''
218 | ifn = new (if node.generator then GeneratorFunction else InterpretedFunction) name, env.copy(), node
219 | if node.id?
220 | env.insert(node.id.name, ifn)
221 | cont(ifn)
222 | when 'VariableDeclaration'
223 | for dec in node.declarations
224 | await root.evaluate dec, env, defer(result), errCont
225 | cont()
226 | when 'VariableDeclarator'
227 | if node.init?
228 | await root.evaluate node.init, env, defer(init), errCont
229 | else
230 | init = undefined
231 | cont(env.insert node.id.name, init, env)
232 | when 'ExpressionStatement'
233 | root.evaluate node.expression, env, cont, errCont
234 | when 'CallExpression'
235 | callee = null
236 | if node.callee.type is 'MemberExpression'
237 | await evalMemberExpr node.callee, env, defer(thisArg, calleeName), errCont
238 | callee = thisArg[calleeName]
239 | else
240 | thisArg = undefined
241 | await root.evaluate node.callee, env, defer(callee), errCont
242 | args =
243 | for arg in node.arguments
244 | await root.evaluate arg, env, defer(argResult), errCont
245 | argResult
246 | if callee == eval
247 | return cont(args[0]) unless Util.isString args[0]
248 | ast = esprima.parse args[0]
249 | fnName =
250 | if node.callee.type is 'MemberExpression' and
251 | node.callee.property.type is 'Identifier'
252 | node.callee.property.name
253 | else if node.callee.type is 'Identifier'
254 | node.callee.name
255 | else
256 | null
257 | if fnName is 'eval'
258 | root.evaluate ast, env, cont, errCont
259 | else
260 | root.evaluate ast, env.getGlobalEnv(), cont, errCont
261 | else
262 | if callee instanceof CPSFunction
263 | callee.__apply__ thisArg, args, cont, errCont
264 | else
265 | cont callee.apply thisArg, args
266 | when 'NewExpression'
267 | await root.evaluate node.callee, env, defer(callee), errCont
268 | args =
269 | for arg in node.arguments
270 | await root.evaluate arg, env, defer(result), errCont
271 | result
272 | if callee.__ctor__?
273 | obj = new callee.__ctor__
274 | if callee instanceof CPSFunction
275 | await callee.__apply__ obj, args, defer(result), errCont
276 | else
277 | callee.apply obj, args
278 | else
279 | if callee instanceof CPSFunction
280 | await callee.bind.__apply__ callee, ([null].concat args), defer(result), errCont
281 | else
282 | obj = new (callee.bind.apply callee, [null].concat args)
283 | cont(obj)
284 | #*** Control Flow ***#
285 | when 'IfStatement', 'ConditionalExpression'
286 | await root.evaluate node.test, env, defer(test), errCont
287 | if (test)
288 | root.evaluate node.consequent, env, cont, errCont
289 | else if node.alternate?
290 | root.evaluate node.alternate, env, cont, errCont
291 | else
292 | cont()
293 | when 'WhileStatement'
294 | while (true)
295 | # Test
296 | await root.evaluate node.test, env, defer(test), errCont
297 | return cont() if not test
298 | # Body
299 | await root.evaluate node.body, env, bodyCont = defer(),
300 | makeLoopCont(node.body, env, bodyCont, cont, errCont)
301 | when 'DoWhileStatement'
302 | while (true)
303 | # Body
304 | await root.evaluate node.body, env, bodyCont = defer(),
305 | makeLoopCont(node.body, env, bodyCont, cont, errCont)
306 | # Test
307 | await root.evaluate node.test, env, defer(test), errCont
308 | return cont() if not test
309 | when 'ForStatement'
310 | await root.evaluate node.init, env, defer(), errCont
311 | while (true)
312 | # Test
313 | await root.evaluate node.test, env, defer(test), errCont
314 | return cont() if not test
315 | # Body
316 | await root.evaluate node.body, env, bodyCont = defer(),
317 | makeLoopCont(node.body, env, bodyCont, cont, errCont)
318 | # Update
319 | await root.evaluate node.update, env, defer(), errCont
320 | when 'ForInStatement'
321 | await root.evaluate node.left, env, defer(), errCont
322 | await root.evaluate node.right, env, defer(obj), errCont
323 | id =
324 | if node.left.type is 'VariableDeclaration'
325 | node.left.declarations[0].id
326 | else
327 | node.left
328 | for k of obj
329 | await assign id, k, env, defer(), errCont
330 | await root.evaluate node.body, env, bodyCont = defer(),
331 | makeLoopCont(node.body, env, bodyCont, cont, errCont)
332 | cont()
333 | when 'ForOfStatement'
334 | await root.evaluate node.left, env, defer(), errCont
335 | await root.evaluate node.right, env, defer(iterable), errCont
336 | id =
337 | if node.left.type is 'VariableDeclaration'
338 | node.left.declarations[0].id
339 | else
340 | node.left
341 | await iterable.iterator.__apply__ iterable, [], defer(iterator), errCont
342 | while true
343 | await iterator.next.__apply__ iterator, [], defer(v), (e) ->
344 | if e instanceof StopIteration then cont() else errCont e
345 | await assign id, v, env, defer(), errCont
346 | await root.evaluate node.body, env, bodyCont = defer(),
347 | makeLoopCont(node.body, env, bodyCont, cont, errCont)
348 | when 'BreakStatement'
349 | errCont(new BreakException)
350 | when 'ContinueStatement'
351 | errCont(new ContinueException)
352 | when 'ReturnStatement'
353 | if node.argument is null
354 | errCont new ReturnException undefined
355 | else
356 | await root.evaluate node.argument, env, defer(result), errCont
357 | errCont new ReturnException result
358 | when 'ThrowStatement'
359 | await root.evaluate node.argument, env, defer(result), errCont
360 | errCont(new JSException result, node, env)
361 | # may be called more than once if try statement contains a yield
362 | when 'TryStatement'
363 | finalizeAndThrow = (e) ->
364 | if node.finalizer
365 | await root.evaluate node.finalizer, env, defer(), errCont
366 | errCont e
367 | finalizeAndCont = ->
368 | if node.finalizer
369 | root.evaluate node.finalizer, env, cont, errCont
370 | else
371 | cont()
372 |
373 | await root.evaluate node.block, env, defer(), (e) ->
374 | if e instanceof YieldException
375 | errCont e
376 | else if e not instanceof InterpreterException and node.handlers.length > 0
377 | # if the error is a JSException then we have to unwrap it
378 | unwrappedError = if e instanceof JSException then e.error else e
379 | catchEnv = env.increaseScope true
380 | catchEnv.set node.handlers[0].param.name, unwrappedError
381 | await root.evaluate node.handlers[0], env, defer(), (unwrappedError) ->
382 | env.decreaseScope()
383 | finalizeAndThrow(unwrappedError)
384 | env.decreaseScope()
385 | finalizeAndCont()
386 | else
387 | finalizeAndThrow(e)
388 | finalizeAndCont()
389 | when 'CatchClause'
390 | root.evaluate node.body, env, cont, errCont
391 | #*** Operator Expressions ***#
392 | when 'LogicalExpression'
393 | await root.evaluate node.left, env, defer(lhs), errCont
394 | switch node.operator
395 | when '&&'
396 | # `lhs && await ...` will not short-circuit due to a bug in IcedCoffeeScript
397 | if lhs then await root.evaluate node.right, env, defer(rhs), errCont
398 | cont(lhs && rhs)
399 | when '||'
400 | if not lhs then await root.evaluate node.right, env, defer(rhs), errCont
401 | cont(lhs || rhs)
402 | else
403 | errCont "Unrecognized operator #{node.operator}"
404 | when 'BinaryExpression'
405 | await root.evaluate node.left, env, defer(lhs), errCont
406 | await root.evaluate node.right, env, defer(rhs), errCont
407 | switch node.operator
408 | when '+'
409 | cont(lhs + rhs)
410 | when '-'
411 | cont(lhs - rhs)
412 | when '*'
413 | cont(lhs * rhs)
414 | when '/'
415 | cont(lhs / rhs)
416 | when '&'
417 | cont(lhs & rhs)
418 | when '|'
419 | cont(lhs | rhs)
420 | when '^'
421 | cont(lhs ^ rhs)
422 | when '>>'
423 | cont(lhs >> rhs)
424 | when '<<'
425 | cont(lhs << rhs)
426 | when '>>>'
427 | cont(lhs >>> rhs)
428 | when '<'
429 | cont(lhs < rhs)
430 | when '>'
431 | cont(lhs > rhs)
432 | when '<='
433 | cont(lhs <= rhs)
434 | when '>='
435 | cont(lhs >= rhs)
436 | when '=='
437 | cont(`lhs == rhs`)
438 | when '==='
439 | cont(`lhs === rhs`)
440 | when '!='
441 | cont(`lhs != rhs`)
442 | when '!=='
443 | cont(`lhs !== rhs`)
444 | when 'instanceof'
445 | cont(lhs instanceof (rhs?.__ctor__ ? rhs))
446 | else
447 | errCont("Unrecognized operator #{node.operator}")
448 | when 'AssignmentExpression'
449 | await root.evaluate node.right, env, defer(value), errCont
450 | if node.operator is '='
451 | assign node.left, value, env, cont, errCont
452 | else
453 | if node.left.type is 'Identifier'
454 | original = env.resolve node.left.name
455 | else if node.left.type is 'MemberExpression'
456 | await evalMemberExpr node.left, env, defer(object, property), errCont
457 | original = object[property]
458 | else
459 | errCont "Invalid LHS in assignment"
460 | switch node.operator
461 | when '+='
462 | original += value
463 | when '-='
464 | original -= value
465 | when '*='
466 | original *= value
467 | when '/='
468 | original /= value
469 | when '&='
470 | original &= value
471 | when '|='
472 | original |= value
473 | else
474 | errCont "Unrecognized compound assignment #{node.operator}"
475 | if node.left.type is 'Identifier'
476 | env.insert node.left.name, original
477 | else if node.left.type is 'MemberExpression'
478 | object[property] = original
479 | cont(original)
480 | when 'UpdateExpression'
481 | await root.evaluate node.argument, env, defer(original), errCont
482 | if node.operator is '++'
483 | newValue = original + 1
484 | else # '--'
485 | newValue = original - 1
486 | if node.argument.type is 'Identifier'
487 | env.insert node.argument.name, newValue
488 | else if node.argument.type is 'MemberExpression'
489 | await evalMemberExpr node.argument, env, defer(object, property), errCont
490 | object[property] = newValue
491 | cont(if node.prefix then newValue else original)
492 | when 'UnaryExpression'
493 | if node.operator is 'delete'
494 | if node.argument.type is 'MemberExpression'
495 | await evalMemberExpr node.argument, env, defer(object, property), errCont
496 | cont(delete object[property])
497 | else
498 | errCont "NYI"
499 | else if node.operator is 'typeof' and
500 | node.argument.type is 'Identifier' and not env.has node.argument.name
501 | cont('undefined')
502 | else
503 | await root.evaluate node.argument, env, defer(arg), errCont
504 | switch node.operator
505 | when '-'
506 | cont(-arg)
507 | when '~'
508 | cont(~arg)
509 | when '!'
510 | cont(!arg)
511 | when 'typeof'
512 | cont(typeof arg)
513 | else
514 | errCont("NYI")
515 | #*** Identifiers and Literals ***#
516 | when 'Identifier'
517 | cont(env.resolve node.name)
518 | when 'MemberExpression'
519 | await evalMemberExpr node, env, defer(object, property), errCont
520 | cont(object[property])
521 | when 'ThisExpression'
522 | cont(env.resolve 'this')
523 | when 'Literal'
524 | cont(node.value)
525 | when 'ObjectExpression'
526 | obj = {}
527 | for prop in node.properties
528 | await root.evaluate prop.value, env, defer(propValue), errCont
529 | obj[prop.key.name ? prop.key.value] = propValue
530 | cont(obj)
531 | when 'ArrayExpression'
532 | cont(
533 | for el in node.elements
534 | await root.evaluate el, env, defer(elValue), errCont)
535 | when 'YieldExpression'
536 | if node.delegate # yield*
537 | await root.evaluate node.argument, env, defer(gen), errCont
538 | await gen.send.__apply__ gen, [], defer(yieldValue), errCont
539 | while true
540 | rv = new iced.Rendezvous
541 | # depending on whether send() or throw() got called, call the same
542 | # method on the child generator
543 | errCont(new YieldException(rv.id(gen.send).defer(v),
544 | rv.id(gen.throw).defer(v), yieldValue))
545 | await rv.wait defer genFn
546 | await genFn.__apply__ gen, [v], defer(yieldValue), (e) ->
547 | if e instanceof StopIteration
548 | cont e.value
549 | else if v instanceof ReturnException
550 | cont()
551 | else
552 | errCont e
553 | else
554 | if node.argument?
555 | await root.evaluate node.argument, env, defer(yieldValue), errCont
556 | errCont(new YieldException cont, errCont, yieldValue)
557 | else
558 | errCont("Unrecognized node '#{node.type}'!")
559 | catch e
560 | errCont(new JSException e, node, env)
561 |
562 | evalMemberExpr = (node, env, cont, errCont) ->
563 | await root.evaluate node.object, env, defer(object), errCont
564 | propNode = node.property
565 | if propNode.type is 'Identifier' and not node.computed
566 | cont(object, propNode.name)
567 | else
568 | await root.evaluate propNode, env, defer(property), errCont
569 | cont(object, property)
570 |
571 | assign = (node, value, env, cont, errCont) ->
572 | if node.type is 'Identifier'
573 | try
574 | env.update node.name, value
575 | catch e
576 | env.globalInsert node.name, value
577 | cont(value)
578 | else if node.type is 'MemberExpression'
579 | await evalMemberExpr node, env, defer(object, property), errCont
580 | object[property] = value
581 | cont(value)
582 | else
583 | errCont("Invalid LHS in assignment")
584 |
585 | makeLoopCont = (body, env, bodyCont, cont, errCont) ->
586 | (e) ->
587 | if e instanceof BreakException
588 | cont()
589 | else if e instanceof ContinueException
590 | bodyCont()
591 | else
592 | errCont(e)
593 |
--------------------------------------------------------------------------------
/lib/util.coffee:
--------------------------------------------------------------------------------
1 | exports.Util =
2 | last: (arr) -> arr[arr.length - 1]
3 |
4 | isString: (s) -> typeof s == 'string' || s instanceof String
5 |
6 | defineNonEnumerable: (obj, k, v) ->
7 | Object.defineProperty obj, k,
8 | value: v
9 | writable: true
10 | enumerable: false
11 | configurable: true
12 |
13 | class exports.Map
14 | constructor: ->
15 | @cache = Object.create null
16 | @proto_cache = undefined
17 | @proto_set = false
18 |
19 | get: (key) ->
20 | key = key.toString()
21 | return @cache[key] unless key is '__proto__'
22 | return @proto_cache
23 |
24 | has: (key) ->
25 | key = key.toString()
26 | return key of @cache unless key is '__proto__'
27 | return @proto_set
28 |
29 | set: (key, value) ->
30 | unless key.toString() is '__proto__'
31 | @cache[key] = value
32 | else
33 | @proto_cache = value
34 | @proto_set = true
35 | value
36 |
37 | items: ->
38 | items = ([k,v] for k, v of @cache)
39 | items.push ['__proto__', @proto_cache] if @proto_set
40 | items
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "metajs",
3 | "version": "1.0.0",
4 | "dependencies": {
5 | "iced-coffee-script": "1.4.0-c",
6 | "optimist": "*",
7 | "esprima": "git+https://github.com/ariya/esprima.git#harmony"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/repl.coffee:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env iced
2 | {evaluate,Environment} = require './lib/interpreter'
3 | esprima = require 'esprima'
4 |
5 | toplevel = ->
6 | repl = require 'repl'
7 | env = new Environment
8 | repl.start
9 | eval: (cmd, ctx, filename, callback) ->
10 | evaluate (esprima.parse cmd[1..-2], loc: true), env, callback, (e) ->
11 | callback("Error: #{e}")
12 |
13 | {argv} = require 'optimist'
14 | if argv._.length < 1
15 | toplevel()
16 | else
17 | fs = require 'fs'
18 | ast = esprima.parse (fs.readFileSync argv._[0]), loc: true
19 | evaluate ast, new Environment, (->), (e) ->
20 | console.log "Error: #{e}"
21 | process.exit 1
22 |
--------------------------------------------------------------------------------
/tests/control.js:
--------------------------------------------------------------------------------
1 | if (true) {
2 | console.log("True");
3 | }
4 | else {
5 | console.log("False");
6 | }
7 |
8 | console.log(typeof foo === 'undefined' ? 'foo exists' : 'foo does not exist');
9 |
10 | for (var i = 0; i < 10; i++) {
11 | console.log(i);
12 | }
13 |
14 | for (var i = 0; i < 10; i++) {
15 | console.log(i);
16 | if (i === 5) break;
17 | }
18 |
19 | console.log(i);
20 |
21 | for (var i = 0; i < 10; i++) {
22 | console.log(i);
23 | if (i === 5) continue;
24 | }
25 |
26 | console.log(i);
27 |
28 | var obj = { a: 1, b: 2, c: 3 };
29 |
30 | for (var k in obj) {
31 | console.log(k, obj[k]);
32 | }
33 |
34 | var obj2 = { i: 0 }
35 | for (obj2.i in obj) {
36 | console.log(obj2.i, obj[obj2.i]);
37 | }
38 |
39 | var rv = (function () {
40 | console.log("foo");
41 | return;
42 | console.log("should not be printed");
43 | })();
44 |
45 | console.log(rv);
46 |
47 | rv = (function() {
48 | console.log("bar");
49 | return null;
50 | console.log("should not be printed");
51 | })();
52 |
53 | console.log(rv);
54 |
55 | console.log("testing exceptions");
56 |
57 | (function() {
58 | var e = "foo";
59 | try {
60 | (function() {
61 | throw new Error("hello world");
62 | })();
63 | }
64 | catch (e) {
65 | var catchVar = "hi";
66 | console.log(e);
67 | e = "blah";
68 | console.log(e);
69 | }
70 | finally {
71 | var finVar = "bye";
72 | console.log("finally");
73 | }
74 | console.log(e);
75 | console.log(catchVar);
76 | console.log(finVar);
77 | })();
78 |
79 | console.log("testing logical operators");
80 |
81 | var falseFn = function() {
82 | console.log("falseFn");
83 | return false;
84 | };
85 |
86 | var trueFn = function() {
87 | console.log("trueFn");
88 | return true;
89 | };
90 |
91 | console.log('&&');
92 | console.log(falseFn() && falseFn());
93 | console.log('&&');
94 | console.log(falseFn() && trueFn());
95 | console.log('&&');
96 | console.log(trueFn() && falseFn());
97 | console.log('&&');
98 | console.log(trueFn() && trueFn());
99 |
100 | console.log('||');
101 | console.log(falseFn() || falseFn());
102 | console.log('||');
103 | console.log(falseFn() || trueFn());
104 | console.log('||');
105 | console.log(trueFn() || falseFn());
106 | console.log('||');
107 | console.log(trueFn() || trueFn());
108 |
109 | console.log('testing empty expression');
110 | ;
--------------------------------------------------------------------------------
/tests/es6/for-of-loop.expected:
--------------------------------------------------------------------------------
1 | 1
2 | 5
3 |
--------------------------------------------------------------------------------
/tests/es6/for-of-loop.js:
--------------------------------------------------------------------------------
1 | var gen = function*() {
2 | yield 1;
3 | yield 5;
4 | };
5 |
6 | for (var v of gen()) {
7 | console.log(v);
8 | }
9 |
--------------------------------------------------------------------------------
/tests/es6/generators.expected:
--------------------------------------------------------------------------------
1 | Generator 1
2 | Generator received hi
3 | 1
4 | Generator received hi
5 | 2
6 | Generator received hi
7 | 3
8 | Generator received hi
9 | 4
10 | Generator received hi
11 | Shutting down generator
12 | Generator exhausted, returned undefined
13 | Generator 2
14 | Shutting down generator
15 | undefined
16 | Generator exhausted, returned undefined
17 | Generator 3
18 | Generator caught [Error: injected error]
19 | Shutting down generator
20 | generator exhausted, returned undefined
21 | Testing return value
22 | Generator 4
23 | Generator exhausted, returned 2
24 | Testing yield*
25 | Generator 5
26 | 1
27 | 2
28 | 0
29 | 2
30 | 4
31 | 0
32 | 3
33 | 6
34 | Generator exhausted, returned undefined
35 | Generator 6
36 | Inner generator caught [Error: injected error]
37 | 2
38 | 4
39 | 0
40 | 3
41 | 6
42 | Generator exhausted, returned undefined
43 |
--------------------------------------------------------------------------------
/tests/es6/generators.js:
--------------------------------------------------------------------------------
1 | function exhaustGenerator(it) {
2 | while (true) {
3 | try {
4 | console.log(it.send("hi"));
5 | }
6 | catch (e) {
7 | if (e instanceof StopIteration) {
8 | console.log("Generator exhausted, returned", e.value);
9 | break;
10 | }
11 | else
12 | throw e;
13 | }
14 | }
15 | }
16 |
17 | var gen = function* () {
18 | try {
19 | for (var i = 0; i < 5; i++) {
20 | console.log("Generator received", yield i);
21 | }
22 | }
23 | catch (e) {
24 | console.log("Generator caught", e);
25 | }
26 | finally {
27 | console.log("Shutting down generator");
28 | }
29 | };
30 |
31 | console.log("Generator 1");
32 |
33 | var it = gen();
34 | it.send();
35 | exhaustGenerator(it);
36 |
37 | console.log("Generator 2");
38 |
39 | it = gen();
40 | it.next();
41 | console.log(it.close());
42 | exhaustGenerator(it);
43 |
44 | console.log("Generator 3");
45 |
46 | it = gen();
47 | it.next();
48 | try {
49 | it.throw(new Error("injected error"));
50 | }
51 | catch (e) {
52 | if (e instanceof StopIteration)
53 | console.log("generator exhausted, returned", e.value);
54 | else
55 | throw e;
56 | }
57 |
58 | console.log("Testing return value");
59 |
60 | console.log("Generator 4");
61 |
62 | gen = function* () {
63 | yield 1;
64 | return 2;
65 | };
66 | it = gen();
67 | it.next();
68 | exhaustGenerator(it);
69 |
70 | console.log("Testing yield*");
71 |
72 | console.log("Generator 5");
73 |
74 | gen = function*() {
75 | for (var i = 0; i < 3; i++) {
76 | var inner = innerGen(i + 1);
77 | yield* inner;
78 | }
79 | };
80 |
81 | var innerGen = function*(j) {
82 | try {
83 | for (var i = 0; i < 3; i++)
84 | yield i * j;
85 | }
86 | catch (e) {
87 | console.log("Inner generator caught", e);
88 | }
89 | };
90 |
91 | it = gen();
92 | it.next();
93 | exhaustGenerator(it);
94 |
95 | console.log("Generator 6");
96 |
97 | it = gen();
98 | it.next();
99 | it.throw(new Error("injected error"));
100 | exhaustGenerator(it);
101 |
--------------------------------------------------------------------------------
/tests/objects.js:
--------------------------------------------------------------------------------
1 | function Foo() {
2 | this.bar = 1;
3 | }
4 |
5 | Foo.prototype.baz = 2;
6 |
7 | var foo1 = new Foo();
8 | var foo2 = new Foo();
9 | console.log(foo1.bar);
10 | console.log(foo1.baz);
11 | console.log(delete foo1.bar);
12 | console.log(delete foo1.baz);
13 | console.log(foo1.bar);
14 | console.log(foo1.baz);
15 | console.log(foo2.bar);
16 | console.log(foo2.baz);
17 |
--------------------------------------------------------------------------------
/tests/reflection.js:
--------------------------------------------------------------------------------
1 | console.log("testing the arguments object");
2 |
3 | (function(foo) {
4 | console.log(arguments);
5 | console.log(arguments.length);
6 | arguments.length = 0;
7 | console.log(arguments.length);
8 | delete arguments.length;
9 | console.log(arguments.length);
10 | console.log(Object.getPrototypeOf(arguments));
11 | })("bar");
12 |
13 | (function(arguments) {
14 | console.log(arguments);
15 | console.log(arguments.length);
16 | console.log(Object.getPrototypeOf(arguments));
17 | })({});
18 |
19 | (function() {
20 | console.log(arguments);
21 | console.log(arguments.length);
22 | })("bar");
23 |
24 | console.log("testing eval()");
25 |
26 | a = -10;
27 | (function() {
28 | var a = 1;
29 | console.log(eval("console.log(a); a++"));
30 | console.log(a);
31 |
32 | console.log(global['eval']("console.log(a); a++"));
33 |
34 | var eeval = eval;
35 | console.log(eeval("console.log(a); a++"));
36 | console.log(a);
37 |
38 | console.log(eval({}));
39 | })();
40 | console.log(a);
41 |
42 | console.log((function() { 1; })());
43 |
44 | console.log("check that we have santized '__proto__'");
45 | var __proto__ = null;
46 | console.log(__proto__);
47 | console.log(toString);
48 | console.log(global.__proto__);
49 |
50 | console.log("invalid instanceof call");
51 | try {
52 | 1 instanceof null;
53 | } catch (e) {
54 | console.log(e);
55 | }
56 |
--------------------------------------------------------------------------------
/tests/scope.js:
--------------------------------------------------------------------------------
1 | console.log("testing lexical scope");
2 |
3 | function f(a) {
4 | var b = 2;
5 | globalVar = "glob";
6 | return function() {
7 | console.log(a);
8 | console.log(b);
9 | }
10 | }
11 |
12 | var g = f(1)
13 |
14 | var a = -1;
15 | var b = -2;
16 |
17 | g();
18 |
19 | console.log(b);
20 | console.log(globalVar);
21 |
22 | function Foo() {
23 | this.baz = 1;
24 | }
25 |
26 | Foo.prototype.bar = function() {
27 | console.log(this instanceof Foo);
28 | console.log(this === global);
29 | console.log(this === undefined);
30 | }
31 |
32 | console.log("testing `this` binding");
33 |
34 | var foo = new Foo();
35 | foo.bar();
36 | var unbound = foo.bar;
37 | unbound();
38 |
39 | Number.prototype.bar = function() {
40 | console.log(typeof this);
41 | }
42 |
43 | var num = 1;
44 | num.bar();
45 |
46 | (function() {
47 | "use strict";
48 | console.log("testing strict mode");
49 |
50 | unbound();
51 | function Bar() { }
52 |
53 | Bar.prototype.bar = function() {
54 | console.log(this instanceof Foo);
55 | console.log(this === global);
56 | console.log(this === undefined);
57 | }
58 |
59 | var bar = new Bar();
60 | bar.bar();
61 | unbound = bar.bar;
62 | unbound();
63 |
64 | Number.prototype.baz = function() {
65 | console.log(typeof this);
66 | }
67 | num.baz();
68 | })();
69 |
--------------------------------------------------------------------------------